[
  {
    "path": ".gitattributes",
    "content": "*.js linguist-language=java\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### Maven template\ntarget/\npom.xml.tag\npom.xml.releaseBackup\npom.xml.versionsBackup\npom.xml.next\nrelease.properties\ndependency-reduced-pom.xml\nbuildNumber.properties\n.mvn/timing.properties\n\n# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)\n!/.mvn/wrapper/maven-wrapper.jar\n### JetBrains template\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n.idea/\n\n# User-specific stuff:\n\n\n# Sensitive or high-churn files:\n\n# Gradle:\n\n\n# CMake\ncmake-build-debug/\ncmake-build-release/\n\n# Mongo Explorer plugin:\n.idea/**/mongoSettings.xml\n\n## File-based project format:\n*.iml\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\napplog/"
  },
  {
    "path": "Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8:slim\nVOLUME /tmp\nADD target/hospital-drug-0.0.1.jar app.jar\nENTRYPOINT [\"java\",\"-jar\",\"/app.jar\",\"--spring.profiles.active=pro\"]"
  },
  {
    "path": "README.md",
    "content": "## 库存管理\n\n- 登记入库的药品。\n- 登记出库的药品。\n- 每日检查库存下限，报警。\n- 每日检查过期的药品，报警并做退回销毁处理。\n- 对有问题的药品的退回供应商。记录退回的药品的名称、数量、金额和退货原因等。\n\n## 销售管理\n\n- 记录每次销售行为。包括药品的编号、名称、数量、金额、经手人、经手日期等。\n- 对每次退货进行记录，登记退货原因。\n\n## 汇总和统计\n\n- 每日统计销售情况并生成报表。\n- 月终和年终的销售数据统计。\n- 查询销售明细和统计数据。\n\n## 明细查询\n\n- 查询药品基本信息。\n- 查询库存情况。\n- 查询退回供应商的药品情况\n- 查询供应商信息\n- 查询与供应商的往来账目查询\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>me.zbl</groupId>\n    <artifactId>hospital-drug</artifactId>\n    <version>0.0.1</version>\n    <packaging>jar</packaging>\n\n    <name>hospital-drug</name>\n    <description>Management system of hospital drug.</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>1.5.9.RELEASE</version>\n        <relativePath/>\n    </parent>\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        <mybatisplus-spring-boot-starter.version>1.0.4</mybatisplus-spring-boot-starter.version>\n        <velocity.version>1.7</velocity.version>\n        <activiti.version>5.22.0</activiti.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n        <!--web -->\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-thymeleaf</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>net.sourceforge.nekohtml</groupId>\n            <artifactId>nekohtml</artifactId>\n        </dependency>\n        <!--mybatis -->\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis</artifactId>\n            <version>3.4.4</version>\n        </dependency>\n        <!-- MyBatis 使用 Java8 新的日期时间 API 必需 -->\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis-typehandlers-jsr310</artifactId>\n            <version>1.0.2</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis.spring.boot</groupId>\n            <artifactId>mybatis-spring-boot-starter</artifactId>\n            <version>1.1.1</version>\n        </dependency>\n        <!--druid -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid</artifactId>\n            <version>1.0.28</version>\n        </dependency>\n        <!--commons -->\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n            <version>3.6</version>\n        </dependency>\n        <dependency>\n            <groupId>commons-configuration</groupId>\n            <artifactId>commons-configuration</artifactId>\n            <version>1.10</version>\n        </dependency>\n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n            <version>2.5</version>\n        </dependency>\n        <!--shiro -->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-core</artifactId>\n            <version>1.3.2</version>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-spring</artifactId>\n            <version>1.3.2</version>\n        </dependency>\n        <!-- shiro ehcache -->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-ehcache</artifactId>\n            <version>1.3.2</version>\n        </dependency>\n        <dependency>\n            <groupId>com.github.theborakompanioni</groupId>\n            <artifactId>thymeleaf-extras-shiro</artifactId>\n            <version>1.2.1</version>\n        </dependency>\n        <!-- utils -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <version>1.2.31</version>\n        </dependency>\n        <!--velocity代码生成使用模板 -->\n        <dependency>\n            <groupId>org.apache.velocity</groupId>\n            <artifactId>velocity</artifactId>\n            <version>1.7</version>\n        </dependency>\n        <!-- ehchache -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-cache</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>net.sf.ehcache</groupId>\n            <artifactId>ehcache</artifactId>\n        </dependency>\n        <!--<dependency>-->\n            <!--<groupId>org.springframework.boot</groupId>-->\n            <!--<artifactId>spring-boot-starter-data-redis</artifactId>-->\n        <!--</dependency>-->\n        <!-- quartz -->\n        <dependency>\n            <groupId>org.quartz-scheduler</groupId>\n            <artifactId>quartz</artifactId>\n            <version>2.2.1</version>\n            <exclusions>\n                <exclusion>\n                    <artifactId>slf4j-api</artifactId>\n                    <groupId>org.slf4j</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <!-- SpringWebSocket依赖 -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-websocket</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context-support</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-devtools</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <!--activity-->\n        <dependency>\n            <groupId>org.activiti</groupId>\n            <artifactId>activiti-engine</artifactId>\n            <version>${activiti.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.activiti</groupId>\n            <artifactId>activiti-spring</artifactId>\n            <version>${activiti.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.activiti</groupId>\n            <artifactId>activiti-modeler</artifactId>\n            <version>${activiti.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.activiti</groupId>\n            <artifactId>activiti-diagram-rest</artifactId>\n            <version>${activiti.version}</version>\n        </dependency>\n\n        <!--swagger2-->\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n            <version>2.6.1</version>\n        </dependency>\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n            <version>2.6.1</version>\n        </dependency>\n\n        <!-- 添加redis支持-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-redis</artifactId>\n        </dependency>\n\n        <!-- xss过滤组件 -->\n        <dependency>\n            <groupId>org.jsoup</groupId>\n            <artifactId>jsoup</artifactId>\n            <version>1.9.2</version>\n        </dependency>\n\n        <!-- PageHelper MyBatis 分页插件 -->\n        <dependency>\n            <groupId>com.github.pagehelper</groupId>\n            <artifactId>pagehelper-spring-boot-starter</artifactId>\n            <version>1.2.5</version>\n        </dependency>\n\n        <!--war包部署需要-->\n        <!--<dependency>-->\n            <!--<groupId>org.springframework.boot</groupId>-->\n            <!--<artifactId>spring-boot-starter-web</artifactId>-->\n            <!--&lt;!&ndash; 移除嵌入式tomcat插件 &ndash;&gt;-->\n            <!--<exclusions>-->\n                <!--<exclusion>-->\n                    <!--<groupId>org.springframework.boot</groupId>-->\n                    <!--<artifactId>spring-boot-starter-tomcat</artifactId>-->\n                <!--</exclusion>-->\n            <!--</exclusions>-->\n        <!--</dependency>-->\n        <!--<dependency>-->\n            <!--<groupId>javax.servlet</groupId>-->\n            <!--<artifactId>javax.servlet-api</artifactId>-->\n            <!--<version>3.1.0</version>-->\n            <!--<scope>provided</scope>-->\n        <!--</dependency>-->\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <configuration>\n                    <executable>true</executable>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.mybatis.generator</groupId>\n                <artifactId>mybatis-generator-maven-plugin</artifactId>\n                <version>1.3.5</version>\n                <configuration>\n                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>\n                    <verbose>true</verbose>\n                    <overwrite>true</overwrite>\n                </configuration>\n                <!--<executions>-->\n                    <!--<execution>-->\n                        <!--<id>Generate MyBatis Artifacts</id>-->\n                        <!--<goals>-->\n                            <!--<goal>generate</goal>-->\n                        <!--</goals>-->\n                    <!--</execution>-->\n                <!--</executions>-->\n                <dependencies>\n                    <dependency>\n                        <groupId>mysql</groupId>\n                        <artifactId>mysql-connector-java</artifactId>\n                        <version>5.1.6</version>\n                    </dependency>\n                </dependencies>\n            </plugin>\n        </plugins>\n    </build>\n    <repositories>\n        <repository>\n            <id>public</id>\n            <name>aliyun nexus</name>\n            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>\n            <releases>\n                <enabled>true</enabled>\n            </releases>\n        </repository>\n    </repositories>\n    <pluginRepositories>\n        <pluginRepository>\n            <id>public</id>\n            <name>aliyun nexus</name>\n            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>\n            <releases>\n                <enabled>true</enabled>\n            </releases>\n            <snapshots>\n                <enabled>false</enabled>\n            </snapshots>\n        </pluginRepository>\n    </pluginRepositories>\n</project>\n"
  },
  {
    "path": "rest-test/test_supplier_list.xml",
    "content": "<RestClientRequest>\n  <option name=\"biscuits\">\n    <list>\n      <Biscuit>\n        <option name=\"date\" value=\"-1\" />\n        <option name=\"domain\" value=\"localhost\" />\n        <option name=\"name\" value=\"JSESSIONID\" />\n        <option name=\"path\" value=\"/\" />\n        <option name=\"value\" value=\"0c13db00-0053-46ab-8e48-838dc2050409\" />\n      </Biscuit>\n    </list>\n  </option>\n  <option name=\"httpMethod\" value=\"GET\" />\n  <option name=\"urlBase\" value=\"http://localhost:8086\" />\n  <option name=\"urlPath\" value=\"/supplier/list\" />\n  <option name=\"headers\">\n    <list>\n      <KeyValuePair>\n        <option name=\"key\" value=\"Accept\" />\n        <option name=\"value\" value=\"*/*\" />\n      </KeyValuePair>\n      <KeyValuePair>\n        <option name=\"key\" value=\"Cache-Control\" />\n        <option name=\"value\" value=\"no-cache\" />\n      </KeyValuePair>\n    </list>\n  </option>\n  <option name=\"parameters\">\n    <list>\n      <KeyValuePair>\n        <option name=\"key\" value=\"offset\" />\n        <option name=\"value\" value=\"0\" />\n      </KeyValuePair>\n      <KeyValuePair>\n        <option name=\"key\" value=\"limit\" />\n        <option name=\"value\" value=\"10\" />\n      </KeyValuePair>\n    </list>\n  </option>\n  <option name=\"parametersEnabled\" value=\"true\" />\n  <option name=\"haveTextToSend\" value=\"false\" />\n  <option name=\"haveFileToSend\" value=\"false\" />\n  <option name=\"isFileUpload\" value=\"false\" />\n  <option name=\"textToSend\" value=\"\" />\n  <option name=\"filesToSend\" value=\"\" />\n</RestClientRequest>"
  },
  {
    "path": "rest-test/test_supplier_save.xml",
    "content": "<RestClientRequest>\n  <option name=\"biscuits\">\n    <list>\n      <Biscuit>\n        <option name=\"date\" value=\"-1\" />\n        <option name=\"domain\" value=\"localhost\" />\n        <option name=\"name\" value=\"JSESSIONID\" />\n        <option name=\"path\" value=\"/\" />\n        <option name=\"value\" value=\"f7f79774-3660-46d2-913b-d1170962a683\" />\n      </Biscuit>\n    </list>\n  </option>\n  <option name=\"httpMethod\" value=\"POST\" />\n  <option name=\"urlBase\" value=\"http://localhost:8086\" />\n  <option name=\"urlPath\" value=\"/supplier/save\" />\n  <option name=\"headers\">\n    <list>\n      <KeyValuePair>\n        <option name=\"key\" value=\"Accept\" />\n        <option name=\"value\" value=\"*/*\" />\n      </KeyValuePair>\n      <KeyValuePair>\n        <option name=\"key\" value=\"Cache-Control\" />\n        <option name=\"value\" value=\"no-cache\" />\n      </KeyValuePair>\n    </list>\n  </option>\n  <option name=\"parameters\">\n    <list>\n      <KeyValuePair>\n        <option name=\"key\" value=\"id\" />\n        <option name=\"value\" value=\"HEB-0004\" />\n      </KeyValuePair>\n      <KeyValuePair>\n        <option name=\"key\" value=\"name\" />\n        <option name=\"value\" value=\"ASS\" />\n      </KeyValuePair>\n    </list>\n  </option>\n  <option name=\"parametersEnabled\" value=\"true\" />\n  <option name=\"haveTextToSend\" value=\"false\" />\n  <option name=\"haveFileToSend\" value=\"false\" />\n  <option name=\"isFileUpload\" value=\"false\" />\n  <option name=\"textToSend\" value=\"\" />\n  <option name=\"filesToSend\" value=\"\" />\n</RestClientRequest>"
  },
  {
    "path": "sql/hospital-drug.sql",
    "content": "/*\nNavicat MySQL Data Transfer\n\nSource Server         : 本地 MySQL\nSource Server Version : 50714\nSource Host           : localhost:3306\nSource Database       : hospital-drug\n\nTarget Server Type    : MYSQL\nTarget Server Version : 50714\nFile Encoding         : 65001\n\nDate: 2018-04-23 13:17:46\n*/\n\nCREATE DATABASE IF NOT EXISTS `hospital-drug`;\nUSE `hospital-drug`;\n\nSET FOREIGN_KEY_CHECKS=0;\n\n-- ----------------------------\n-- Table structure for act_id_user\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-- Records of act_id_user\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for act_re_deployment\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-- Records of act_re_deployment\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for act_re_procdef\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-- Records of act_re_procdef\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for act_ru_execution\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-- Records of act_ru_execution\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for act_ru_task\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-- Records of act_ru_task\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for app_consumer\n-- ----------------------------\nDROP TABLE IF EXISTS `app_consumer`;\nCREATE TABLE `app_consumer` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `name` varchar(20) NOT NULL,\n  `tel` varchar(12) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='顾客表-存储顾客的基本信息';\n\n-- ----------------------------\n-- Records of app_consumer\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for app_drug\n-- ----------------------------\nDROP TABLE IF EXISTS `app_drug`;\nCREATE TABLE `app_drug` (\n  `id` varchar(20) NOT NULL COMMENT '主键',\n  `name` varchar(30) NOT NULL COMMENT '药品名称',\n  `quantity` int(8) NOT NULL DEFAULT '0' COMMENT '库存数',\n  `invalid_date` date NOT NULL COMMENT '失效日期',\n  `price` decimal(10,2) NOT NULL COMMENT '单价',\n  `invalid` varchar(2) NOT NULL DEFAULT '0' COMMENT '是否问题药品',\n  `quality_guarantee_period` int(11) unsigned NOT NULL COMMENT '保质期（月）',\n  `lower_limit` int(8) unsigned NOT NULL,\n  `supplier_id` varchar(20) NOT NULL,\n  PRIMARY KEY (`id`),\n  KEY `supplier_id` (`supplier_id`),\n  CONSTRAINT `app_drug_ibfk_1` FOREIGN KEY (`supplier_id`) REFERENCES `app_supplier` (`id`) ON DELETE CASCADE ON UPDATE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='药品表-存储药品的基本信息';\n\n-- ----------------------------\n-- Records of app_drug\n-- ----------------------------\nINSERT INTO `app_drug` VALUES ('6901894121021', '藿香正气水', '1000', '2018-04-06', '10.00', '0', '20180405', '20', 'HEB-0001');\n\n-- ----------------------------\n-- Table structure for app_expire\n-- ----------------------------\nDROP TABLE IF EXISTS `app_expire`;\nCREATE TABLE `app_expire` (\n  `id` int(20) NOT NULL COMMENT '主键',\n  `drug_id` varchar(20) NOT NULL COMMENT '药品 ID',\n  `expired_date` date NOT NULL COMMENT '药品过期日期',\n  PRIMARY KEY (`id`),\n  KEY `drug_id` (`drug_id`),\n  CONSTRAINT `app_expire_ibfk_1` FOREIGN KEY (`drug_id`) REFERENCES `app_drug` (`id`) ON DELETE CASCADE ON UPDATE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='过期记录表-每次入库输入该批次的生产日期，计算过期的日期，存到这个表';\n\n-- ----------------------------\n-- Records of app_expire\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for app_inventory_record\n-- ----------------------------\nDROP TABLE IF EXISTS `app_inventory_record`;\nCREATE TABLE `app_inventory_record` (\n  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `supplier_id` varchar(20) NOT NULL COMMENT '供应商 ID',\n  `drug_id` varchar(20) NOT NULL COMMENT '药品 ID',\n  `name` varchar(30) NOT NULL COMMENT '药品名称',\n  `type` varchar(2) NOT NULL DEFAULT '1' COMMENT '1：入库，2：出库销售，3：出库退回',\n  `quantity` int(8) NOT NULL COMMENT '进货/退回/销售数量',\n  `ammount` decimal(10,2) NOT NULL COMMENT '金额',\n  `comment` varchar(100) DEFAULT NULL COMMENT '入库、出库、退货原因等',\n  `consumer_id` int(11) DEFAULT NULL COMMENT '顾客 ID',\n  `manager` varchar(20) NOT NULL COMMENT '经办人',\n  `gmt_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  KEY `supplier_id` (`supplier_id`),\n  KEY `consumer_id` (`consumer_id`),\n  CONSTRAINT `app_inventory_record_ibfk_1` FOREIGN KEY (`supplier_id`) REFERENCES `app_supplier` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `app_inventory_record_ibfk_2` FOREIGN KEY (`consumer_id`) REFERENCES `app_consumer` (`id`) ON DELETE CASCADE ON UPDATE CASCADE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='出入库记录表-存储每次出库和入库情况（注：销售、退回供应商都算出库，顾客退货算入库）';\n\n-- ----------------------------\n-- Records of app_inventory_record\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for app_supplier\n-- ----------------------------\nDROP TABLE IF EXISTS `app_supplier`;\nCREATE TABLE `app_supplier` (\n  `id` varchar(20) NOT NULL,\n  `name` varchar(50) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='供应商表-存储供应商的基本信息';\n\n-- ----------------------------\n-- Records of app_supplier\n-- ----------------------------\nINSERT INTO `app_supplier` VALUES ('HEB-0001', '石药集团');\n\n-- ----------------------------\n-- Table structure for blog_content\n-- ----------------------------\nDROP TABLE IF EXISTS `blog_content`;\nCREATE TABLE `blog_content` (\n  `cid` bigint(20) NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) DEFAULT NULL COMMENT '标题',\n  `slug` varchar(255) DEFAULT NULL,\n  `created` bigint(20) DEFAULT NULL COMMENT '创建人id',\n  `modified` bigint(20) DEFAULT NULL COMMENT '最近修改人id',\n  `content` text COMMENT '内容',\n  `type` varchar(16) DEFAULT NULL COMMENT '类型',\n  `tags` varchar(200) DEFAULT NULL COMMENT '标签',\n  `categories` varchar(200) DEFAULT NULL COMMENT '分类',\n  `hits` int(5) DEFAULT NULL,\n  `comments_num` int(5) DEFAULT '0' COMMENT '评论数量',\n  `allow_comment` int(1) DEFAULT '0' COMMENT '开启评论',\n  `allow_ping` int(1) DEFAULT '0' COMMENT '允许ping',\n  `allow_feed` int(1) DEFAULT '0' COMMENT '允许反馈',\n  `status` int(1) DEFAULT NULL COMMENT '状态',\n  `author` varchar(100) DEFAULT NULL COMMENT '作者',\n  `gtm_create` datetime DEFAULT NULL COMMENT '创建时间',\n  `gtm_modified` datetime DEFAULT NULL COMMENT '修改时间',\n  PRIMARY KEY (`cid`)\n) ENGINE=InnoDB AUTO_INCREMENT=122 DEFAULT CHARSET=utf8 COMMENT='文章内容';\n\n-- ----------------------------\n-- Records of blog_content\n-- ----------------------------\nINSERT INTO `blog_content` VALUES ('75', '基于 Springboot 和 Mybatis 的后台管理系统 BootDo', null, null, null, '<h3 style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif;\\\">项目介绍</h3><ul style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 0px 30px; list-style-position: initial; list-style-image: initial; color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><li><p>面向学习型的开源框架，简洁高效，减少过渡封装，展现技术本质</p></li><li><p>Springboot作为基础框架，使用mybatis作为持久层框架</p></li><li><p>使用官方推荐的thymeleaf做为模板引擎，shiro作为安全框架,主流技术，“一网打尽”</p></li><li><p>基于注解的sql写法，零XML，极简配置，一键前后台代码生成</p></li></ul><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><span style=\\\"font-weight: bolder;\\\">演示地址</span>&nbsp;<a href=\\\"http://47.93.239.129/\\\" style=\\\"outline: 0px; color: rgb(68, 102, 187);\\\">http://47.93.239.129</a></p><h3 style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif;\\\">功能简介</h3><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\">1. 用户管理<br>2. 角色管理<br>3. 部门管理<br>4. 菜单管理<br>5. 系统日志<br>6. 代码生成<br>7. 内容管理</p><h3 style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif;\\\">所用框架</h3><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><span style=\\\"font-weight: bolder;\\\">前端</span><br>1. Bootstrap<br>2. jQuery<br>3. bootstrap-table<br>4. layer<br>5. jsTree&nbsp;<br>6. summernote<br>7. jquery-validate<br>8. jquery-treegrid</p><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><span style=\\\"font-weight: bolder;\\\">后端</span><br>1. SpringBoot&nbsp;<br>2. MyBatis<br>3. Thymeleaf<br>4. Shiro<br>5. druid</p><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><span style=\\\"font-weight: bolder;\\\">项目截图</span></p><p style=\\\"color: rgb(17, 17, 17); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, sans-serif; font-size: 16px;\\\"><img height=\\\"400\\\" src=\\\"https://static.oschina.net/uploads/space/2017/0912/182421_5LaN_3244087.png\\\" width=\\\"650\\\" style=\\\"border-width: initial; border-style: none; outline: 0px; width: 882px; max-width: -webkit-fit-content; height: auto;\\\"></p>', 'article', null, null, null, null, '0', '0', '1', '1', 'bootdo', '2017-09-22 14:44:44', '2017-09-22 14:44:44');\nINSERT INTO `blog_content` VALUES ('100', 'springboot thymeleaf和shiro 整合——按钮可见性', null, null, null, '<p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">添加依赖</p><pre class=\\\"hljs xml\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 2px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">&lt;<span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">dependency</span>&gt;</span><code class=\\\"hljs xml\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; display: block; overflow-x: auto; padding: 10px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 4px; font-size: 13px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\"> \\r\\n   <span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">groupId</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span>com.github.theborakompanioni<span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;/</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">groupId</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">artifactId</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span>thymeleaf-extras-shiro<span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;/</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">artifactId</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">version</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span></code>1.2.1<code class=\\\"hljs xml\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; display: block; overflow-x: auto; padding: 10px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 4px; font-size: 13px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;/</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">version</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span> \\r\\n<span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&lt;/</span><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\"><span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">dependency</span></span></span><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">&gt;</span></span></code></pre><p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">&nbsp;</p><p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">在shiro的configuration中配置</p><pre class=\\\"hljs java\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 2px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\"><span class=\\\"hljs-meta\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(127, 159, 127);\\\">@Bean</span>\\r\\n    <span class=\\\"hljs-function\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">public</span> ShiroDialect <span class=\\\"hljs-title\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">shiroDialect</span><span class=\\\"hljs-params\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">()</span> </span>{\\r\\n        <span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">return</span> <span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">new</span> ShiroDialect();\\r\\n    }</pre><p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">&nbsp;</p><p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">在html中加入xmlns</p><pre class=\\\"hljs xml\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 2px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\"><span class=\\\"hljs-tag\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">&lt;<span class=\\\"hljs-name\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(239, 239, 143);\\\">html</span> <span class=\\\"hljs-attr\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">lang</span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"zh_CN\\\"</span> <span class=\\\"hljs-attr\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">xmlns:th</span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"http://www.thymeleaf.org\\\"</span>\\r\\n      <span class=\\\"hljs-attr\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\">xmlns:shiro</span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"http://www.pollix.at/thymeleaf/shiro\\\"</span>&gt;</span></pre><p style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px; color: rgb(61, 70, 77); font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif; font-size: 16px; background-color: rgb(248, 248, 248);\\\">例子</p><pre class=\\\"hljs scala\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 2px; background: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; word-wrap: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace;\\\">&lt;button shiro:hasPermission=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"sys:user:add\\\"</span> <span class=\\\"hljs-class\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">type</span></span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"button\\\"</span> <span class=\\\"hljs-class\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">class</span></span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"btn &nbsp;btn-primary\\\"</span> onclick=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"add()\\\"</span>&gt;\\r\\n&nbsp;&nbsp; &lt;i <span class=\\\"hljs-class\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(227, 206, 171);\\\">class</span></span>=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"fa fa-plus\\\"</span> aria-hidden=<span class=\\\"hljs-string\\\" style=\\\"box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: rgb(204, 147, 147);\\\">\\\"true\\\"</span>&gt;&lt;/i&gt;添加\\r\\n&lt;/button&gt;</pre>', 'article', null, null, null, null, '1', null, '0', '1', 'bootdo', '2017-09-22 13:24:30', '2017-09-22 13:24:30');\nINSERT INTO `blog_content` VALUES ('108', 'spring boot ehcache整合', null, null, null, '<h3 id=\\\"pomxml配置-引入依赖包\\\" style=\\\"font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; color: rgb(63, 63, 63); margin: 0.8em 0px; font-size: 1.7em; padding: 0px;\\\">pom.xml配置 引入依赖包</h3><pre class=\\\"prettyprint\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; font-size: 14px; white-space: nowrap; padding: 5px 5px 5px 60px; margin-bottom: 1.1em; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-color: rgba(128, 128, 128, 0.075); border-radius: 0px; position: relative; overflow-y: hidden;\\\"><code class=\\\"hljs xml has-numbering\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; display: block; word-wrap: normal;\\\"><span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">dependency</span>&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">groupId</span>&gt;</span>org.springframework.boot<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">groupId</span>&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">artifactId</span>&gt;</span>spring-boot-starter-cache<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">artifactId</span>&gt;</span>\\r\\n<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">dependency</span>&gt;</span>\\r\\n<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">dependency</span>&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">groupId</span>&gt;</span>net.sf.ehcache<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">groupId</span>&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">artifactId</span>&gt;</span>ehcache<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">artifactId</span>&gt;</span>\\r\\n<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">dependency</span>&gt;</span></code><ul class=\\\"pre-numbering\\\" style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; list-style: none; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; border-right: 1px solid rgb(221, 221, 221); text-align: right;\\\"><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">1</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">2</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">3</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">4</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">5</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">6</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">7</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">8</li></ul></pre><h3 id=\\\"编写配置类设置缓存机制\\\" style=\\\"font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; color: rgb(63, 63, 63); margin: 0.8em 0px; font-size: 1.7em; padding: 0px;\\\">编写配置类,设置缓存机制</h3><pre class=\\\"prettyprint\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; font-size: 14px; white-space: nowrap; padding: 5px 5px 5px 60px; margin-bottom: 1.1em; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-color: rgba(128, 128, 128, 0.075); border-radius: 0px; position: relative; overflow-y: hidden;\\\"><code class=\\\"hljs java has-numbering\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; display: block; word-wrap: normal;\\\"><span class=\\\"hljs-annotation\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(155, 133, 157);\\\">@Configuration</span>\\r\\n<span class=\\\"hljs-annotation\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(155, 133, 157);\\\">@EnableCaching</span>\\r\\n<span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">public</span> <span class=\\\"hljs-class\\\" style=\\\"margin: 0px; padding: 0px;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">class</span> <span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">CacheConfiguration</span> {</span>\\r\\n\\r\\n    <span class=\\\"hljs-annotation\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(155, 133, 157);\\\">@Bean</span>\\r\\n    <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">public</span> EhCacheCacheManager <span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px;\\\">ehCacheCacheManager</span>(EhCacheManagerFactoryBean bean) {\\r\\n        <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">return</span> <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">new</span> EhCacheCacheManager(bean.getObject());\\r\\n    }\\r\\n\\r\\n    <span class=\\\"hljs-annotation\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(155, 133, 157);\\\">@Bean</span>\\r\\n    <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">public</span> EhCacheManagerFactoryBean <span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px;\\\">ehCacheManagerFactoryBean</span>() {\\r\\n        EhCacheManagerFactoryBean cacheManagerFactoryBean = <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">new</span> EhCacheManagerFactoryBean();\\r\\n        cacheManagerFactoryBean.setConfigLocation(<span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">new</span> ClassPathResource(<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"config/ehcache.xml\\\"</span>));\\r\\n        cacheManagerFactoryBean.setShared(<span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">true</span>);\\r\\n        <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">return</span> cacheManagerFactoryBean;\\r\\n    }\\r\\n}</code><ul class=\\\"pre-numbering\\\" style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; list-style: none; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; border-right: 1px solid rgb(221, 221, 221); text-align: right;\\\"><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">1</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">2</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">3</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">4</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">5</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">6</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">7</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">8</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">9</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">10</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">11</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">12</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">13</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">14</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">15</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">16</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">17</li></ul></pre><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(63, 63, 63); font-family: &quot;microsoft yahei&quot;; font-size: 15px;\\\">ehcache.xml配置:</p><pre class=\\\"prettyprint\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; font-size: 14px; white-space: nowrap; padding: 5px 5px 5px 60px; margin-bottom: 1.1em; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-color: rgba(128, 128, 128, 0.075); border-radius: 0px; position: relative; overflow-y: hidden;\\\"><code class=\\\"hljs xml has-numbering\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; display: block; word-wrap: normal;\\\"><span class=\\\"hljs-pi\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?&gt;</span>\\r\\n<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">ehcache</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">xmlns:xsi</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"http://www.w3.org/2001/XMLSchema-instance\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">xsi:noNamespaceSchemaLocation</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"http://ehcache.org/ehcache.xsd\\\"</span>\\r\\n    <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">updateCheck</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span>&gt;</span>\\r\\n    <span class=\\\"hljs-comment\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(136, 0, 0);\\\">&lt;!-- diskStore：为缓存路径，ehcache分为内存和磁盘两级，此属性定义磁盘的缓存位置。\\r\\n    参数解释如下： user.home – 用户主目录 \\r\\n    user.dir – 用户当前工作目录 \\r\\n    java.io.tmpdir – 默认临时文件路径 --&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">diskStore</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">path</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"java.io.tmpdir/Tmp_EhCache\\\"</span> /&gt;</span>\\r\\n    <span class=\\\"hljs-comment\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(136, 0, 0);\\\">&lt;!-- defaultCache：默认缓存策略，当ehcache找不到定义的缓存时，则使用这个缓存策略。只能定义一个。 --&gt;</span>\\r\\n    <span class=\\\"hljs-comment\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(136, 0, 0);\\\">&lt;!-- name:缓存名称。 \\r\\n        maxElementsInMemory:缓存最大数目\\r\\n        maxElementsOnDisk：硬盘最大缓存个数。 \\r\\n        eternal:对象是否永久有效，一但设置了，timeout将不起作用。 \\r\\n        overflowToDisk:是否保存到磁盘，当系统当机时 \\r\\n        timeToIdleSeconds:设置对象在失效前的允许闲置时间（单位：秒）。仅当eternal=false对象不是永久有效时使 用，可选属性，默认值是0，也就是可闲置时间无穷大。\\r\\n        timeToLiveSeconds:设置对象在失效前允许存活时间（单位：秒）。最大时间介于创建时间和失效时间之间。仅 当eternal=false对象不是永久有效时使用，默认是0.，也就是对象存活时间无穷大。 \\r\\n        diskPersistent：是否缓存虚拟机重启期数据Whether the disk store persists between restarts \\r\\n        of the Virtual Machine. The default value is false. \\r\\n        diskSpoolBufferSizeMB：这个参数设置DiskStore（磁盘缓存）的缓存区大小。默认是30MB。每个Cache都应该 有自己的一个缓冲区。 \\r\\n        diskExpiryThreadIntervalSeconds：磁盘失效线程运行时间间隔，默认是120秒。 \\r\\n        memoryStoreEvictionPolicy：当达到maxElementsInMemory限制时，Ehcache将会根据指定的策略去清理内 存。默认策略是LRU（最近最少使用）。\\r\\n        你可以设置为FIFO（先进先出）或是LFU（较少使用）。 \\r\\n        clearOnFlush：内存数量最大时是否清除。\\r\\n        memoryStoreEvictionPolicy:可选策略有：LRU（最近最少使用，默认策略）、FIFO（先进先出）、LFU（最少 访问次数）。 \\r\\n         FIFO，first in first out，这个是大家最熟的，先进先出。\\r\\n         LFU， Less Frequently Used，就是上面例子中使用的策略，直白一点就是讲一直以来最少被使用的。如上面 所讲，缓存的元素有一个hit属性，hit值最小的将会被清出缓存。 \\r\\n         LRU，Least Recently Used，最近最少使用的，缓存的元素有一个时间戳，当缓存容量满了，而又需要腾出地 方来缓存新的元素的时候，\\r\\n         那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 --&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">defaultCache</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">eternal</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">maxElementsInMemory</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"1000\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">overflowToDisk</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">diskPersistent</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span>\\r\\n        <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">timeToIdleSeconds</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"0\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">timeToLiveSeconds</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"600\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">memoryStoreEvictionPolicy</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"LRU\\\"</span> /&gt;</span>\\r\\n    <span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">cache</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">name</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"snailAuthCache\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">eternal</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">maxElementsInMemory</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"10000\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">overflowToDisk</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">diskPersistent</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"false\\\"</span>\\r\\n        <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">timeToIdleSeconds</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"0\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">timeToLiveSeconds</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"0\\\"</span> <span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">memoryStoreEvictionPolicy</span>=<span class=\\\"hljs-value\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"LFU\\\"</span> /&gt;</span>\\r\\n<span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">ehcache</span>&gt;</span></code><ul class=\\\"pre-numbering\\\" style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; list-style: none; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; border-right: 1px solid rgb(221, 221, 221); text-align: right;\\\"><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">1</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">2</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">3</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">4</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">5</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">6</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">7</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">8</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">9</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">10</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">11</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">12</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">13</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">14</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">15</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">16</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">17</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">18</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">19</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">20</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">21</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">22</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">23</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">24</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">25</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">26</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">27</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">28</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">29</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">30</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">31</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">32</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">33</li></ul><div class=\\\"save_code tracking-ad\\\" data-mod=\\\"popu_249\\\" style=\\\"margin: 0px; padding: 0px; position: absolute; height: 60px; right: 30px; top: 5px; color: rgb(255, 255, 255); cursor: pointer; z-index: 2;\\\"><a style=\\\"color: rgb(202, 12, 22); margin: 0px; padding: 0px; outline: none;\\\"><img src=\\\"http://static.blog.csdn.net/images/save_snippets.png\\\" style=\\\"outline: none; max-width: 100%;\\\"></a></div></pre><h3 id=\\\"测试\\\" style=\\\"font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; color: rgb(63, 63, 63); margin: 0.8em 0px; font-size: 1.7em; padding: 0px;\\\"><br></h3>', 'article', null, null, null, null, '1', null, '0', '1', 'bootdo', '2017-09-22 17:48:29', '2017-09-22 17:48:29');\nINSERT INTO `blog_content` VALUES ('109', 'spring-boot整合ehcache实现缓存机制', null, null, null, '<p><br></p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　EhCache 是一个纯Java的进程内缓存框架，具有快速、精干等特点，是Hibernate中默认的CacheProvider。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　ehcache提供了多种缓存策略，主要分为内存和磁盘两级，所以无需担心容量问题。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　spring-boot是一个快速的集成框架，其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置，从而使开发人员不再需要定义样板化的配置。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　由于spring-boot无需任何样板化的配置文件，所以spring-boot集成一些其他框架时会有略微的不同。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　1.spring-boot是一个通过maven管理的jar包的框架，集成ehcache需要的依赖如下</p><div class=\\\"cnblogs_code\\\" style=\\\"background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div><pre style=\\\"margin-bottom: 0px; line-height: 1.42857; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n     <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-context-support<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n         <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>net.sf.ehcache<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n      <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>ehcache<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n          <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>2.8.3<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>        </pre><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div></div><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　具体pom.xml文件如下</p><div class=\\\"cnblogs_code\\\" style=\\\"background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div><pre style=\\\"margin-bottom: 0px; line-height: 1.42857; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;?</span><span style=\\\"color: rgb(255, 0, 255); line-height: 1.5 !important;\\\">xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">?&gt;</span>\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">project </span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">xmlns</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"http://maven.apache.org/POM/4.0.0\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> xmlns:xsi</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"http://www.w3.org/2001/XMLSchema-instance\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">\\r\\n    xsi:schemaLocation</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\\\"</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">modelVersion</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>4.0.0<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">modelVersion</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>com.lclc.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>boot-cache<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>0.0.1-SNAPSHOT<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">&lt;!--</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\"> Inherit defaults from Spring Boot </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">--&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">parent</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-boot-starter-parent<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>1.1.3.RELEASE<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">parent</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencies</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-boot-starter-web<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-boot-starter-data-jpa<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-boot-starter-thymeleaf<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        \\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>mysql<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>mysql-connector-java<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>com.google.guava<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>guava<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>17.0<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        \\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-context-support<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>net.sf.ehcache<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>ehcache<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>2.8.3<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">version</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependency</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencies</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencyManagement</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencies</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencies</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">dependencyManagement</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">build</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">plugins</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">plugin</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n                <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>org.springframework.boot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">groupId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n                <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-boot-maven-plugin<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">artifactId</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">plugin</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">plugins</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">build</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repositories</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-snapshots<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>http://repo.spring.io/snapshot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">snapshots</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n                <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">enabled</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>true<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">enabled</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">snapshots</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-milestones<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>http://repo.spring.io/milestone<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">repositories</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepositories</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-snapshots<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>http://repo.spring.io/snapshot<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>spring-milestones<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">id</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>http://repo.spring.io/milestone<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">url</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n        <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepository</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">pluginRepositories</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">project</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span></pre><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div></div><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;　　2.使用ehcache，我们需要一个ehcache.xml来定义一些cache的属性。</p><div class=\\\"cnblogs_code\\\" style=\\\"background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div><pre style=\\\"margin-bottom: 0px; line-height: 1.42857; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;?</span><span style=\\\"color: rgb(255, 0, 255); line-height: 1.5 !important;\\\">xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">?&gt;</span>\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">ehcache </span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">xmlns:xsi</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"http://www.w3.org/2001/XMLSchema-instance\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> xsi:noNamespaceSchemaLocation</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"http://ehcache.org/ehcache.xsd\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">\\r\\n  updateCheck</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span>\\r\\n          <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">diskStore </span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">path</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"java.io.tmpdir/Tmp_EhCache\\\"</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">/&gt;</span>\\r\\n           <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">defaultCache </span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">eternal</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> maxElementsInMemory</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"1000\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> overflowToDisk</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> diskPersistent</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">\\r\\n    timeToIdleSeconds</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"0\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> timeToLiveSeconds</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"600\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> memoryStoreEvictionPolicy</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"LRU\\\"</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">/&gt;</span>\\r\\n\\r\\n            <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">cache </span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">name</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"demo\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> eternal</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> maxElementsInMemory</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"100\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> overflowToDisk</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> diskPersistent</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"false\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\">\\r\\n    timeToIdleSeconds</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"0\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> timeToLiveSeconds</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"300\\\"</span><span style=\\\"color: rgb(255, 0, 0); line-height: 1.5 !important;\\\"> memoryStoreEvictionPolicy</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">=\\\"LRU\\\"</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">/&gt;</span>\\r\\n\\r\\n<span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&lt;/</span><span style=\\\"color: rgb(128, 0, 0); line-height: 1.5 !important;\\\">ehcache</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">&gt;</span></pre><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div></div><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;　　解释下这个xml文件中的标签。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　(1).<span style=\\\"color: rgb(128, 0, 0);\\\">diskStore：</span>&nbsp;为缓存路径，ehcache分为内存和磁盘两级，此属性定义磁盘的缓存位置。参数解释如下：　　　　<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　　　user.home – 用户主目录<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　　 　user.dir&nbsp; – 用户当前工作目录<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;　　　　&nbsp; java.io.tmpdir – 默认临时文件路径</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　(2).<span style=\\\"color: rgb(128, 0, 0);\\\">defaultCache：<span style=\\\"color: rgb(0, 0, 0);\\\">默认缓存策略，当ehcache找不到定义的缓存时，则使用这个缓存策略。只能定义一个。</span></span></p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\"><span style=\\\"color: rgb(128, 0, 0);\\\"><span style=\\\"color: rgb(0, 0, 0);\\\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3).<span style=\\\"color: rgb(128, 0, 0);\\\">cache</span>：自定缓存策略，为自定义的缓存策略。参数解释如下：</span></span></p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\"><span style=\\\"color: rgb(128, 0, 0);\\\"><span style=\\\"color: rgb(0, 0, 0);\\\">　　　 cache元素的属性：&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name：缓存名称&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory：内存中最大缓存对象数&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsOnDisk：硬盘中最大缓存对象数，若是0表示无穷大&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal：true表示对象永不过期，此时会忽略timeToIdleSeconds和timeToLiveSeconds属性，默认为false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk：true表示当内存缓存的对象数目达到了maxElementsInMemory界限后，会把溢出的对象写到硬盘缓存中。注意：如果缓存的对象要写入到硬盘中的话，则该对象必须实现了Serializable接口才行。&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskSpoolBufferSizeMB：磁盘缓存区大小，默认为30MB。每个Cache都应该有自己的一个缓存区。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskPersistent：是否缓存虚拟机重启期数据&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskExpiryThreadIntervalSeconds：磁盘失效线程运行时间间隔，默认为120秒&nbsp; &nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds： 设定允许对象处于空闲状态的最长时间，以秒为单位。当对象自从最近一次被访问后，如果处于空闲状态的时间超过了timeToIdleSeconds属性值，这个对象就会过期，EHCache将把它从缓存中清空。只有当eternal属性为false，该属性才有效。如果该属性值为0，则表示对象可以无限期地处于空闲状态&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds：设定对象允许存在于缓存中的最长时间，以秒为单位。当对象自从被存放到缓存中后，如果处于缓存中的时间超过了 timeToLiveSeconds属性值，这个对象就会过期，EHCache将把它从缓存中清除。只有当eternal属性为false，该属性才有效。如果该属性值为0，则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性，才有意义&nbsp; &nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memoryStoreEvictionPolicy：当达到maxElementsInMemory限制时，Ehcache将会根据指定的策略去清理内存。可选策略有：LRU（最近最少使用，默认策略）、FIFO（先进先出）、LFU（最少访问次数）。&nbsp;&nbsp;</span></span></p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\"><span style=\\\"color: rgb(128, 0, 0);\\\"><span style=\\\"color: rgb(0, 0, 0);\\\">　　3.将ehcache的管理器暴露给spring的上下文容器，</span></span></p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\"><span style=\\\"color: rgb(128, 0, 0);\\\"><span style=\\\"color: rgb(0, 0, 0);\\\">　　</span></span></p><div class=\\\"cnblogs_code\\\" style=\\\"background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div><pre style=\\\"margin-bottom: 0px; line-height: 1.42857; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">@Configuration\\r\\n</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">//</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\"> 标注启动了缓存</span>\\r\\n<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">@EnableCaching\\r\\n</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">class</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> CacheConfiguration {\\r\\n\\r\\n    </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">/*</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">\\r\\n     * ehcache 主要的管理器\\r\\n     </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">*/</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">\\r\\n    @Bean(name </span>= \\\"appEhCacheCacheManager\\\"<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">)\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){\\r\\n        </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">return</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">new</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> EhCacheCacheManager (bean.getObject ());\\r\\n    }\\r\\n\\r\\n    </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">/*</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">\\r\\n     * 据shared与否的设置,Spring分别通过CacheManager.create()或new CacheManager()方式来创建一个ehcache基地.\\r\\n     </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">*/</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">\\r\\n    @Bean\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){\\r\\n        EhCacheManagerFactoryBean cacheManagerFactoryBean </span>= <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">new</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> EhCacheManagerFactoryBean ();\\r\\n        cacheManagerFactoryBean.setConfigLocation (</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">new</span> ClassPathResource (\\\"conf/ehcache-app.xml\\\"<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">));\\r\\n        cacheManagerFactoryBean.setShared (</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">true</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">);\\r\\n        </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">return</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> cacheManagerFactoryBean;\\r\\n    }\\r\\n}</span></pre><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div></div><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;&nbsp; 　　　　<span style=\\\"color: rgb(0, 0, 0);\\\">@Configuration</span>：为spring-boot注解，主要标注此为配置类，优先扫描。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp; 　　　　<span style=\\\"color: rgb(0, 0, 0);\\\">@Bean</span>：向spring容器中加入bean。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　至此所有的配置都做好了，通过spring-boot进行集成框架就是这么简单。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　4.使用ehcache</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　使用ehcache主要通过spring的缓存机制，上面我们将spring的缓存机制使用了ehcache进行实现，所以使用方面就完全使用spring缓存机制就行了。<br>　　　　具体牵扯到几个注解：</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　@Cacheable：负责将方法的返回值加入到缓存中，参数3<br>　　　　@CacheEvict：负责清除缓存，参数4</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　　参数解释：</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　value：缓存位置名称，不能为空，如果使用EHCache，就是ehcache.xml中声明的cache的name<br>　　　　key：缓存的key，默认为空，既表示使用方法的参数类型及参数值作为key，支持SpEL<br>　　　　condition：触发条件，只有满足条件的情况才会加入缓存，默认为空，既表示全部都加入缓存，支持SpEL</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　allEntries：CacheEvict参数，true表示清除value中的全部缓存，默认为false</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　不多说，直接上代码：</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　</p><div class=\\\"cnblogs_code\\\" style=\\\"background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div><pre style=\\\"margin-bottom: 0px; line-height: 1.42857; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;\\\"><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">@Service\\r\\n</span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">class</span> CacheDemoServiceImpl <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">implements</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> CacheDemoService {\\r\\n\\r\\n    </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">/**</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">\\r\\n     * 缓存的key\\r\\n     </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">*/</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">static</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">final</span> String THING_ALL_KEY   = \\\"\\\\\\\"thing_all\\\\\\\"\\\"<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">;\\r\\n    </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">/**</span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">\\r\\n     * value属性表示使用哪个缓存策略，缓存策略在ehcache.xml\\r\\n     </span><span style=\\\"color: rgb(0, 128, 0); line-height: 1.5 !important;\\\">*/</span>\\r\\n    <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">static</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">final</span> String DEMO_CACHE_NAME = \\\"demo\\\"<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">;\\r\\n   \\r\\n    @CacheEvict(value </span>= DEMO_CACHE_NAME,key =<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> THING_ALL_KEY)\\r\\n    @Override\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">void</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> create(Thing thing){\\r\\n        Long id </span>=<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> getNextId ();\\r\\n        thing.setId (id);\\r\\n        data.put (id, thing);\\r\\n    } \\r\\n      \\r\\n     @Cacheable(value </span>=<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> DEMO_CACHE_NAME,key = \\\"#thing.getId()+\\'thing\\'\\\")\\r\\n    @Override\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> Thing findById(Long id){\\r\\n        System.err.println (</span>\\\"没有走缓存！\\\" +<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> id);\\r\\n        </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">return</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> data.get (id);\\r\\n    }\\r\\n\\r\\n      @Cacheable(value </span>= DEMO_CACHE_NAME,key =<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> THING_ALL_KEY)\\r\\n    @Override\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> List&lt;Thing&gt;<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> findAll(){\\r\\n        </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">return</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> Lists.newArrayList (data.values ());\\r\\n    }\\r\\n   \\r\\n   </span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">\\r\\n      @Override\\r\\n    @CachePut(value </span>= DEMO_CACHE_NAME,key = \\\"#thing.getId()+\\'thing\\'\\\"<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\">)\\r\\n    @CacheEvict(value </span>= DEMO_CACHE_NAME,key =<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> THING_ALL_KEY)\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> Thing update(Thing thing){\\r\\n        System.out.println (thing);\\r\\n        data.put (thing.getId (), thing);\\r\\n        </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">return</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> thing;\\r\\n    }\\r\\n\\r\\n    @CacheEvict(value </span>=<span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> DEMO_CACHE_NAME)\\r\\n    @Override\\r\\n    </span><span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">public</span> <span style=\\\"color: rgb(0, 0, 255); line-height: 1.5 !important;\\\">void</span><span style=\\\"color: rgb(0, 0, 0); line-height: 1.5 !important;\\\"> delete(Long id){\\r\\n        data.remove (id);\\r\\n    }\\r\\n   \\r\\n}</span></pre><div class=\\\"cnblogs_code_toolbar\\\" style=\\\"margin-top: 5px;\\\"><span class=\\\"cnblogs_code_copy\\\" style=\\\"padding-right: 5px; line-height: 1.5 !important;\\\"><a title=\\\"复制代码\\\" style=\\\"color: rgb(86, 182, 233); background-color: rgb(245, 245, 245) !important; border: none !important;\\\"><img src=\\\"http://common.cnblogs.com/images/copycode.gif\\\" alt=\\\"复制代码\\\" style=\\\"max-width: 900px; border-width: initial !important; border-style: none !important;\\\"></a></span></div></div><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">　　　　5.只需要通过注解在service层方法上打注解便可以使用缓存，在find**上存入缓存，在delete**,update**上清除缓存。</p><p style=\\\"margin-top: 10px; margin-right: auto; margin-left: auto; color: rgb(35, 35, 35); font-family: Verdana, Arial, helvetica, sans-seriff; font-size: 14px;\\\">&nbsp;</p>', 'article', null, null, null, null, '1', null, '0', '1', 'bootdo', '2017-09-24 11:15:18', '2017-09-24 11:15:18');\nINSERT INTO `blog_content` VALUES ('110', 'spring boot 图片上传后的图片读取路径在win与linux环境配置的差别', null, null, null, '<ol><li><p style=\\\"margin-bottom: 0px; padding: 0px; color: rgb(69, 69, 69); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 16px;\\\">win</p><p style=\\\"margin-bottom: 0px; padding: 0px; color: rgb(69, 69, 69); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 16px;\\\"></p><div class=\\\"dp-highlighter bg_java\\\" style=\\\"padding: 1px 0px 0px; font-family: Consolas, &quot;Courier New&quot;, Courier, mono, serif; font-size: 12px; background-color: rgb(231, 229, 220); width: 849.412px; overflow-x: auto; overflow-y: hidden; position: relative; color: rgb(69, 69, 69); margin: 18px 0px !important;\\\"><div class=\\\"bar\\\" style=\\\"margin: 0px; padding: 0px 0px 0px 45px;\\\"><div class=\\\"tools\\\" style=\\\"margin: 0px; padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: rgb(248, 248, 248); border-left: 3px solid rgb(108, 226, 108); border-right: 1px solid rgb(231, 229, 220);\\\"><b>[java]</b>&nbsp;<a href=\\\"http://blog.csdn.net/qq1115094858/article/details/51873698#\\\" class=\\\"ViewSource\\\" title=\\\"view plain\\\" style=\\\"background-image: url(&quot;images/default/ico_plain.gif&quot;); background-position: left top; background-repeat: no-repeat; color: rgb(202, 12, 22); margin: 0px 10px 0px 0px; padding: 1px; outline: none; border: none; font-size: 9px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">view plain</a><span class=\\\"tracking-ad\\\" data-mod=\\\"popu_168\\\" style=\\\"margin: 0px; padding: 0px;\\\">&nbsp;<a href=\\\"http://blog.csdn.net/qq1115094858/article/details/51873698#\\\" class=\\\"CopyToClipboard\\\" title=\\\"copy\\\" style=\\\"background-image: url(&quot;images/default/ico_copy.gif&quot;); background-position: left top; background-repeat: no-repeat; color: rgb(202, 12, 22); margin: 0px 10px 0px 0px; padding: 1px; outline: none; border: none; font-size: 9px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">copy</a><div style=\\\"margin: 0px; padding: 0px; position: absolute; left: 294px; top: 296px; width: 16px; height: 16px; z-index: 99;\\\"></div></span><span class=\\\"tracking-ad\\\" data-mod=\\\"popu_169\\\" style=\\\"margin: 0px; padding: 0px;\\\"></span></div></div><ol start=\\\"1\\\" class=\\\"dp-j\\\" style=\\\"padding: 0px; list-style-position: initial; list-style-image: initial; border-top: none; border-right: 1px solid rgb(231, 229, 220); border-bottom: none; border-left: none; border-image: initial; background-color: rgb(255, 255, 255); color: rgb(92, 92, 92); margin-right: 0px !important; margin-bottom: 1px !important; margin-left: 45px !important;\\\"><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Component</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">class</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;WebConfigurer&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">extends</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;WebMvcConfigurerAdapter&nbsp;{&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Override</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">void</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;addResourceHandlers(ResourceHandlerRegistry&nbsp;registry)&nbsp;{&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registry.addResourceHandler(<span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"/files/**\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">).addResourceLocations(</span><span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"file:///E:/var/spring/uploaded_files/\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">);&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">}&nbsp;&nbsp;</span></li></ol></div><span style=\\\"color: rgb(69, 69, 69); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 16px;\\\">linux</span><br style=\\\"color: rgb(69, 69, 69); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 16px;\\\"><div class=\\\"dp-highlighter bg_java\\\" style=\\\"padding: 1px 0px 0px; font-family: Consolas, &quot;Courier New&quot;, Courier, mono, serif; font-size: 12px; background-color: rgb(231, 229, 220); width: 849.412px; overflow-x: auto; overflow-y: hidden; position: relative; color: rgb(69, 69, 69); margin: 18px 0px !important;\\\"><div class=\\\"bar\\\" style=\\\"margin: 0px; padding: 0px 0px 0px 45px;\\\"><div class=\\\"tools\\\" style=\\\"margin: 0px; padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: rgb(248, 248, 248); border-left: 3px solid rgb(108, 226, 108); border-right: 1px solid rgb(231, 229, 220);\\\"><b>[java]</b>&nbsp;<a href=\\\"http://blog.csdn.net/qq1115094858/article/details/51873698#\\\" class=\\\"ViewSource\\\" title=\\\"view plain\\\" style=\\\"background-image: url(&quot;images/default/ico_plain.gif&quot;); background-position: left top; background-repeat: no-repeat; color: rgb(202, 12, 22); margin: 0px 10px 0px 0px; padding: 1px; outline: none; border: none; font-size: 9px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">view plain</a><span class=\\\"tracking-ad\\\" data-mod=\\\"popu_168\\\" style=\\\"margin: 0px; padding: 0px;\\\">&nbsp;<a href=\\\"http://blog.csdn.net/qq1115094858/article/details/51873698#\\\" class=\\\"CopyToClipboard\\\" title=\\\"copy\\\" style=\\\"background-image: url(&quot;images/default/ico_copy.gif&quot;); background-position: left top; background-repeat: no-repeat; color: rgb(202, 12, 22); margin: 0px 10px 0px 0px; padding: 1px; outline: none; border: none; font-size: 9px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">copy</a><div style=\\\"margin: 0px; padding: 0px; position: absolute; left: 294px; top: 528px; width: 16px; height: 16px; z-index: 99;\\\"></div></span><span class=\\\"tracking-ad\\\" data-mod=\\\"popu_169\\\" style=\\\"margin: 0px; padding: 0px;\\\"></span></div></div><ol start=\\\"1\\\" class=\\\"dp-j\\\" style=\\\"padding: 0px; list-style-position: initial; list-style-image: initial; border-top: none; border-right: 1px solid rgb(231, 229, 220); border-bottom: none; border-left: none; border-image: initial; background-color: rgb(255, 255, 255); color: rgb(92, 92, 92); margin-right: 0px !important; margin-bottom: 1px !important; margin-left: 45px !important;\\\"><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Component</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">class</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;WebConfigurer&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">extends</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;WebMvcConfigurerAdapter&nbsp;{&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Override</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; font-weight: bold; border: none; color: rgb(0, 102, 153); background-color: inherit;\\\">void</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;addResourceHandlers(ResourceHandlerRegistry&nbsp;registry)&nbsp;{&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registry.addResourceHandler(<span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"/files/**\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">).addResourceLocations(</span><span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"file:///var/spring/uploaded_files\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">);&nbsp;&nbsp;</span></span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; color: inherit; line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"\\\" style=\\\"margin-left: 40px; list-style: decimal; border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin-top: 0px !important; margin-right: 0px !important; margin-bottom: 0px !important; padding: 0px 3px 0px 10px !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">}&nbsp;&nbsp;</span></li><li></li></ol></div></li></ol>', 'article', null, null, null, null, '1', null, '1', '1', 'bootdo', '2017-09-24 09:15:35', '2017-09-24 09:15:35');\nINSERT INTO `blog_content` VALUES ('111', 'Springmvc提交日期类型参数', null, null, null, '<ol style=\\\"color: rgb(63, 63, 63); font-family: &quot;microsoft yahei&quot;; font-size: 15px;\\\"><li><p style=\\\"margin-bottom: 1.1em; padding: 0px;\\\">背景介绍&nbsp;<br>在springmvc框架中，前台传入到后台的form会经过springmvc自动封装到pojo类中，后台接受的时候可以在参数内直接接受这个java类。</p></li><li><p style=\\\"margin-bottom: 1.1em; padding: 0px;\\\">传参&nbsp;<br>通常情况下，前台的表单的类型诸如int,string等，都会根据pojo中字段的类型自动转换。所以为我们省去了不少麻烦，但很可惜其中不包括日期类型。</p></li><li><p style=\\\"margin-bottom: 1.1em; padding: 0px;\\\">原因&nbsp;<br>因为日期的格式多种多样，spring自身不适合对其进行封装。好在spring给出了便捷的方法给我们自己转换数据类型。</p></li><li><p style=\\\"margin-bottom: 1.1em; padding: 0px;\\\">具体实现</p></li></ol><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(63, 63, 63); font-family: &quot;microsoft yahei&quot;; font-size: 15px;\\\">在controller层中，加入以下代码段</p><pre class=\\\"prettyprint\\\" name=\\\"code\\\" style=\\\"white-space: nowrap; position: relative; overflow-y: hidden; margin-bottom: 1.1em; font-family: &quot;Source Code Pro&quot;, monospace; padding: 5px 5px 5px 60px; font-size: 14px; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-width: 0px; border-color: rgb(136, 136, 136); border-radius: 0px;\\\"><code class=\\\"hljs java has-numbering\\\" style=\\\"display: block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; word-wrap: normal;\\\"><span class=\\\"hljs-annotation\\\" style=\\\"color: rgb(155, 133, 157);\\\">@InitBinder</span>\\r\\n<span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">public</span> <span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">void</span> <span class=\\\"hljs-title\\\">initBinder</span>(WebDataBinder binder) {\\r\\n    SimpleDateFormat dateFormat = <span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">new</span> SimpleDateFormat(<span class=\\\"hljs-string\\\" style=\\\"color: rgb(0, 136, 0);\\\">\\\"yyyy-MM-dd\\\"</span>);\\r\\n    dateFormat.setLenient(<span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">false</span>);\\r\\n    binder.registerCustomEditor(Date.class, <span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">new</span> CustomDateEditor(dateFormat, <span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">true</span>));<span class=\\\"hljs-comment\\\" style=\\\"color: rgb(136, 0, 0);\\\">//true:允许输入空值，false:不能为空值</span>\\r\\n}</code><ul class=\\\"pre-numbering\\\" style=\\\"position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;\\\"><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">1</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">2</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">3</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">4</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">5</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">6</li></ul></pre><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(63, 63, 63); font-family: &quot;microsoft yahei&quot;; font-size: 15px;\\\">可以解决这个问题。但是这个时候Date类型的参数是null的话，还是会报错。采用另外一种方式则更好，为null也不会报错，就是把请求参数封装为一个vo类，在对应的类属性上加上注解，这样</p><pre class=\\\"prettyprint\\\" name=\\\"code\\\" style=\\\"white-space: nowrap; position: relative; overflow-y: hidden; margin-bottom: 1.1em; font-family: &quot;Source Code Pro&quot;, monospace; padding: 5px 5px 5px 60px; font-size: 14px; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-width: 0px; border-color: rgb(136, 136, 136); border-radius: 0px;\\\"><code class=\\\"hljs java has-numbering\\\" style=\\\"display: block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; word-wrap: normal;\\\"><span class=\\\"hljs-annotation\\\" style=\\\"color: rgb(155, 133, 157);\\\">@DateTimeFormat</span>(iso = ISO.DATE_TIME, pattern = <span class=\\\"hljs-string\\\" style=\\\"color: rgb(0, 136, 0);\\\">\\\"w:yyyy\\\"</span>)\\r\\n<span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">private</span> Date startTime;\\r\\n或者\\r\\n<span class=\\\"hljs-annotation\\\" style=\\\"color: rgb(155, 133, 157);\\\">@DateTimeFormat</span>(pattern=<span class=\\\"hljs-string\\\" style=\\\"color: rgb(0, 136, 0);\\\">\\\"yyyy-MM-dd HH:mm:ss\\\"</span>)\\r\\n<span class=\\\"hljs-keyword\\\" style=\\\"color: rgb(0, 0, 136);\\\">private</span> Date lastLoginDate;</code><ul class=\\\"pre-numbering\\\" style=\\\"position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;\\\"><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">1</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">2</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">3</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">4</li><li style=\\\"padding: 0px 5px; list-style: none; margin-left: 0px;\\\">5</li></ul></pre><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(63, 63, 63); font-family: &quot;microsoft yahei&quot;; font-size: 15px;\\\">另外如果使用验证框架，方法参数这样写(@Valid XxxParam param, BindingResult binding) ，就能直接通过BindingResult得到验证结果了。</p>', 'article', null, null, null, null, '1', null, '1', '1', 'bootdo', '2017-09-25 21:34:51', '2017-09-25 21:34:51');\nINSERT INTO `blog_content` VALUES ('112', ' SpringBoot 在启动时运行代码', null, null, null, '<p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">在Spring boot项目的实际开发中，我们有时需要项目服务启动时加载一些数据或预先完成某些动作。为了解决这样的问题，Spring&nbsp;boot 为我们提供了一个方法：通过实现接口 CommandLineRunner 来实现这样的需求。</p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">实现方式：只需要一个类即可，无需其他配置。&nbsp;</p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">实现步骤：</p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">1.创建实现接口 CommandLineRunner 的类 MyStartupRunnerTest</p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\"></p><div class=\\\"dp-highlighter bg_java\\\" style=\\\"font-family: Consolas, &quot;Courier New&quot;, Courier, mono, serif; font-size: 12px; background-color: rgb(231, 229, 220); width: 936.531px; overflow-x: auto; overflow-y: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); color: rgb(85, 85, 85); margin: 18px 0px !important;\\\"><div class=\\\"bar\\\" style=\\\"padding-left: 45px;\\\"><div class=\\\"tools\\\" style=\\\"padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: rgb(248, 248, 248); border-left: 3px solid rgb(108, 226, 108); border-right: 1px solid rgb(231, 229, 220);\\\"><strong>[java]</strong>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"ViewSource\\\" title=\\\"view plain\\\" style=\\\"background-image: url(&quot;images/default/ico_plain.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">view plain</a>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"CopyToClipboard\\\" title=\\\"copy\\\" style=\\\"background-image: url(&quot;images/default/ico_copy.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">copy</a><div style=\\\"position: absolute; left: 559px; top: 655px; width: 18px; height: 18px; z-index: 99;\\\"></div><div style=\\\"position: absolute; left: 721px; top: 723px; width: 18px; height: 18px; z-index: 99;\\\"></div></div></div><ol start=\\\"1\\\" class=\\\"dp-j\\\" style=\\\"padding: 0px; border: none; list-style-position: initial; list-style-image: initial; background-color: rgb(255, 255, 255); color: rgb(92, 92, 92); margin-right: 0px !important; margin-bottom: 1px !important; margin-left: 45px !important;\\\"><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">package</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;com.energy;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.boot.CommandLineRunner;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.core.annotation.Order;&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.stereotype.Component;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">/**</span>&nbsp;</span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">&nbsp;*&nbsp;Created&nbsp;by&nbsp;CavanLiu&nbsp;on&nbsp;2017/2/28&nbsp;0028.</span>&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">&nbsp;*/</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Component</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Order</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">(value=</span><span class=\\\"number\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(192, 0, 0); background-color: inherit;\\\">1</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">)</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">class</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;MyStartupRunnerTest&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">implements</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;CommandLineRunner&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">{&nbsp;&nbsp;</span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Override</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">void</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;run(String...&nbsp;args)&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">throws</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;Exception&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"&gt;&gt;&gt;&gt;This&nbsp;is&nbsp;MyStartupRunnerTest&nbsp;Order=1.&nbsp;Only&nbsp;testing&nbsp;CommandLineRunner...&lt;&lt;&lt;&lt;\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">);&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">}&nbsp;&nbsp;</span></li></ol></div><p style=\\\"margin-bottom: 0px; padding: 0px; color: rgb(85, 85, 85); font-family: Arial; font-size: 14px;\\\"></p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">2.创建实现接口CommandLineRunner 的类 MyStartupRunnerTest2</p><div class=\\\"dp-highlighter bg_java\\\" style=\\\"font-family: Consolas, &quot;Courier New&quot;, Courier, mono, serif; font-size: 12px; background-color: rgb(231, 229, 220); width: 936.531px; overflow-x: auto; overflow-y: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); color: rgb(85, 85, 85); margin: 18px 0px !important;\\\"><div class=\\\"bar\\\" style=\\\"padding-left: 45px;\\\"><div class=\\\"tools\\\" style=\\\"padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: rgb(248, 248, 248); border-left: 3px solid rgb(108, 226, 108); border-right: 1px solid rgb(231, 229, 220);\\\"><strong>[java]</strong>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"ViewSource\\\" title=\\\"view plain\\\" style=\\\"background-image: url(&quot;images/default/ico_plain.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">view plain</a>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"CopyToClipboard\\\" title=\\\"copy\\\" style=\\\"background-image: url(&quot;images/default/ico_copy.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">copy</a><div style=\\\"position: absolute; left: 559px; top: 1094px; width: 18px; height: 18px; z-index: 99;\\\"></div><div style=\\\"position: absolute; left: 721px; top: 1160px; width: 18px; height: 18px; z-index: 99;\\\"></div></div></div><ol start=\\\"1\\\" class=\\\"dp-j\\\" style=\\\"padding: 0px; border: none; list-style-position: initial; list-style-image: initial; background-color: rgb(255, 255, 255); color: rgb(92, 92, 92); margin-right: 0px !important; margin-bottom: 1px !important; margin-left: 45px !important;\\\"><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">package</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;com.energy;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.boot.CommandLineRunner;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.core.annotation.Order;&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">import</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;org.springframework.stereotype.Component;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">/**</span>&nbsp;</span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">&nbsp;*&nbsp;Created&nbsp;by&nbsp;CavanLiu&nbsp;on&nbsp;2017/2/28&nbsp;0028.</span>&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"comment\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); background-color: inherit;\\\">&nbsp;*/</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Component</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Order</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">(value=</span><span class=\\\"number\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(192, 0, 0); background-color: inherit;\\\">2</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">)</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">class</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;MyStartupRunnerTest2&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">implements</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;CommandLineRunner&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">{&nbsp;&nbsp;</span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"annotation\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(100, 100, 100); background-color: inherit;\\\">@Override</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;&nbsp;</span></span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;<span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">public</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">void</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;run(String...&nbsp;args)&nbsp;</span><span class=\\\"keyword\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); background-color: inherit; font-weight: bold;\\\">throws</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&nbsp;Exception&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class=\\\"string\\\" style=\\\"margin: 0px; padding: 0px; border: none; color: blue; background-color: inherit;\\\">\\\"&gt;&gt;&gt;&gt;This&nbsp;is&nbsp;MyStartupRunnerTest&nbsp;Order=2.&nbsp;Only&nbsp;testing&nbsp;CommandLineRunner...&lt;&lt;&lt;&lt;\\\"</span><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">);&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">}&nbsp;&nbsp;</span></li></ol></div><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">3.启动Spring boot后查看控制台输出信息，如下所示：</p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\"></p><div class=\\\"dp-highlighter bg_plain\\\" style=\\\"font-family: Consolas, &quot;Courier New&quot;, Courier, mono, serif; font-size: 12px; background-color: rgb(231, 229, 220); width: 936.531px; overflow-x: auto; overflow-y: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); color: rgb(85, 85, 85); margin: 18px 0px !important;\\\"><div class=\\\"bar\\\" style=\\\"padding-left: 45px;\\\"><div class=\\\"tools\\\" style=\\\"padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: rgb(248, 248, 248); border-left: 3px solid rgb(108, 226, 108); border-right: 1px solid rgb(231, 229, 220);\\\"><strong>[plain]</strong>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"ViewSource\\\" title=\\\"view plain\\\" style=\\\"background-image: url(&quot;images/default/ico_plain.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">view plain</a>&nbsp;<a target=\\\"_blank\\\" href=\\\"http://blog.csdn.net/mimica247706624/article/details/58596490#\\\" class=\\\"CopyToClipboard\\\" title=\\\"copy\\\" style=\\\"background-image: url(&quot;images/default/ico_copy.gif&quot;); background-position: left top; background-repeat: no-repeat; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(160, 160, 160); display: inline-block; width: 16px; height: 16px; text-indent: -2000px;\\\">copy</a><div style=\\\"position: absolute; left: 563px; top: 1532px; width: 18px; height: 18px; z-index: 99;\\\"></div><div style=\\\"position: absolute; left: 725px; top: 1597px; width: 18px; height: 18px; z-index: 99;\\\"></div></div></div><ol start=\\\"1\\\" style=\\\"padding: 0px; border: none; list-style-position: initial; list-style-image: initial; background-color: rgb(255, 255, 255); color: rgb(92, 92, 92); margin-right: 0px !important; margin-bottom: 1px !important; margin-left: 45px !important;\\\"><li class=\\\"alt\\\" style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; background-color: inherit;\\\">&gt;&gt;&gt;&gt;This&nbsp;is&nbsp;MyStartupRunnerTest&nbsp;Order=1.&nbsp;Only&nbsp;testing&nbsp;CommandLineRunner...&lt;&lt;&lt;&lt;&nbsp;&nbsp;</span></span></li><li style=\\\"border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;\\\"><span style=\\\"margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;\\\">&gt;&gt;&gt;&gt;This&nbsp;is&nbsp;MyStartupRunnerTest2&nbsp;Order=2.&nbsp;Only&nbsp;testing&nbsp;CommandLineRunner...&lt;&lt;&lt;&lt;&nbsp;&nbsp;</span></li></ol></div><p style=\\\"margin-bottom: 0px; padding: 0px; color: rgb(85, 85, 85); font-family: Arial; font-size: 14px;\\\"></p><p style=\\\"margin-bottom: 1.1em; padding: 0px; color: rgb(85, 85, 85); font-family: &quot;microsoft yahei&quot;; font-size: 14px;\\\">4.Application启动类代码略。</p><p><span style=\\\"color: rgb(85, 85, 85); font-family: Arial; font-size: 14px;\\\">说明：CommandLineRunner接口的运行顺序是依据@Order注解的value由小到大执行，即value值越小优先级越高。</span><br></p>', 'article', null, null, null, null, '1', null, '1', '1', 'bootdo', '2017-09-26 15:18:15', '2017-09-26 15:18:15');\nINSERT INTO `blog_content` VALUES ('115', 'communication', null, null, null, '<h2 style=\\\"color: rgb(103, 106, 108);\\\"><span style=\\\"font-family: Times; font-size: 17.5px; font-weight: bold;\\\"><a href=\\\"https://jq.qq.com/?_wv=1027&amp;k=5EfMNFL\\\" target=\\\"_blank\\\" style=\\\"color: rgb(42, 100, 150); text-decoration-line: underline; outline: 0px;\\\">qq群 669039323</a></span></h2>', null, null, 'communication', null, null, '1', null, '0', '1', 'bootdo', '2017-09-30 14:43:30', '2017-09-30 14:43:30');\nINSERT INTO `blog_content` VALUES ('116', 'ablout', null, null, null, '<h1 style=\\\"box-sizing: inherit; font-size: 28px; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); min-height: 1rem; -webkit-font-smoothing: antialiased; cursor: text; position: relative; margin-top: 0px !important;\\\">BootDo 面向学习型的开源框架</h1><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"平台简介\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E5%B9%B3%E5%8F%B0%E7%AE%80%E4%BB%8B\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>平台简介</h2><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">BootDo是高效率，低封装，面向学习型，面向微服的<strong style=\\\"box-sizing: inherit;\\\">开源</strong>Java EE开发框架。</p><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">BootDo是在SpringBoot基础上搭建的一个Java基础开发平台，MyBatis为数据访问层，ApacheShiro为权限授权层，Ehcahe对常用数据进行缓存。</p><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">BootDo主要定位于后台管理系统学习交流，已内置后台管理系统的基础功能和高效的<strong style=\\\"box-sizing: inherit;\\\">代码生成</strong>工具， 包括：系统权限组件、数据权限组件、数据字典组件、核心工具组件、视图操作组件、工作流组件、代码生成等。 前端界面风格采用了结构简单、性能优良、页面美观大气的Twitter Bootstrap页面展示框架。 采用分层设计、双重验证、提交数据安全编码、密码加密、访问验证、数据权限验证。 使用Maven做项目管理，提高项目的易开发性、扩展性。</p><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">BootDo目前包括以下四大模块，系统管理（SYS）模块、 内容管理（CMS）模块、在线办公（OA）模块、代码生成（GEN）模块。&nbsp;<strong style=\\\"box-sizing: inherit;\\\">系统管理模块</strong>&nbsp;，包括企业组织架构（用户管理、机构管理、区域管理）、 菜单管理、角色权限管理、字典管理等功能；&nbsp;<strong style=\\\"box-sizing: inherit;\\\">内容管理模块</strong>&nbsp;，包括内容管理（文章、链接），栏目管理、站点管理、 公共留言、文件管理、前端网站展示等功能；&nbsp;<strong style=\\\"box-sizing: inherit;\\\">在线办公模块</strong>&nbsp;，提供简单的请假流程实例；<strong style=\\\"box-sizing: inherit;\\\">代码生成模块</strong>&nbsp;，完成重复的工作。</p><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">BootDo 提供了常用工具进行封装，包括日志工具、缓存工具、服务器端验证、数据字典、当前组织机构数据 （用户、机构、区域）以及其它常用小工具等。另外还提供一个强大的在线&nbsp;<strong style=\\\"box-sizing: inherit;\\\">代码生成</strong>&nbsp;工具。</p><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"内置功能\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E5%86%85%E7%BD%AE%E5%8A%9F%E8%83%BD\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>内置功能</h2><ol class=\\\"task-list\\\" style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">用户管理：用户是系统操作者，该功能主要完成系统用户配置。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">机构管理：配置系统组织机构（公司、部门、小组），树结构展现，可随意调整上下级。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">区域管理：系统城市区域模型，如：国家、省市、地市、区县的维护。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">菜单管理：配置系统菜单，操作权限，按钮权限标识等。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">角色管理：角色菜单权限分配、设置角色按机构进行数据范围权限划分。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">字典管理：对系统中经常使用的一些较为固定的数据进行维护，如：是否、男女、类别、级别等。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">操作日志：系统正常操作日志记录和查询；系统异常信息日志记录和查询。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">连接池监视：监视当期系统数据库连接池状态，可进行分析SQL找出系统性能瓶颈。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">工作流引擎：实现业务工单流转、在线流程设计器。</li></ol><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"技术选型\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>技术选型</h2><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">1、后端</p><ul class=\\\"task-list\\\" style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">核心框架：Spring Boot</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">安全框架：Apache Shiro</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">模板引擎：Thymeleaf</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">持久层框架：MyBatis</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">数据库连接池：Alibaba Druid</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">缓存框架：Ehcache 、Redis</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">日志管理：SLF4J</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">工具类：Apache Commons、Jackson 、Xstream 1.4、Dozer 5.3、POI 3.9</li></ul><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">2、前端</p><ul class=\\\"task-list\\\" style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">JS框架：jQuery</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">客户端验证：JQuery Validation</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">富文本在线编辑：summernote</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">在线文件管理：CKFinder</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">数据表格：bootstrapTable</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">弹出层：layer</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">树结构控件：jsTree</li></ul><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">4、平台</p><ul class=\\\"task-list\\\" style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">服务器中间件：SpringBoot内置</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">数据库支持：目前仅提供MySql数据库的支持，但不限于数据库，平台留有其它数据库支持接口， 你可以很方便的更改为其它数据库，如：SqlServer 2008、MySql 5.5、H2等</li><li style=\\\"box-sizing: inherit; list-style-type: initial;\\\">开发环境：Java、Eclipse Java EE 、Maven 、Git</li></ul><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"安全考虑\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E5%AE%89%E5%85%A8%E8%80%83%E8%99%91\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>安全考虑</h2><ol class=\\\"task-list\\\" style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">开发语言：系统采用Java 语言开发，具有卓越的通用性、高效性、平台移植性和安全性。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">分层设计：（数据库层，数据访问层，业务逻辑层，展示层）层次清楚，低耦合，各层必须通过接口才能接入并进行参数校验（如：在展示层不可直接操作数据库），保证数据操作的安全。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">双重验证：用户表单提交双验证：包括服务器端验证及客户端验证，防止用户通过浏览器恶意修改（如不可写文本域、隐藏变量篡改、上传非法文件等），跳过客户端验证操作数据库。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">安全编码：用户表单提交所有数据，在服务器端都进行安全编码，防止用户提交非法脚本及SQL注入获取敏感数据等，确保数据安全。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">密码加密：登录用户密码进行SHA1散列加密，此加密方法是不可逆的。保证密文泄露后的安全问题。</li><li style=\\\"box-sizing: inherit; list-style-type: decimal;\\\">强制访问：系统对所有管理端链接都进行用户身份权限验证，防止用户直接填写url进行访问。</li></ol><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"演示地址\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E6%BC%94%E7%A4%BA%E5%9C%B0%E5%9D%80\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>演示地址</h2><h6 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; color: rgb(119, 119, 119); margin-top: 20px; font-size: 14px; -webkit-font-smoothing: antialiased; cursor: text; position: relative;\\\"><a id=\\\"布嘟开源wwwbootdocom\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E5%B8%83%E5%98%9F%E5%BC%80%E6%BA%90wwwbootdocom\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>布嘟开源<a href=\\\"http://www.bootdo.com./blog\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word;\\\">www.bootdo.com</a></h6><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"交流反馈\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E4%BA%A4%E6%B5%81%E5%8F%8D%E9%A6%88\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>交流反馈</h2><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"qq群-669039323\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#qq%E7%BE%A4-669039323\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>QQ群 669039323</h2><h2 style=\\\"box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-weight: bold; line-height: 1.33em; color: rgb(0, 0, 0); margin-top: 20px; font-size: 24px; padding-bottom: 0.3em; -webkit-font-smoothing: antialiased; cursor: text; position: relative; border-bottom: 1px solid rgb(204, 204, 204);\\\"><a id=\\\"版权声明\\\" class=\\\"anchor\\\" href=\\\"https://gitee.com/lcg0124/bootdo#%E7%89%88%E6%9D%83%E5%A3%B0%E6%98%8E\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word; display: block; padding-left: 30px; margin-left: -20px; position: absolute; top: 0px; left: 0px; bottom: 0px; outline: none;\\\"></a>版权声明</h2><p style=\\\"box-sizing: inherit; margin-bottom: 15px; line-height: 25px; word-break: break-word; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px;\\\">本软件使用&nbsp;<a href=\\\"http://www.apache.org/licenses/LICENSE-2.0\\\" style=\\\"box-sizing: inherit; color: rgb(9, 94, 171); word-wrap: break-word;\\\">Apache License 2.0</a>&nbsp;协议，请严格遵照协议内容</p><ul class=\\\"task-list\\\" style=\\\"box-sizing: inherit; line-height: 24px; padding-left: 30px; color: rgb(64, 72, 91); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Liberation Sans&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Wenquanyi Micro Hei&quot;, &quot;WenQuanYi Zen Hei&quot;, &quot;ST Heiti&quot;, SimHei, &quot;WenQuanYi Zen Hei Sharp&quot;, sans-serif; font-size: 15px; margin-bottom: 0px !important;\\\"><li class=\\\"task-list-item\\\" style=\\\"box-sizing: inherit; list-style-type: initial;\\\"><input type=\\\"checkbox\\\" class=\\\"task-list-item-checkbox\\\" checked=\\\"\\\" disabled=\\\"\\\" style=\\\"margin-top: 0px; cursor: default; transition: border 0.2s linear, box-shadow 0.2s linear; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px inset; vertical-align: middle;\\\">&nbsp;注：已上内容为整体规化，部分功能还在实现中</li></ul>', null, null, 'about', null, null, '1', null, '0', '1', 'bootdo', '2017-09-30 14:43:09', '2017-09-30 14:43:09');\nINSERT INTO `blog_content` VALUES ('117', '页面加载速度优化建议', null, null, null, '<p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">1、合并Js文件和CSS</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">将JS代码和CSS样式分别合并到一个共享的文件，这样不仅能简化代码，而且在执行JS文件的时候，如果JS文件比较多，就需要进行多次“Get”请求，延长加载速度，将JS文件合并在一起后，自然就减少了Get请求次数，提高了加载速度。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">2、Sprites图片技术</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">Spriting是一种网页图片应用处理方式，它是将一个页面涉及到的所有零星图片都包含到一张大图中去，然后利用CSS技术展现出来。这样一来，当访问该页面时，载入的图片就不会像以前那样一幅一幅地慢慢显示出来了，可以减少了整个网页的图片大小，并且利用CSSSprites能很好地减少网页的http请求，从而大大的提高页面的性能。CSSSprites在国内很多人叫css精灵，很早就有了，在很多大型网站都有用到，特别是一些所有页面都存在的图标用得比较多，很好的提升加载速度。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">3、压缩文本和图片</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">压缩技术如gzip可以有效减少页面加载的时间。包括HTML，XML，JSON(JavaScript对象符号)，JavaScript和CSS等，压缩率都可以在大小70%左右。文本压缩用得比较多，一般直接在空间开启就行，而图片的压缩就比较随意，很多都是直接上传，其实还有很大的压缩空间。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">4、延迟显示可见区域外的内容</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">为了确保用户可以更快地看见可见区域的网页可以延迟加载或展现可见区域外的内容，为了避免页面变形，可以使用占位符标签制定正确的高度和宽度。比如WP的jQueryImage LazyLoad插件就可以在用户停留在第一屏的时候，不加载任何第一屏以下的图片信息，只有当用户把鼠标往下滚动的时候，这些图片才开始加载。这样很明显提升可见区域的加载速度，提高用户体验。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">5、确保功能图片优先加载</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">网站主要考虑可用性的重要性，一个功能按钮要提前加载出来，用户进入下载页，一个只需要8s时间的下载花了5s在等待、寻找下载按钮图片，谁能忍受?</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">6、重新布置Call-to-Action按钮</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">其实这个和上面一条是差不多的，都是从用户体验速度着手，跳过了网页的整体加载速度。速度没变，只是让一些行为按钮提前，Call-to-Action按钮一般习惯设计在页面底部，这样的习惯对于用户来说并不总是好的，购买用户需要等到最下面加载出来才能点击下一步操作。可以调整CTA按钮的位置或使用滑动的图片按钮。很多大型购物网站的加入购物车就是这种类型。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">7、图片格式优化</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">不恰当的图像格式是一种极为常见的减慢加载速度的罪魁祸首。正确的图片格式可以让图片缩小数倍，如果保存为最佳格式。可以节省大量带宽，减少处理时间时间，大大加快页面加载速度，这是一种很常见的做法。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">8、使用 Progressive JPEGs</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">ProgressiveJPEGs图片是JPEG格式的一个特殊变种，名为“高级JPEG”。在创建高级JPEG文件时，数据是这样安排的：在装入图像时，开始只显示一个模糊的图像，随着数据的装入，图像逐步变得清晰。它相当于交织的GIF格式的图片。高级JPEG主要是考虑到使用调制解调器的慢速网络而设计的，快速网络的使用者通常不会体会到它和正常JPEG格式图片的区别。对于网速比较慢的用户，这无疑有很好的体验。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">9、精简代码</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">这个可以说是最直接的一个方法，也是用得比较多的，对网页代码进行瘦身，删除不必要的沉冗代码，比如不必要的空格、换行符、注释等，包括JS代码中的无用代码也需要清除。其中对于注释代码的清除可能有些人存在误区，甚至有的在里面堆砌关键词。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">10、延迟加载和执行非必要脚本</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">网页中有很多脚本是在页面完全加载完前都不需要执行的，可以延迟加载和执行非必要脚本。这些脚本可以在onload事件之后执行，避免对网页上重要内容的呈现造成影响。这些脚本可能是你自己网页的甲苯，往往更多的是一些第三方脚本，这样的有很多，比如评论、广告、智能推荐、百度云图、分享等等，这些完全可以等主体内容加载完后再执行。</p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\"><span style=\\\"font-weight: 700;\\\">11、使用AJAX</span></p><p style=\\\"margin-bottom: 24px; color: rgb(14, 14, 14); font-family: Arial, &quot;Hiragino Sans GB&quot;, 冬青黑, &quot;Microsoft YaHei&quot;, 微软雅黑, SimSun, 宋体, Helvetica, Tahoma, &quot;Arial sans-serif&quot;; font-size: 16px; text-align: justify;\\\">AJAX即“Asynchronous Javascript +XML“，是指一种创建交互式网页应用的网页开发技术。通过在后台与服务器进行少量数据交换，AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下，对网页的某部分进行更新。传统的网页(不使用AJAX)如果需要更新内容，必须重载整个网页面。</p>', null, null, '', null, null, '1', null, '0', '1', 'bootdo', '2017-09-30 16:13:35', '2017-09-30 16:13:35');\nINSERT INTO `blog_content` VALUES ('118', 'elementUI select组件使用详解', null, null, null, '<article style=\\\"padding: 20px 0px; border-top: 1px solid rgb(228, 235, 244); border-left: 1px solid rgb(228, 235, 244); border-right: 1px solid rgb(228, 235, 244); color: rgb(51, 51, 51); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 16px;\\\"><div id=\\\"article_content\\\" class=\\\"article_content csdn-tracking-statistics\\\" data-mod=\\\"popu_307\\\" data-dsm=\\\"post\\\" style=\\\"margin: 0px 0px 50px; padding: 20px 30px 0px; color: rgb(69, 69, 69); overflow: hidden;\\\"><div class=\\\"markdown_views\\\" style=\\\"margin: 0px; padding: 0px; font-family: &quot;microsoft yahei&quot;; font-size: 15px; color: rgb(63, 63, 63);\\\"><h1 id=\\\"elementui-select组件使用详解\\\" style=\\\"margin-top: 0.8em; margin-bottom: 0.8em; font-size: 2.6em; font-family: inherit; padding: 0px;\\\">elementUI select组件使用详解</h1><ul style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 0px; list-style-position: initial; list-style-image: initial;\\\"><li style=\\\"margin: 0px 0px 0px 40px; padding: 0px; list-style: disc;\\\"><strong>动态生成option选项</strong></li><li style=\\\"margin: 0px 0px 0px 40px; padding: 0px; list-style: disc;\\\"><strong>option选项绑定对应的文本值和value值</strong></li><li style=\\\"margin: 0px 0px 0px 40px; padding: 0px; list-style: disc;\\\"><strong>作为表单项目，新增、编辑功能</strong></li><li style=\\\"margin: 0px 0px 0px 40px; padding: 0px; list-style: disc;\\\"><strong>对选项改变后触发相关事件</strong></li></ul><pre class=\\\"prettyprint\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; font-size: 14px; white-space: nowrap; padding: 5px 5px 5px 60px; margin-bottom: 1.1em; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-color: rgba(128, 128, 128, 0.075); border-radius: 0px; position: relative; overflow-y: hidden;\\\"><code class=\\\"hljs lasso has-numbering\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; display: block; word-wrap: normal;\\\"><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>div id<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"app\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n    <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span> :model<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"form\\\"</span>  ref<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"form\\\"</span> label<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-width</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"100px\\\"</span> class<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"demo-ruleForm\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n        <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span><span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-item</span> label<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"姓名选择\\\"</span> prop<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"typeId\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n            <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-select</span> v<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-model</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"form.typeId\\\"</span> placeholder<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"请选择\\\"</span> @change<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"change\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n                <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-option</span> v<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-for</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"item in items\\\"</span> :label<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"item.name\\\"</span> :value<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"item.id\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-option</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n            <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-select</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n        <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span><span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-item</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n        <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span><span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-item</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n            <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span> <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">type</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"primary\\\"</span> @click<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"add()\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>新增<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n            <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span> <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">type</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"primary\\\"</span> @click<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"edit()\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>编辑<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n            <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span> @click<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">=</span><span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"cancel()\\\"</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>取消<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-button</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n        <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span><span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-item</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n    <span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/el<span class=\\\"hljs-attribute\\\" style=\\\"margin: 0px; padding: 0px;\\\">-form</span><span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span>\\r\\n<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&lt;</span>/div<span class=\\\"hljs-subst\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 0);\\\">&gt;</span></code><ul class=\\\"pre-numbering\\\" style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; list-style: none; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; border-right: 1px solid rgb(221, 221, 221); text-align: right;\\\"><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">1</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">2</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">3</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">4</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">5</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">6</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">7</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">8</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">9</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">10</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">11</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">12</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">13</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">14</li></ul></pre><pre class=\\\"prettyprint\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; font-size: 14px; white-space: nowrap; padding: 5px 5px 5px 60px; margin-bottom: 1.1em; line-height: 1.45; background-color: rgba(128, 128, 128, 0.05); border-color: rgba(128, 128, 128, 0.075); border-radius: 0px; position: relative; overflow-y: hidden;\\\"><code class=\\\"hljs xml has-numbering\\\" style=\\\"font-family: &quot;Source Code Pro&quot;, monospace; white-space: pre; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; display: block; word-wrap: normal;\\\"><span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">script</span>&gt;</span><span class=\\\"javascript\\\" style=\\\"margin: 0px; padding: 0px;\\\">\\r\\n    <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">var</span> vm = <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">new</span> Vue({\\r\\n        el:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"#app\\\"</span>,\\r\\n        mounted(){\\r\\n            <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.getData();\\r\\n        },\\r\\n        data:{\\r\\n            form:{\\r\\n                typeId:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\'\\'</span>\\r\\n            },\\r\\n            items:[],\\r\\n            datas:[{name:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"senbo\\\"</span>,id:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\'1\\'</span>},{name:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"muse\\\"</span>,id:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\'2\\'</span>},{name:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"bobo\\\"</span>,id:<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\'3\\'</span>}]\\r\\n        },\\r\\n        methods:{\\r\\n            getData:<span class=\\\"hljs-function\\\" style=\\\"margin: 0px; padding: 0px;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">function</span><span class=\\\"hljs-params\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">()</span>{</span>\\r\\n                <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.items = <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.datas; \\r\\n\\r\\n            },\\r\\n            add:<span class=\\\"hljs-function\\\" style=\\\"margin: 0px; padding: 0px;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">function</span><span class=\\\"hljs-params\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">()</span>{</span>\\r\\n                <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.form.typeId = <span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"\\\"</span>;\\r\\n            },\\r\\n            cancel(){\\r\\n                 <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.form.typeId = <span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"\\\"</span>;   \\r\\n            },\\r\\n            change:<span class=\\\"hljs-function\\\" style=\\\"margin: 0px; padding: 0px;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">function</span><span class=\\\"hljs-params\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">()</span>{</span>\\r\\n                console.log(<span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.form.typeId)\\r\\n            },\\r\\n            edit:<span class=\\\"hljs-function\\\" style=\\\"margin: 0px; padding: 0px;\\\"><span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">function</span><span class=\\\"hljs-params\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(102, 0, 102);\\\">()</span>{</span>\\r\\n                <span class=\\\"hljs-keyword\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">this</span>.form.typeId =<span class=\\\"hljs-string\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 136, 0);\\\">\\\"1\\\"</span>;\\r\\n            }\\r\\n        }\\r\\n    })\\r\\n</span><span class=\\\"hljs-tag\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 102, 102);\\\">&lt;/<span class=\\\"hljs-title\\\" style=\\\"margin: 0px; padding: 0px; color: rgb(0, 0, 136);\\\">script</span>&gt;</span></code><ul class=\\\"pre-numbering\\\" style=\\\"margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px 40px; list-style: none; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; border-right: 1px solid rgb(221, 221, 221); text-align: right;\\\"><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">1</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">2</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">3</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">4</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">5</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">6</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">7</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">8</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">9</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">10</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">11</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">12</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">13</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">14</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">15</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">16</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">17</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">18</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">19</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">20</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">21</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">22</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">23</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">24</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">25</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">26</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">27</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">28</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">29</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">30</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">31</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">32</li><li style=\\\"margin: 0px; padding: 0px 5px; list-style: none; color: rgb(153, 153, 153);\\\">33</li></ul></pre></div></div></article><div class=\\\"article_copyright\\\" style=\\\"margin: 0px 0px -20px; padding: 0px 20px 30px; border-bottom: 1px solid rgb(228, 235, 244); border-left: 1px solid rgb(228, 235, 244); border-right: 1px solid rgb(228, 235, 244); font-size: 14px; color: rgb(120, 128, 135); clear: both; overflow: hidden; font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun;\\\">转自http://blog.csdn.net/museions/article/details/77824361</div>', 'article', null, '', null, null, '1', null, '0', '1', 'bootdo', '2017-10-12 10:41:07', '2017-10-12 10:41:07');\nINSERT INTO `blog_content` VALUES ('119', 'Java程序员秋招面经大合集（BAT美团网易小米华为中兴等）', null, null, null, '<h1 class=\\\"title\\\" style=\\\"font-size: 34px; margin-top: 20px; margin-bottom: 0px; font-family: -apple-system, &quot;SF UI Display&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-weight: 700; line-height: 1.3; color: rgb(51, 51, 51); word-break: break-word !important;\\\">Java程序员秋招面经大合集（BAT美团网易小米华为中兴等）</h1><div data-note-content=\\\"\\\" class=\\\"show-content\\\" style=\\\"color: rgb(47, 47, 47); font-size: 16px; line-height: 1.7; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; word-break: break-word !important;\\\"><blockquote style=\\\"padding-top: 20px; padding-bottom: 20px; margin-bottom: 25px; font-size: 16px; border-left-width: 6px; border-left-color: rgb(180, 180, 180); background-color: rgb(247, 247, 247); line-height: 30px; word-break: break-word !important;\\\"><ul style=\\\"padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Cvte提前批</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">阿里内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">便利蜂内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">小米内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">金山wps内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">多益网络</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">拼多多学霸批</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">搜狗校招</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">涂鸦移动</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">中国电信it研发中心</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">中兴</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">华为</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">苏宁内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">美团内推</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">百度</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">腾讯</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">招商银行信用卡</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">招银网络科技</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">网易</li><li style=\\\"line-height: 30px; margin-bottom: 0px;\\\">Vivo</li></ul></blockquote><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">Cvte提前批</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍你的项目</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">加密解密了解么？几种算法，讲一下你了解的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">多线程了解么？什么是线程安全？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">说一个你最熟悉的设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下你项目中用到了哪些设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java的hashmap的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap的线程安全性，什么是线程安全的？如何实现线程安全</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（视频）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍项目</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Mysql的数据库引擎，区别特点</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计模式了解？讲一下最熟悉的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">写一个单例模式，答主写的是双检查锁单例，问了为什么用Volatile，synchronize移到方法最外面会怎么样？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">单例模式在你项目里哪些应用？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据连接池</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对高负载有了解么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你意向的技术方向是哪块？（答主回答的高并发，然后面试官说他是做高负载的）</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对高并发有了解么？</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">阿里内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">听说你有博客，博客里大概有什么内容？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍，最复杂的表</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap为什么大小是2的幂次</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍一下红黑树</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Arraylist的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">场景题：设计判断论文抄袭的系统</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">堆排序的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">抽象工厂和工厂方法模式的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">工厂模式的思想</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">object类你知道的方法</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">哪里用到了工厂模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Forward和redirect的区别</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（视频）</h2><p style=\\\"margin-bottom: 25px; word-break: break-word !important;\\\">1， 自我介绍<br>2， 项目介绍<br>3， 项目架构<br>4， 项目难点<br>5， Synchronize关键字为什么jdk1.5后效率提高了<br>6， 线程池的使用时的注意事项<br>7， Spring中autowire和resourse关键字的区别<br>8， Hashmap的原理<br>9， Hashmap的大小为什么指定为2的幂次<br>10， 讲一下线程状态转移图<br>11， 消息队列了解么<br>12， 分布式了解么</p><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">便利蜂内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">volatile和synchronized</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">来个算法题：一个无序数组，其中一个数字出现的次数大于其他数字之和，求这个数字 （主元素）</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">答完再来一个：一个数组，有正有负，不改变顺序的情况下，求和最大的最长子序列</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目用到什么数据库？隔离级别？每个隔离级别各做了什么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的索引？mysql不同引擎索引的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">垃圾回收算法的过程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你了解的垃圾收集器？ Cms收集器的过程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎样进入老年代？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">平时用到了什么设计模式？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下你最熟的两个设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">用过什么系统？shell写过脚本吗？</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">小米内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">看你最近博客写的是redis，介绍redis和mysql的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的应用场景</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap中jdk1.8之后做了哪些优化</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">垃圾回收的过程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Jvm的参数设置</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目中的优化</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">金山wps内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对Java的面向对象的理解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对java多线程的理解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的索引</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的隔离级别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计模式的理解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲几个设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对算法有什么了解？答主先回答了动态规划，解释了一下dp的思想</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">快排的思想讲一下</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Tcp怎么保证可靠传输（中间穿插了好多小问题）</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Tcp的拥塞控制</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">让你设计一个即时聊天的系统</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">支付宝转账，是如何实现，几个小时通知转账成功的（面试官想让回答长连接，答主一直没get到点）</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">解释一下长连接</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">多益网络</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（视频）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对面向对象的理解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍多态</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java新建线程有哪几种方式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">线程池的作用</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">看过框架源码么</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">拼多多学霸批</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场面）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：一棵二叉排序树，给定一个数，找到与给定数差值最小的数</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">场景题：设计一个系统，解决抢购时所需要的大量的短链接的功能，如何保证高并发，如何设计短链接</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（现场面）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">代码量多少</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">给了一张纸，各种名词，会的写出来</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">然后给它解释那些会的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计题：设计一个系统，记录qq用户前一天的登录状态，提供16g内存和2tb的硬盘，要做到查询指定qq号的前一天的登录状态，快速查询O(1)复杂度</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">搜狗校招</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）：</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：两个排序的数组A和B分别含有m和n个数，找到两个排序数组的中位数，答主用的二分，时间复杂度为O(log (m+n))。结果面试官不满意，让用归并的思想做，时间复杂度其实更高了</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍网络编程</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">涂鸦移动</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的索引原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">索引使用的注意事项</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的引擎</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java垃圾回收机制</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java的finalize，finally，final三个关键字的区别和应用场景</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">String类可以被继承么<br>手撕算法：假设你是一个专业的窃贼，准备沿着一条街打劫房屋。每个房子都存放着特定金额的钱。你面临的唯一约束条件是：相邻的房子装着相互联系的防盗系统，且 当相邻的两个房子同一天被打劫时，该系统会自动报警。<br>给定一个非负整数列表，表示每个房子中存放的钱， 算一算，如果今晚去打劫，你最多可以得到多少钱 在不触动报警装置的情况下。</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">对游戏的了解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">算法题：给一个整数数组，找到两个数使得他们的和等于一个给定的数 target。</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">红黑树</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的应用</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">中国电信it研发中心</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目里用的什么服务器</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自己写一个tomcat服务器，你会怎么写</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">分布式服务器会出现哪些问题</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么解决session一致性缓存的问题</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的优势和特点</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">一千万用户并发抢购，怎么设计</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">如果成功的用户有10万，redis存不下怎么处理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你项目中的难点</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍spring中的熟悉的注解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">让你实现autowire注解的功能你会如何实现</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis和mysql的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的持久化有哪些方式，具体原理</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">中兴</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">专业面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你了解的设计模式，讲两个</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java collection类，集合，讲两个你了解的，说实现原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java线程池的作用</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你觉得你在你实验室处于什么水平</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">综合面试（现场）</h2><p style=\\\"margin-bottom: 25px; word-break: break-word !important;\\\">说好的综合面试纯聊天呢？<br>1． 自我介绍<br>2． 项目介绍<br>3． 说一下你知道的设计模式<br>4． 画一个策略模式的uml图<br>5． Java多线程的理解<br>6． 内存屏障是什么<br>7． 数据库索引<br>8． 项目中的优化<br>9． 然后开始聊人生<br>10． 你的缺点，你最不喜欢什么样的人，你的家庭等等</p><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">华为</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目架构</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目一个完整的执行流程（由于我是搞java的，而面试官是搞c的，所以全程尬聊）</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目优化</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么管理项目进度</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">平常的爱好</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">感觉面试官也不是搞java的，所以又是一阵尬聊</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">苏宁内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">面过哪些公司了</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">有哪些offer了</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">聊到多益，于是开始聊最近微博上很火的多益老板</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">得出结论，我和面试官都觉得多益老板三观有问题，但做游戏就是要偏执的人</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你博客主要哪方面的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">多线程并发包了解么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下countDownLatch</li></ol><p style=\\\"margin-bottom: 25px; word-break: break-word !important;\\\">苏宁聊了20分钟八卦就面完了，一轮技术面</p><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">美团内推</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（电话）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">了解redis源码么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">了解redis集群么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">hashmap容量为什么是2的幂次</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">hashset的源码</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">object类你知道的方法</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">hashcode和equals</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你重写过hashcode和equals么，要注意什么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">假设现在一个学生类，有学号和姓名，我现在hashcode方法重写的时候，只将学号参与计算，会出现什么情况？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">往set里面put一个学生对象，然后将这个学生对象的学号改了，再put进去，可以放进set么？并讲出为什么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的持久化？有哪些方式，原理是什么？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下稳定的排序算法和不稳定的排序算法</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下快速排序的思想</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲一下数据的acid</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">什么是一致性</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">什么是隔离性</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Mysql的隔离级别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">每个隔离级别是如何解决</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Mysql要加上nextkey锁，语句该怎么写</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java的内存模型，垃圾回收</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">线程池的参数</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">每个参数解释一遍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">然后面试官设置了每个参数，给了是个线程，让描述出完整的线程池执行的流程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Nio和IO有什么区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Nio和aio的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Spring的aop怎么实现</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Spring的aop有哪些实现方式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">动态代理的实现方式和区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Linux了解么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么查看系统负载</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Cpu load的参数如果为4，描述一下现在系统处于什么情况</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Linux，查找磁盘上最大的文件的命令</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Linux，如何查看系统日志文件</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：leeetcode原题 22，Generate Parentheses，给定 n 对括号，请写一个函数以将其生成新的括号组合，并返回所有组合结果。</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">三面（现场）</h2><p style=\\\"margin-bottom: 25px; word-break: break-word !important;\\\">三面没怎么问技术，问了很多技术管理方面的问题</p><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么管理项目成员</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">当意见不一致时，如何沟通并说服开发成员，并举个例子</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么保证项目的进度</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的索引原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">非聚簇索引和聚簇索引</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">索引的使用注意事项</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">联合索引</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">从底层解释最左匹配原则</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Mysql对联合索引有优化么？会自动调整顺序么？哪个版本开始优化？</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的应用</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的持久化的方式和原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">技术选型，一个新技术和一个稳定的旧技术，你会怎么选择，选择的考虑有哪些</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">说你印象最深的美团点评技术团队的三篇博客</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">最近在学什么新技术</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你是怎么去接触一门新技术的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">会看哪些书</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么选择要看的书</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">百度</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java中的多态</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Object类下的方法</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Finalize的作用和使用场景</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashcode和equals</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">为什么要同时重写hashcode和equals</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">不同时重写会出现哪些问题</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hashmap如何变线程安全，每种方式的优缺点</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">垃圾回收机制</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Jvm的参数你知道的说一下</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计模式了解的说一下啊</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕一个单例模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">快速排序的思想讲一下</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">给个数组，模拟快排的过程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手写快排</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计题，一个图书馆管理系统，数据库怎么设计，需求自己定</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis的特点</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">分布式事务了解么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">反爬虫的机制，有哪些方式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：反转单链表</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：实现类似微博子结构的数据结构，输入一系列父子关系，输出一个类似微博评论的父子结构图</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手写java多线程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手写java的soeket编程，服务端和客户端</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">进程间的通信方式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法： 爬楼梯，写出状态转移方程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">智力题：时针分针什么时候重合</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">三面（现场）</h2><p style=\\\"margin-bottom: 25px; word-break: break-word !important;\\\">由于三面面试官不懂java，我不熟c加加，所以全程尬聊</p><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：给定一个数字三角形，找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\"></li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">然后继续在这个问题上扩展</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">求出最短那条的路径</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">递归求出所有的路径</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计模式讲一下熟悉的</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">会不会滥用设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">多线程条件变量为什么要在while体里</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你遇到什么挫折</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">腾讯</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hibernate的作用，你的理解</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">多线程的理解，如何保证线程安全</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">mysql数据库的引擎和区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">场景题：千万用户抢购，如何处理高并发，并且有一个链接，指向前一天抢购成功的用户，如何设计这个系统和数据库</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">如果后台处理抢购请求的服务器，每次最多承受200的负载，系统该怎么设计</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">手撕算法：最小公倍数和最大公约数</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目里一个完整请求的流程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目的优化</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hibernate和mybatis的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">为什么用ssh框架</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Mysql的容灾备份</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Redis和memcache 的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">为什么选择redis</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Java的full gc</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Full gc会导致什么问题</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">招商银行信用卡</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">分布式事务</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">设计模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">访问者模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">装饰者模式</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">有哪些offer</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">为什么还来我们这</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">招银网络科技</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">写一个两个有序链表合并成一个有序链表</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">死锁是什么呢</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么解决死锁</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">http请求流程</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">为什么负载均衡</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么实现负载均衡</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库挂了怎么办？除了热备份还有什么方法</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">讲讲你对spring的理解，不要把ioc和aop背给我听</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">算法：找出两个数组相等的数，不能用其他数据结构</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">算法：给定一个数字，一个数组，找出数组中相加等于这两个数的和，不能用数据结构</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">算法：如何判断一个树是不是另一颗树的子树</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">如何解决并发访问的错误</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">网易</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面（现场）</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">I++操作怎么保证线程安全</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">场景题：设计一个下单系统，下单成功后可以给用户发优惠券</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">接上面场景题：服务器挂了，优惠券还没发怎么办</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库挂了怎么怎么办</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么保证一致性</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">分布式事务知道么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">介绍分布式事务</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">你的职业规划</li></ol><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">二面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Nio的原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Channel和buffer</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">directBuffer和buffer的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">nio和aio的区别</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">锁的实现原理</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">怎么解决缓存和主存的一致性问题</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">缓存还没更新到主存，服务器挂了怎么办</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库挂了怎么办</li></ol><h1 style=\\\"font-size: 26px; margin-top: 0px; margin-bottom: 15px; font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); text-rendering: optimizeLegibility;\\\">Vivo</h1><h2 style=\\\"font-family: inherit; font-weight: 700; line-height: 1.7; color: rgb(47, 47, 47); margin: 0px 0px 15px; font-size: 24px; text-rendering: optimizeLegibility;\\\">一面</h2><ol style=\\\"margin-bottom: 20px; padding: 0px; margin-left: 22px; word-break: break-word !important;\\\"><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">自我介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">项目介绍</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Hibernate的batch有数量限制么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Jquery用过么</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Extjs的优缺点</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">有没有扩展过extjs</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">读写锁</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">什么时候用读锁</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">什么时候用写锁</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">Cas的原理，使用场景</li><li style=\\\"line-height: 30px; margin-bottom: 10px;\\\">数据库的瓶颈</li></ol><div><br></div><div><br></div><div>转自<a href=\\\"http://www.jianshu.com//p/72712546648b\\\" target=\\\"_blank\\\">http://www.jianshu.com//p/72712546648b</a></div></div>', 'article', null, '', null, null, '1', null, '0', '1', 'Bootdo', '2017-10-13 13:45:20', '2017-10-13 13:45:20');\nINSERT INTO `blog_content` VALUES ('121', 'Spring Cloud下微服务权限方案', null, null, null, '<p><br></p><div class=\\\"Layout-navbarHolder\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; height: 59px; color: rgb(51, 51, 51); font-family: -apple-system, &quot;Helvetica Neue&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: medium;\\\"><header class=\\\"Navbar ScrollBackFixed\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; flex-direction: row; -webkit-box-align: center; align-items: center; flex-shrink: 0; contain: layout; -webkit-box-pack: justify; justify-content: space-between; height: 59px; width: 1519.2px; border-bottom: 1px solid rgba(0, 0, 0, 0.08); color: rgb(128, 128, 128); background: rgba(255, 255, 255, 0.97); z-index: 2; position: fixed; border-top-color: rgba(0, 0, 0, 0.08); border-right-color: rgba(0, 0, 0, 0.08); border-left-color: rgba(0, 0, 0, 0.08); transform: translateY(-100%); will-change: transform;\\\"><div class=\\\"Navbar-functionality\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; flex-direction: row; -webkit-box-align: center; align-items: center; flex-shrink: 0; position: absolute; right: 0px; top: 0px; height: 58px; align-self: stretch;\\\"><a class=\\\"Navbar-write\\\" style=\\\"box-sizing: inherit; color: inherit; display: flex; -webkit-box-align: center; align-items: center; padding: 0px 10px; white-space: nowrap; transition: color 0.2s;\\\"><span class=\\\"icon icon-ic_nav_new\\\" style=\\\"box-sizing: inherit; font-size: 24px; speak: none; font-feature-settings: normal; line-height: 1; -webkit-font-smoothing: antialiased; margin-right: 3px; font-family: icomoon !important;\\\"></span>写文章</a><button class=\\\"Button Navbar-loginButon Button--blue\\\" type=\\\"button\\\" style=\\\"box-sizing: inherit; padding: 0px 16px; color: rgb(0, 128, 255); font-size: 14px; line-height: 30px; background-image: none; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: 1px; border-style: solid; border-color: rgb(0, 128, 255); -webkit-appearance: none; border-radius: 4px; height: 32px; margin-right: 16px; margin-left: 6px; width: 72px;\\\">登录</button></div></header></div><div style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; color: rgb(51, 51, 51); font-family: -apple-system, &quot;Helvetica Neue&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: medium;\\\"></div><div class=\\\"Layout-main av-card av-paddingBottom av-bodyFont Layout-titleImage--normal\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; margin: 22px auto 0px; padding: 0px; width: 660px; z-index: 1; color: rgb(51, 51, 51); font-family: -apple-system, &quot;Helvetica Neue&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: medium;\\\"><div class=\\\"PostIndex-header av-paddingTop av-card\\\" data-zop=\\\"{&quot;authorName&quot;:&quot;老A&quot;,&quot;itemId&quot;:&quot;29345083&quot;,&quot;title&quot;:&quot;Spring Cloud下微服务权限方案&quot;,&quot;type&quot;:&quot;article&quot;}\\\" data-za-module=\\\"PostItem\\\" data-za-module-info=\\\"{&quot;card&quot;:{&quot;content&quot;:{&quot;type&quot;:&quot;Post&quot;,&quot;token&quot;:&quot;29345083&quot;}}}\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; position: relative;\\\"><div class=\\\"TitleImage\\\" style=\\\"box-sizing: inherit; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; margin-bottom: 22px;\\\"><img alt=\\\"Spring Cloud下微服务权限方案\\\" src=\\\"https://pic4.zhimg.com/v2-32e374b99a4332ca8bd52fca9d090617_r.png\\\" class=\\\"TitleImage-imagePure TitleImage-imagePure--fixed\\\" height=\\\"396px\\\" style=\\\"box-sizing: inherit; overflow: hidden; width: 660px; display: block;\\\"></div><h1 class=\\\"PostIndex-title av-paddingSide av-titleFont\\\" style=\\\"box-sizing: inherit; margin-top: 0px; margin-bottom: 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; font-size: 32px; line-height: 1.3;\\\">Spring Cloud下微服务权限方案</h1><div class=\\\"PostIndex-author\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; flex-direction: row; -webkit-box-align: center; align-items: center; flex-shrink: 0; position: relative; font-size: 14px; color: rgb(128, 128, 128); margin-top: 22px;\\\"><a href=\\\"https://www.zhihu.com/people/lao-a-68-38\\\" target=\\\"_blank\\\" style=\\\"box-sizing: inherit; color: inherit;\\\"><img class=\\\"Avatar-hemingway PostIndex-authorAvatar Avatar--xs\\\" alt=\\\"老A\\\" src=\\\"https://pic1.zhimg.com/v2-3b6c82a0652b73ee56207a2f45955ca8_xs.jpg\\\" srcset=\\\"https://pic1.zhimg.com/v2-3b6c82a0652b73ee56207a2f45955ca8_l.jpg 2x\\\" style=\\\"box-sizing: inherit; overflow: hidden; width: 36px; height: 36px; border-radius: 50%; margin-right: 12px;\\\"></a><a href=\\\"https://www.zhihu.com/people/lao-a-68-38\\\" target=\\\"_blank\\\" class=\\\"PostIndex-authorName\\\" style=\\\"box-sizing: inherit; color: rgb(128, 128, 128); min-width: 0px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;\\\">老A</a><span class=\\\"Bull\\\" style=\\\"box-sizing: inherit; margin: 0px 6px;\\\"></span><div class=\\\"HoverTitle\\\" data-hover-title=\\\"2017 年 9月 14 日星期四晚上 7 点 12 分\\\" style=\\\"box-sizing: inherit; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; position: relative;\\\"><time datetime=\\\"Thu Sep 14 2017 19:12:26 GMT+0800 (中国标准时间)\\\" style=\\\"box-sizing: inherit;\\\">1 个月前</time></div></div></div><div class=\\\"RichText PostIndex-content av-paddingSide av-card\\\" style=\\\"box-sizing: inherit; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0; word-break: break-word; margin: 30px 0px; line-height: 1.7;\\\"><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">背景</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">从传统的单体应用转型Spring Cloud的朋友都在问我，Spring Cloud下的微服务权限怎么管？怎么设计比较合理？从大层面讲叫服务权限，往小处拆分，分别为三块：用户认证、用户权限、服务校验。</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">用户认证</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">传统的单体应用可能习惯了session的存在，而到了Spring cloud的微服务化后，session虽然可以采取分布式会话来解决，但终究不是上上策。开始有人推行Spring Cloud Security结合很好的OAuth2，后面为了优化OAuth 2中Access Token的存储问题，提高后端服务的可用性和扩展性，有了更好Token验证方式JWT（JSON Web Token）。这里要强调一点的是，OAuth2和JWT这两个根本没有可比性，是两个完全不同的东西。 OAuth2是一种授权框架，而JWT是一种认证协议</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">OAuth2认证框架</h2><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">OAuth2中包含四个角色：</h2><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">资源拥有者(Resource Owner)</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">资源服务器(Resource Server)</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">授权服务器(Authorization Server)</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">客户端(Client)</li></ul><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">OAuth2包含4种授权模式</h2><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">授权码（认证码）模式 （Authorization code)</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">简化（隐形）模式 (Impilict</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">用户名密码模式 (Resource Owner Password Credential)</li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">客户端模式 (Client Credential)</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">其中，OAuth2的运行流程如下图，摘自RFC 6749：</p><div class=\\\"highlight\\\" style=\\\"box-sizing: inherit; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0;\\\"><pre style=\\\"box-sizing: inherit; margin-top: 1em; margin-bottom: 1em; padding: 10px; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace; font-size: 14px; word-wrap: normal; background: rgb(235, 238, 245);\\\"><code class=\\\"language-text\\\" style=\\\"box-sizing: inherit; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace;\\\"><span style=\\\"box-sizing: inherit;\\\"></span>+--------+                               +---------------+\\r\\n|        |--(A)- Authorization Request -&gt;|   Resource    |\\r\\n|        |                               |     Owner     |\\r\\n|        |&lt;-(B)-- Authorization Grant ---|               |\\r\\n|        |                               +---------------+\\r\\n|        |\\r\\n|        |                               +---------------+\\r\\n|        |--(C)-- Authorization Grant --&gt;| Authorization |\\r\\n| Client |                               |     Server    |\\r\\n|        |&lt;-(D)----- Access Token -------|               |\\r\\n|        |                               +---------------+\\r\\n|        |\\r\\n|        |                               +---------------+\\r\\n|        |--(E)----- Access Token ------&gt;|    Resource   |\\r\\n|        |                               |     Server    |\\r\\n|        |&lt;-(F)--- Protected Resource ---|               |\\r\\n+--------+                               +---------------+\\r\\n</code></pre></div><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">我们在Spring Cloud OAuth2中，所有访问微服务资源的请求都在Http Header中携带Token，被访问的服务接下来再去请求授权服务器验证Token的有效性，目前这种方式，我们需要两次或者更多次的请求，所有的Token有效性校验都落在的授权服务器上，对于我们系统的水平扩展成为一个非常大的瓶颈。</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">JWT认证协议</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">授权服务器将用户信息和授权范围序列化后放入一个JSON字符串，然后使用Base64进行编码，最终在授权服务器用私钥对这个字符串进行签名，得到一个JSON Web Token。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">假设其他所有的资源服务器都将持有一个RSA公钥，当资源服务器接收到这个在Http Header中存有Token的请求，资源服务器就可以拿到这个Token，并验证它是否使用正确的私钥签名（是否经过授权服务器签名，也就是验签）。验签通过，反序列化后就拿到Toekn中包含的有效验证信息。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">其中，主体运作流程图如下：</p><div class=\\\"highlight\\\" style=\\\"box-sizing: inherit; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: stretch; align-items: stretch; flex-shrink: 0;\\\"><pre style=\\\"box-sizing: inherit; margin-top: 1em; margin-bottom: 1em; padding: 10px; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace; font-size: 14px; word-wrap: normal; background: rgb(235, 238, 245);\\\"><code class=\\\"language-text\\\" style=\\\"box-sizing: inherit; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace;\\\"><span style=\\\"box-sizing: inherit;\\\"></span>+-----------+                                     +-------------+\\r\\n|           |       1-Request Authorization       |             |\\r\\n|           |------------------------------------&gt;|             |\\r\\n|           |     grant_type&amp;username&amp;password    |             |--+\\r\\n|           |                                     |Authorization|  | 2-Gen\\r\\n|           |                                     |Service      |  |   JWT\\r\\n|           |       3-Response Authorization      |             |&lt;-+\\r\\n|           |&lt;------------------------------------| Private Key |\\r\\n|           |    access_token / refresh_token     |             |\\r\\n|           |    token_type / expire_in           |             |\\r\\n|  Client   |                                     +-------------+\\r\\n|           |                                 \\r\\n|           |                                     +-------------+\\r\\n|           |       4-Request Resource            |             |\\r\\n|           |-----------------------------------&gt; |             |\\r\\n|           | Authorization: bearer Access Token  |             |--+\\r\\n|           |                                     | Resource    |  | 5-Verify\\r\\n|           |                                     | Service     |  |  Token\\r\\n|           |       6-Response Resource           |             |&lt;-+\\r\\n|           |&lt;----------------------------------- | Public Key  |\\r\\n+-----------+                                     +-------------+\\r\\n</code></pre></div><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">通过上述的方式，我们可以很好地完成服务化后的用户认证。</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">用户权限</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">传统的单体应用的权限拦截，大家都喜欢shiro，而且用的颇为顺手。可是一旦拆分后，这权限开始分散在各个API了，shiro还好使吗？笔者在项目中，并没有用shiro。前后端分离后，交互都是token，后端的服务无状态化，前端按钮资源化，权限放哪儿管好使？</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">抽象与设计</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">在介绍灵活的核心设计前，先给大家普及一个入门的概念：RBAC（Role-Based Access Control，基于角色的访问控制），就是用户通过角色与权限进行关联。简单地说，一个用户拥有若干角色，每一个角色拥有若干权限。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">RBAC其实是一种分析模型，主要分为：基本模型RBAC0（Core RBAC）、角色分层模型RBAC1（Hierarchal RBAC）、角色限制模型RBAC2（Constraint RBAC）和统一模型RBAC3（Combines RBAC）。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">更多详情大家可以了解：<a href=\\\"http://link.zhihu.com/?target=http%3A//blog.csdn.net/zwk626542417/article/details/46726491\\\" class=\\\" wrap external\\\" target=\\\"_blank\\\" rel=\\\"nofollow noreferrer\\\" style=\\\"box-sizing: inherit; color: rgb(34, 85, 153); border-bottom: 1px solid rgba(64, 64, 64, 0.72); word-break: break-all;\\\">RBAC权限模型<span class=\\\"icon-external\\\" style=\\\"box-sizing: inherit; font-size: 24px; speak: none; font-feature-settings: normal; line-height: 1; -webkit-font-smoothing: antialiased; font-family: icomoon !important;\\\"></span></a></p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">核心UML</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><img src=\\\"https://pic2.zhimg.com/v2-3e3eed438a7df522714407c5436c9bc9_b.png\\\" data-rawwidth=\\\"1168\\\" data-rawheight=\\\"532\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"1168\\\" data-original=\\\"https://pic2.zhimg.com/v2-3e3eed438a7df522714407c5436c9bc9_r.png\\\" data-actualsrc=\\\"https://pic2.zhimg.com/v2-3e3eed438a7df522714407c5436c9bc9_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">这是笔者通过多种业务场景后抽象的RBAC关系图</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">类说明</h2><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">Group</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">群或组，拥有一定数量权限的集合，亦可以是权限的载体。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">子类：User（用户）、Role（角色）、Position（岗位）、Unit（部门），通过用户的特定构成，形成不同业务场景的群或组，而通过对群或组的父类授权，完成了用户的权限获取。</p><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">Permission</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">权限，拥有一定数量资源的集成，亦可以是资源的载体。</p><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">Resources</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">权限下有资源，资源的来源有：Menu（菜单）、Button（动作权限）、页面元素（按钮、tab等）、数据权限等</p><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">Program</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">程序，相关权限控制的呈现载体，可以在多个菜单中挂载。</p><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">常见web程序基本构成</li></ul><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><img src=\\\"https://pic1.zhimg.com/v2-9f156709621fdd7685db9781829e2948_b.png\\\" data-rawwidth=\\\"873\\\" data-rawheight=\\\"492\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"873\\\" data-original=\\\"https://pic1.zhimg.com/v2-9f156709621fdd7685db9781829e2948_r.png\\\" data-actualsrc=\\\"https://pic1.zhimg.com/v2-9f156709621fdd7685db9781829e2948_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">模型与微服务的关系</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">如果把Spring Cloud服务化后的所有api接口都定义为上文的Resources，那么我们可以看到这么一个情况。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">比如一个用户的增删改查，我们的页面会这么做</p><img src=\\\"https://pic1.zhimg.com/v2-ac1fa4fc0005af11c0a7aa59fe62cbbc_b.png\\\" data-rawwidth=\\\"2880\\\" data-rawheight=\\\"1460\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"2880\\\" data-original=\\\"https://pic1.zhimg.com/v2-ac1fa4fc0005af11c0a7aa59fe62cbbc_r.png\\\" data-actualsrc=\\\"https://pic1.zhimg.com/v2-ac1fa4fc0005af11c0a7aa59fe62cbbc_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">页面元素资源编码资源URI资源请求方式查询user_btn_get/api/user/{id}GET增加user_btn_add/api/userPOST编辑user_btn_edit/api/user/{id}PUT删除user_btn_del/api/user/{id}DELETE</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">在抽象成上述的映射关系后，我们的前后端的资源有了参照，我们对于用户组的权限授权就容易了。比如我授予一个用户增加、删除权限。在前端我们只需要检验该资源编码的有无就可以控制按钮的显示和隐藏，而在后端我们只需要统一拦截判断该用户是否具有URI和对应请求方式即可。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">至于权限的统一拦截是放置在Zuul这个网关上，还是落在具体的后端服务的拦截器上（Filter、Inteceptor），都可以轻而易举地实现。不在局限于代码的侵入性。放置Zuul流程图如下：</p><img src=\\\"https://pic3.zhimg.com/v2-efbe4a2af48e48c86867a49f04759b7a_b.png\\\" data-rawwidth=\\\"1426\\\" data-rawheight=\\\"710\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"1426\\\" data-original=\\\"https://pic3.zhimg.com/v2-efbe4a2af48e48c86867a49f04759b7a_r.png\\\" data-actualsrc=\\\"https://pic3.zhimg.com/v2-efbe4a2af48e48c86867a49f04759b7a_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">要是权限的统一拦截放置在Zuul上，会有一个问题，那就是后端服务安不安全，服务只需要通过注册中心，即可对其他服务进行调用。这里就涉及到后面的第三个模块，服务之间的鉴权。</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">服务之间的鉴权</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">因为我们都知道服务之间开源通过注册中心寻到客户端后，直接远程过程调用的。对于生产上的各个服务，一个个敏感性的接口，我们更是需要加以保护。主题的流程如下图：</p><img src=\\\"https://pic4.zhimg.com/v2-2c574cb730d4e02834e238d0f7fc40eb_b.png\\\" data-rawwidth=\\\"1700\\\" data-rawheight=\\\"926\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"1700\\\" data-original=\\\"https://pic4.zhimg.com/v2-2c574cb730d4e02834e238d0f7fc40eb_r.png\\\" data-actualsrc=\\\"https://pic4.zhimg.com/v2-2c574cb730d4e02834e238d0f7fc40eb_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">笔者的实现方式是基于Spring Cloud的FeignClient Inteceprot（自动申请服务token、传递当前上下文）和Mvc Inteceptor（服务token校验、更新当前上下文）来实现，从而对服务的安全性做进一步保护。</p><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">结合Spring Cloud的特性后，整体流程图如下：</p><img src=\\\"https://pic1.zhimg.com/v2-467d442498d0ed41372a7567fc36a714_b.png\\\" data-rawwidth=\\\"2182\\\" data-rawheight=\\\"1638\\\" class=\\\"origin_image zh-lightbox-thumb lazy\\\" width=\\\"2182\\\" data-original=\\\"https://pic1.zhimg.com/v2-467d442498d0ed41372a7567fc36a714_r.png\\\" data-actualsrc=\\\"https://pic1.zhimg.com/v2-467d442498d0ed41372a7567fc36a714_b.png\\\" style=\\\"box-sizing: inherit; overflow: hidden; display: block; max-width: 100%; margin: 24px auto; cursor: -webkit-zoom-in;\\\"><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\"><br style=\\\"box-sizing: inherit;\\\"></p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">优化点</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">虽然通过上述的用户合法性检验、用户权限拦截以及服务之间的鉴权，保证了Api接口的安全性，但是其间的Http访问频率是比较高的，请求数量上来的时候，慢的问题是就会特别明显。可以考虑一定的优化策略，比如用户权限缓存、服务授权信息的派发与混存、定时刷新服务鉴权Token等。</p><h2 style=\\\"box-sizing: inherit; margin: 20px 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;\\\">结语</h2><p style=\\\"box-sizing: inherit; margin-top: 20px; margin-bottom: 20px;\\\">上述是笔者在项目里的大体思路，有兴趣的朋友可以借鉴我的开源项目，欢迎star：</p><ul style=\\\"box-sizing: inherit; margin: 20px 0px; padding: 0px 0px 0px 40px;\\\"><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">gitchina：<a href=\\\"http://link.zhihu.com/?target=http%3A//git.oschina.net/geek_qi/ace-security%25EF%25BC%2588Jwt%25E3%2580%2581%25E7%2594%25A8%25E6%2588%25B7%25E6%259D%2583%25E9%2599%2590%25EF%25BC%2589\\\" class=\\\" wrap external\\\" target=\\\"_blank\\\" rel=\\\"nofollow noreferrer\\\" style=\\\"box-sizing: inherit; color: rgb(34, 85, 153); border-bottom: 1px solid rgba(64, 64, 64, 0.72); word-break: break-all;\\\">http://git.oschina.net/geek_qi/ace-security（Jwt、用户权限）<span class=\\\"icon-external\\\" style=\\\"box-sizing: inherit; font-size: 24px; speak: none; font-feature-settings: normal; line-height: 1; -webkit-font-smoothing: antialiased; font-family: icomoon !important;\\\"></span></a></li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">github：<a href=\\\"http://link.zhihu.com/?target=https%3A//github.com/wxiaoqi/ace-security\\\" class=\\\" external\\\" target=\\\"_blank\\\" rel=\\\"nofollow noreferrer\\\" style=\\\"box-sizing: inherit; color: rgb(34, 85, 153); border-bottom: 1px solid rgba(64, 64, 64, 0.72); word-break: break-all;\\\"><span class=\\\"invisible\\\" style=\\\"box-sizing: inherit; font-stretch: normal; font-size: 0px; line-height: 0; font-family: a; color: transparent; text-shadow: none; background-color: transparent;\\\">https://</span><span class=\\\"visible\\\" style=\\\"box-sizing: inherit;\\\">github.com/wxiaoqi/ace-</span><span class=\\\"invisible\\\" style=\\\"box-sizing: inherit; font-stretch: normal; font-size: 0px; line-height: 0; font-family: a; color: transparent; text-shadow: none; background-color: transparent;\\\">security</span><span class=\\\"ellipsis\\\" style=\\\"box-sizing: inherit;\\\"></span><span class=\\\"icon-external\\\" style=\\\"box-sizing: inherit; font-size: 24px; speak: none; font-feature-settings: normal; line-height: 1; -webkit-font-smoothing: antialiased; font-family: icomoon !important;\\\"></span></a></li><li style=\\\"box-sizing: inherit; list-style-type: initial; margin-top: 10px; list-style-position: outside;\\\">gitchina：<a href=\\\"http://link.zhihu.com/?target=http%3A//git.oschina.net/geek_qi/ace-gate%25EF%25BC%2588%25E6%259C%258D%25E5%258A%25A1%25E9%2589%25B4%25E6%259D%2583%25EF%25BC%2589\\\" class=\\\" wrap external\\\" target=\\\"_blank\\\" rel=\\\"nofollow noreferrer\\\" style=\\\"box-sizing: inherit; color: rgb(34, 85, 153); border-bottom: 1px solid rgba(64, 64, 64, 0.72); word-break: break-all;\\\">http://git.oschina.net/geek_qi/ace-gate（服务鉴权）</a></li></ul></div></div>', 'article', null, '', null, null, '1', null, '0', '1', 'bootdo', '2017-10-25 12:28:19', '2017-10-25 12:28:19');\n\n-- ----------------------------\n-- Table structure for oa_notify\n-- ----------------------------\nDROP TABLE IF EXISTS `oa_notify`;\nCREATE TABLE `oa_notify` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n  `type` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '类型',\n  `title` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '标题',\n  `content` varchar(2000) COLLATE utf8_bin DEFAULT NULL COMMENT '内容',\n  `files` varchar(2000) COLLATE utf8_bin DEFAULT NULL COMMENT '附件',\n  `status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '状态',\n  `create_by` bigint(20) DEFAULT NULL COMMENT '创建者',\n  `create_date` datetime DEFAULT NULL COMMENT '创建时间',\n  `update_by` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '更新者',\n  `update_date` datetime DEFAULT NULL COMMENT '更新时间',\n  `remarks` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '备注信息',\n  `del_flag` char(1) COLLATE utf8_bin DEFAULT '0' COMMENT '删除标记',\n  PRIMARY KEY (`id`),\n  KEY `oa_notify_del_flag` (`del_flag`)\n) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='通知通告';\n\n-- ----------------------------\n-- Records of oa_notify\n-- ----------------------------\nINSERT INTO `oa_notify` VALUES ('41', '3', '十九大召开了', '十九大召开了，竟然没邀请我', '', '1', '1', null, null, '2017-10-10 17:21:11', '', null);\nINSERT INTO `oa_notify` VALUES ('42', '3', '苹果发布新手机了', '有全面屏的iphoneX', '', '1', '1', null, null, '2017-10-10 18:51:14', '', null);\nINSERT INTO `oa_notify` VALUES ('43', '3', '十九大要消灭贫困人口', '我还只有两三年的活头了', '', '1', '1', null, null, '2017-10-11 09:56:35', '', null);\nINSERT INTO `oa_notify` VALUES ('44', '3', '骑士又输了', '捉急', '', '1', '1', null, null, '2017-10-26 13:59:34', '', null);\nINSERT INTO `oa_notify` VALUES ('45', '3', '火箭5连败', '没有保罗不行呀', '', '1', '1', null, null, '2017-12-30 12:10:20', '', null);\n\n-- ----------------------------\n-- Table structure for oa_notify_record\n-- ----------------------------\nDROP TABLE IF EXISTS `oa_notify_record`;\nCREATE TABLE `oa_notify_record` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n  `notify_id` bigint(20) DEFAULT NULL COMMENT '通知通告ID',\n  `user_id` bigint(20) DEFAULT NULL COMMENT '接受人',\n  `is_read` tinyint(1) DEFAULT '0' COMMENT '阅读标记',\n  `read_date` date DEFAULT NULL COMMENT '阅读时间',\n  PRIMARY KEY (`id`),\n  KEY `oa_notify_record_notify_id` (`notify_id`),\n  KEY `oa_notify_record_user_id` (`user_id`),\n  KEY `oa_notify_record_read_flag` (`is_read`)\n) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='通知通告发送记录';\n\n-- ----------------------------\n-- Records of oa_notify_record\n-- ----------------------------\nINSERT INTO `oa_notify_record` VALUES ('18', '41', '1', '1', '2017-10-26');\nINSERT INTO `oa_notify_record` VALUES ('19', '42', '1', '1', '2017-10-26');\nINSERT INTO `oa_notify_record` VALUES ('20', '43', '136', '0', null);\nINSERT INTO `oa_notify_record` VALUES ('21', '43', '133', '0', null);\nINSERT INTO `oa_notify_record` VALUES ('22', '43', '130', '0', null);\nINSERT INTO `oa_notify_record` VALUES ('23', '43', '1', '1', '2017-10-26');\nINSERT INTO `oa_notify_record` VALUES ('24', '44', '1', '1', '2017-12-29');\nINSERT INTO `oa_notify_record` VALUES ('25', '45', '1', '1', '2018-01-07');\nINSERT INTO `oa_notify_record` VALUES ('26', '45', '135', '0', null);\n\n-- ----------------------------\n-- Table structure for salary\n-- ----------------------------\nDROP TABLE IF EXISTS `salary`;\nCREATE TABLE `salary` (\n  `id` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '编号',\n  `PROC_INS_ID` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '流程实例ID',\n  `USER_ID` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '变动用户',\n  `OFFICE_ID` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '归属部门',\n  `POST` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '岗位',\n  `AGE` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '性别',\n  `EDU` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '学历',\n  `CONTENT` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '调整原因',\n  `OLDA` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '现行标准 薪酬档级',\n  `OLDB` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '现行标准 月工资额',\n  `OLDC` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '现行标准 年薪总额',\n  `NEWA` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '调整后标准 薪酬档级',\n  `NEWB` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '调整后标准 月工资额',\n  `NEWC` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '调整后标准 年薪总额',\n  `ADD_NUM` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '月增资',\n  `EXE_DATE` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '执行时间',\n  `HR_TEXT` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '人力资源部门意见',\n  `LEAD_TEXT` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '分管领导意见',\n  `MAIN_LEAD_TEXT` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '集团主要领导意见',\n  `create_by` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '创建者',\n  `create_date` datetime NOT NULL COMMENT '创建时间',\n  `update_by` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '更新者',\n  `update_date` datetime NOT NULL COMMENT '更新时间',\n  `remarks` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '备注信息',\n  `del_flag` char(1) COLLATE utf8_bin NOT NULL DEFAULT '0' COMMENT '删除标记',\n  PRIMARY KEY (`id`),\n  KEY `OA_TEST_AUDIT_del_flag` (`del_flag`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='审批流程测试表';\n\n-- ----------------------------\n-- Records of salary\n-- ----------------------------\nINSERT INTO `salary` VALUES ('825693cd6c1c4f6b86699fc3f1a54887', '', '136', '', '', '', '', '技能提高', '', '', '', '', '100', '', '', '', '同意', '同意', '总经理审批', '1', '2017-12-15 22:01:41', '1', '2017-12-15 22:01:41', null, '1');\nINSERT INTO `salary` VALUES ('a80e1d9ef35a4502bd65b0e5ba7eafff', '', 'cccc', 'ccc', 'ccccc', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '2017-11-30 16:35:15', '', '2017-11-30 16:35:15', '', '');\nINSERT INTO `salary` VALUES ('b5d228f729f74833883917825749f0d5', '', '', '', '', '', '', '', '', '', '', '', '', '防守打法', '', '', '', '', '', '', '2017-11-30 19:58:36', '', '2017-11-30 19:58:36', '', '');\nINSERT INTO `salary` VALUES ('cc2e8083f9d8478f831b2ea852e5c17b', '', '', 'cc', 'cc', '', '', 'xxx', '', '', '', '', '', '', '', '', '', '', '', '', '2017-11-30 19:18:59', '', '2017-11-30 19:18:59', '', '');\nINSERT INTO `salary` VALUES ('cebdb316794b48be87d93dd4dbfb7d4b', '', '', '', '发的顺丰', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '2017-11-30 19:58:43', '', '2017-11-30 19:58:43', '', '');\n\n-- ----------------------------\n-- Table structure for sys_dept\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_dept`;\nCREATE TABLE `sys_dept` (\n  `dept_id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `parent_id` bigint(20) DEFAULT NULL COMMENT '上级部门ID，一级部门为0',\n  `name` varchar(50) DEFAULT NULL COMMENT '部门名称',\n  `order_num` int(11) DEFAULT NULL COMMENT '排序',\n  `del_flag` tinyint(4) DEFAULT '0' COMMENT '是否删除  -1：已删除  0：正常',\n  PRIMARY KEY (`dept_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='部门管理';\n\n-- ----------------------------\n-- Records of sys_dept\n-- ----------------------------\nINSERT INTO `sys_dept` VALUES ('6', '0', '总部', '1', '1');\nINSERT INTO `sys_dept` VALUES ('9', '0', '销售部', '2', '1');\nINSERT INTO `sys_dept` VALUES ('11', '0', '仓储', '3', '1');\n\n-- ----------------------------\n-- Table structure for sys_dict\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_dict`;\nCREATE TABLE `sys_dict` (\n  `id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '编号',\n  `name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '标签名',\n  `value` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '数据值',\n  `type` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '类型',\n  `description` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '描述',\n  `sort` decimal(10,0) DEFAULT NULL COMMENT '排序（升序）',\n  `parent_id` bigint(64) DEFAULT '0' COMMENT '父级编号',\n  `create_by` int(64) DEFAULT NULL COMMENT '创建者',\n  `create_date` datetime DEFAULT NULL COMMENT '创建时间',\n  `update_by` bigint(64) DEFAULT NULL COMMENT '更新者',\n  `update_date` datetime DEFAULT NULL COMMENT '更新时间',\n  `remarks` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '备注信息',\n  `del_flag` char(1) COLLATE utf8_bin DEFAULT '0' COMMENT '删除标记',\n  PRIMARY KEY (`id`),\n  KEY `sys_dict_value` (`value`),\n  KEY `sys_dict_label` (`name`),\n  KEY `sys_dict_del_flag` (`del_flag`)\n) ENGINE=InnoDB AUTO_INCREMENT=123 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='字典表';\n\n-- ----------------------------\n-- Records of sys_dict\n-- ----------------------------\nINSERT INTO `sys_dict` VALUES ('1', '正常', '0', 'del_flag', '删除标记', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('3', '显示', '1', 'show_hide', '显示/隐藏', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('4', '隐藏', '0', 'show_hide', '显示/隐藏', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('5', '是', '1', 'yes_no', '是/否', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('6', '否', '0', 'yes_no', '是/否', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('7', '红色', 'red', 'color', '颜色值', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('8', '绿色', 'green', 'color', '颜色值', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('9', '蓝色', 'blue', 'color', '颜色值', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('10', '黄色', 'yellow', 'color', '颜色值', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('11', '橙色', 'orange', 'color', '颜色值', '50', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('12', '默认主题', 'default', 'theme', '主题方案', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('13', '天蓝主题', 'cerulean', 'theme', '主题方案', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('14', '橙色主题', 'readable', 'theme', '主题方案', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('15', '红色主题', 'united', 'theme', '主题方案', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('16', 'Flat主题', 'flat', 'theme', '主题方案', '60', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('17', '国家', '1', 'sys_area_type', '区域类型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('18', '省份、直辖市', '2', 'sys_area_type', '区域类型', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('19', '地市', '3', 'sys_area_type', '区域类型', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('20', '区县', '4', 'sys_area_type', '区域类型', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('21', '公司', '1', 'sys_office_type', '机构类型', '60', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('22', '部门', '2', 'sys_office_type', '机构类型', '70', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('23', '小组', '3', 'sys_office_type', '机构类型', '80', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('24', '其它', '4', 'sys_office_type', '机构类型', '90', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('25', '综合部', '1', 'sys_office_common', '快捷通用部门', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('26', '开发部', '2', 'sys_office_common', '快捷通用部门', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('27', '人力部', '3', 'sys_office_common', '快捷通用部门', '50', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('28', '一级', '1', 'sys_office_grade', '机构等级', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('29', '二级', '2', 'sys_office_grade', '机构等级', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('30', '三级', '3', 'sys_office_grade', '机构等级', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('31', '四级', '4', 'sys_office_grade', '机构等级', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('32', '所有数据', '1', 'sys_data_scope', '数据范围', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('33', '所在公司及以下数据', '2', 'sys_data_scope', '数据范围', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('34', '所在公司数据', '3', 'sys_data_scope', '数据范围', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('35', '所在部门及以下数据', '4', 'sys_data_scope', '数据范围', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('36', '所在部门数据', '5', 'sys_data_scope', '数据范围', '50', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('37', '仅本人数据', '8', 'sys_data_scope', '数据范围', '90', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('38', '按明细设置', '9', 'sys_data_scope', '数据范围', '100', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('39', '系统管理', '1', 'sys_user_type', '用户类型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('40', '部门经理', '2', 'sys_user_type', '用户类型', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('41', '普通用户', '3', 'sys_user_type', '用户类型', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('42', '基础主题', 'basic', 'cms_theme', '站点主题', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('43', '蓝色主题', 'blue', 'cms_theme', '站点主题', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('44', '红色主题', 'red', 'cms_theme', '站点主题', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('45', '文章模型', 'article', 'cms_module', '栏目模型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('46', '图片模型', 'picture', 'cms_module', '栏目模型', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('47', '下载模型', 'download', 'cms_module', '栏目模型', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('48', '链接模型', 'link', 'cms_module', '栏目模型', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('49', '专题模型', 'special', 'cms_module', '栏目模型', '50', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('50', '默认展现方式', '0', 'cms_show_modes', '展现方式', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('51', '首栏目内容列表', '1', 'cms_show_modes', '展现方式', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('52', '栏目第一条内容', '2', 'cms_show_modes', '展现方式', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('53', '发布', '0', 'cms_del_flag', '内容状态', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('54', '删除', '1', 'cms_del_flag', '内容状态', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('55', '审核', '2', 'cms_del_flag', '内容状态', '15', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('56', '首页焦点图', '1', 'cms_posid', '推荐位', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('57', '栏目页文章推荐', '2', 'cms_posid', '推荐位', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('58', '咨询', '1', 'cms_guestbook', '留言板分类', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('59', '建议', '2', 'cms_guestbook', '留言板分类', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('60', '投诉', '3', 'cms_guestbook', '留言板分类', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('61', '其它', '4', 'cms_guestbook', '留言板分类', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('62', '公休', '1', 'oa_leave_type', '请假类型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('63', '病假', '2', 'oa_leave_type', '请假类型', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('64', '事假', '3', 'oa_leave_type', '请假类型', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('65', '调休', '4', 'oa_leave_type', '请假类型', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('66', '婚假', '5', 'oa_leave_type', '请假类型', '60', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('67', '接入日志', '1', 'sys_log_type', '日志类型', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('68', '异常日志', '2', 'sys_log_type', '日志类型', '40', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('69', '请假流程', 'leave', 'act_type', '流程类型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('70', '审批测试流程', 'test_audit', 'act_type', '流程类型', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('71', '分类1', '1', 'act_category', '流程分类', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('72', '分类2', '2', 'act_category', '流程分类', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('73', '增删改查', 'crud', 'gen_category', '代码生成分类', '10', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('74', '增删改查（包含从表）', 'crud_many', 'gen_category', '代码生成分类', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('75', '树结构', 'tree', 'gen_category', '代码生成分类', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('76', '=', '=', 'gen_query_type', '查询方式', '10', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('77', '!=', '!=', 'gen_query_type', '查询方式', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('78', '&gt;', '&gt;', 'gen_query_type', '查询方式', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('79', '&lt;', '&lt;', 'gen_query_type', '查询方式', '40', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('80', 'Between', 'between', 'gen_query_type', '查询方式', '50', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('81', 'Like', 'like', 'gen_query_type', '查询方式', '60', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('82', 'Left Like', 'left_like', 'gen_query_type', '查询方式', '70', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('83', 'Right Like', 'right_like', 'gen_query_type', '查询方式', '80', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('84', '文本框', 'input', 'gen_show_type', '字段生成方案', '10', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('85', '文本域', 'textarea', 'gen_show_type', '字段生成方案', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('86', '下拉框', 'select', 'gen_show_type', '字段生成方案', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('87', '复选框', 'checkbox', 'gen_show_type', '字段生成方案', '40', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('88', '单选框', 'radiobox', 'gen_show_type', '字段生成方案', '50', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('89', '日期选择', 'dateselect', 'gen_show_type', '字段生成方案', '60', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('90', '人员选择', 'userselect', 'gen_show_type', '字段生成方案', '70', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('91', '部门选择', 'officeselect', 'gen_show_type', '字段生成方案', '80', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('92', '区域选择', 'areaselect', 'gen_show_type', '字段生成方案', '90', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('93', 'String', 'String', 'gen_java_type', 'Java类型', '10', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('94', 'Long', 'Long', 'gen_java_type', 'Java类型', '20', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('95', '仅持久层', 'dao', 'gen_category', '代码生成分类', '40', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('96', '男', '1', 'sex', '性别', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('97', '女', '2', 'sex', '性别', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('98', 'Integer', 'Integer', 'gen_java_type', 'Java类型', '30', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('99', 'Double', 'Double', 'gen_java_type', 'Java类型', '40', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('100', 'Date', 'java.util.Date', 'gen_java_type', 'Java类型', '50', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('104', 'Custom', 'Custom', 'gen_java_type', 'Java类型', '90', '0', '1', null, '1', null, null, '1');\nINSERT INTO `sys_dict` VALUES ('105', '会议通告', '1', 'oa_notify_type', '通知通告类型', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('106', '奖惩通告', '2', 'oa_notify_type', '通知通告类型', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('107', '活动通告', '3', 'oa_notify_type', '通知通告类型', '30', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('108', '草稿', '0', 'oa_notify_status', '通知通告状态', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('109', '发布', '1', 'oa_notify_status', '通知通告状态', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('110', '未读', '0', 'oa_notify_read', '通知通告状态', '10', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('111', '已读', '1', 'oa_notify_read', '通知通告状态', '20', '0', '1', null, '1', null, null, '0');\nINSERT INTO `sys_dict` VALUES ('112', '草稿', '0', 'oa_notify_status', '通知通告状态', '10', '0', '1', null, '1', null, '', '0');\nINSERT INTO `sys_dict` VALUES ('113', '删除', '0', 'del_flag', '删除标记', null, null, null, null, null, null, '', '');\nINSERT INTO `sys_dict` VALUES ('118', '关于', 'about', 'blog_type', '博客类型', null, null, null, null, null, null, '全url是:/blog/open/page/about', '');\nINSERT INTO `sys_dict` VALUES ('119', '交流', 'communication', 'blog_type', '博客类型', null, null, null, null, null, null, '', '');\nINSERT INTO `sys_dict` VALUES ('120', '文章', 'article', 'blog_type', '博客类型', null, null, null, null, null, null, '', '');\nINSERT INTO `sys_dict` VALUES ('121', '编码', 'code', 'hobby', '爱好', null, null, null, null, null, null, '', '');\nINSERT INTO `sys_dict` VALUES ('122', '绘画', 'painting', 'hobby', '爱好', null, null, null, null, null, null, '', '');\n\n-- ----------------------------\n-- Table structure for sys_file\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_file`;\nCREATE TABLE `sys_file` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `type` int(11) DEFAULT NULL COMMENT '文件类型',\n  `url` varchar(200) DEFAULT NULL COMMENT 'URL地址',\n  `create_date` datetime DEFAULT NULL COMMENT '创建时间',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文件上传';\n\n-- ----------------------------\n-- Records of sys_file\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for sys_log\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_log`;\nCREATE TABLE `sys_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_id` bigint(20) DEFAULT NULL COMMENT '用户id',\n  `username` varchar(50) DEFAULT NULL COMMENT '用户名',\n  `operation` varchar(50) DEFAULT NULL COMMENT '用户操作',\n  `time` int(11) DEFAULT NULL COMMENT '响应时间',\n  `method` varchar(200) DEFAULT NULL COMMENT '请求方法',\n  `params` varchar(5000) DEFAULT NULL COMMENT '请求参数',\n  `ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=757 DEFAULT CHARSET=utf8 COMMENT='系统日志';\n\n-- ----------------------------\n-- Records of sys_log\n-- ----------------------------\nINSERT INTO `sys_log` VALUES ('609', '1', 'admin', '登录', '22', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:30:31');\nINSERT INTO `sys_log` VALUES ('610', '1', 'admin', '请求访问主页', '64', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:30:31');\nINSERT INTO `sys_log` VALUES ('611', '1', 'admin', 'error', null, 'http://localhost:8086/index', 'org.springframework.web.HttpRequestMethodNotSupportedException: Request method \\'POST\\' not supported', null, '2018-04-04 17:32:56');\nINSERT INTO `sys_log` VALUES ('612', '1', 'admin', '请求访问主页', '16', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:32:57');\nINSERT INTO `sys_log` VALUES ('613', '1', 'admin', '请求访问主页', '15', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:34:15');\nINSERT INTO `sys_log` VALUES ('614', '1', 'admin', '请求访问主页', '16', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:34:18');\nINSERT INTO `sys_log` VALUES ('615', '1', 'admin', '请求访问主页', '13', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:34:20');\nINSERT INTO `sys_log` VALUES ('616', '1', 'admin', '请求访问主页', '17', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:34:21');\nINSERT INTO `sys_log` VALUES ('617', '1', 'admin', '登录', '16', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:37:09');\nINSERT INTO `sys_log` VALUES ('618', '1', 'admin', '请求访问主页', '86', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:37:10');\nINSERT INTO `sys_log` VALUES ('619', '1', 'admin', '登录', '15', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:42:08');\nINSERT INTO `sys_log` VALUES ('620', '1', 'admin', '请求访问主页', '140', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:42:08');\nINSERT INTO `sys_log` VALUES ('621', '1', 'admin', '登录', '7', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:42:30');\nINSERT INTO `sys_log` VALUES ('622', '1', 'admin', '请求访问主页', '20', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:42:30');\nINSERT INTO `sys_log` VALUES ('623', '1', 'admin', '编辑角色', '6', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:44:33');\nINSERT INTO `sys_log` VALUES ('624', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:44:59');\nINSERT INTO `sys_log` VALUES ('625', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:45:05');\nINSERT INTO `sys_log` VALUES ('626', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:45:12');\nINSERT INTO `sys_log` VALUES ('627', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:45:14');\nINSERT INTO `sys_log` VALUES ('628', '1', 'admin', '添加用户', '3', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:46:11');\nINSERT INTO `sys_log` VALUES ('629', '1', 'admin', '添加用户', '2', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:46:37');\nINSERT INTO `sys_log` VALUES ('630', '1', 'admin', '删除用户', '93', 'me.zbl.system.controller.UserController.remove()', null, '127.0.0.1', '2018-04-04 17:46:41');\nINSERT INTO `sys_log` VALUES ('631', '1', 'admin', '批量删除用户', '84', 'me.zbl.system.controller.UserController.batchRemove()', null, '127.0.0.1', '2018-04-04 17:46:51');\nINSERT INTO `sys_log` VALUES ('632', '1', 'admin', '添加用户', '6', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:46:54');\nINSERT INTO `sys_log` VALUES ('633', '1', 'admin', '编辑用户', '51', 'me.zbl.system.controller.UserController.edit()', null, '127.0.0.1', '2018-04-04 17:48:48');\nINSERT INTO `sys_log` VALUES ('634', '1', 'admin', '更新用户', '54', 'me.zbl.system.controller.UserController.update()', null, '127.0.0.1', '2018-04-04 17:48:58');\nINSERT INTO `sys_log` VALUES ('635', '1', 'admin', '编辑用户', '14', 'me.zbl.system.controller.UserController.edit()', null, '127.0.0.1', '2018-04-04 17:49:26');\nINSERT INTO `sys_log` VALUES ('636', '1', 'admin', '更新用户', '145', 'me.zbl.system.controller.UserController.update()', null, '127.0.0.1', '2018-04-04 17:49:28');\nINSERT INTO `sys_log` VALUES ('637', '1', 'admin', '添加角色', '0', 'me.zbl.system.controller.RoleController.add()', null, '127.0.0.1', '2018-04-04 17:50:07');\nINSERT INTO `sys_log` VALUES ('638', '1', 'admin', '保存角色', '113', 'me.zbl.system.controller.RoleController.save()', null, '127.0.0.1', '2018-04-04 17:50:30');\nINSERT INTO `sys_log` VALUES ('639', '1', 'admin', '编辑角色', '3', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:50:37');\nINSERT INTO `sys_log` VALUES ('640', '1', 'admin', '更新角色', '107', 'me.zbl.system.controller.RoleController.update()', null, '127.0.0.1', '2018-04-04 17:51:02');\nINSERT INTO `sys_log` VALUES ('641', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:51:16');\nINSERT INTO `sys_log` VALUES ('642', '1', 'admin', '添加用户', '2', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:51:24');\nINSERT INTO `sys_log` VALUES ('643', '1', 'admin', '保存用户', '82', 'me.zbl.system.controller.UserController.save()', null, '127.0.0.1', '2018-04-04 17:52:33');\nINSERT INTO `sys_log` VALUES ('644', '-1', '获取用户信息为空', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:52:45');\nINSERT INTO `sys_log` VALUES ('645', '138', 'administrator', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:52:49');\nINSERT INTO `sys_log` VALUES ('646', '138', 'administrator', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:52:49');\nINSERT INTO `sys_log` VALUES ('647', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:53:00');\nINSERT INTO `sys_log` VALUES ('648', '1', 'admin', '请求访问主页', '82', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:53:00');\nINSERT INTO `sys_log` VALUES ('649', '1', 'admin', '添加用户', '5', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:53:15');\nINSERT INTO `sys_log` VALUES ('650', '1', 'admin', '编辑用户', '14', 'me.zbl.system.controller.UserController.edit()', null, '127.0.0.1', '2018-04-04 17:53:39');\nINSERT INTO `sys_log` VALUES ('651', '1', 'admin', '删除用户', '87', 'me.zbl.system.controller.UserController.remove()', null, '127.0.0.1', '2018-04-04 17:53:56');\nINSERT INTO `sys_log` VALUES ('652', '1', 'admin', '添加用户', '2', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:53:58');\nINSERT INTO `sys_log` VALUES ('653', '1', 'admin', '保存用户', '84', 'me.zbl.system.controller.UserController.save()', null, '127.0.0.1', '2018-04-04 17:54:18');\nINSERT INTO `sys_log` VALUES ('654', '-1', '获取用户信息为空', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:54:23');\nINSERT INTO `sys_log` VALUES ('655', '139', 'admin2', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 17:54:27');\nINSERT INTO `sys_log` VALUES ('656', '139', 'admin2', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 17:54:27');\nINSERT INTO `sys_log` VALUES ('657', '139', 'admin2', '添加用户', '3', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 17:55:33');\nINSERT INTO `sys_log` VALUES ('658', '139', 'admin2', '保存用户', '115', 'me.zbl.system.controller.UserController.save()', null, '127.0.0.1', '2018-04-04 17:56:22');\nINSERT INTO `sys_log` VALUES ('659', '139', 'admin2', '编辑角色', '4', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 17:56:47');\nINSERT INTO `sys_log` VALUES ('660', '1', 'admin', '登录', '5', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:03:11');\nINSERT INTO `sys_log` VALUES ('661', '1', 'admin', '请求访问主页', '47', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:03:11');\nINSERT INTO `sys_log` VALUES ('662', '1', 'admin', '请求访问主页', '7', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:03:53');\nINSERT INTO `sys_log` VALUES ('663', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:04:09');\nINSERT INTO `sys_log` VALUES ('664', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:04:29');\nINSERT INTO `sys_log` VALUES ('665', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:05:10');\nINSERT INTO `sys_log` VALUES ('666', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:05:24');\nINSERT INTO `sys_log` VALUES ('667', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:05:38');\nINSERT INTO `sys_log` VALUES ('668', '1', 'admin', '请求访问主页', '11', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:06:13');\nINSERT INTO `sys_log` VALUES ('669', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:06:15');\nINSERT INTO `sys_log` VALUES ('670', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:06:25');\nINSERT INTO `sys_log` VALUES ('671', '1', 'admin', '请求访问主页', '47', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:06:48');\nINSERT INTO `sys_log` VALUES ('672', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:07:14');\nINSERT INTO `sys_log` VALUES ('673', '1', 'admin', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:07:17');\nINSERT INTO `sys_log` VALUES ('674', '1', 'admin', '请求访问主页', '15', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:07:17');\nINSERT INTO `sys_log` VALUES ('675', '1', 'admin', '登录', '4', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:07:40');\nINSERT INTO `sys_log` VALUES ('676', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:07:40');\nINSERT INTO `sys_log` VALUES ('677', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:11:08');\nINSERT INTO `sys_log` VALUES ('678', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:12:49');\nINSERT INTO `sys_log` VALUES ('679', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:14:51');\nINSERT INTO `sys_log` VALUES ('680', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:20:11');\nINSERT INTO `sys_log` VALUES ('681', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:20:19');\nINSERT INTO `sys_log` VALUES ('682', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:20:19');\nINSERT INTO `sys_log` VALUES ('683', '1', 'admin', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:20:23');\nINSERT INTO `sys_log` VALUES ('684', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:20:23');\nINSERT INTO `sys_log` VALUES ('685', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:20:43');\nINSERT INTO `sys_log` VALUES ('686', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:20:47');\nINSERT INTO `sys_log` VALUES ('687', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:20:47');\nINSERT INTO `sys_log` VALUES ('688', '1', 'admin', '登录', '4', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:28:31');\nINSERT INTO `sys_log` VALUES ('689', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:28:31');\nINSERT INTO `sys_log` VALUES ('690', '-1', '获取用户信息为空', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:34:40');\nINSERT INTO `sys_log` VALUES ('691', '-1', '获取用户信息为空', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:34:42');\nINSERT INTO `sys_log` VALUES ('692', '-1', '获取用户信息为空', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:35:00');\nINSERT INTO `sys_log` VALUES ('693', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 18:35:04');\nINSERT INTO `sys_log` VALUES ('694', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:35:04');\nINSERT INTO `sys_log` VALUES ('695', '1', 'admin', '请求访问主页', '7', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:35:36');\nINSERT INTO `sys_log` VALUES ('696', '1', 'admin', '更新用户', '67', 'me.zbl.system.controller.UserController.updatePeronal()', null, '127.0.0.1', '2018-04-04 18:37:43');\nINSERT INTO `sys_log` VALUES ('697', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:39:00');\nINSERT INTO `sys_log` VALUES ('698', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:39:14');\nINSERT INTO `sys_log` VALUES ('699', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:39:33');\nINSERT INTO `sys_log` VALUES ('700', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:40:53');\nINSERT INTO `sys_log` VALUES ('701', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:41:17');\nINSERT INTO `sys_log` VALUES ('702', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:41:57');\nINSERT INTO `sys_log` VALUES ('703', '1', 'admin', '请求访问主页', '11', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:42:13');\nINSERT INTO `sys_log` VALUES ('704', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:42:18');\nINSERT INTO `sys_log` VALUES ('705', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:43:12');\nINSERT INTO `sys_log` VALUES ('706', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:43:37');\nINSERT INTO `sys_log` VALUES ('707', '1', 'admin', '请求访问主页', '8', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:43:57');\nINSERT INTO `sys_log` VALUES ('708', '1', 'admin', '请求访问主页', '10', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:44:11');\nINSERT INTO `sys_log` VALUES ('709', '1', 'admin', '请求访问主页', '7', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:44:14');\nINSERT INTO `sys_log` VALUES ('710', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:49:54');\nINSERT INTO `sys_log` VALUES ('711', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:50:34');\nINSERT INTO `sys_log` VALUES ('712', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:50:48');\nINSERT INTO `sys_log` VALUES ('713', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:52:00');\nINSERT INTO `sys_log` VALUES ('714', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:53:23');\nINSERT INTO `sys_log` VALUES ('715', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:53:39');\nINSERT INTO `sys_log` VALUES ('716', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 18:57:02');\nINSERT INTO `sys_log` VALUES ('717', '1', 'admin', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 20:06:31');\nINSERT INTO `sys_log` VALUES ('718', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:06:31');\nINSERT INTO `sys_log` VALUES ('719', '1', 'admin', 'error', null, 'http://localhost:8086/common/sysFile/remove', 'java.lang.NullPointerException', null, '2018-04-04 20:06:51');\nINSERT INTO `sys_log` VALUES ('720', '1', 'admin', 'error', null, 'http://localhost:8086/common/sysFile/info/%7Bid%7D', 'org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type \\'java.lang.String\\' to required type \\'java.lang.Long\\'; nested exception is java.lang.NumberFormatException: For input string: \\\"{id}\\\"', null, '2018-04-04 20:12:27');\nINSERT INTO `sys_log` VALUES ('721', '1', 'admin', '登录', '3', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 20:12:45');\nINSERT INTO `sys_log` VALUES ('722', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:12:45');\nINSERT INTO `sys_log` VALUES ('723', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 20:12:53');\nINSERT INTO `sys_log` VALUES ('724', '1', 'admin', '请求访问主页', '4', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:12:53');\nINSERT INTO `sys_log` VALUES ('725', '1', 'admin', '登录', '2', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 20:25:32');\nINSERT INTO `sys_log` VALUES ('726', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:25:32');\nINSERT INTO `sys_log` VALUES ('727', '1', 'admin', '请求访问主页', '4', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:25:36');\nINSERT INTO `sys_log` VALUES ('728', '1', 'admin', '请求访问主页', '5', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:25:38');\nINSERT INTO `sys_log` VALUES ('729', '1', 'admin', '添加用户', '2', 'me.zbl.system.controller.UserController.add()', null, '127.0.0.1', '2018-04-04 20:31:06');\nINSERT INTO `sys_log` VALUES ('730', '1', 'admin', '请求更改用户密码', '1', 'me.zbl.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2018-04-04 20:31:27');\nINSERT INTO `sys_log` VALUES ('731', '1', 'admin', '请求更改用户密码', '0', 'me.zbl.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2018-04-04 20:31:33');\nINSERT INTO `sys_log` VALUES ('732', '1', 'admin', '编辑用户', '11', 'me.zbl.system.controller.UserController.edit()', null, '127.0.0.1', '2018-04-04 20:32:48');\nINSERT INTO `sys_log` VALUES ('733', '1', 'admin', '编辑用户', '4', 'me.zbl.system.controller.UserController.edit()', null, '127.0.0.1', '2018-04-04 20:32:57');\nINSERT INTO `sys_log` VALUES ('734', '1', 'admin', '编辑角色', '16', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:37:59');\nINSERT INTO `sys_log` VALUES ('735', '1', 'admin', '编辑角色', '1', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:38:06');\nINSERT INTO `sys_log` VALUES ('736', '1', 'admin', '编辑角色', '4', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:38:21');\nINSERT INTO `sys_log` VALUES ('737', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:38:29');\nINSERT INTO `sys_log` VALUES ('738', '1', 'admin', '请求访问主页', '6', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:39:02');\nINSERT INTO `sys_log` VALUES ('739', '1', 'admin', '编辑角色', '1', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:39:31');\nINSERT INTO `sys_log` VALUES ('740', '1', 'admin', '请求访问主页', '4', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 20:41:23');\nINSERT INTO `sys_log` VALUES ('741', '1', 'admin', '编辑角色', '1', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:41:42');\nINSERT INTO `sys_log` VALUES ('742', '1', 'admin', '编辑角色', '2', 'me.zbl.system.controller.RoleController.edit()', null, '127.0.0.1', '2018-04-04 20:41:48');\nINSERT INTO `sys_log` VALUES ('743', '1', 'admin', '登录', '19', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:56:21');\nINSERT INTO `sys_log` VALUES ('744', '1', 'admin', '请求访问主页', '50', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 21:56:22');\nINSERT INTO `sys_log` VALUES ('745', '-1', '获取用户信息为空', '登录', '6', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:56:33');\nINSERT INTO `sys_log` VALUES ('746', '140', 'cangchu', '登录', '6', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:56:36');\nINSERT INTO `sys_log` VALUES ('747', '140', 'cangchu', '请求访问主页', '178', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 21:56:37');\nINSERT INTO `sys_log` VALUES ('748', '1', 'admin', '登录', '6', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:56:48');\nINSERT INTO `sys_log` VALUES ('749', '1', 'admin', '请求访问主页', '14', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 21:56:48');\nINSERT INTO `sys_log` VALUES ('750', '139', 'admin2', '登录', '6', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:57:07');\nINSERT INTO `sys_log` VALUES ('751', '139', 'admin2', '请求访问主页', '11', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 21:57:07');\nINSERT INTO `sys_log` VALUES ('752', '1', 'admin', '登录', '7', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 21:57:13');\nINSERT INTO `sys_log` VALUES ('753', '1', 'admin', '请求访问主页', '9', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 21:57:13');\nINSERT INTO `sys_log` VALUES ('754', '1', 'admin', '登录', '17', 'me.zbl.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2018-04-04 23:01:55');\nINSERT INTO `sys_log` VALUES ('755', '1', 'admin', '请求访问主页', '47', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 23:01:55');\nINSERT INTO `sys_log` VALUES ('756', '1', 'admin', '请求访问主页', '11', 'me.zbl.system.controller.LoginController.index()', null, '127.0.0.1', '2018-04-04 23:02:08');\n\n-- ----------------------------\n-- Table structure for sys_menu\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_menu`;\nCREATE TABLE `sys_menu` (\n  `menu_id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `parent_id` bigint(20) DEFAULT NULL COMMENT '父菜单ID，一级菜单为0',\n  `name` varchar(50) DEFAULT NULL COMMENT '菜单名称',\n  `url` varchar(200) DEFAULT NULL COMMENT '菜单URL',\n  `perms` varchar(500) DEFAULT NULL COMMENT '授权(多个用逗号分隔，如：user:list,user:create)',\n  `type` int(11) DEFAULT NULL COMMENT '类型   0：目录   1：菜单   2：按钮',\n  `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标',\n  `order_num` int(11) DEFAULT NULL COMMENT '排序',\n  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',\n  `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',\n  PRIMARY KEY (`menu_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8 COMMENT='菜单管理';\n\n-- ----------------------------\n-- Records of sys_menu\n-- ----------------------------\nINSERT INTO `sys_menu` VALUES ('1', '0', '基础管理', '', '', '0', 'fa fa-bars', '0', '2017-08-09 22:49:47', null);\nINSERT INTO `sys_menu` VALUES ('2', '3', '系统菜单', 'sys/menu/', 'sys:menu:menu', '1', 'fa fa-th-list', '2', '2017-08-09 22:55:15', null);\nINSERT INTO `sys_menu` VALUES ('3', '0', '系统管理', null, null, '0', 'fa fa-desktop', '1', '2017-08-09 23:06:55', '2017-08-14 14:13:43');\nINSERT INTO `sys_menu` VALUES ('6', '3', '用户管理', 'sys/user/', 'sys:user:user', '1', 'fa fa-user', '0', '2017-08-10 14:12:11', null);\nINSERT INTO `sys_menu` VALUES ('7', '3', '角色管理', 'sys/role', 'sys:role:role', '1', 'fa fa-paw', '1', '2017-08-10 14:13:19', null);\nINSERT INTO `sys_menu` VALUES ('12', '6', '新增', '', 'sys:user:add', '2', '', '0', '2017-08-14 10:51:35', null);\nINSERT INTO `sys_menu` VALUES ('13', '6', '编辑', '', 'sys:user:edit', '2', '', '0', '2017-08-14 10:52:06', null);\nINSERT INTO `sys_menu` VALUES ('14', '6', '删除', null, 'sys:user:remove', '2', null, '0', '2017-08-14 10:52:24', null);\nINSERT INTO `sys_menu` VALUES ('15', '7', '新增', '', 'sys:role:add', '2', '', '0', '2017-08-14 10:56:37', null);\nINSERT INTO `sys_menu` VALUES ('20', '2', '新增', '', 'sys:menu:add', '2', '', '0', '2017-08-14 10:59:32', null);\nINSERT INTO `sys_menu` VALUES ('21', '2', '编辑', '', 'sys:menu:edit', '2', '', '0', '2017-08-14 10:59:56', null);\nINSERT INTO `sys_menu` VALUES ('22', '2', '删除', '', 'sys:menu:remove', '2', '', '0', '2017-08-14 11:00:26', null);\nINSERT INTO `sys_menu` VALUES ('24', '6', '批量删除', '', 'sys:user:batchRemove', '2', '', '0', '2017-08-14 17:27:18', null);\nINSERT INTO `sys_menu` VALUES ('25', '6', '停用', null, 'sys:user:disable', '2', null, '0', '2017-08-14 17:27:43', null);\nINSERT INTO `sys_menu` VALUES ('26', '6', '重置密码', '', 'sys:user:resetPwd', '2', '', '0', '2017-08-14 17:28:34', null);\nINSERT INTO `sys_menu` VALUES ('27', '91', '系统日志', 'common/log', 'common:log', '1', 'fa fa-warning', '0', '2017-08-14 22:11:53', null);\nINSERT INTO `sys_menu` VALUES ('28', '27', '刷新', null, 'sys:log:list', '2', null, '0', '2017-08-14 22:30:22', null);\nINSERT INTO `sys_menu` VALUES ('29', '27', '删除', null, 'sys:log:remove', '2', null, '0', '2017-08-14 22:30:43', null);\nINSERT INTO `sys_menu` VALUES ('30', '27', '清空', null, 'sys:log:clear', '2', null, '0', '2017-08-14 22:31:02', null);\nINSERT INTO `sys_menu` VALUES ('48', '77', '代码生成', 'common/generator', 'common:generator', '1', 'fa fa-code', '3', null, null);\nINSERT INTO `sys_menu` VALUES ('49', '0', '博客管理', '', '', '0', 'fa fa-rss', '6', null, null);\nINSERT INTO `sys_menu` VALUES ('50', '49', '文章列表', 'blog/bContent', 'blog:bContent:bContent', '1', 'fa fa-file-image-o', '1', null, null);\nINSERT INTO `sys_menu` VALUES ('51', '50', '新增', '', 'blog:bContent:add', '2', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('55', '7', '编辑', '', 'sys:role:edit', '2', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('56', '7', '删除', '', 'sys:role:remove', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('57', '91', '运行监控', '/druid/index.html', '', '1', 'fa fa-caret-square-o-right', '1', null, null);\nINSERT INTO `sys_menu` VALUES ('58', '50', '编辑', '', 'blog:bContent:edit', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('59', '50', '删除', '', 'blog:bContent:remove', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('60', '50', '批量删除', '', 'blog:bContent:batchRemove', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('61', '2', '批量删除', '', 'sys:menu:batchRemove', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('62', '7', '批量删除', '', 'sys:role:batchRemove', '2', null, null, null, null);\nINSERT INTO `sys_menu` VALUES ('68', '49', '发布文章', '/blog/bContent/add', 'blog:bContent:add', '1', 'fa fa-edit', '0', null, null);\nINSERT INTO `sys_menu` VALUES ('71', '1', '文件管理', '/common/sysFile', 'common:sysFile:sysFile', '1', 'fa fa-folder-open', '2', null, null);\nINSERT INTO `sys_menu` VALUES ('72', '77', '计划任务', 'common/job', 'common:taskScheduleJob', '1', 'fa fa-hourglass-1', '4', null, null);\nINSERT INTO `sys_menu` VALUES ('73', '3', '部门管理', '/system/sysDept', 'system:sysDept:sysDept', '1', 'fa fa-users', '3', null, null);\nINSERT INTO `sys_menu` VALUES ('74', '73', '增加', '/system/sysDept/add', 'system:sysDept:add', '2', null, '1', null, null);\nINSERT INTO `sys_menu` VALUES ('75', '73', '刪除', 'system/sysDept/remove', 'system:sysDept:remove', '2', null, '2', null, null);\nINSERT INTO `sys_menu` VALUES ('76', '73', '编辑', '/system/sysDept/edit', 'system:sysDept:edit', '2', null, '3', null, null);\nINSERT INTO `sys_menu` VALUES ('77', '0', '系统工具', '', '', '0', 'fa fa-gear', '4', null, null);\nINSERT INTO `sys_menu` VALUES ('78', '1', '数据字典', '/common/dict', 'common:dict:dict', '1', 'fa fa-book', '1', null, null);\nINSERT INTO `sys_menu` VALUES ('79', '78', '增加', '/common/dict/add', 'common:dict:add', '2', null, '2', null, null);\nINSERT INTO `sys_menu` VALUES ('80', '78', '编辑', '/common/dict/edit', 'common:dict:edit', '2', null, '2', null, null);\nINSERT INTO `sys_menu` VALUES ('81', '78', '删除', '/common/dict/remove', 'common:dict:remove', '2', '', '3', null, null);\nINSERT INTO `sys_menu` VALUES ('83', '78', '批量删除', '/common/dict/batchRemove', 'common:dict:batchRemove', '2', '', '4', null, null);\nINSERT INTO `sys_menu` VALUES ('84', '0', '办公管理', '', '', '0', 'fa fa-laptop', '5', null, null);\nINSERT INTO `sys_menu` VALUES ('85', '84', '通知公告', 'oa/notify', 'oa:notify:notify', '1', 'fa fa-pencil-square', null, null, null);\nINSERT INTO `sys_menu` VALUES ('86', '85', '新增', 'oa/notify/add', 'oa:notify:add', '2', 'fa fa-plus', '1', null, null);\nINSERT INTO `sys_menu` VALUES ('87', '85', '编辑', 'oa/notify/edit', 'oa:notify:edit', '2', 'fa fa-pencil-square-o', '2', null, null);\nINSERT INTO `sys_menu` VALUES ('88', '85', '删除', 'oa/notify/remove', 'oa:notify:remove', '2', 'fa fa-minus', null, null, null);\nINSERT INTO `sys_menu` VALUES ('89', '85', '批量删除', 'oa/notify/batchRemove', 'oa:notify:batchRemove', '2', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('90', '84', '我的通知', 'oa/notify/selfNotify', '', '1', 'fa fa-envelope-square', null, null, null);\nINSERT INTO `sys_menu` VALUES ('91', '0', '系统监控', '', '', '0', 'fa fa-video-camera', '5', null, null);\nINSERT INTO `sys_menu` VALUES ('92', '91', '在线用户', 'sys/online', '', '1', 'fa fa-user', null, null, null);\nINSERT INTO `sys_menu` VALUES ('93', '0', '工作流程', '', '', '0', 'fa fa-print', '6', null, null);\nINSERT INTO `sys_menu` VALUES ('94', '93', '模型管理', 'activiti/model', '', '1', 'fa fa-sort-amount-asc', null, null, null);\nINSERT INTO `sys_menu` VALUES ('95', '94', '全部权限', '', 'activiti:model', '2', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('96', '93', '流程管理', 'activiti/process', '', '1', 'fa fa-flag', null, null, null);\nINSERT INTO `sys_menu` VALUES ('97', '0', '图表管理', '', '', '0', 'fa fa-bar-chart', '7', null, null);\nINSERT INTO `sys_menu` VALUES ('98', '97', '百度chart', '/chart/graph_echarts.html', '', '1', 'fa fa-area-chart', null, null, null);\nINSERT INTO `sys_menu` VALUES ('99', '96', '所有权限', '', 'act:process', '2', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('101', '93', '待办任务', 'activiti/task/todo', '', '1', '', null, null, null);\nINSERT INTO `sys_menu` VALUES ('104', '77', 'swagger', '/swagger-ui.html', '', '1', '', null, null, null);\n\n-- ----------------------------\n-- Table structure for sys_role\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_role`;\nCREATE TABLE `sys_role` (\n  `role_id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `role_name` varchar(100) DEFAULT NULL COMMENT '角色名称',\n  `role_sign` varchar(100) DEFAULT NULL COMMENT '角色标识',\n  `remark` varchar(100) DEFAULT NULL COMMENT '备注',\n  `user_id_create` bigint(255) DEFAULT NULL COMMENT '创建用户id',\n  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',\n  `gmt_modified` datetime DEFAULT NULL COMMENT '创建时间',\n  PRIMARY KEY (`role_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8 COMMENT='角色';\n\n-- ----------------------------\n-- Records of sys_role\n-- ----------------------------\nINSERT INTO `sys_role` VALUES ('1', '超级用户角色', 'admin', '拥有最高权限', '2', '2017-08-12 00:43:52', '2017-08-12 19:14:59');\nINSERT INTO `sys_role` VALUES ('59', '仓储管理员', null, '仓储管理员', null, null, null);\nINSERT INTO `sys_role` VALUES ('60', '管理员', null, '普通管理员', null, null, null);\n\n-- ----------------------------\n-- Table structure for sys_role_menu\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_role_menu`;\nCREATE TABLE `sys_role_menu` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',\n  `menu_id` bigint(20) DEFAULT NULL COMMENT '菜单ID',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=3307 DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系';\n\n-- ----------------------------\n-- Records of sys_role_menu\n-- ----------------------------\nINSERT INTO `sys_role_menu` VALUES ('367', '44', '1');\nINSERT INTO `sys_role_menu` VALUES ('368', '44', '32');\nINSERT INTO `sys_role_menu` VALUES ('369', '44', '33');\nINSERT INTO `sys_role_menu` VALUES ('370', '44', '34');\nINSERT INTO `sys_role_menu` VALUES ('371', '44', '35');\nINSERT INTO `sys_role_menu` VALUES ('372', '44', '28');\nINSERT INTO `sys_role_menu` VALUES ('373', '44', '29');\nINSERT INTO `sys_role_menu` VALUES ('374', '44', '30');\nINSERT INTO `sys_role_menu` VALUES ('375', '44', '38');\nINSERT INTO `sys_role_menu` VALUES ('376', '44', '4');\nINSERT INTO `sys_role_menu` VALUES ('377', '44', '27');\nINSERT INTO `sys_role_menu` VALUES ('378', '45', '38');\nINSERT INTO `sys_role_menu` VALUES ('379', '46', '3');\nINSERT INTO `sys_role_menu` VALUES ('380', '46', '20');\nINSERT INTO `sys_role_menu` VALUES ('381', '46', '21');\nINSERT INTO `sys_role_menu` VALUES ('382', '46', '22');\nINSERT INTO `sys_role_menu` VALUES ('383', '46', '23');\nINSERT INTO `sys_role_menu` VALUES ('384', '46', '11');\nINSERT INTO `sys_role_menu` VALUES ('385', '46', '12');\nINSERT INTO `sys_role_menu` VALUES ('386', '46', '13');\nINSERT INTO `sys_role_menu` VALUES ('387', '46', '14');\nINSERT INTO `sys_role_menu` VALUES ('388', '46', '24');\nINSERT INTO `sys_role_menu` VALUES ('389', '46', '25');\nINSERT INTO `sys_role_menu` VALUES ('390', '46', '26');\nINSERT INTO `sys_role_menu` VALUES ('391', '46', '15');\nINSERT INTO `sys_role_menu` VALUES ('392', '46', '2');\nINSERT INTO `sys_role_menu` VALUES ('393', '46', '6');\nINSERT INTO `sys_role_menu` VALUES ('394', '46', '7');\nINSERT INTO `sys_role_menu` VALUES ('598', '50', '38');\nINSERT INTO `sys_role_menu` VALUES ('632', '38', '42');\nINSERT INTO `sys_role_menu` VALUES ('737', '51', '38');\nINSERT INTO `sys_role_menu` VALUES ('738', '51', '39');\nINSERT INTO `sys_role_menu` VALUES ('739', '51', '40');\nINSERT INTO `sys_role_menu` VALUES ('740', '51', '41');\nINSERT INTO `sys_role_menu` VALUES ('741', '51', '4');\nINSERT INTO `sys_role_menu` VALUES ('742', '51', '32');\nINSERT INTO `sys_role_menu` VALUES ('743', '51', '33');\nINSERT INTO `sys_role_menu` VALUES ('744', '51', '34');\nINSERT INTO `sys_role_menu` VALUES ('745', '51', '35');\nINSERT INTO `sys_role_menu` VALUES ('746', '51', '27');\nINSERT INTO `sys_role_menu` VALUES ('747', '51', '28');\nINSERT INTO `sys_role_menu` VALUES ('748', '51', '29');\nINSERT INTO `sys_role_menu` VALUES ('749', '51', '30');\nINSERT INTO `sys_role_menu` VALUES ('750', '51', '1');\nINSERT INTO `sys_role_menu` VALUES ('1064', '54', '53');\nINSERT INTO `sys_role_menu` VALUES ('1095', '55', '2');\nINSERT INTO `sys_role_menu` VALUES ('1096', '55', '6');\nINSERT INTO `sys_role_menu` VALUES ('1097', '55', '7');\nINSERT INTO `sys_role_menu` VALUES ('1098', '55', '3');\nINSERT INTO `sys_role_menu` VALUES ('1099', '55', '50');\nINSERT INTO `sys_role_menu` VALUES ('1100', '55', '49');\nINSERT INTO `sys_role_menu` VALUES ('1101', '55', '1');\nINSERT INTO `sys_role_menu` VALUES ('1856', '53', '28');\nINSERT INTO `sys_role_menu` VALUES ('1857', '53', '29');\nINSERT INTO `sys_role_menu` VALUES ('1858', '53', '30');\nINSERT INTO `sys_role_menu` VALUES ('1859', '53', '27');\nINSERT INTO `sys_role_menu` VALUES ('1860', '53', '57');\nINSERT INTO `sys_role_menu` VALUES ('1861', '53', '71');\nINSERT INTO `sys_role_menu` VALUES ('1862', '53', '48');\nINSERT INTO `sys_role_menu` VALUES ('1863', '53', '72');\nINSERT INTO `sys_role_menu` VALUES ('1864', '53', '1');\nINSERT INTO `sys_role_menu` VALUES ('1865', '53', '7');\nINSERT INTO `sys_role_menu` VALUES ('1866', '53', '55');\nINSERT INTO `sys_role_menu` VALUES ('1867', '53', '56');\nINSERT INTO `sys_role_menu` VALUES ('1868', '53', '62');\nINSERT INTO `sys_role_menu` VALUES ('1869', '53', '15');\nINSERT INTO `sys_role_menu` VALUES ('1870', '53', '2');\nINSERT INTO `sys_role_menu` VALUES ('1871', '53', '61');\nINSERT INTO `sys_role_menu` VALUES ('1872', '53', '20');\nINSERT INTO `sys_role_menu` VALUES ('1873', '53', '21');\nINSERT INTO `sys_role_menu` VALUES ('1874', '53', '22');\nINSERT INTO `sys_role_menu` VALUES ('2084', '56', '68');\nINSERT INTO `sys_role_menu` VALUES ('2085', '56', '60');\nINSERT INTO `sys_role_menu` VALUES ('2086', '56', '59');\nINSERT INTO `sys_role_menu` VALUES ('2087', '56', '58');\nINSERT INTO `sys_role_menu` VALUES ('2088', '56', '51');\nINSERT INTO `sys_role_menu` VALUES ('2089', '56', '50');\nINSERT INTO `sys_role_menu` VALUES ('2090', '56', '49');\nINSERT INTO `sys_role_menu` VALUES ('2243', '48', '72');\nINSERT INTO `sys_role_menu` VALUES ('2247', '63', '-1');\nINSERT INTO `sys_role_menu` VALUES ('2248', '63', '84');\nINSERT INTO `sys_role_menu` VALUES ('2249', '63', '85');\nINSERT INTO `sys_role_menu` VALUES ('2250', '63', '88');\nINSERT INTO `sys_role_menu` VALUES ('2251', '63', '87');\nINSERT INTO `sys_role_menu` VALUES ('2252', '64', '84');\nINSERT INTO `sys_role_menu` VALUES ('2253', '64', '89');\nINSERT INTO `sys_role_menu` VALUES ('2254', '64', '88');\nINSERT INTO `sys_role_menu` VALUES ('2255', '64', '87');\nINSERT INTO `sys_role_menu` VALUES ('2256', '64', '86');\nINSERT INTO `sys_role_menu` VALUES ('2257', '64', '85');\nINSERT INTO `sys_role_menu` VALUES ('2258', '65', '89');\nINSERT INTO `sys_role_menu` VALUES ('2259', '65', '88');\nINSERT INTO `sys_role_menu` VALUES ('2260', '65', '86');\nINSERT INTO `sys_role_menu` VALUES ('2262', '67', '48');\nINSERT INTO `sys_role_menu` VALUES ('2263', '68', '88');\nINSERT INTO `sys_role_menu` VALUES ('2264', '68', '87');\nINSERT INTO `sys_role_menu` VALUES ('2265', '69', '89');\nINSERT INTO `sys_role_menu` VALUES ('2266', '69', '88');\nINSERT INTO `sys_role_menu` VALUES ('2267', '69', '86');\nINSERT INTO `sys_role_menu` VALUES ('2268', '69', '87');\nINSERT INTO `sys_role_menu` VALUES ('2269', '69', '85');\nINSERT INTO `sys_role_menu` VALUES ('2270', '69', '84');\nINSERT INTO `sys_role_menu` VALUES ('2271', '70', '85');\nINSERT INTO `sys_role_menu` VALUES ('2272', '70', '89');\nINSERT INTO `sys_role_menu` VALUES ('2273', '70', '88');\nINSERT INTO `sys_role_menu` VALUES ('2274', '70', '87');\nINSERT INTO `sys_role_menu` VALUES ('2275', '70', '86');\nINSERT INTO `sys_role_menu` VALUES ('2276', '70', '84');\nINSERT INTO `sys_role_menu` VALUES ('2277', '71', '87');\nINSERT INTO `sys_role_menu` VALUES ('2278', '72', '59');\nINSERT INTO `sys_role_menu` VALUES ('2279', '73', '48');\nINSERT INTO `sys_role_menu` VALUES ('2280', '74', '88');\nINSERT INTO `sys_role_menu` VALUES ('2281', '74', '87');\nINSERT INTO `sys_role_menu` VALUES ('2282', '75', '88');\nINSERT INTO `sys_role_menu` VALUES ('2283', '75', '87');\nINSERT INTO `sys_role_menu` VALUES ('2284', '76', '85');\nINSERT INTO `sys_role_menu` VALUES ('2285', '76', '89');\nINSERT INTO `sys_role_menu` VALUES ('2286', '76', '88');\nINSERT INTO `sys_role_menu` VALUES ('2287', '76', '87');\nINSERT INTO `sys_role_menu` VALUES ('2288', '76', '86');\nINSERT INTO `sys_role_menu` VALUES ('2289', '76', '84');\nINSERT INTO `sys_role_menu` VALUES ('2292', '78', '88');\nINSERT INTO `sys_role_menu` VALUES ('2293', '78', '87');\nINSERT INTO `sys_role_menu` VALUES ('2294', '78', null);\nINSERT INTO `sys_role_menu` VALUES ('2295', '78', null);\nINSERT INTO `sys_role_menu` VALUES ('2296', '78', null);\nINSERT INTO `sys_role_menu` VALUES ('2308', '80', '87');\nINSERT INTO `sys_role_menu` VALUES ('2309', '80', '86');\nINSERT INTO `sys_role_menu` VALUES ('2310', '80', '-1');\nINSERT INTO `sys_role_menu` VALUES ('2311', '80', '84');\nINSERT INTO `sys_role_menu` VALUES ('2312', '80', '85');\nINSERT INTO `sys_role_menu` VALUES ('2328', '79', '72');\nINSERT INTO `sys_role_menu` VALUES ('2329', '79', '48');\nINSERT INTO `sys_role_menu` VALUES ('2330', '79', '77');\nINSERT INTO `sys_role_menu` VALUES ('2331', '79', '84');\nINSERT INTO `sys_role_menu` VALUES ('2332', '79', '89');\nINSERT INTO `sys_role_menu` VALUES ('2333', '79', '88');\nINSERT INTO `sys_role_menu` VALUES ('2334', '79', '87');\nINSERT INTO `sys_role_menu` VALUES ('2335', '79', '86');\nINSERT INTO `sys_role_menu` VALUES ('2336', '79', '85');\nINSERT INTO `sys_role_menu` VALUES ('2337', '79', '-1');\nINSERT INTO `sys_role_menu` VALUES ('2338', '77', '89');\nINSERT INTO `sys_role_menu` VALUES ('2339', '77', '88');\nINSERT INTO `sys_role_menu` VALUES ('2340', '77', '87');\nINSERT INTO `sys_role_menu` VALUES ('2341', '77', '86');\nINSERT INTO `sys_role_menu` VALUES ('2342', '77', '85');\nINSERT INTO `sys_role_menu` VALUES ('2343', '77', '84');\nINSERT INTO `sys_role_menu` VALUES ('2344', '77', '72');\nINSERT INTO `sys_role_menu` VALUES ('2345', '77', '-1');\nINSERT INTO `sys_role_menu` VALUES ('2346', '77', '77');\nINSERT INTO `sys_role_menu` VALUES ('2974', '57', '93');\nINSERT INTO `sys_role_menu` VALUES ('2975', '57', '99');\nINSERT INTO `sys_role_menu` VALUES ('2976', '57', '95');\nINSERT INTO `sys_role_menu` VALUES ('2977', '57', '101');\nINSERT INTO `sys_role_menu` VALUES ('2978', '57', '96');\nINSERT INTO `sys_role_menu` VALUES ('2979', '57', '94');\nINSERT INTO `sys_role_menu` VALUES ('2980', '57', '-1');\nINSERT INTO `sys_role_menu` VALUES ('2981', '58', '93');\nINSERT INTO `sys_role_menu` VALUES ('2982', '58', '99');\nINSERT INTO `sys_role_menu` VALUES ('2983', '58', '95');\nINSERT INTO `sys_role_menu` VALUES ('2984', '58', '101');\nINSERT INTO `sys_role_menu` VALUES ('2985', '58', '96');\nINSERT INTO `sys_role_menu` VALUES ('2986', '58', '94');\nINSERT INTO `sys_role_menu` VALUES ('2987', '58', '-1');\nINSERT INTO `sys_role_menu` VALUES ('3115', '1', '103');\nINSERT INTO `sys_role_menu` VALUES ('3116', '1', '98');\nINSERT INTO `sys_role_menu` VALUES ('3117', '1', '101');\nINSERT INTO `sys_role_menu` VALUES ('3118', '1', '99');\nINSERT INTO `sys_role_menu` VALUES ('3119', '1', '95');\nINSERT INTO `sys_role_menu` VALUES ('3120', '1', '92');\nINSERT INTO `sys_role_menu` VALUES ('3121', '1', '57');\nINSERT INTO `sys_role_menu` VALUES ('3122', '1', '30');\nINSERT INTO `sys_role_menu` VALUES ('3123', '1', '29');\nINSERT INTO `sys_role_menu` VALUES ('3124', '1', '28');\nINSERT INTO `sys_role_menu` VALUES ('3125', '1', '90');\nINSERT INTO `sys_role_menu` VALUES ('3126', '1', '89');\nINSERT INTO `sys_role_menu` VALUES ('3127', '1', '88');\nINSERT INTO `sys_role_menu` VALUES ('3128', '1', '87');\nINSERT INTO `sys_role_menu` VALUES ('3129', '1', '86');\nINSERT INTO `sys_role_menu` VALUES ('3130', '1', '72');\nINSERT INTO `sys_role_menu` VALUES ('3131', '1', '48');\nINSERT INTO `sys_role_menu` VALUES ('3132', '1', '68');\nINSERT INTO `sys_role_menu` VALUES ('3133', '1', '60');\nINSERT INTO `sys_role_menu` VALUES ('3134', '1', '59');\nINSERT INTO `sys_role_menu` VALUES ('3135', '1', '58');\nINSERT INTO `sys_role_menu` VALUES ('3136', '1', '51');\nINSERT INTO `sys_role_menu` VALUES ('3137', '1', '76');\nINSERT INTO `sys_role_menu` VALUES ('3138', '1', '75');\nINSERT INTO `sys_role_menu` VALUES ('3139', '1', '74');\nINSERT INTO `sys_role_menu` VALUES ('3140', '1', '62');\nINSERT INTO `sys_role_menu` VALUES ('3141', '1', '56');\nINSERT INTO `sys_role_menu` VALUES ('3142', '1', '55');\nINSERT INTO `sys_role_menu` VALUES ('3143', '1', '15');\nINSERT INTO `sys_role_menu` VALUES ('3144', '1', '26');\nINSERT INTO `sys_role_menu` VALUES ('3145', '1', '25');\nINSERT INTO `sys_role_menu` VALUES ('3146', '1', '24');\nINSERT INTO `sys_role_menu` VALUES ('3147', '1', '14');\nINSERT INTO `sys_role_menu` VALUES ('3148', '1', '13');\nINSERT INTO `sys_role_menu` VALUES ('3149', '1', '12');\nINSERT INTO `sys_role_menu` VALUES ('3150', '1', '61');\nINSERT INTO `sys_role_menu` VALUES ('3151', '1', '22');\nINSERT INTO `sys_role_menu` VALUES ('3152', '1', '21');\nINSERT INTO `sys_role_menu` VALUES ('3153', '1', '20');\nINSERT INTO `sys_role_menu` VALUES ('3154', '1', '83');\nINSERT INTO `sys_role_menu` VALUES ('3155', '1', '81');\nINSERT INTO `sys_role_menu` VALUES ('3156', '1', '80');\nINSERT INTO `sys_role_menu` VALUES ('3157', '1', '79');\nINSERT INTO `sys_role_menu` VALUES ('3158', '1', '71');\nINSERT INTO `sys_role_menu` VALUES ('3159', '1', '102');\nINSERT INTO `sys_role_menu` VALUES ('3160', '1', '97');\nINSERT INTO `sys_role_menu` VALUES ('3161', '1', '96');\nINSERT INTO `sys_role_menu` VALUES ('3162', '1', '94');\nINSERT INTO `sys_role_menu` VALUES ('3163', '1', '93');\nINSERT INTO `sys_role_menu` VALUES ('3164', '1', '27');\nINSERT INTO `sys_role_menu` VALUES ('3165', '1', '91');\nINSERT INTO `sys_role_menu` VALUES ('3166', '1', '85');\nINSERT INTO `sys_role_menu` VALUES ('3167', '1', '84');\nINSERT INTO `sys_role_menu` VALUES ('3168', '1', '50');\nINSERT INTO `sys_role_menu` VALUES ('3169', '1', '49');\nINSERT INTO `sys_role_menu` VALUES ('3170', '1', '73');\nINSERT INTO `sys_role_menu` VALUES ('3171', '1', '7');\nINSERT INTO `sys_role_menu` VALUES ('3172', '1', '6');\nINSERT INTO `sys_role_menu` VALUES ('3173', '1', '2');\nINSERT INTO `sys_role_menu` VALUES ('3174', '1', '3');\nINSERT INTO `sys_role_menu` VALUES ('3175', '1', '78');\nINSERT INTO `sys_role_menu` VALUES ('3176', '1', '1');\nINSERT INTO `sys_role_menu` VALUES ('3177', '1', '104');\nINSERT INTO `sys_role_menu` VALUES ('3178', '1', '77');\nINSERT INTO `sys_role_menu` VALUES ('3179', '1', '-1');\nINSERT INTO `sys_role_menu` VALUES ('3284', '60', '3');\nINSERT INTO `sys_role_menu` VALUES ('3285', '60', '76');\nINSERT INTO `sys_role_menu` VALUES ('3286', '60', '75');\nINSERT INTO `sys_role_menu` VALUES ('3287', '60', '74');\nINSERT INTO `sys_role_menu` VALUES ('3288', '60', '62');\nINSERT INTO `sys_role_menu` VALUES ('3289', '60', '56');\nINSERT INTO `sys_role_menu` VALUES ('3290', '60', '55');\nINSERT INTO `sys_role_menu` VALUES ('3291', '60', '15');\nINSERT INTO `sys_role_menu` VALUES ('3292', '60', '26');\nINSERT INTO `sys_role_menu` VALUES ('3293', '60', '25');\nINSERT INTO `sys_role_menu` VALUES ('3294', '60', '24');\nINSERT INTO `sys_role_menu` VALUES ('3295', '60', '14');\nINSERT INTO `sys_role_menu` VALUES ('3296', '60', '13');\nINSERT INTO `sys_role_menu` VALUES ('3297', '60', '12');\nINSERT INTO `sys_role_menu` VALUES ('3298', '60', '61');\nINSERT INTO `sys_role_menu` VALUES ('3299', '60', '22');\nINSERT INTO `sys_role_menu` VALUES ('3300', '60', '21');\nINSERT INTO `sys_role_menu` VALUES ('3301', '60', '20');\nINSERT INTO `sys_role_menu` VALUES ('3302', '60', '73');\nINSERT INTO `sys_role_menu` VALUES ('3303', '60', '7');\nINSERT INTO `sys_role_menu` VALUES ('3304', '60', '6');\nINSERT INTO `sys_role_menu` VALUES ('3305', '60', '2');\nINSERT INTO `sys_role_menu` VALUES ('3306', '60', '-1');\n\n-- ----------------------------\n-- Table structure for sys_task\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_task`;\nCREATE TABLE `sys_task` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron表达式',\n  `method_name` varchar(255) DEFAULT NULL COMMENT '任务调用的方法名',\n  `is_concurrent` varchar(255) DEFAULT NULL COMMENT '任务是否有状态',\n  `description` varchar(255) DEFAULT NULL COMMENT '任务描述',\n  `update_by` varchar(64) DEFAULT NULL COMMENT '更新者',\n  `bean_class` varchar(255) DEFAULT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名',\n  `create_date` datetime DEFAULT NULL COMMENT '创建时间',\n  `job_status` varchar(255) DEFAULT NULL COMMENT '任务状态',\n  `job_group` varchar(255) DEFAULT NULL COMMENT '任务分组',\n  `update_date` datetime DEFAULT NULL COMMENT '更新时间',\n  `create_by` varchar(64) DEFAULT NULL COMMENT '创建者',\n  `spring_bean` varchar(255) DEFAULT NULL COMMENT 'Spring bean',\n  `job_name` varchar(255) DEFAULT NULL COMMENT '任务名',\n  PRIMARY KEY (`id`)\n) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;\n\n-- ----------------------------\n-- Records of sys_task\n-- ----------------------------\nINSERT INTO `sys_task` VALUES ('2', '0/10 * * * * ?', 'run1', '1', '', '4028ea815a3d2a8c015a3d2f8d2a0002', 'com.bootdo.common.task.WelcomeJob', '2017-05-19 18:30:56', '0', 'group1', '2017-05-19 18:31:07', null, '', 'welcomJob');\n\n-- ----------------------------\n-- Table structure for sys_user\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_user`;\nCREATE TABLE `sys_user` (\n  `user_id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `username` varchar(50) DEFAULT NULL COMMENT '用户名',\n  `name` varchar(100) DEFAULT NULL,\n  `password` varchar(50) DEFAULT NULL COMMENT '密码',\n  `dept_id` bigint(20) DEFAULT NULL,\n  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',\n  `mobile` varchar(100) DEFAULT NULL COMMENT '手机号',\n  `status` tinyint(255) DEFAULT NULL COMMENT '状态 0:禁用，1:正常',\n  `user_id_create` bigint(255) DEFAULT NULL COMMENT '创建用户id',\n  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',\n  `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',\n  `sex` bigint(32) DEFAULT NULL COMMENT '性别',\n  `birth` datetime DEFAULT NULL COMMENT '出身日期',\n  `pic_id` bigint(32) DEFAULT NULL,\n  `live_address` varchar(500) DEFAULT NULL COMMENT '现居住地',\n  `hobby` varchar(255) DEFAULT NULL COMMENT '爱好',\n  `province` varchar(255) DEFAULT NULL COMMENT '省份',\n  `city` varchar(255) DEFAULT NULL COMMENT '所在城市',\n  `district` varchar(255) DEFAULT NULL COMMENT '所在地区',\n  PRIMARY KEY (`user_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8;\n\n-- ----------------------------\n-- Records of sys_user\n-- ----------------------------\nINSERT INTO `sys_user` VALUES ('1', 'admin', '超级管理员', 'd0af8fa1272ef5a152d9e27763eea293', '6', 'admin@example.com', '17699999999', '1', '1', '2017-08-15 21:40:39', '2017-08-15 21:41:00', '96', '2017-12-14 00:00:00', '138', 'ccc', '', '河北省', '石家庄市', '裕华区');\nINSERT INTO `sys_user` VALUES ('139', 'admin2', '管理员-郑', '88d17235f597d36e4bca125853a9022a', '6', '1146556298@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);\nINSERT INTO `sys_user` VALUES ('140', 'cangchu', '仓储管理员', '098dc79ecd794a97dfae13b62a939052', '11', '234567890@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);\n\n-- ----------------------------\n-- Table structure for sys_user_plus\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_user_plus`;\nCREATE TABLE `sys_user_plus` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_id` bigint(20) NOT NULL,\n  `payment` double DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n-- ----------------------------\n-- Records of sys_user_plus\n-- ----------------------------\n\n-- ----------------------------\n-- Table structure for sys_user_role\n-- ----------------------------\nDROP TABLE IF EXISTS `sys_user_role`;\nCREATE TABLE `sys_user_role` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',\n  `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=140 DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';\n\n-- ----------------------------\n-- Records of sys_user_role\n-- ----------------------------\nINSERT INTO `sys_user_role` VALUES ('73', '30', '48');\nINSERT INTO `sys_user_role` VALUES ('74', '30', '49');\nINSERT INTO `sys_user_role` VALUES ('75', '30', '50');\nINSERT INTO `sys_user_role` VALUES ('76', '31', '48');\nINSERT INTO `sys_user_role` VALUES ('77', '31', '49');\nINSERT INTO `sys_user_role` VALUES ('78', '31', '52');\nINSERT INTO `sys_user_role` VALUES ('79', '32', '48');\nINSERT INTO `sys_user_role` VALUES ('80', '32', '49');\nINSERT INTO `sys_user_role` VALUES ('81', '32', '50');\nINSERT INTO `sys_user_role` VALUES ('82', '32', '51');\nINSERT INTO `sys_user_role` VALUES ('83', '32', '52');\nINSERT INTO `sys_user_role` VALUES ('84', '33', '38');\nINSERT INTO `sys_user_role` VALUES ('85', '33', '49');\nINSERT INTO `sys_user_role` VALUES ('86', '33', '52');\nINSERT INTO `sys_user_role` VALUES ('87', '34', '50');\nINSERT INTO `sys_user_role` VALUES ('88', '34', '51');\nINSERT INTO `sys_user_role` VALUES ('89', '34', '52');\nINSERT INTO `sys_user_role` VALUES ('124', null, '48');\nINSERT INTO `sys_user_role` VALUES ('136', '1', '1');\nINSERT INTO `sys_user_role` VALUES ('138', '139', '60');\nINSERT INTO `sys_user_role` VALUES ('139', '140', '59');\n"
  },
  {
    "path": "src/main/java/me/zbl/HospitalApplication.java",
    "content": "package me.zbl;\n\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.web.servlet.ServletComponentScan;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\n@EnableTransactionManagement\n@ServletComponentScan\n@MapperScan(\"me.zbl.*.dao\")\n@SpringBootApplication\npublic class HospitalApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(HospitalApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/config/ActivitiConfig.java",
    "content": "package me.zbl.activity.config;\n\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@Configuration\npublic class ActivitiConfig {\n\n  //流程配置，与spring整合采用SpringProcessEngineConfiguration这个实现\n  @Bean\n  public ProcessEngineConfiguration processEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) {\n    SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();\n    processEngineConfiguration.setDataSource(dataSource);\n    processEngineConfiguration.setDatabaseSchemaUpdate(\"true\");\n    processEngineConfiguration.setDatabaseType(\"mysql\");\n\n    processEngineConfiguration.setTransactionManager(transactionManager);\n\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  //八大接口\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  //八大接口 end\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/config/ActivitiConstant.java",
    "content": "package me.zbl.activity.config;\n\n/**\n *\n */\npublic class ActivitiConstant {\n\n  public static final String[] ACTIVITI_SALARY = new String[]{\"salary\", \"salary\"};\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/controller/ModelController.java",
    "content": "package me.zbl.activity.controller;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.R;\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.ActivitiException;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.repository.Deployment;\nimport org.activiti.engine.repository.Model;\nimport org.activiti.rest.editor.model.ModelEditorJsonRestResource;\nimport org.apache.batik.transcoder.TranscoderInput;\nimport org.apache.batik.transcoder.TranscoderOutput;\nimport org.apache.batik.transcoder.image.PNGTranscoder;\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.*;\nimport java.util.List;\n\nimport static org.activiti.editor.constants.ModelDataJsonConstants.*;\n\n/**\n * @author 郑保乐\n */\n@RequestMapping(\"/activiti\")\n@RestController\npublic class ModelController extends BaseController {\n\n  protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);\n\n  @Autowired\n  private RepositoryService repositoryService;\n\n  @Autowired\n  private ObjectMapper objectMapper;\n\n  @GetMapping(\"/model\")\n  ModelAndView model() {\n    return new ModelAndView(\"act/model/model\");\n  }\n\n  @GetMapping(\"/model/list\")\n  PageWrapper list(int offset, int limit) {\n    List<Model> list = repositoryService.createModelQuery().listPage(offset\n            , limit);\n    int total = (int) repositoryService.createModelQuery().count();\n    PageWrapper pageUtil = new PageWrapper(list, total);\n    return pageUtil;\n  }\n\n  @RequestMapping(\"/model/add\")\n  public void newModel(HttpServletResponse response) throws UnsupportedEncodingException {\n\n    //初始化一个空模型\n    Model model = repositoryService.newModel();\n    //设置一些默认信息\n    String name = \"new-process\";\n    String description = \"\";\n    int revision = 1;\n    String key = \"process\";\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    try {\n      response.sendRedirect(\"/modeler.html?modelId=\" + id);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n\n  @GetMapping(value = \"/model/{modelId}/json\")\n  public ObjectNode getEditorJson(@PathVariable String modelId) {\n    ObjectNode modelNode = null;\n    Model model = repositoryService.getModel(modelId);\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.put(\"model\", editorJsonNode);\n\n      } catch (Exception e) {\n        LOGGER.error(\"Error creating model JSON\", e);\n        throw new ActivitiException(\"Error creating model JSON\", e);\n      }\n    }\n    return modelNode;\n  }\n\n  @RequestMapping(value = \"/editor/stencilset\", method = RequestMethod.GET, produces = \"application/json;charset=utf-8\")\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  @GetMapping(\"/model/edit/{id}\")\n  public void edit(HttpServletResponse response, @PathVariable(\"id\") String id) {\n    try {\n      response.sendRedirect(\"/modeler.html?modelId=\" + id);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n\n  @DeleteMapping(\"/model/{id}\")\n  public R remove(@PathVariable(\"id\") String id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    repositoryService.deleteModel(id);\n    return R.ok();\n  }\n\n  @PostMapping(\"/model/deploy/{id}\")\n  public R deploy(@PathVariable(\"id\") String id) throws Exception {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    //获取模型\n    Model modelData = repositoryService.getModel(id);\n    byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());\n\n    if (bytes == null) {\n      return R.error(\"模型数据为空，请先设计流程并成功保存，再进行发布。\");\n    }\n\n    JsonNode modelNode = new ObjectMapper().readTree(bytes);\n\n    BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);\n    if (model.getProcesses().size() == 0) {\n      return R.error(\"数据模型不符要求，请至少设计一条主线流程。\");\n    }\n    byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);\n\n    //发布流程\n    String processName = modelData.getName() + \".bpmn20.xml\";\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\n    return R.ok();\n  }\n\n  @PostMapping(\"/model/batchRemove\")\n  public R batchRemove(@RequestParam(\"ids[]\") String[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    for (String id : ids) {\n      repositoryService.deleteModel(id);\n    }\n    return R.ok();\n  }\n\n  @RequestMapping(value = \"/model/{modelId}/save\", method = RequestMethod.PUT)\n  @ResponseStatus(value = HttpStatus.OK)\n  public void saveModel(@PathVariable String modelId\n          , String name, String description\n          , String json_xml, String svg_xml) {\n    try {\n\n      Model model = repositoryService.getModel(modelId);\n\n      ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());\n\n      modelJson.put(MODEL_NAME, name);\n      modelJson.put(MODEL_DESCRIPTION, description);\n      model.setMetaInfo(modelJson.toString());\n      model.setName(name);\n\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      LOGGER.error(\"Error saving model\", e);\n      throw new ActivitiException(\"Error saving model\", e);\n    }\n  }\n\n  @GetMapping(\"/model/export/{id}\")\n  public void exportToXml(@PathVariable(\"id\") String id, HttpServletResponse response) {\n    try {\n      org.activiti.engine.repository.Model modelData = repositoryService.getModel(id);\n      BpmnJsonConverter jsonConverter = new BpmnJsonConverter();\n      JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));\n      BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);\n      BpmnXMLConverter xmlConverter = new BpmnXMLConverter();\n      byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);\n\n      ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);\n      IOUtils.copy(in, response.getOutputStream());\n      String filename = bpmnModel.getMainProcess().getId() + \".bpmn20.xml\";\n      response.setHeader(\"Content-Disposition\", \"attachment; filename=\" + filename);\n      response.flushBuffer();\n    } catch (Exception e) {\n      throw new ActivitiException(\"导出model的xml文件失败，模型ID=\" + id, e);\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/controller/ProcessController.java",
    "content": "package me.zbl.activity.controller;\n\nimport me.zbl.activity.service.ProcessService;\nimport me.zbl.activity.vo.ProcessVO;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.R;\nimport org.activiti.engine.ActivitiException;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.RuntimeService;\nimport org.activiti.engine.repository.Deployment;\nimport org.activiti.engine.repository.ProcessDefinition;\nimport org.apache.commons.io.FilenameUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\n\nimport javax.servlet.http.HttpServletResponse;\nimport javax.xml.stream.XMLStreamException;\nimport java.io.InputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.zip.ZipInputStream;\n\n@RequestMapping(\"activiti/process\")\n@RestController\npublic class ProcessController extends BaseController {\n\n  @Autowired\n  private RepositoryService repositoryService;\n\n  @Autowired\n  private ProcessService processService;\n\n  @Autowired\n  private RuntimeService runtimeService;\n\n  @GetMapping\n  ModelAndView process() {\n    return new ModelAndView(\"act/process/process\");\n  }\n\n  @GetMapping(\"list\")\n  PageWrapper list(int offset, int limit) {\n    List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()\n            .listPage(offset, limit);\n    int count = (int) repositoryService.createProcessDefinitionQuery().count();\n    List<Object> list = new ArrayList<>();\n    for (ProcessDefinition processDefinition : processDefinitions) {\n      list.add(new ProcessVO(processDefinition));\n    }\n    PageWrapper pageWrapper = new PageWrapper(list, count);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n  public ModelAndView add() {\n    return new ModelAndView(\"act/process/add\");\n  }\n\n  @PostMapping(\"/save\")\n  @Transactional(readOnly = false)\n  public R deploy(String exportDir, String category, MultipartFile file) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    String message = \"\";\n    String fileName = file.getOriginalFilename();\n    try {\n      InputStream fileInputStream = file.getInputStream();\n      Deployment deployment = null;\n      String extension = FilenameUtils.getExtension(fileName);\n      if (extension.equals(\"zip\") || extension.equals(\"bar\")) {\n        ZipInputStream zip = new ZipInputStream(fileInputStream);\n        deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();\n      } else if (extension.equals(\"png\")) {\n        deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();\n      } else if (fileName.indexOf(\"bpmn20.xml\") != -1) {\n        deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();\n      } else if (extension.equals(\"bpmn\")) { // bpmn扩展名特殊处理，转换为bpmn20.xml\n        String baseName = FilenameUtils.getBaseName(fileName);\n        deployment = repositoryService.createDeployment().addInputStream(baseName + \".bpmn20.xml\", fileInputStream).deploy();\n      } else {\n        message = \"不支持的文件类型：\" + extension;\n      }\n\n      List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();\n\n      // 设置流程分类\n      for (ProcessDefinition processDefinition : list) {\n        //\t\t\t\t\tActUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);\n        repositoryService.setProcessDefinitionCategory(processDefinition.getId(), category);\n        message += \"部署成功，流程ID=\" + processDefinition.getId() + \"<br/>\";\n      }\n\n      if (list.size() == 0) {\n        message = \"部署失败，没有流程。\";\n      }\n\n    } catch (Exception e) {\n      throw new ActivitiException(\"部署失败！\", e);\n    }\n    return R.ok(message);\n  }\n\n  /**\n   * 将部署的流程转换为模型\n   *\n   * @param procDefId\n   * @param redirectAttributes\n   *\n   * @return\n   *\n   * @throws UnsupportedEncodingException\n   * @throws XMLStreamException\n   */\n  @RequestMapping(value = \"/convertToModel/{procDefId}\")\n  public R convertToModel(@PathVariable(\"procDefId\") String procDefId, RedirectAttributes redirectAttributes) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    org.activiti.engine.repository.Model modelData = null;\n    try {\n      modelData = processService.convertToModel(procDefId);\n      return R.ok(\"转换模型成功，模型ID=\" + modelData.getId());\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.ok(\"转换模型失败\");\n    }\n\n  }\n\n  @RequestMapping(value = \"/resource/read/{xml}/{id}\")\n  public void resourceRead(@PathVariable(\"xml\") String resType, @PathVariable(\"id\") String id, HttpServletResponse response) throws Exception {\n    InputStream resourceAsStream = processService.resourceRead(id, resType);\n    byte[] b = new byte[1024];\n    int len = -1;\n    while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {\n      response.getOutputStream().write(b, 0, len);\n    }\n  }\n\n  @PostMapping(\"/remove\")\n  public R remove(String id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    repositoryService.deleteDeployment(id, true);\n    return R.ok();\n  }\n\n  @PostMapping(\"/batchRemove\")\n  public R batchRemove(@RequestParam(\"ids[]\") String[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    for (String id : ids) {\n      repositoryService.deleteDeployment(id, true);\n    }\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/controller/SalaryController.java",
    "content": "package me.zbl.activity.controller;\n\nimport me.zbl.activity.domain.SalaryDO;\nimport me.zbl.activity.service.SalaryService;\nimport me.zbl.activity.utils.ActivitiUtils;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport me.zbl.common.utils.ShiroUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 审批流程测试表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-11-25 13:33:16\n */\n\n@Controller\n@RequestMapping(\"/act/salary\")\npublic class SalaryController extends BaseController {\n\n  @Autowired\n  ActivitiUtils activitiUtils;\n  @Autowired\n  private SalaryService salaryService;\n\n  @GetMapping()\n  String Salary() {\n    return \"activity/salary/salary\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<SalaryDO> salaryList = salaryService.list(query);\n    int total = salaryService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(salaryList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/form\")\n  String add() {\n    return \"act/salary/add\";\n  }\n\n  @GetMapping(\"/form/{taskId}\")\n  String edit(@PathVariable(\"taskId\") String taskId, Model model) {\n    SalaryDO salary = salaryService.get(activitiUtils.getBusinessKeyByTaskId(taskId));\n    salary.setTaskId(taskId);\n    model.addAttribute(\"salary\", salary);\n    return \"act/salary/edit\";\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  public R saveOrUpdate(SalaryDO salary) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    salary.setCreateDate(new Date());\n    salary.setUpdateDate(new Date());\n    salary.setCreateBy(ShiroUtils.getUserId().toString());\n    salary.setUpdateBy(ShiroUtils.getUserId().toString());\n    salary.setDelFlag(\"1\");\n    if (salaryService.save(salary) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @ResponseBody\n  @RequestMapping(\"/update\")\n  public R update(SalaryDO salary) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    String taskKey = activitiUtils.getTaskByTaskId(salary.getTaskId()).getTaskDefinitionKey();\n    if (\"audit2\".equals(taskKey)) {\n      salary.setHrText(salary.getTaskComment());\n    } else if (\"audit3\".equals(taskKey)) {\n      salary.setLeadText(salary.getTaskComment());\n    } else if (\"audit4\".equals(taskKey)) {\n      salary.setMainLeadText(salary.getTaskComment());\n    } else if (\"apply_end\".equals(salary.getTaskComment())) {\n      //流程完成，兑现\n    }\n    salaryService.update(salary);\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  public R remove(String id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (salaryService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  public R remove(@RequestParam(\"ids[]\") String[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    salaryService.batchRemove(ids);\n    return R.ok();\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/controller/TaskController.java",
    "content": "package me.zbl.activity.controller;\n\nimport me.zbl.activity.service.ActTaskService;\nimport me.zbl.activity.vo.ProcessVO;\nimport me.zbl.activity.vo.TaskVO;\nimport me.zbl.common.utils.PageWrapper;\nimport org.activiti.engine.FormService;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.TaskService;\nimport org.activiti.engine.repository.ProcessDefinition;\nimport org.activiti.engine.task.Task;\nimport org.springframework.beans.factory.annotation.Autowired;\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;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n *\n */\n@RequestMapping(\"activiti/task\")\n@RestController\npublic class TaskController {\n\n  @Autowired\n  RepositoryService repositoryService;\n  @Autowired\n  FormService formService;\n  @Autowired\n  TaskService taskService;\n  @Autowired\n  ActTaskService actTaskService;\n\n  @GetMapping(\"goto\")\n  public ModelAndView gotoTask() {\n    return new ModelAndView(\"act/task/gotoTask\");\n  }\n\n  @GetMapping(\"/gotoList\")\n  PageWrapper list(int offset, int limit) {\n    List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()\n            .listPage(offset, limit);\n    int count = (int) repositoryService.createProcessDefinitionQuery().count();\n    List<Object> list = new ArrayList<>();\n    for (ProcessDefinition processDefinition : processDefinitions) {\n      list.add(new ProcessVO(processDefinition));\n    }\n\n    PageWrapper pageWrapper = new PageWrapper(list, count);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/form/{procDefId}\")\n  public void startForm(@PathVariable(\"procDefId\") String procDefId, HttpServletResponse response) throws IOException {\n    String formKey = actTaskService.getFormKey(procDefId, null);\n    response.sendRedirect(formKey);\n  }\n\n  @GetMapping(\"/form/{procDefId}/{taskId}\")\n  public void form(@PathVariable(\"procDefId\") String procDefId, @PathVariable(\"taskId\") String taskId, HttpServletResponse response) throws IOException {\n    // 获取流程XML上的表单KEY\n\n    String formKey = actTaskService.getFormKey(procDefId, taskId);\n\n\n    response.sendRedirect(formKey + \"/\" + taskId);\n  }\n\n  @GetMapping(\"/todo\")\n  ModelAndView todo() {\n    return new ModelAndView(\"act/task/todoTask\");\n  }\n\n  @GetMapping(\"/todoList\")\n  List<TaskVO> todoList() {\n    List<Task> tasks = taskService.createTaskQuery().taskAssignee(\"admin\").list();\n    List<TaskVO> taskVOS = new ArrayList<>();\n    for (Task task : tasks) {\n      TaskVO taskVO = new TaskVO(task);\n      taskVOS.add(taskVO);\n    }\n    return taskVOS;\n  }\n\n\n  /**\n   * 读取带跟踪的图片\n   */\n  @RequestMapping(value = \"/trace/photo/{procDefId}/{execId}\")\n  public void tracePhoto(@PathVariable(\"procDefId\") String procDefId, @PathVariable(\"execId\") String execId, HttpServletResponse response) throws Exception {\n    InputStream imageStream = actTaskService.tracePhoto(procDefId, execId);\n\n    // 输出资源内容到相应对象\n    byte[] b = new byte[1024];\n    int len;\n    while ((len = imageStream.read(b, 0, 1024)) != -1) {\n      response.getOutputStream().write(b, 0, len);\n    }\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/dao/SalaryDao.java",
    "content": "package me.zbl.activity.dao;\n\nimport me.zbl.activity.domain.SalaryDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 审批流程测试表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-11-25 13:28:58\n */\n@Mapper\npublic interface SalaryDao {\n\n  SalaryDO get(String id);\n\n  List<SalaryDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(SalaryDO salary);\n\n  int update(SalaryDO salary);\n\n  int remove(String id);\n\n  int batchRemove(String[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/domain/ActivitiDO.java",
    "content": "package me.zbl.activity.domain;\n\nimport org.activiti.engine.history.HistoricActivityInstance;\nimport org.activiti.engine.history.HistoricTaskInstance;\nimport org.activiti.engine.repository.ProcessDefinition;\nimport org.activiti.engine.runtime.ProcessInstance;\nimport org.activiti.engine.task.Task;\n\nimport java.util.Date;\nimport java.util.List;\n\n/**\n *\n */\npublic class ActivitiDO {\n\n    private String taskId;        // 任务编号\n    private String taskName;    // 任务名称\n    private String taskDefKey;    // 任务定义Key（任务环节标识）\n\n    private String procInsId;    // 流程实例ID\n    private String procDefId;    // 流程定义ID\n    private String procDefKey;    // 流程定义Key（流程定义标识）\n\n    private String businessTable;    // 业务绑定Table\n    private String businessId;        // 业务绑定ID\n\n    private String title;        // 任务标题\n\n    private String status;        // 任务状态（todo/claim/finish）\n\n    private String procExecUrl;    // 流程执行（办理）RUL\n    private String comment;    // 任务意见\n    private String flag;        // 意见状态\n\n    private Task task;            // 任务对象\n    private ProcessDefinition procDef;    // 流程定义对象\n    private ProcessInstance procIns;    // 流程实例对象\n    private HistoricTaskInstance histTask; // 历史任务\n    private HistoricActivityInstance histIns;    //历史活动任务\n\n    private String assignee; // 任务执行人编号\n    private String assigneeName; // 任务执行人名称\n\n    private Variable vars;        // 流程变量\n    private Variable taskVars;    // 流程任务变量\n\n    private Date beginDate;    // 开始查询日期\n    private Date endDate;    // 结束查询日期\n\n    private List<ActivitiDO> list; // 任务列表\n\n    public String getTaskId() {\n        return taskId;\n    }\n\n    public void setTaskId(String taskId) {\n        this.taskId = taskId;\n    }\n\n    public String getTaskName() {\n        return taskName;\n    }\n\n    public void setTaskName(String taskName) {\n        this.taskName = taskName;\n    }\n\n    public String getTaskDefKey() {\n        return taskDefKey;\n    }\n\n    public void setTaskDefKey(String taskDefKey) {\n        this.taskDefKey = taskDefKey;\n    }\n\n    public String getProcInsId() {\n        return procInsId;\n    }\n\n    public void setProcInsId(String procInsId) {\n        this.procInsId = procInsId;\n    }\n\n    public String getProcDefId() {\n        return procDefId;\n    }\n\n    public void setProcDefId(String procDefId) {\n        this.procDefId = procDefId;\n    }\n\n    public String getProcDefKey() {\n        return procDefKey;\n    }\n\n    public void setProcDefKey(String procDefKey) {\n        this.procDefKey = procDefKey;\n    }\n\n    public String getBusinessTable() {\n        return businessTable;\n    }\n\n    public void setBusinessTable(String businessTable) {\n        this.businessTable = businessTable;\n    }\n\n    public String getBusinessId() {\n        return businessId;\n    }\n\n    public void setBusinessId(String businessId) {\n        this.businessId = businessId;\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 String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public String getProcExecUrl() {\n        return procExecUrl;\n    }\n\n    public void setProcExecUrl(String procExecUrl) {\n        this.procExecUrl = procExecUrl;\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 getFlag() {\n        return flag;\n    }\n\n    public void setFlag(String flag) {\n        this.flag = flag;\n    }\n\n    public Task getTask() {\n        return task;\n    }\n\n    public void setTask(Task task) {\n        this.task = task;\n    }\n\n    public ProcessDefinition getProcDef() {\n        return procDef;\n    }\n\n    public void setProcDef(ProcessDefinition procDef) {\n        this.procDef = procDef;\n    }\n\n    public ProcessInstance getProcIns() {\n        return procIns;\n    }\n\n    public void setProcIns(ProcessInstance procIns) {\n        this.procIns = procIns;\n    }\n\n    public HistoricTaskInstance getHistTask() {\n        return histTask;\n    }\n\n    public void setHistTask(HistoricTaskInstance histTask) {\n        this.histTask = histTask;\n    }\n\n    public HistoricActivityInstance getHistIns() {\n        return histIns;\n    }\n\n    public void setHistIns(HistoricActivityInstance histIns) {\n        this.histIns = histIns;\n    }\n\n    public String getAssignee() {\n        return assignee;\n    }\n\n    public void setAssignee(String assignee) {\n        this.assignee = assignee;\n    }\n\n    public String getAssigneeName() {\n        return assigneeName;\n    }\n\n    public void setAssigneeName(String assigneeName) {\n        this.assigneeName = assigneeName;\n    }\n\n    public Variable getVars() {\n        return vars;\n    }\n\n    public void setVars(Variable vars) {\n        this.vars = vars;\n    }\n\n    public Variable getTaskVars() {\n        return taskVars;\n    }\n\n    public void setTaskVars(Variable taskVars) {\n        this.taskVars = taskVars;\n    }\n\n    public Date getBeginDate() {\n        return beginDate;\n    }\n\n    public void setBeginDate(Date beginDate) {\n        this.beginDate = beginDate;\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 List<ActivitiDO> getList() {\n        return list;\n    }\n\n    public void setList(List<ActivitiDO> list) {\n        this.list = list;\n    }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/domain/SalaryDO.java",
    "content": "package me.zbl.activity.domain;\n\nimport org.springframework.format.annotation.DateTimeFormat;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n\n/**\n * 审批流程测试表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-11-25 13:28:58\n */\npublic class SalaryDO extends TaskDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //编号\n  private String id;\n  //流程实例ID\n  private String procInsId;\n  //变动用户\n  private String userId;\n  //归属部门\n  private String officeId;\n  //岗位\n  private String post;\n  //性别\n  private String age;\n  //学历\n  private String edu;\n  //调整原因\n  private String content;\n  //现行标准 薪酬档级\n  private String olda;\n  //现行标准 月工资额\n  private String oldb;\n  //现行标准 年薪总额\n  private String oldc;\n  //调整后标准 薪酬档级\n  private String newa;\n  //调整后标准 月工资额\n  private String newb;\n  //调整后标准 年薪总额\n  private String newc;\n  //月增资\n  private String addNum;\n  //执行时间\n  private String exeDate;\n  //人力资源部门意见\n  private String hrText;\n  //分管领导意见\n  private String leadText;\n  //集团主要领导意见\n  private String mainLeadText;\n  //创建者\n  private String createBy;\n  //创建时间\n  @DateTimeFormat(pattern = \"yyyy-MM-dd\")\n  private Date createDate;\n  //更新者\n  private String updateBy;\n  //更新时间\n  @DateTimeFormat(pattern = \"yyyy-MM-dd\")\n  private Date updateDate;\n  //备注信息\n  private String remarks;\n  //删除标记\n  private String delFlag;\n\n  /**\n   * 获取：编号\n   */\n  public String getId() {\n    return id;\n  }\n\n  /**\n   * 设置：编号\n   */\n  public void setId(String id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：流程实例ID\n   */\n  public String getProcInsId() {\n    return procInsId;\n  }\n\n  /**\n   * 设置：流程实例ID\n   */\n  public void setProcInsId(String procInsId) {\n    this.procInsId = procInsId;\n  }\n\n  /**\n   * 获取：变动用户\n   */\n  public String getUserId() {\n    return userId;\n  }\n\n  /**\n   * 设置：变动用户\n   */\n  public void setUserId(String userId) {\n    this.userId = userId;\n  }\n\n  /**\n   * 获取：归属部门\n   */\n  public String getOfficeId() {\n    return officeId;\n  }\n\n  /**\n   * 设置：归属部门\n   */\n  public void setOfficeId(String officeId) {\n    this.officeId = officeId;\n  }\n\n  /**\n   * 获取：岗位\n   */\n  public String getPost() {\n    return post;\n  }\n\n  /**\n   * 设置：岗位\n   */\n  public void setPost(String post) {\n    this.post = post;\n  }\n\n  /**\n   * 获取：性别\n   */\n  public String getAge() {\n    return age;\n  }\n\n  /**\n   * 设置：性别\n   */\n  public void setAge(String age) {\n    this.age = age;\n  }\n\n  /**\n   * 获取：学历\n   */\n  public String getEdu() {\n    return edu;\n  }\n\n  /**\n   * 设置：学历\n   */\n  public void setEdu(String edu) {\n    this.edu = edu;\n  }\n\n  /**\n   * 获取：调整原因\n   */\n  public String getContent() {\n    return content;\n  }\n\n  /**\n   * 设置：调整原因\n   */\n  public void setContent(String content) {\n    this.content = content;\n  }\n\n  /**\n   * 获取：现行标准 薪酬档级\n   */\n  public String getOlda() {\n    return olda;\n  }\n\n  /**\n   * 设置：现行标准 薪酬档级\n   */\n  public void setOlda(String olda) {\n    this.olda = olda;\n  }\n\n  /**\n   * 获取：现行标准 月工资额\n   */\n  public String getOldb() {\n    return oldb;\n  }\n\n  /**\n   * 设置：现行标准 月工资额\n   */\n  public void setOldb(String oldb) {\n    this.oldb = oldb;\n  }\n\n  /**\n   * 获取：现行标准 年薪总额\n   */\n  public String getOldc() {\n    return oldc;\n  }\n\n  /**\n   * 设置：现行标准 年薪总额\n   */\n  public void setOldc(String oldc) {\n    this.oldc = oldc;\n  }\n\n  /**\n   * 获取：调整后标准 薪酬档级\n   */\n  public String getNewa() {\n    return newa;\n  }\n\n  /**\n   * 设置：调整后标准 薪酬档级\n   */\n  public void setNewa(String newa) {\n    this.newa = newa;\n  }\n\n  /**\n   * 获取：调整后标准 月工资额\n   */\n  public String getNewb() {\n    return newb;\n  }\n\n  /**\n   * 设置：调整后标准 月工资额\n   */\n  public void setNewb(String newb) {\n    this.newb = newb;\n  }\n\n  /**\n   * 获取：调整后标准 年薪总额\n   */\n  public String getNewc() {\n    return newc;\n  }\n\n  /**\n   * 设置：调整后标准 年薪总额\n   */\n  public void setNewc(String newc) {\n    this.newc = newc;\n  }\n\n  /**\n   * 获取：月增资\n   */\n  public String getAddNum() {\n    return addNum;\n  }\n\n  /**\n   * 设置：月增资\n   */\n  public void setAddNum(String addNum) {\n    this.addNum = addNum;\n  }\n\n  /**\n   * 获取：执行时间\n   */\n  public String getExeDate() {\n    return exeDate;\n  }\n\n  /**\n   * 设置：执行时间\n   */\n  public void setExeDate(String exeDate) {\n    this.exeDate = exeDate;\n  }\n\n  /**\n   * 获取：人力资源部门意见\n   */\n  public String getHrText() {\n    return hrText;\n  }\n\n  /**\n   * 设置：人力资源部门意见\n   */\n  public void setHrText(String hrText) {\n    this.hrText = hrText;\n  }\n\n  /**\n   * 获取：分管领导意见\n   */\n  public String getLeadText() {\n    return leadText;\n  }\n\n  /**\n   * 设置：分管领导意见\n   */\n  public void setLeadText(String leadText) {\n    this.leadText = leadText;\n  }\n\n  /**\n   * 获取：集团主要领导意见\n   */\n  public String getMainLeadText() {\n    return mainLeadText;\n  }\n\n  /**\n   * 设置：集团主要领导意见\n   */\n  public void setMainLeadText(String mainLeadText) {\n    this.mainLeadText = mainLeadText;\n  }\n\n  /**\n   * 获取：创建者\n   */\n  public String getCreateBy() {\n    return createBy;\n  }\n\n  /**\n   * 设置：创建者\n   */\n  public void setCreateBy(String createBy) {\n    this.createBy = createBy;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getCreateDate() {\n    return createDate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setCreateDate(Date createDate) {\n    this.createDate = createDate;\n  }\n\n  /**\n   * 获取：更新者\n   */\n  public String getUpdateBy() {\n    return updateBy;\n  }\n\n  /**\n   * 设置：更新者\n   */\n  public void setUpdateBy(String updateBy) {\n    this.updateBy = updateBy;\n  }\n\n  /**\n   * 获取：更新时间\n   */\n  public Date getUpdateDate() {\n    return updateDate;\n  }\n\n  /**\n   * 设置：更新时间\n   */\n  public void setUpdateDate(Date updateDate) {\n    this.updateDate = updateDate;\n  }\n\n  /**\n   * 获取：备注信息\n   */\n  public String getRemarks() {\n    return remarks;\n  }\n\n  /**\n   * 设置：备注信息\n   */\n  public void setRemarks(String remarks) {\n    this.remarks = remarks;\n  }\n\n  /**\n   * 获取：删除标记\n   */\n  public String getDelFlag() {\n    return delFlag;\n  }\n\n  /**\n   * 设置：删除标记\n   */\n  public void setDelFlag(String delFlag) {\n    this.delFlag = delFlag;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/domain/TaskDO.java",
    "content": "package me.zbl.activity.domain;\n\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n */\npublic class TaskDO {\n\n  private String taskId;\n  private String taskComment;\n  private String taskPass;\n  private Map<String, Object> vars;\n\n  public String getTaskId() {\n    return taskId;\n  }\n\n  public void setTaskId(String taskId) {\n    this.taskId = taskId;\n  }\n\n  public String getTaskComment() {\n    return taskComment;\n  }\n\n  public void setTaskComment(String taskComment) {\n    this.taskComment = taskComment;\n  }\n\n  public String getTaskPass() {\n    return taskPass;\n  }\n\n  public void setTaskPass(String taskPass) {\n    this.taskPass = taskPass;\n  }\n\n  public Map<String, Object> getVars() {\n    return vars;\n  }\n\n  public void setVars(Map<String, Object> vars) {\n    this.vars = vars;\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/domain/Variable.java",
    "content": "package me.zbl.activity.domain;\n\n\n/**\n *\n */\npublic class Variable {\n\n  private String keys;\n  private String values;\n  private String types;\n\n  public String getKeys() {\n    return keys;\n  }\n\n  public void setKeys(String keys) {\n    this.keys = keys;\n  }\n\n  public String getValues() {\n    return values;\n  }\n\n  public void setValues(String values) {\n    this.values = values;\n  }\n\n  public String getTypes() {\n    return types;\n  }\n\n  public void setTypes(String types) {\n    this.types = types;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/ActTaskService.java",
    "content": "package me.zbl.activity.service;\n\nimport me.zbl.activity.domain.ActivitiDO;\n\nimport java.io.InputStream;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n */\npublic interface ActTaskService {\n\n  List<ActivitiDO> listTodo(ActivitiDO act);\n\n  void complete(String taskId, String procInsId, String comment, String title, Map<String, Object> vars);\n\n  void complete(String taskId, Map<String, Object> vars);\n\n  String startProcess(String procDefKey, String businessTable, String businessId, String title, Map<String, Object> vars);\n\n  String getFormKey(String procDefId, String taskDefKey);\n\n  InputStream tracePhoto(String processDefinitionId, String executionId);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/ProcessService.java",
    "content": "package me.zbl.activity.service;\n\nimport org.activiti.engine.repository.Model;\nimport org.springframework.stereotype.Service;\n\nimport java.io.InputStream;\n\n/**\n\n */\n@Service\npublic interface ProcessService {\n\n  Model convertToModel(String procDefId) throws Exception;\n\n  InputStream resourceRead(String id, String resType) throws Exception;\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/SalaryService.java",
    "content": "package me.zbl.activity.service;\n\nimport me.zbl.activity.domain.SalaryDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 审批流程测试表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-11-25 13:33:16\n */\npublic interface SalaryService {\n\n  SalaryDO get(String id);\n\n  List<SalaryDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(SalaryDO salary);\n\n  int update(SalaryDO salary);\n\n  int remove(String id);\n\n  int batchRemove(String[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/impl/ActTaskServiceImpl.java",
    "content": "package me.zbl.activity.service.impl;\n\nimport me.zbl.activity.domain.ActivitiDO;\nimport me.zbl.activity.service.ActTaskService;\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.common.utils.StringUtils;\nimport org.activiti.bpmn.model.BpmnModel;\nimport org.activiti.engine.*;\nimport org.activiti.engine.history.HistoricActivityInstance;\nimport org.activiti.engine.history.HistoricProcessInstance;\nimport org.activiti.engine.impl.RepositoryServiceImpl;\nimport org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;\nimport org.activiti.engine.impl.pvm.PvmTransition;\nimport org.activiti.engine.impl.pvm.process.ActivityImpl;\nimport org.activiti.engine.runtime.ProcessInstance;\nimport org.activiti.engine.task.Task;\nimport org.activiti.image.ProcessDiagramGenerator;\nimport org.activiti.spring.ProcessEngineFactoryBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n *\n */\n@Service\npublic class ActTaskServiceImpl implements ActTaskService {\n\n  @Autowired\n  TaskService taskService;\n  @Autowired\n  IdentityService identityService;\n  @Autowired\n  RuntimeService runtimeService;\n  @Autowired\n  FormService formService;\n\n  @Autowired\n  RepositoryService repositoryService;\n\n  @Autowired\n  private ProcessEngineFactoryBean processEngineFactory;\n\n  @Autowired\n  private ProcessEngine processEngine;\n\n  @Autowired\n  private HistoryService historyService;\n\n  @Override\n  public List<ActivitiDO> listTodo(ActivitiDO act) {\n    String userId = String.valueOf(ShiroUtils.getUserId());\n    List<ActivitiDO> result = new ArrayList<ActivitiDO>();\n    return result;\n  }\n\n  /**\n   * 提交任务, 并保存意见\n   *\n   * @param taskId    任务ID\n   * @param procInsId 流程实例ID，如果为空，则不保存任务提交意见\n   * @param comment   任务提交意见的内容\n   * @param title     流程标题，显示在待办任务标题\n   * @param vars      任务变量\n   */\n  @Override\n  public void complete(String taskId, String procInsId, String comment, String title, Map<String, Object> vars) {\n    // 添加意见\n    if (StringUtils.isNotBlank(procInsId) && StringUtils.isNotBlank(comment)) {\n      taskService.addComment(taskId, procInsId, comment);\n    }\n\n    // 设置流程变量\n    if (vars == null) {\n      vars = new HashMap<>();\n    }\n\n    // 设置流程标题\n    if (StringUtils.isNotBlank(title)) {\n      vars.put(\"title\", title);\n    }\n\n    // 提交任务\n    taskService.complete(taskId, vars);\n  }\n\n  @Override\n  public void complete(String taskId, Map<String, Object> vars) {\n    // 2.1根据人物ID查询流程实力ID\n    Task task = taskService.createTaskQuery()\n            .taskId(taskId).singleResult();\n    // 获取流程实例ID\n    String processInstance = task.getProcessInstanceId();\n    // 2.2根据流程实例ID，人物ID，评论的消息，保存教师或者学术对与该学生申请的评论信息\n    //        taskService.addComment(taskId,\n    //                processInstance, \"\");\n    //        Map<String,Object> vars = new HashMap<>();\n    //        vars.put(\"pass\",  \"1\" );\n    //        vars.put(\"title\",\"\");\n    taskService.complete(taskId, vars);\n  }\n\n  /**\n   * 启动流程\n   *\n   * @param procDefKey    流程定义KEY\n   * @param businessTable 业务表表名\n   * @param businessId    业务表编号\n   * @param title         流程标题，显示在待办任务标题\n   * @param vars          流程变量\n   *\n   * @return 流程实例ID\n   */\n  @Override\n  public String startProcess(String procDefKey, String businessTable, String businessId, String title, Map<String, Object> vars) {\n    String userId = ShiroUtils.getUser().getUsername();//ObjectUtils.toString(UserUtils.getUser().getId())\n\n    // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中\n    identityService.setAuthenticatedUserId(userId);\n\n    // 设置流程变量\n    if (vars == null) {\n      vars = new HashMap();\n    }\n\n    // 设置流程标题\n    if (StringUtils.isNotBlank(title)) {\n      vars.put(\"title\", title);\n    }\n\n    // 启动流程\n    ProcessInstance procIns = runtimeService.startProcessInstanceByKey(procDefKey, businessId, vars);\n\n    return null;\n  }\n\n  /**\n   * 获取流程表单（首先获取任务节点表单KEY，如果没有则取流程开始节点表单KEY）\n   *\n   * @return\n   */\n  @Override\n  public String getFormKey(String procDefId, String taskDefKey) {\n    String formKey = \"\";\n    if (StringUtils.isNotBlank(procDefId)) {\n      if (StringUtils.isNotBlank(taskDefKey)) {\n        try {\n          formKey = formService.getTaskFormKey(procDefId, taskDefKey);\n        } catch (Exception e) {\n          formKey = \"\";\n        }\n      }\n      if (StringUtils.isBlank(formKey)) {\n        formKey = formService.getStartFormKey(procDefId);\n      }\n      if (StringUtils.isBlank(formKey)) {\n        formKey = \"/404\";\n      }\n    }\n    return formKey;\n  }\n\n  @Override\n  public InputStream tracePhoto(String xx, String pProcessInstanceId) {\n    ////\t\tProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();\n    //        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);\n    //\n    //        List<String> activeActivityIds = new ArrayList();\n    //        if (runtimeService.createExecutionQuery().executionId(executionId).count() > 0){\n    //            activeActivityIds = runtimeService.getActiveActivityIds(executionId);\n    //        }\n    //\n    //        // 不使用spring请使用下面的两行代码\n    //        // ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl)ProcessEngines.getDefaultProcessEngine();\n    //        // Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());\n    //\n    //        // 使用spring注入引擎请使用下面的这行代码\n    //        Context.setProcessEngineConfiguration(processEngineFactory.getProcessEngineConfiguration());\n    ////\t\treturn ProcessDiagramGenerator.generateDiagram(bpmnModel, \"png\", activeActivityIds);\n    //        return processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator()\n    //                .generateDiagram(bpmnModel, \"png\", activeActivityIds);\n\n    //  获取历史流程实例\n    HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()\n            .processInstanceId(pProcessInstanceId).singleResult();\n\n    if (historicProcessInstance != null) {\n      // 获取流程定义\n      ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)\n              .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());\n\n      // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序\n      List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()\n              .processInstanceId(pProcessInstanceId).orderByHistoricActivityInstanceId().asc().list();\n\n      // 已执行的节点ID集合\n      List<String> executedActivityIdList = new ArrayList<String>();\n      int index = 1;\n      //获取已经执行的节点ID\n      for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {\n        executedActivityIdList.add(activityInstance.getActivityId());\n        index++;\n      }\n\n      // 已执行的线集合\n      List<String> flowIds = new ArrayList<String>();\n      // 获取流程走过的线\n      flowIds = getHighLightedFlows(processDefinition, historicActivityInstanceList);\n\n\n      BpmnModel bpmnModel = repositoryService\n              .getBpmnModel(historicProcessInstance.getProcessDefinitionId());\n      // 获取流程图图像字符流\n      ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();\n      //配置字体\n\n      InputStream imageStream = pec.generateDiagram(bpmnModel, \"png\", executedActivityIdList, flowIds, \"宋体\", \"微软雅黑\", \"黑体\", null, 2.0);\n      return imageStream;\n    }\n    return null;\n  }\n\n\n  /**\n   * 获取需要高亮的线\n   *\n   * @param processDefinitionEntity\n   * @param historicActivityInstances\n   *\n   * @return\n   */\n  private List<String> getHighLightedFlows(\n          ProcessDefinitionEntity processDefinitionEntity,\n          List<HistoricActivityInstance> historicActivityInstances) {\n    List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId\n    for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 对历史流程节点进行遍历\n      ActivityImpl activityImpl = processDefinitionEntity\n              .findActivity(historicActivityInstances.get(i)\n                      .getActivityId());// 得到节点定义的详细信息\n      List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用以保存后需开始时间相同的节点\n      ActivityImpl sameActivityImpl1 = processDefinitionEntity\n              .findActivity(historicActivityInstances.get(i + 1)\n                      .getActivityId());\n      // 将后面第一个节点放在时间相同节点的集合里\n      sameStartTimeNodes.add(sameActivityImpl1);\n      for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {\n        HistoricActivityInstance activityImpl1 = historicActivityInstances\n                .get(j);// 后续第一个节点\n        HistoricActivityInstance activityImpl2 = historicActivityInstances\n                .get(j + 1);// 后续第二个节点\n        if (activityImpl1.getStartTime().equals(\n                activityImpl2.getStartTime())) {\n          // 如果第一个节点和第二个节点开始时间相同保存\n          ActivityImpl sameActivityImpl2 = processDefinitionEntity\n                  .findActivity(activityImpl2.getActivityId());\n          sameStartTimeNodes.add(sameActivityImpl2);\n        } else {\n          // 有不相同跳出循环\n          break;\n        }\n      }\n      List<PvmTransition> pvmTransitions = activityImpl\n              .getOutgoingTransitions();// 取出节点的所有出去的线\n      for (PvmTransition pvmTransition : pvmTransitions) {\n        // 对所有的线进行遍历\n        ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition\n                .getDestination();\n        // 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示\n        if (sameStartTimeNodes.contains(pvmActivityImpl)) {\n          highFlows.add(pvmTransition.getId());\n        }\n      }\n    }\n    return highFlows;\n  }\n\n}\n\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/impl/ProcessServiceImpl.java",
    "content": "package me.zbl.activity.service.impl;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport me.zbl.activity.service.ProcessService;\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.RepositoryService;\nimport org.activiti.engine.RuntimeService;\nimport org.activiti.engine.repository.Model;\nimport org.activiti.engine.repository.ProcessDefinition;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport javax.xml.stream.XMLInputFactory;\nimport javax.xml.stream.XMLStreamReader;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\n\n/**\n\n */\n@Service\npublic class ProcessServiceImpl implements ProcessService {\n\n  @Autowired\n  RepositoryService repositoryService;\n  @Autowired\n  RuntimeService runtimeService;\n\n  @Override\n  public Model convertToModel(String procDefId) throws Exception {\n\n    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();\n    InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),\n            processDefinition.getResourceName());\n    XMLInputFactory xif = XMLInputFactory.newInstance();\n    InputStreamReader in = new InputStreamReader(bpmnStream, \"UTF-8\");\n    XMLStreamReader xtr = xif.createXMLStreamReader(in);\n    BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);\n\n    BpmnJsonConverter converter = new BpmnJsonConverter();\n    ObjectNode modelNode = converter.convertToJson(bpmnModel);\n    org.activiti.engine.repository.Model modelData = repositoryService.newModel();\n    modelData.setKey(processDefinition.getKey());\n    modelData.setName(processDefinition.getResourceName());\n    modelData.setCategory(processDefinition.getCategory());//.getDeploymentId());\n    modelData.setDeploymentId(processDefinition.getDeploymentId());\n    modelData.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(modelData.getKey()).count() + 1)));\n\n    ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();\n    modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());\n    modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, modelData.getVersion());\n    modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());\n    modelData.setMetaInfo(modelObjectNode.toString());\n\n    repositoryService.saveModel(modelData);\n\n    repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes(\"utf-8\"));\n\n    return modelData;\n  }\n\n  @Override\n  public InputStream resourceRead(String id, String resType) {\n\n\n    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();\n\n\n    String resourceName = \"\";\n    if (resType.equals(\"image\")) {\n      resourceName = processDefinition.getDiagramResourceName();\n    } else if (resType.equals(\"xml\")) {\n      resourceName = processDefinition.getResourceName();\n    }\n\n    InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);\n    return resourceAsStream;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/service/impl/SalaryServiceImpl.java",
    "content": "package me.zbl.activity.service.impl;\n\nimport me.zbl.activity.config.ActivitiConstant;\nimport me.zbl.activity.dao.SalaryDao;\nimport me.zbl.activity.domain.SalaryDO;\nimport me.zbl.activity.service.SalaryService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\n\n\n@Service\npublic class SalaryServiceImpl implements SalaryService {\n\n  @Autowired\n  private SalaryDao salaryDao;\n  @Autowired\n  private ActTaskServiceImpl actTaskService;\n\n  @Override\n  public SalaryDO get(String id) {\n    return salaryDao.get(id);\n  }\n\n  @Override\n  public List<SalaryDO> list(Map<String, Object> map) {\n    return salaryDao.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return salaryDao.count(map);\n  }\n\n  @Transactional(rollbackFor = Exception.class)\n  @Override\n  public int save(SalaryDO salary) {\n    salary.setId(UUID.randomUUID().toString().replace(\"-\", \"\"));\n    actTaskService.startProcess(ActivitiConstant.ACTIVITI_SALARY[0], ActivitiConstant.ACTIVITI_SALARY[1], salary.getId(), salary.getContent(), new HashMap<>());\n    return salaryDao.save(salary);\n  }\n\n  @Transactional(rollbackFor = Exception.class)\n  @Override\n  public int update(SalaryDO salary) {\n    Map<String, Object> vars = new HashMap<>(16);\n    vars.put(\"pass\", salary.getTaskPass());\n    vars.put(\"title\", \"\");\n    actTaskService.complete(salary.getTaskId(), vars);\n    return salaryDao.update(salary);\n  }\n\n  @Override\n  public int remove(String id) {\n    return salaryDao.remove(id);\n  }\n\n  @Override\n  public int batchRemove(String[] ids) {\n    return salaryDao.batchRemove(ids);\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/utils/ActivitiUtils.java",
    "content": "package me.zbl.activity.utils;\n\nimport org.activiti.engine.RuntimeService;\nimport org.activiti.engine.TaskService;\nimport org.activiti.engine.runtime.ProcessInstance;\nimport org.activiti.engine.task.Task;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n\n */\n@Component\npublic class ActivitiUtils {\n\n  /**\n   * 根据taskId查找businessKey\n   */\n  @Autowired\n  TaskService taskService;\n  @Autowired\n  RuntimeService runtimeService;\n\n  public String getBusinessKeyByTaskId(String taskId) {\n    Task task = taskService\n            .createTaskQuery()\n            .taskId(taskId)\n            .singleResult();\n    ProcessInstance pi = runtimeService\n            .createProcessInstanceQuery()\n            .processInstanceId(task.getProcessInstanceId())\n            .singleResult();\n    return pi.getBusinessKey();\n  }\n\n  public Task getTaskByTaskId(String taskId) {\n    Task task = taskService\n            .createTaskQuery()\n            .taskId(taskId)\n            .singleResult();\n    return task;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/vo/DeploymentResponse.java",
    "content": "package me.zbl.activity.vo;\n\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport org.activiti.engine.repository.Deployment;\nimport org.activiti.rest.common.util.DateToStringSerializer;\n\nimport java.util.Date;\n\npublic class DeploymentResponse {\n\n  private String id;\n  private String name;\n  @JsonSerialize(using = DateToStringSerializer.class, as = Date.class)\n  private Date deploymentTime;\n  private String category;\n  private String tenantId;\n\n  public DeploymentResponse(Deployment deployment) {\n    setId(deployment.getId());\n    setName(deployment.getName());\n    setDeploymentTime(deployment.getDeploymentTime());\n    setCategory(deployment.getCategory());\n    setTenantId(deployment.getTenantId());\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String 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 Date getDeploymentTime() {\n    return deploymentTime;\n  }\n\n  public void setDeploymentTime(Date deploymentTime) {\n    this.deploymentTime = deploymentTime;\n  }\n\n  public String getCategory() {\n    return category;\n  }\n\n  public void setCategory(String category) {\n    this.category = category;\n  }\n\n  public String getTenantId() {\n    return tenantId;\n  }\n\n  public void setTenantId(String tenantId) {\n    this.tenantId = tenantId;\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/activity/vo/ProcessVO.java",
    "content": "package me.zbl.activity.vo;\n\nimport org.activiti.engine.repository.Deployment;\nimport org.activiti.engine.repository.ProcessDefinition;\n\npublic class ProcessVO {\n\n  private String id;\n  private String name;\n  private String deploymentId;\n\n  public ProcessVO(Deployment processDefinition) {\n    this.setId(processDefinition.getId());\n    this.name = processDefinition.getName();\n  }\n\n  public ProcessVO(ProcessDefinition processDefinition) {\n    this.setId(processDefinition.getId());\n    this.name = processDefinition.getName();\n    this.deploymentId = processDefinition.getDeploymentId();\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String 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 getDeploymentId() {\n    return deploymentId;\n  }\n\n  public void setDeploymentId(String deploymentId) {\n    this.deploymentId = deploymentId;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/activity/vo/TaskVO.java",
    "content": "package me.zbl.activity.vo;\n\nimport org.activiti.engine.task.Task;\n\n/**\n\n */\npublic class TaskVO {\n\n  private String id;\n  private String name;\n  private String key;\n  private String description;\n  private String formKey;\n  private String assignee;\n  private String processId;\n  private String processDefinitionId;\n  private String executionId;\n\n  public TaskVO(Task task) {\n\n    this.setId(task.getId());\n    this.setKey(task.getTaskDefinitionKey());\n    this.setName(task.getName());\n    this.setDescription(task.getDescription());\n    this.setAssignee(task.getAssignee());\n    this.setFormKey(task.getFormKey());\n    this.setProcessId(task.getProcessInstanceId());\n    this.setProcessDefinitionId(task.getProcessDefinitionId());\n    this.setExecutionId(task.getExecutionId());\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String id) {\n    this.id = id;\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 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  public String getFormKey() {\n    return formKey;\n  }\n\n  public void setFormKey(String formKey) {\n    this.formKey = formKey;\n  }\n\n  public String getAssignee() {\n    return assignee;\n  }\n\n  public void setAssignee(String assignee) {\n    this.assignee = assignee;\n  }\n\n  public String getProcessId() {\n    return processId;\n  }\n\n  public void setProcessId(String processId) {\n    this.processId = processId;\n  }\n\n  public String getProcessDefinitionId() {\n    return processDefinitionId;\n  }\n\n  public void setProcessDefinitionId(String processDefinitionId) {\n    this.processDefinitionId = processDefinitionId;\n  }\n\n  public String getExecutionId() {\n    return executionId;\n  }\n\n  public void setExecutionId(String executionId) {\n    this.executionId = executionId;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/ConsumerController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.Consumer;\nimport me.zbl.app.service.ConsumerService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 顾客管理\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-19\n */\n@Controller\npublic class ConsumerController {\n\n  @Autowired\n  private ConsumerService consumerService;\n\n  @GetMapping(\"/consumer/index\")\n  public String index() {\n    return \"app/data-maintenance/consumer/index\";\n  }\n\n  @GetMapping(\"/consumer/add\")\n  public String add() {\n    return \"app/data-maintenance/consumer/add\";\n  }\n\n  @GetMapping(\"/consumer/edit/{id}\")\n  public String edit(@PathVariable(\"id\") String id, Model model) {\n    Consumer find = consumerService.selectByPrimaryKey(id);\n    model.addAttribute(\"consumer\", find);\n    return \"app/data-maintenance/consumer/edit\";\n  }\n\n  /**\n   * 顾客列表\n   */\n  @GetMapping(\"/consumer/list\")\n  @ResponseBody\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<Consumer> consumers = consumerService.selectAllConsumer(query);\n    return new PageWrapper(consumers, consumerService.count());\n  }\n\n  /**\n   * 顾客保存\n   */\n  @PostMapping(\"/consumer/save\")\n  @ResponseBody\n  public R save(Consumer consumer) {\n    try {\n      consumerService.insertConsumer(consumer);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  /**\n   * 顾客更新\n   */\n  @PutMapping(\"/consumer/save\")\n  @ResponseBody\n  public R saveUpdate(Consumer consumer) {\n    try {\n      consumerService.updateConsumer(consumer);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  /**\n   * 顾客删除\n   */\n  @DeleteMapping(\"/consumer/remove/{id}\")\n  @ResponseBody\n  public R remove(@PathVariable(\"id\") String id) {\n    try {\n      consumerService.deleteConsumer(id);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  /**\n   * 下拉选择顾客\n   */\n  @GetMapping(\"/consumer/search\")\n  @ResponseBody\n  public Map<String, Object> search(@RequestParam(\"q\") String name) {\n    Map<String, Object> entity = new HashMap<>();\n    List<Consumer> consumers = consumerService.searchByName(name);\n    List<Map<String, Object>> results = new ArrayList<>();\n    consumers.forEach(c -> {\n      Map<String, Object> item = new HashMap<>();\n      item.put(\"id\", c.getId());\n      item.put(\"text\", c.getName() + '-' + c.getTel());\n      results.add(item);\n    });\n    entity.put(\"results\", results);\n    return entity;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/DrugController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.Drug;\nimport me.zbl.app.domain.DrugDO;\nimport me.zbl.app.service.DrugService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-19\n */\n@Controller\npublic class DrugController {\n\n  @Autowired\n  DrugService drugService;\n\n  @GetMapping(\"/drug/index\")\n  public String index() {\n    return \"app/data-maintenance/drug/index\";\n  }\n\n  @GetMapping(\"/drug/add\")\n  public String add() {\n    return \"app/data-maintenance/drug/add\";\n  }\n\n  @GetMapping(\"/drug/edit/{id}\")\n  public String edit(@PathVariable(\"id\") String id, Model model) {\n    Drug find = drugService.selectDrugByPrimaryKey(id);\n    model.addAttribute(\"drug\", find);\n    return \"app/data-maintenance/drug/edit\";\n  }\n\n  @DeleteMapping(\"/drug/remove/{id}\")\n  @ResponseBody\n  public R remove(@PathVariable(\"id\") String id) {\n    try {\n      drugService.deleteDrug(id);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  @GetMapping(\"/drug/list\")\n  @ResponseBody\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<DrugDO> drugs = drugService.selectAllDrug(query);\n    return new PageWrapper(drugs, drugService.count());\n  }\n\n  @PostMapping(\"/drug/save\")\n  @ResponseBody\n  public R save(Drug drug) {\n    try {\n      drugService.insertDrug(drug);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  @PutMapping(\"/drug/save\")\n  @ResponseBody\n  public R saveEdit(Drug drug) {\n    try {\n      drugService.updateDrug(drug);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/DrugInController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.DrugInDO;\nimport me.zbl.app.domain.DrugInFormDO;\nimport me.zbl.app.service.DrugInService;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 药品入库\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\n@Controller\npublic class DrugInController extends BaseController {\n\n  @Autowired\n  private DrugInService service;\n\n  /**\n   * 药品入库页面\n   */\n  @GetMapping(\"/inventory/drugin\")\n  public String drugInPage() {\n    return \"app/inventory/drug-in/drug-in\";\n  }\n\n  /**\n   * 药品入库登记\n   */\n  @GetMapping(\"/inventory/add\")\n  public String drugInAddPage() {\n    return \"app/inventory/drug-in/add\";\n  }\n\n  /**\n   * 入库记录列表\n   *\n   * @param params 查询参数\n   */\n  @ResponseBody\n  @GetMapping(\"/inventory/list\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<DrugInDO> list = service.list(query);\n    return new PageWrapper(list, service.count());\n  }\n\n  /**\n   * 入库记录保存\n   *\n   * @param params 参数\n   */\n  @ResponseBody\n  @PostMapping(\"/inventory/drugin/save\")\n  public R save(DrugInFormDO params) {\n    //    经办人姓名取当前用户的用户名\n    String username = getUser().getName();\n    params.setManager(username);\n    try {\n      service.drugInSave(params);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/DrugOutController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.DrugOutDO;\nimport me.zbl.app.domain.DrugOutFormDO;\nimport me.zbl.app.service.DrugOutService;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 药品出库\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-08\n */\n@Controller\npublic class DrugOutController extends BaseController {\n\n  @Autowired\n  private DrugOutService service;\n\n  /**\n   * 药品出库页面\n   */\n  @GetMapping(\"/inventory/drugout\")\n  public String drugOutPage() {\n    return \"app/inventory/drug-out/drug-out\";\n  }\n\n  /**\n   * 药品出库登记\n   */\n  @GetMapping(\"/inventory/out\")\n  public String drugOutAddPage() {\n    return \"app/inventory/drug-out/out\";\n  }\n\n  /**\n   * 出库记录列表\n   *\n   * @param params 查询参数\n   */\n  @ResponseBody\n  @GetMapping(\"/inventory/listout\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<DrugOutDO> list = service.list(query);\n    return new PageWrapper(list, service.count());\n  }\n\n  /**\n   * 出库记录保存\n   *\n   * @param params 参数\n   */\n  @ResponseBody\n  @PostMapping(\"/inventory/drugout/save\")\n  public R save(DrugOutFormDO params) {\n    //    经办人姓名取当前用户的用户名\n    String username = getUser().getName();\n    params.setManager(username);\n    //    保存出库记录\n    try {\n      service.drugOutSave(params);\n    } catch (IllegalArgumentException e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    //    检查库存下限\n    service.checkLowerLimit();\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/SaleController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.BackFormDO;\nimport me.zbl.app.domain.DrugOutFormDO;\nimport me.zbl.app.domain.SaleDO;\nimport me.zbl.app.service.DrugInService;\nimport me.zbl.app.service.DrugOutService;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-23\n */\n@Controller\npublic class SaleController extends BaseController {\n\n  @Autowired\n  private DrugOutService drugOutService;\n\n  @Autowired\n  DrugInService drugInService;\n\n  @GetMapping(\"/sale/index\")\n  public String index() {\n    return \"app/sale/index\";\n  }\n\n  @GetMapping(\"/sale/add\")\n  public String add() {\n    return \"app/sale/add\";\n  }\n\n  @GetMapping(\"/sale/back\")\n  public String back() {\n    return \"app/sale/back\";\n  }\n\n  @GetMapping(\"/sta/index\")\n  public String statistics() {\n    return \"app/statistics/index\";\n  }\n\n  @GetMapping(\"/sale_detail/index\")\n  public String saleDetail() {\n    return \"app/sale-detail/index\";\n  }\n\n  @GetMapping(\"/sale/list\")\n  @ResponseBody\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<SaleDO> list = drugOutService.saleList(query);\n    return new PageWrapper(list, drugOutService.countSale());\n  }\n\n  @PostMapping(\"/sale/save\")\n  @ResponseBody\n  public R saleSave(DrugOutFormDO drugOutFormDO) {\n    drugOutFormDO.setManager(getUser().getName());\n    try {\n      drugOutService.saleSave(drugOutFormDO);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    //    检查库存下限\n    drugOutService.checkLowerLimit();\n    return R.ok();\n  }\n\n  @PostMapping(\"/sale/back\")\n  @ResponseBody\n  public R saleBackSave(BackFormDO backFormDO) {\n    backFormDO.setManager(getUser().getName());\n    try {\n      drugInService.back(backFormDO);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  @GetMapping(\"/sale/sta_sale_day\")\n  @ResponseBody\n  public Object staSaleDay() {\n    return drugOutService.staSaleDay();\n  }\n\n  @GetMapping(\"/sale/sta_sale_month\")\n  @ResponseBody\n  public Object staSaleMonth() {\n    return drugOutService.staSaleMonth();\n  }\n\n  @GetMapping(\"/sale/sta_sale_year\")\n  @ResponseBody\n  public Object staSaleYear() {\n    return drugOutService.staSaleYear();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/controller/SupplierController.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.controller;\n\nimport me.zbl.app.domain.Supplier;\nimport me.zbl.app.service.SupplierService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 供应商数据维护\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-17\n */\n@Controller\npublic class SupplierController {\n\n  @Autowired\n  SupplierService supplierService;\n\n  @GetMapping(\"/supplier/index\")\n  public String index() {\n    return \"app/data-maintenance/supplier/index\";\n  }\n\n  @GetMapping(\"/supplier/add\")\n  public String add() {\n    return \"app/data-maintenance/supplier/add\";\n  }\n\n  @GetMapping(\"/supplier/edit/{id}\")\n  public String edit(@PathVariable(\"id\") String id, Model model) {\n    Supplier find = supplierService.selectByPrimaryKey(id);\n    model.addAttribute(\"supplier\", find);\n    return \"app/data-maintenance/supplier/edit\";\n  }\n\n  /**\n   * 供应商列表\n   */\n  @GetMapping(\"/supplier/list\")\n  @ResponseBody\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<Supplier> list = supplierService.selectAllSupplier(query);\n    return new PageWrapper(list, supplierService.count());\n  }\n\n  /**\n   * 供应商保存\n   */\n  @PostMapping(\"/supplier/save\")\n  @ResponseBody\n  public R save(Supplier supplier) {\n    try {\n      supplierService.insertSupplier(supplier);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  @PutMapping(\"/supplier/save\")\n  @ResponseBody\n  public R saveUpdate(Supplier supplier) {\n    try {\n      supplierService.updateSupplier(supplier);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n\n  @DeleteMapping(\"/supplier/remove/{id}\")\n  @ResponseBody\n  public R remove(@PathVariable(\"id\") String id) {\n    try {\n      supplierService.deleteSupplier(id);\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error(1, e.getMessage());\n    }\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/dao/ConsumerMapper.java",
    "content": "package me.zbl.app.dao;\n\nimport me.zbl.app.domain.Consumer;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface ConsumerMapper {\n\n  List<Consumer> selectByName(String name);\n\n  List<Consumer> selectAllConsumer(Map<String, Object> params);\n\n  Consumer selectConsumerByTel(String tel);\n\n  int count();\n\n  int deleteByPrimaryKey(String id);\n\n  int insert(Consumer record);\n\n  int insertSelective(Consumer record);\n\n  Consumer selectByPrimaryKey(String id);\n\n  int updateByPrimaryKeySelective(Consumer record);\n\n  int updateByPrimaryKey(Consumer record);\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/dao/DrugMapper.java",
    "content": "package me.zbl.app.dao;\n\nimport me.zbl.app.domain.Drug;\nimport me.zbl.app.domain.DrugDO;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface DrugMapper {\n\n  List<DrugDO> selectAllDrug(Map<String, Object> params);\n\n  int count();\n\n  List<Drug> selectOverLowerLimit();\n\n  List<Drug> selectByExpireDate(Date date);\n\n  int increaseAndDecreaseQuantity(Map<String, Object> params);\n\n  int deleteByPrimaryKey(String id);\n\n  int insert(Drug record);\n\n  int insertSelective(Drug record);\n\n  Drug selectByPrimaryKey(String id);\n\n  int updateByPrimaryKeySelective(Drug record);\n\n  int updateByPrimaryKey(Drug record);\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/dao/ExpireMapper.java",
    "content": "package me.zbl.app.dao;\n\nimport me.zbl.app.domain.Expire;\n\nimport java.util.Date;\nimport java.util.List;\n\npublic interface ExpireMapper {\n\n  List<Expire> selectByDate(Date date);\n\n  int deleteByPrimaryKey(String id);\n\n  int insert(Expire record);\n\n  int insertSelective(Expire record);\n\n  Expire selectByPrimaryKey(String id);\n\n  int updateByPrimaryKeySelective(Expire record);\n\n  int updateByPrimaryKey(Expire record);\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/dao/InventoryMapper.java",
    "content": "package me.zbl.app.dao;\n\nimport me.zbl.app.domain.*;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface InventoryMapper {\n\n  int saleSave(DrugOutFormDO drugOutFormDO);\n\n  int drugOutSave(DrugOutFormDO drugOutFormDO);\n\n  int drugInSave(DrugInFormDO drugInFormDO);\n\n  List<StaSaleDO> staSaleDay();\n\n  List<StaSaleDO> staSaleMonth();\n\n  List<StaSaleDO> staSaleYear();\n\n  List<DrugInDO> inList(Map<String, Object> param);\n\n  List<DrugOutDO> outList(Map<String, Object> param);\n\n  List<SaleDO> saleList(Map<String, Object> param);\n\n  int deleteByPrimaryKey(String id);\n\n  int countIn();\n\n  int countOut();\n\n  int countSale();\n\n  int insert(Inventory record);\n\n  int insertSelective(Inventory record);\n\n  Inventory selectByPrimaryKey(String id);\n\n  int updateByPrimaryKeySelective(Inventory record);\n\n  int updateByPrimaryKey(Inventory record);\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/dao/SupplierMapper.java",
    "content": "package me.zbl.app.dao;\n\nimport me.zbl.app.domain.Supplier;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface SupplierMapper {\n\n  List<Supplier> selectAllSupplier(Map<String, Object> params);\n\n  int count();\n\n  int deleteByPrimaryKey(String id);\n\n  int insert(Supplier record);\n\n  int insertSelective(Supplier record);\n\n  Supplier selectByPrimaryKey(String id);\n\n  int updateByPrimaryKeySelective(Supplier record);\n\n  int updateByPrimaryKey(Supplier record);\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/BackFormDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\n/**\n * 退货表单\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-24\n */\npublic class BackFormDO {\n\n  //  流水号\n  private String orderId;\n  //  药品是否有问题\n  private boolean hasProblem;\n  //  退货操作人\n  private String manager;\n  //  原因备注\n  private String comment;\n\n  public String getOrderId() {\n    return orderId;\n  }\n\n  public void setOrderId(String orderId) {\n    this.orderId = orderId;\n  }\n\n  public boolean isHasProblem() {\n    return hasProblem;\n  }\n\n  public void setHasProblem(boolean hasProblem) {\n    this.hasProblem = hasProblem;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\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": "src/main/java/me/zbl/app/domain/Consumer.java",
    "content": "package me.zbl.app.domain;\n\npublic class Consumer {\n    private String id;\n\n    private String name;\n\n    private String tel;\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 getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name == null ? null : name.trim();\n    }\n\n    public String getTel() {\n        return tel;\n    }\n\n    public void setTel(String tel) {\n        this.tel = tel == null ? null : tel.trim();\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/Drug.java",
    "content": "package me.zbl.app.domain;\n\nimport java.math.BigDecimal;\n\npublic class Drug {\n    private String id;\n\n    private String name;\n\n    private Integer quantity;\n\n    private BigDecimal price;\n\n    private String invalid;\n\n    private Integer qualityGuaranteePeriod;\n\n    private Integer lowerLimit;\n\n    private String supplierId;\n\n    private String specification;\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 getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name == null ? null : name.trim();\n    }\n\n    public Integer getQuantity() {\n        return quantity;\n    }\n\n    public void setQuantity(Integer quantity) {\n        this.quantity = quantity;\n    }\n\n    public BigDecimal getPrice() {\n        return price;\n    }\n\n    public void setPrice(BigDecimal price) {\n        this.price = price;\n    }\n\n    public String getInvalid() {\n        return invalid;\n    }\n\n    public void setInvalid(String invalid) {\n        this.invalid = invalid == null ? null : invalid.trim();\n    }\n\n    public Integer getQualityGuaranteePeriod() {\n        return qualityGuaranteePeriod;\n    }\n\n    public void setQualityGuaranteePeriod(Integer qualityGuaranteePeriod) {\n        this.qualityGuaranteePeriod = qualityGuaranteePeriod;\n    }\n\n    public Integer getLowerLimit() {\n        return lowerLimit;\n    }\n\n    public void setLowerLimit(Integer lowerLimit) {\n        this.lowerLimit = lowerLimit;\n    }\n\n    public String getSupplierId() {\n        return supplierId;\n    }\n\n    public void setSupplierId(String supplierId) {\n        this.supplierId = supplierId == null ? null : supplierId.trim();\n    }\n\n    public String getSpecification() {\n        return specification;\n    }\n\n    public void setSpecification(String specification) {\n        this.specification = specification == null ? null : specification.trim();\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/DrugDO.java",
    "content": "package me.zbl.app.domain;\n\nimport java.math.BigDecimal;\n\npublic class DrugDO {\n    private String id;\n\n    private String name;\n\n    private Integer quantity;\n\n    private BigDecimal price;\n\n    private String invalid;\n\n    private Integer qualityGuaranteePeriod;\n\n    private Integer lowerLimit;\n\n    private String supplierId;\n\n    private String specification;\n\n    private String supplier;\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 getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name == null ? null : name.trim();\n    }\n\n    public Integer getQuantity() {\n        return quantity;\n    }\n\n    public void setQuantity(Integer quantity) {\n        this.quantity = quantity;\n    }\n\n    public BigDecimal getPrice() {\n        return price;\n    }\n\n    public void setPrice(BigDecimal price) {\n        this.price = price;\n    }\n\n    public String getInvalid() {\n        return invalid;\n    }\n\n    public void setInvalid(String invalid) {\n        this.invalid = invalid == null ? null : invalid.trim();\n    }\n\n    public Integer getQualityGuaranteePeriod() {\n        return qualityGuaranteePeriod;\n    }\n\n    public void setQualityGuaranteePeriod(Integer qualityGuaranteePeriod) {\n        this.qualityGuaranteePeriod = qualityGuaranteePeriod;\n    }\n\n    public Integer getLowerLimit() {\n        return lowerLimit;\n    }\n\n    public void setLowerLimit(Integer lowerLimit) {\n        this.lowerLimit = lowerLimit;\n    }\n\n    public String getSupplierId() {\n        return supplierId;\n    }\n\n    public void setSupplierId(String supplierId) {\n        this.supplierId = supplierId == null ? null : supplierId.trim();\n    }\n\n    public String getSpecification() {\n        return specification;\n    }\n\n    public void setSpecification(String specification) {\n        this.specification = specification == null ? null : specification.trim();\n    }\n\n    public String getSupplier() {\n        return supplier;\n    }\n\n    public void setSupplier(String supplier) {\n        this.supplier = supplier;\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/DrugInDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 药品入库列表\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic class DrugInDO {\n\n  //  类型\n  private String type;\n  //  经办人\n  private String manager;\n  //  实时库存\n  private int quantityNow;\n  //  药品编号\n  private String drugId;\n  //  药品名称\n  private String drugName;\n  //  单价\n  private BigDecimal price;\n  //  供应商\n  private String supplierName;\n  //  规格\n  private String specification;\n  //  数量\n  private Integer quantity;\n  //  总金额\n  private BigDecimal ammount;\n  //  入库时间\n  private Date gmtCreated;\n\n  public String getDrugName() {\n    return drugName;\n  }\n\n  public void setDrugName(String drugName) {\n    this.drugName = drugName;\n  }\n\n  public BigDecimal getPrice() {\n    return price;\n  }\n\n  public void setPrice(BigDecimal price) {\n    this.price = price;\n  }\n\n  public String getSupplierName() {\n    return supplierName;\n  }\n\n  public void setSupplierName(String supplierName) {\n    this.supplierName = supplierName;\n  }\n\n  public String getSpecification() {\n    return specification;\n  }\n\n  public void setSpecification(String specification) {\n    this.specification = specification;\n  }\n\n  public Integer getQuantity() {\n    return quantity;\n  }\n\n  public void setQuantity(Integer quantity) {\n    this.quantity = quantity;\n  }\n\n  public BigDecimal getAmmount() {\n    return ammount;\n  }\n\n  public void setAmmount(BigDecimal ammount) {\n    this.ammount = ammount;\n  }\n\n  public Date getGmtCreated() {\n    return gmtCreated;\n  }\n\n  public void setGmtCreated(Date gmtCreated) {\n    this.gmtCreated = gmtCreated;\n  }\n\n  public String getDrugId() {\n    return drugId;\n  }\n\n  public void setDrugId(String drugId) {\n    this.drugId = drugId;\n  }\n\n  public int getQuantityNow() {\n    return quantityNow;\n  }\n\n  public void setQuantityNow(int quantityNow) {\n    this.quantityNow = quantityNow;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\n  }\n\n  public String getType() {\n    return type;\n  }\n\n  public void setType(String type) {\n    this.type = type;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/DrugInFormDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\nimport org.springframework.data.annotation.Transient;\n\nimport java.util.Date;\n\n/**\n * 入库登记表单\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic class DrugInFormDO {\n\n  private String id;\n\n  //  生产日期\n  @Transient\n  private Date madeDate;\n  //  药品 id\n  private String drugId;\n  //  入库数量\n  private int quantity;\n  //  经办人\n  private String manager;\n  //  总金额\n  private float ammount;\n\n  public String getDrugId() {\n    return drugId;\n  }\n\n  public void setDrugId(String drugId) {\n    this.drugId = drugId;\n  }\n\n  public int getQuantity() {\n    return quantity;\n  }\n\n  public void setQuantity(int quantity) {\n    this.quantity = quantity;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\n  }\n\n  public float getAmmount() {\n    return ammount;\n  }\n\n  public void setAmmount(float ammount) {\n    this.ammount = ammount;\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String id) {\n    this.id = id;\n  }\n\n  public Date getMadeDate() {\n    return madeDate;\n  }\n\n  public void setMadeDate(Date madeDate) {\n    this.madeDate = madeDate;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/DrugOutDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 药品入库列表\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic class DrugOutDO {\n\n  //  原因备注\n  private String comment;\n  //  类型\n  private String type;\n  //  经办人\n  private String manager;\n  //  实时库存\n  private int quantityNow;\n  //  药品编号\n  private String drugId;\n  //  药品名称\n  private String drugName;\n  //  单价\n  private BigDecimal price;\n  //  供应商\n  private String supplierName;\n  //  规格\n  private String specification;\n  //  数量\n  private Integer quantity;\n  //  总金额\n  private BigDecimal ammount;\n  //  入库时间\n  private Date gmtCreated;\n\n  public String getDrugName() {\n    return drugName;\n  }\n\n  public void setDrugName(String drugName) {\n    this.drugName = drugName;\n  }\n\n  public BigDecimal getPrice() {\n    return price;\n  }\n\n  public void setPrice(BigDecimal price) {\n    this.price = price;\n  }\n\n  public String getSupplierName() {\n    return supplierName;\n  }\n\n  public void setSupplierName(String supplierName) {\n    this.supplierName = supplierName;\n  }\n\n  public String getSpecification() {\n    return specification;\n  }\n\n  public void setSpecification(String specification) {\n    this.specification = specification;\n  }\n\n  public Integer getQuantity() {\n    return quantity;\n  }\n\n  public void setQuantity(Integer quantity) {\n    this.quantity = quantity;\n  }\n\n  public BigDecimal getAmmount() {\n    return ammount;\n  }\n\n  public void setAmmount(BigDecimal ammount) {\n    this.ammount = ammount;\n  }\n\n  public Date getGmtCreated() {\n    return gmtCreated;\n  }\n\n  public void setGmtCreated(Date gmtCreated) {\n    this.gmtCreated = gmtCreated;\n  }\n\n  public String getDrugId() {\n    return drugId;\n  }\n\n  public void setDrugId(String drugId) {\n    this.drugId = drugId;\n  }\n\n  public int getQuantityNow() {\n    return quantityNow;\n  }\n\n  public void setQuantityNow(int quantityNow) {\n    this.quantityNow = quantityNow;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\n  }\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 getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/DrugOutFormDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\n/**\n * 出库登记表单\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic class DrugOutFormDO {\n\n  private String id;\n\n  //  药品 id\n  private String drugId;\n  //  出库数量\n  private int quantity;\n  //  原因备注\n  private String comment;\n  //  经办人\n  private String manager;\n  //  总金额\n  private float ammount;\n  //  顾客 id\n  private String consumer;\n\n  public String getDrugId() {\n    return drugId;\n  }\n\n  public void setDrugId(String drugId) {\n    this.drugId = drugId;\n  }\n\n  public int getQuantity() {\n    return quantity;\n  }\n\n  public void setQuantity(int quantity) {\n    this.quantity = quantity;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\n  }\n\n  public float getAmmount() {\n    return ammount;\n  }\n\n  public void setAmmount(float ammount) {\n    this.ammount = ammount;\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String id) {\n    this.id = id;\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 getConsumer() {\n    return consumer;\n  }\n\n  public void setConsumer(String consumer) {\n    this.consumer = consumer;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/Expire.java",
    "content": "package me.zbl.app.domain;\n\nimport java.util.Date;\n\npublic class Expire {\n    private String id;\n\n    private String drugId;\n\n    private Date expiredDate;\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 getDrugId() {\n        return drugId;\n    }\n\n    public void setDrugId(String drugId) {\n        this.drugId = drugId == null ? null : drugId.trim();\n    }\n\n    public Date getExpiredDate() {\n        return expiredDate;\n    }\n\n    public void setExpiredDate(Date expiredDate) {\n        this.expiredDate = expiredDate;\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/Inventory.java",
    "content": "package me.zbl.app.domain;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\npublic class Inventory {\n    private String id;\n\n    private String consumerId;\n\n    private String drugId;\n\n    private String type;\n\n    private Integer quantity;\n\n    private BigDecimal ammount;\n\n    private String comment;\n\n    private String manager;\n\n    private Date gmtCreated;\n\n    private Date gmtModified;\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 getConsumerId() {\n        return consumerId;\n    }\n\n    public void setConsumerId(String consumerId) {\n        this.consumerId = consumerId == null ? null : consumerId.trim();\n    }\n\n    public String getDrugId() {\n        return drugId;\n    }\n\n    public void setDrugId(String drugId) {\n        this.drugId = drugId == null ? null : drugId.trim();\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type == null ? null : type.trim();\n    }\n\n    public Integer getQuantity() {\n        return quantity;\n    }\n\n    public void setQuantity(Integer quantity) {\n        this.quantity = quantity;\n    }\n\n    public BigDecimal getAmmount() {\n        return ammount;\n    }\n\n    public void setAmmount(BigDecimal ammount) {\n        this.ammount = ammount;\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public void setComment(String comment) {\n        this.comment = comment == null ? null : comment.trim();\n    }\n\n    public String getManager() {\n        return manager;\n    }\n\n    public void setManager(String manager) {\n        this.manager = manager == null ? null : manager.trim();\n    }\n\n    public Date getGmtCreated() {\n        return gmtCreated;\n    }\n\n    public void setGmtCreated(Date gmtCreated) {\n        this.gmtCreated = gmtCreated;\n    }\n\n    public Date getGmtModified() {\n        return gmtModified;\n    }\n\n    public void setGmtModified(Date gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/SaleDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 药品入库列表\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic class SaleDO {\n\n  //  订单编号\n  private String orderId;\n  //  原因备注\n  private String comment;\n  //  类型\n  private String type;\n  //  经办人\n  private String manager;\n  //  实时库存\n  private int quantityNow;\n  //  药品编号\n  private String drugId;\n  //  药品名称\n  private String drugName;\n  //  单价\n  private BigDecimal price;\n  //  供应商\n  private String supplierName;\n  //  规格\n  private String specification;\n  //  数量\n  private Integer quantity;\n  //  总金额\n  private BigDecimal ammount;\n  //  顾客姓名\n  private String consumer;\n  //  入库时间\n  private Date gmtCreated;\n\n  public String getDrugName() {\n    return drugName;\n  }\n\n  public void setDrugName(String drugName) {\n    this.drugName = drugName;\n  }\n\n  public BigDecimal getPrice() {\n    return price;\n  }\n\n  public void setPrice(BigDecimal price) {\n    this.price = price;\n  }\n\n  public String getSupplierName() {\n    return supplierName;\n  }\n\n  public void setSupplierName(String supplierName) {\n    this.supplierName = supplierName;\n  }\n\n  public String getSpecification() {\n    return specification;\n  }\n\n  public void setSpecification(String specification) {\n    this.specification = specification;\n  }\n\n  public Integer getQuantity() {\n    return quantity;\n  }\n\n  public void setQuantity(Integer quantity) {\n    this.quantity = quantity;\n  }\n\n  public BigDecimal getAmmount() {\n    return ammount;\n  }\n\n  public void setAmmount(BigDecimal ammount) {\n    this.ammount = ammount;\n  }\n\n  public Date getGmtCreated() {\n    return gmtCreated;\n  }\n\n  public void setGmtCreated(Date gmtCreated) {\n    this.gmtCreated = gmtCreated;\n  }\n\n  public String getDrugId() {\n    return drugId;\n  }\n\n  public void setDrugId(String drugId) {\n    this.drugId = drugId;\n  }\n\n  public int getQuantityNow() {\n    return quantityNow;\n  }\n\n  public void setQuantityNow(int quantityNow) {\n    this.quantityNow = quantityNow;\n  }\n\n  public String getManager() {\n    return manager;\n  }\n\n  public void setManager(String manager) {\n    this.manager = manager;\n  }\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 getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public String getConsumer() {\n    return consumer;\n  }\n\n  public void setConsumer(String consumer) {\n    this.consumer = consumer;\n  }\n\n  public String getOrderId() {\n    return orderId;\n  }\n\n  public void setOrderId(String orderId) {\n    this.orderId = orderId;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/StaSaleDO.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.domain;\n\n/**\n * 销售情况统计数据\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-25\n */\npublic class StaSaleDO {\n\n  //  日期标识\n  private String dateUnit;\n  //  销量\n  private float saleCount;\n\n  public String getDateUnit() {\n    return dateUnit;\n  }\n\n  public void setDateUnit(String dateUnit) {\n    this.dateUnit = dateUnit;\n  }\n\n  public float getSaleCount() {\n    return saleCount;\n  }\n\n  public void setSaleCount(float saleCount) {\n    this.saleCount = saleCount;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/domain/Supplier.java",
    "content": "package me.zbl.app.domain;\n\npublic class Supplier {\n    private String id;\n\n    private String name;\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 getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name == null ? null : name.trim();\n    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/app/service/ConsumerService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\nimport me.zbl.app.domain.Consumer;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 顾客业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-17\n */\npublic interface ConsumerService {\n\n  List<Consumer> searchByName(String name);\n\n  Consumer selectByPrimaryKey(String id);\n\n  List<Consumer> selectAllConsumer(Map<String, Object> params);\n\n  int count();\n\n  int insertConsumer(Consumer consumer);\n\n  int deleteConsumer(String id);\n\n  int updateConsumer(Consumer consumer);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/DrugInService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\nimport me.zbl.app.domain.BackFormDO;\nimport me.zbl.app.domain.DrugInDO;\nimport me.zbl.app.domain.DrugInFormDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 药品入库业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\npublic interface DrugInService {\n\n  int back(BackFormDO backFormDO);\n\n  List<DrugInDO> list(Map<String, Object> params);\n\n  int count();\n\n  int drugInSave(DrugInFormDO drugInFormDO);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/DrugOutService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\nimport com.github.pagehelper.Page;\nimport me.zbl.app.domain.DrugOutDO;\nimport me.zbl.app.domain.DrugOutFormDO;\nimport me.zbl.app.domain.SaleDO;\nimport me.zbl.app.domain.StaSaleDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 药品出库业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-08\n */\npublic interface DrugOutService {\n\n  List<StaSaleDO> staSaleDay();\n\n  List<StaSaleDO> staSaleMonth();\n\n  List<StaSaleDO> staSaleYear();\n\n  List<DrugOutDO> list(Map<String, Object> params);\n\n  Page<SaleDO> saleList(Map<String, Object> params);\n\n  int count();\n\n  int countSale();\n\n  int drugOutSave(DrugOutFormDO drugOutFormDO) throws IllegalArgumentException;\n\n  int saleSave(DrugOutFormDO drugOutFormDO);\n\n  /**\n   * 检查库存下限\n   */\n  void checkLowerLimit();\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/DrugService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\nimport me.zbl.app.domain.Drug;\nimport me.zbl.app.domain.DrugDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 药品管理业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-19\n */\npublic interface DrugService {\n\n  Drug selectDrugByPrimaryKey(String id);\n\n  List<DrugDO> selectAllDrug(Map<String, Object> params);\n\n  int count();\n\n  int insertDrug(Drug drug);\n\n  int updateDrug(Drug drug);\n\n  int deleteDrug(String id);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/ExpireNotifyService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\n/**\n * 药品过期提醒业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-12\n */\npublic interface ExpireNotifyService {\n\n  /**\n   * 向仓库管理员角色的用户发送药品过期提醒\n   */\n  void notifyDrugsExpiredToday();\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/SupplierService.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service;\n\nimport me.zbl.app.domain.Supplier;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 供应商业务接口\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-17\n */\npublic interface SupplierService {\n\n  Supplier selectByPrimaryKey(String id);\n\n  List<Supplier> selectAllSupplier(Map<String, Object> params);\n\n  int count();\n\n  int insertSupplier(Supplier supplier);\n\n  int deleteSupplier(String id);\n\n  int updateSupplier(Supplier id);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/ConsumerServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport me.zbl.app.dao.ConsumerMapper;\nimport me.zbl.app.domain.Consumer;\nimport me.zbl.app.service.ConsumerService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\n/**\n * 顾客业务实现\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-19\n */\n@Service\npublic class ConsumerServiceImpl implements ConsumerService {\n\n  @Autowired\n  private ConsumerMapper consumerMapper;\n\n  @Override\n  public List<Consumer> searchByName(String name) {\n    return consumerMapper.selectByName(name);\n  }\n\n  @Override\n  public Consumer selectByPrimaryKey(String id) {\n    return consumerMapper.selectByPrimaryKey(id);\n  }\n\n  @Override\n  public List<Consumer> selectAllConsumer(Map<String, Object> params) {\n    return consumerMapper.selectAllConsumer(params);\n  }\n\n  @Override\n  public int count() {\n    return consumerMapper.count();\n  }\n\n  @Override\n  public int insertConsumer(Consumer consumer) {\n    Optional<Consumer> find = Optional.ofNullable(consumerMapper.selectConsumerByTel(consumer.getTel()));\n    if (find.isPresent()) {\n      throw new IllegalArgumentException(\"用户电话号码已存在\");\n    }\n    return consumerMapper.insertSelective(consumer);\n  }\n\n  @Override\n  public int deleteConsumer(String id) {\n    return consumerMapper.deleteByPrimaryKey(id);\n  }\n\n  @Override\n  public int updateConsumer(Consumer consumer) {\n    return consumerMapper.updateByPrimaryKeySelective(consumer);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/DrugInServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport me.zbl.app.dao.DrugMapper;\nimport me.zbl.app.dao.ExpireMapper;\nimport me.zbl.app.dao.InventoryMapper;\nimport me.zbl.app.domain.*;\nimport me.zbl.app.service.DrugInService;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.*;\n\n/**\n * 药品入库业务实现\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-07\n */\n@Service\npublic class DrugInServiceImpl implements DrugInService {\n\n  @Autowired\n  private ExpireMapper expireMapper;\n\n  @Autowired\n  private InventoryMapper inventoryMapper;\n\n  @Autowired\n  private DrugMapper drugMapper;\n\n  @Override\n  public int back(BackFormDO backFormDO) {\n    int result = 0;\n    String orderId = backFormDO.getOrderId();\n    Inventory order = inventoryMapper.selectByPrimaryKey(orderId);\n    if (null == order) {\n      throw new IllegalArgumentException(\"订单不存在\");\n    }\n    order.setManager(backFormDO.getManager());\n    order.setComment(backFormDO.getComment());\n    order.setId(null);\n    order.setGmtCreated(null);\n    order.setGmtModified(null);\n    // 如果没有问题，直接入库\n    if (!backFormDO.isHasProblem()) {\n      order.setType(\"2\");\n      // 保存入库记录\n      result = inventoryMapper.insertSelective(order);\n      // 更新库存\n      Map<String, Object> param = new HashMap<>();\n      param.put(\"drugId\", order.getDrugId());\n      param.put(\"quantity\", order.getQuantity());\n      drugMapper.increaseAndDecreaseQuantity(param);\n    }\n    // 药品存在问题，直接退回供应商\n    else {\n      order.setType(\"4\");\n      // 保存入库记录\n      result = inventoryMapper.insertSelective(order);\n    }\n    // 删除订单\n    inventoryMapper.deleteByPrimaryKey(orderId);\n    return result;\n  }\n\n  @Override\n  public List<DrugInDO> list(Map<String, Object> params) {\n    return inventoryMapper.inList(params);\n  }\n\n  @Override\n  public int count() {\n    return inventoryMapper.countIn();\n  }\n\n  @Override\n  public int drugInSave(DrugInFormDO drugInFormDO) throws IllegalArgumentException {\n    Optional.ofNullable(drugMapper.selectByPrimaryKey(drugInFormDO.getDrugId()))\n            .orElseThrow(() -> new IllegalArgumentException(\"输入的药品编号不存在\"));\n\n    // 生产日期\n    Date madeDate = drugInFormDO.getMadeDate();\n    // 保质期\n    int guarantee = drugMapper.selectByPrimaryKey(drugInFormDO.getDrugId()).getQualityGuaranteePeriod();\n    // 计算过期日期\n    Date expire = DateUtils.addMonths(madeDate, guarantee);\n    Expire exp = new Expire();\n    exp.setDrugId(drugInFormDO.getDrugId());\n    exp.setExpiredDate(expire);\n    // 保存过期提醒记录\n    expireMapper.insertSelective(exp);\n    // 库存记录\n    Map<String, Object> params = new HashMap<>();\n    params.put(\"drugId\", drugInFormDO.getDrugId());\n    params.put(\"quantity\", drugInFormDO.getQuantity());\n    // 更新药品的库存\n    drugMapper.increaseAndDecreaseQuantity(params);\n    // 保存仓储变动记录\n    return inventoryMapper.drugInSave(drugInFormDO);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/DrugOutServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport com.github.pagehelper.Page;\nimport me.zbl.app.dao.DrugMapper;\nimport me.zbl.app.dao.InventoryMapper;\nimport me.zbl.app.domain.*;\nimport me.zbl.app.service.DrugOutService;\nimport me.zbl.oa.domain.NotifyDO;\nimport me.zbl.oa.service.NotifyService;\nimport me.zbl.util.PageUtil;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.math.BigDecimal;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\n/**\n * 药品出库业务实现\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-08\n */\n@Service\npublic class DrugOutServiceImpl implements DrugOutService {\n\n  @Autowired\n  private DrugMapper drugMapper;\n\n  @Autowired\n  private InventoryMapper inventoryMapper;\n\n  @Autowired\n  private NotifyService notifyService;\n\n  @Override\n  public List<StaSaleDO> staSaleDay() {\n    return inventoryMapper.staSaleDay();\n  }\n\n  @Override\n  public List<StaSaleDO> staSaleMonth() {\n    return inventoryMapper.staSaleMonth();\n  }\n\n  @Override\n  public List<StaSaleDO> staSaleYear() {\n    return inventoryMapper.staSaleYear();\n  }\n\n  @Override\n  public List<DrugOutDO> list(Map<String, Object> params) {\n    return inventoryMapper.outList(params);\n  }\n\n  @Override\n  public Page<SaleDO> saleList(Map<String, Object> params) {\n    return PageUtil.page(params, () -> inventoryMapper.saleList(params));\n  }\n\n  @Override\n  public int count() {\n    return inventoryMapper.countOut();\n  }\n\n  @Override\n  public int countSale() {\n    return inventoryMapper.countSale();\n  }\n\n  @Transactional\n  @Override\n  public int drugOutSave(DrugOutFormDO drugOutFormDO) {\n    Optional.ofNullable(drugMapper.selectByPrimaryKey(drugOutFormDO.getDrugId())).\n            orElseThrow(() -> new IllegalArgumentException(\"输入的药品编号不存在\"));\n    Map<String, Object> params = new HashMap<>();\n    String drugId = drugOutFormDO.getDrugId();\n    params.put(\"drugId\", drugId);\n    params.put(\"quantity\", 0 - drugOutFormDO.getQuantity());\n    // 更新药品的库存\n    drugMapper.increaseAndDecreaseQuantity(params);\n    Drug post = drugMapper.selectByPrimaryKey(drugId);\n    if (post.getQuantity() < 0) {\n      throw new IllegalArgumentException(\"库存不足！\");\n    }\n    if (StringUtils.isEmpty(drugOutFormDO.getComment())) {\n      drugOutFormDO.setComment(\"退回供应商出库\");\n    }\n    // 保存仓储变动记录\n    return inventoryMapper.drugOutSave(drugOutFormDO);\n  }\n\n  @Override\n  public int saleSave(DrugOutFormDO drugOutFormDO) {\n    Optional.ofNullable(drugMapper.selectByPrimaryKey(drugOutFormDO.getDrugId())).\n            orElseThrow(() -> new IllegalArgumentException(\"输入的药品编号不存在\"));\n    Map<String, Object> params = new HashMap<>();\n    String drugId = drugOutFormDO.getDrugId();\n    params.put(\"drugId\", drugId);\n    params.put(\"quantity\", 0 - drugOutFormDO.getQuantity());\n    // 更新药品的库存\n    drugMapper.increaseAndDecreaseQuantity(params);\n    Drug post = drugMapper.selectByPrimaryKey(drugId);\n    if (post.getQuantity() < 0) {\n      throw new IllegalArgumentException(\"库存不足！\");\n    }\n    BigDecimal price = post.getPrice();\n    int quantity = drugOutFormDO.getQuantity();\n    float ammount = price.floatValue() * (float) quantity;\n    drugOutFormDO.setAmmount(ammount);\n    if (StringUtils.isEmpty(drugOutFormDO.getComment())) {\n      drugOutFormDO.setComment(\"销售出库\");\n    }\n    // 保存仓储变动记录\n    return inventoryMapper.saleSave(drugOutFormDO);\n  }\n\n  @Override\n  public void checkLowerLimit() {\n    List<Drug> drugs = drugMapper.selectOverLowerLimit();\n    drugs.forEach(d -> {\n      String title = \"有药品的库存低于预定下限值\";\n      //      药品编号\n      String drugId = d.getId();\n      //      药名\n      String name = d.getName();\n      //      消息内容\n      String content = \"有药品的库存低于预定下限值，请及时进货！药品编号：\" + drugId + \"，药名：\" + name + \"\";\n\n      NotifyDO notify = new NotifyDO();\n      notify.setTitle(title);\n      notify.setStatus(\"1\");\n      notify.setContent(content);\n      notify.setType(\"5\");\n      notify.setCreateBy((long) 1);\n      notify.setUserIds(new Long[]{(long) 140});\n      //     发送消息\n      notifyService.save(notify);\n    });\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/DrugServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport me.zbl.app.dao.DrugMapper;\nimport me.zbl.app.dao.SupplierMapper;\nimport me.zbl.app.domain.Drug;\nimport me.zbl.app.domain.DrugDO;\nimport me.zbl.app.domain.Supplier;\nimport me.zbl.app.service.DrugService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\n/**\n * 药品管理业务实现\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-19\n */\n@Service\npublic class DrugServiceImpl implements DrugService {\n\n  @Autowired\n  private DrugMapper drugMapper;\n\n  @Autowired\n  private SupplierMapper supplierMapper;\n\n  @Override\n  public Drug selectDrugByPrimaryKey(String id) {\n    return drugMapper.selectByPrimaryKey(id);\n  }\n\n  @Override\n  public List<DrugDO> selectAllDrug(Map<String, Object> params) {\n    return drugMapper.selectAllDrug(params);\n  }\n\n  @Override\n  public int count() {\n    return drugMapper.count();\n  }\n\n  @Override\n  public int insertDrug(Drug drug) {\n    Drug find = drugMapper.selectByPrimaryKey(drug.getId());\n    if (null != find) {\n      throw new IllegalArgumentException(\"药品编号已经存在\");\n    }\n    Optional<Supplier> supplier = Optional.ofNullable(supplierMapper.\n            selectByPrimaryKey(drug.getSupplierId()));\n    supplier.orElseThrow(() -> new IllegalArgumentException(\"供应商编号不存在\"));\n    return drugMapper.insertSelective(drug);\n  }\n\n  @Override\n  public int updateDrug(Drug drug) {\n    return drugMapper.updateByPrimaryKeySelective(drug);\n  }\n\n  @Override\n  public int deleteDrug(String id) {\n    return drugMapper.deleteByPrimaryKey(id);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/ExpireNotifyServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport me.zbl.app.dao.DrugMapper;\nimport me.zbl.app.domain.Drug;\nimport me.zbl.app.service.ExpireNotifyService;\nimport me.zbl.oa.domain.NotifyDO;\nimport me.zbl.oa.service.NotifyService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * 药品过期提醒业务实现\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-12\n */\n@Service\npublic class ExpireNotifyServiceImpl implements ExpireNotifyService {\n\n  @Autowired\n  private DrugMapper drugMapper;\n\n  @Autowired\n  NotifyService notifyService;\n\n  @Override\n  public void notifyDrugsExpiredToday() {\n    List<Drug> drugs = drugMapper.selectByExpireDate(new Date());\n    drugs.forEach(d -> {\n      String title = \"有药品将要在今天过期\";\n      //      药品编号\n      String drugId = d.getId();\n      //      药名\n      String name = d.getName();\n      //      消息内容\n      String content = \"有一批药品将于今天过期，如有剩余存货请及时处理！药品编号：\" + drugId + \"，药名：\" + name + \"\";\n\n      NotifyDO notify = new NotifyDO();\n      notify.setTitle(title);\n      notify.setStatus(\"1\");\n      notify.setContent(content);\n      notify.setType(\"4\");\n      notify.setCreateBy((long) 1);\n      notify.setUserIds(new Long[]{(long) 140});\n      //     发送消息\n      notifyService.save(notify);\n    });\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/service/impl/SupplierServiceImpl.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.service.impl;\n\nimport me.zbl.app.dao.SupplierMapper;\nimport me.zbl.app.domain.Supplier;\nimport me.zbl.app.service.SupplierService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-17\n */\n@Service\npublic class SupplierServiceImpl implements SupplierService {\n\n  @Autowired\n  SupplierMapper supplierMapper;\n\n  @Override\n  public Supplier selectByPrimaryKey(String id) {\n    return supplierMapper.selectByPrimaryKey(id);\n  }\n\n  @Override\n  public List<Supplier> selectAllSupplier(Map<String, Object> params) {\n    return supplierMapper.selectAllSupplier(params);\n  }\n\n  @Override\n  public int count() {\n    return supplierMapper.count();\n  }\n\n  @Override\n  public int insertSupplier(Supplier supplier) {\n    Supplier virtual = supplierMapper.selectByPrimaryKey(supplier.getId());\n    if (null != virtual) {\n      throw new IllegalArgumentException(\"该编号已经存在\");\n    }\n    return supplierMapper.insertSelective(supplier);\n  }\n\n  @Override\n  public int deleteSupplier(String id) {\n    return supplierMapper.deleteByPrimaryKey(id);\n  }\n\n  @Override\n  public int updateSupplier(Supplier supplier) {\n    return supplierMapper.updateByPrimaryKeySelective(supplier);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/app/task/InventoryCheckTask.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app.task;\n\nimport me.zbl.app.service.DrugOutService;\nimport me.zbl.app.service.ExpireNotifyService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n/**\n * 定时任务\n * <p>\n * 1. 药品过期检查\n * 2. 药品库存检查\n *\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-12\n */\n@Component\npublic class InventoryCheckTask {\n\n  private static final Logger log = LoggerFactory.getLogger(InventoryCheckTask.class);\n\n  @Autowired\n  private ExpireNotifyService expireNotifyService;\n\n  @Autowired\n  private DrugOutService drugOutService;\n\n  /**\n   * 检查药品过期\n   * 每天 00:00 执行\n   */\n  @Scheduled(cron = \"0 0 0  * * ?\")\n  public void checkExpire() {\n    expireNotifyService.notifyDrugsExpiredToday();\n    log.info(\"定时任务：发送药品过期提醒\");\n  }\n\n  /**\n   * 检查药品库存\n   * 每天 00:00 执行\n   */\n  @Scheduled(cron = \"0 0 0  * * ?\")\n  public void checkLowerLimit() {\n    drugOutService.checkLowerLimit();\n    log.info(\"定时任务：发送药品库存提醒\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/controller/BlogController.java",
    "content": "package me.zbl.blog.controller;\n\nimport me.zbl.blog.domain.ContentDO;\nimport me.zbl.blog.service.ContentService;\nimport me.zbl.common.utils.DateUtils;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n */\n@RequestMapping(\"/blog\")\n@Controller\npublic class BlogController {\n\n  @Autowired\n  ContentService bContentService;\n\n  @GetMapping()\n  String blog() {\n    return \"blog/index/main\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/open/list\")\n  public PageWrapper opentList(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<ContentDO> bContentList = bContentService.list(query);\n    int total = bContentService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(bContentList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/open/post/{cid}\")\n  String post(@PathVariable(\"cid\") Long cid, Model model) {\n    ContentDO bContentDO = bContentService.get(cid);\n    model.addAttribute(\"bContent\", bContentDO);\n    model.addAttribute(\"gtmModified\", DateUtils.format(bContentDO.getGtmModified()));\n    return \"blog/index/post\";\n  }\n\n  @GetMapping(\"/open/page/{categories}\")\n  String about(@PathVariable(\"categories\") String categories, Model model) {\n    Map<String, Object> map = new HashMap<>(16);\n    map.put(\"categories\", categories);\n    ContentDO bContentDO = null;\n    if (bContentService.list(map).size() > 0) {\n      bContentDO = bContentService.list(map).get(0);\n    }\n    model.addAttribute(\"bContent\", bContentDO);\n    return \"blog/index/post\";\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/controller/ContentController.java",
    "content": "package me.zbl.blog.controller;\n\nimport me.zbl.blog.domain.ContentDO;\nimport me.zbl.blog.service.ContentService;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文章内容\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-09 10:03:34\n */\n@Controller\n@RequestMapping(\"/blog/bContent\")\npublic class ContentController extends BaseController {\n\n  @Autowired\n  ContentService bContentService;\n\n  @GetMapping()\n  @RequiresPermissions(\"blog:bContent:bContent\")\n  String bContent() {\n    return \"blog/bContent/bContent\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  @RequiresPermissions(\"blog:bContent:bContent\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    List<ContentDO> bContentList = bContentService.list(query);\n    int total = bContentService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(bContentList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n  @RequiresPermissions(\"blog:bContent:add\")\n  String add() {\n    return \"blog/bContent/add\";\n  }\n\n  @GetMapping(\"/edit/{cid}\")\n  @RequiresPermissions(\"blog:bContent:edit\")\n  String edit(@PathVariable(\"cid\") Long cid, Model model) {\n    ContentDO bContentDO = bContentService.get(cid);\n    model.addAttribute(\"bContent\", bContentDO);\n    return \"blog/bContent/edit\";\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @RequiresPermissions(\"blog:bContent:add\")\n  @PostMapping(\"/save\")\n  public R save(ContentDO bContent) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (bContent.getAllowComment() == null) {\n      bContent.setAllowComment(0);\n    }\n    if (bContent.getAllowFeed() == null) {\n      bContent.setAllowFeed(0);\n    }\n    if (null == bContent.getType()) {\n      bContent.setType(\"article\");\n    }\n    bContent.setGtmCreate(new Date());\n    bContent.setGtmModified(new Date());\n    int count;\n    if (bContent.getCid() == null || \"\".equals(bContent.getCid())) {\n      count = bContentService.save(bContent);\n    } else {\n      count = bContentService.update(bContent);\n    }\n    if (count > 0) {\n      return R.ok().put(\"cid\", bContent.getCid());\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @RequiresPermissions(\"blog:bContent:edit\")\n  @ResponseBody\n  @RequestMapping(\"/update\")\n  public R update(ContentDO bContent) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    bContent.setGtmCreate(new Date());\n    bContentService.update(bContent);\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @RequiresPermissions(\"blog:bContent:remove\")\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  public R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (bContentService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @RequiresPermissions(\"blog:bContent:batchRemove\")\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  public R remove(@RequestParam(\"ids[]\") Long[] cids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    bContentService.batchRemove(cids);\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/dao/ContentDao.java",
    "content": "package me.zbl.blog.dao;\n\nimport me.zbl.blog.domain.ContentDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文章内容\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 16:17:48\n */\n@Mapper\npublic interface ContentDao {\n\n  ContentDO get(Long cid);\n\n  List<ContentDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(ContentDO content);\n\n  int update(ContentDO content);\n\n  int remove(Long cid);\n\n  int batchRemove(Long[] cids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/domain/ContentDO.java",
    "content": "package me.zbl.blog.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n\n/**\n * 文章内容\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-22 13:16:10\n */\npublic class ContentDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //\n  private Long cid;\n  //标题\n  private String title;\n  //\n  private String slug;\n  //创建人id\n  private Long created;\n  //最近修改人id\n  private Long modified;\n  //内容\n  private String content;\n  //类型\n  private String type;\n  //标签\n  private String tags;\n  //分类\n  private String categories;\n  //\n  private Integer hits;\n  //评论数量\n  private Integer commentsNum;\n  //开启评论\n  private Integer allowComment;\n  //允许ping\n  private Integer allowPing;\n  //允许反馈\n  private Integer allowFeed;\n  //状态\n  private Integer status;\n  //作者\n  private String author;\n  //创建时间\n  private Date gtmCreate;\n  //修改时间\n  private Date gtmModified;\n\n  /**\n   * 获取：\n   */\n  public Long getCid() {\n    return cid;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setCid(Long cid) {\n    this.cid = cid;\n  }\n\n  /**\n   * 获取：标题\n   */\n  public String getTitle() {\n    return title;\n  }\n\n  /**\n   * 设置：标题\n   */\n  public void setTitle(String title) {\n    this.title = title;\n  }\n\n  /**\n   * 获取：\n   */\n  public String getSlug() {\n    return slug;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setSlug(String slug) {\n    this.slug = slug;\n  }\n\n  /**\n   * 获取：创建人id\n   */\n  public Long getCreated() {\n    return created;\n  }\n\n  /**\n   * 设置：创建人id\n   */\n  public void setCreated(Long created) {\n    this.created = created;\n  }\n\n  /**\n   * 获取：最近修改人id\n   */\n  public Long getModified() {\n    return modified;\n  }\n\n  /**\n   * 设置：最近修改人id\n   */\n  public void setModified(Long modified) {\n    this.modified = modified;\n  }\n\n  /**\n   * 获取：内容\n   */\n  public String getContent() {\n    return content;\n  }\n\n  /**\n   * 设置：内容\n   */\n  public void setContent(String content) {\n    this.content = content;\n  }\n\n  /**\n   * 获取：类型\n   */\n  public String getType() {\n    return type;\n  }\n\n  /**\n   * 设置：类型\n   */\n  public void setType(String type) {\n    this.type = type;\n  }\n\n  /**\n   * 获取：标签\n   */\n  public String getTags() {\n    return tags;\n  }\n\n  /**\n   * 设置：标签\n   */\n  public void setTags(String tags) {\n    this.tags = tags;\n  }\n\n  /**\n   * 获取：分类\n   */\n  public String getCategories() {\n    return categories;\n  }\n\n  /**\n   * 设置：分类\n   */\n  public void setCategories(String categories) {\n    this.categories = categories;\n  }\n\n  /**\n   * 获取：\n   */\n  public Integer getHits() {\n    return hits;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setHits(Integer hits) {\n    this.hits = hits;\n  }\n\n  /**\n   * 获取：评论数量\n   */\n  public Integer getCommentsNum() {\n    return commentsNum;\n  }\n\n  /**\n   * 设置：评论数量\n   */\n  public void setCommentsNum(Integer commentsNum) {\n    this.commentsNum = commentsNum;\n  }\n\n  /**\n   * 获取：开启评论\n   */\n  public Integer getAllowComment() {\n    return allowComment;\n  }\n\n  /**\n   * 设置：开启评论\n   */\n  public void setAllowComment(Integer allowComment) {\n    this.allowComment = allowComment;\n  }\n\n  /**\n   * 获取：允许ping\n   */\n  public Integer getAllowPing() {\n    return allowPing;\n  }\n\n  /**\n   * 设置：允许ping\n   */\n  public void setAllowPing(Integer allowPing) {\n    this.allowPing = allowPing;\n  }\n\n  /**\n   * 获取：允许反馈\n   */\n  public Integer getAllowFeed() {\n    return allowFeed;\n  }\n\n  /**\n   * 设置：允许反馈\n   */\n  public void setAllowFeed(Integer allowFeed) {\n    this.allowFeed = allowFeed;\n  }\n\n  /**\n   * 获取：状态\n   */\n  public Integer getStatus() {\n    return status;\n  }\n\n  /**\n   * 设置：状态\n   */\n  public void setStatus(Integer status) {\n    this.status = status;\n  }\n\n  /**\n   * 获取：作者\n   */\n  public String getAuthor() {\n    return author;\n  }\n\n  /**\n   * 设置：作者\n   */\n  public void setAuthor(String author) {\n    this.author = author;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getGtmCreate() {\n    return gtmCreate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setGtmCreate(Date gtmCreate) {\n    this.gtmCreate = gtmCreate;\n  }\n\n  /**\n   * 获取：修改时间\n   */\n  public Date getGtmModified() {\n    return gtmModified;\n  }\n\n  /**\n   * 设置：修改时间\n   */\n  public void setGtmModified(Date gtmModified) {\n    this.gtmModified = gtmModified;\n  }\n\n  @Override\n  public String toString() {\n    return \"ContentDO{\" +\n            \"cid=\" + cid +\n            \", title='\" + title + '\\'' +\n            \", slug='\" + slug + '\\'' +\n            \", created=\" + created +\n            \", modified=\" + modified +\n            \", content='\" + content + '\\'' +\n            \", type='\" + type + '\\'' +\n            \", tags='\" + tags + '\\'' +\n            \", categories='\" + categories + '\\'' +\n            \", hits=\" + hits +\n            \", commentsNum=\" + commentsNum +\n            \", allowComment=\" + allowComment +\n            \", allowPing=\" + allowPing +\n            \", allowFeed=\" + allowFeed +\n            \", status=\" + status +\n            \", author='\" + author + '\\'' +\n            \", gtmCreate=\" + gtmCreate +\n            \", gtmModified=\" + gtmModified +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/service/ContentService.java",
    "content": "package me.zbl.blog.service;\n\nimport me.zbl.blog.domain.ContentDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文章内容\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-09 10:03:34\n */\npublic interface ContentService {\n\n  ContentDO get(Long cid);\n\n  List<ContentDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(ContentDO bContent);\n\n  int update(ContentDO bContent);\n\n  int remove(Long cid);\n\n  int batchRemove(Long[] cids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/blog/service/impl/ContentServiceImpl.java",
    "content": "package me.zbl.blog.service.impl;\n\nimport me.zbl.blog.dao.ContentDao;\nimport me.zbl.blog.domain.ContentDO;\nimport me.zbl.blog.service.ContentService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n\n@Service\npublic class ContentServiceImpl implements ContentService {\n\n  @Autowired\n  private ContentDao bContentMapper;\n\n  @Override\n  public ContentDO get(Long cid) {\n    return bContentMapper.get(cid);\n  }\n\n  @Override\n  public List<ContentDO> list(Map<String, Object> map) {\n    return bContentMapper.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return bContentMapper.count(map);\n  }\n\n  @Override\n  public int save(ContentDO bContent) {\n    return bContentMapper.save(bContent);\n  }\n\n  @Override\n  public int update(ContentDO bContent) {\n    return bContentMapper.update(bContent);\n  }\n\n  @Override\n  public int remove(Long cid) {\n    return bContentMapper.remove(cid);\n  }\n\n  @Override\n  public int batchRemove(Long[] cids) {\n    return bContentMapper.batchRemove(cids);\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/annotation/Log.java",
    "content": "package me.zbl.common.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface Log {\n\n  String value() default \"\";\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/aspect/LogAspect.java",
    "content": "package me.zbl.common.aspect;\n\nimport me.zbl.common.annotation.Log;\nimport me.zbl.common.domain.LogDO;\nimport me.zbl.common.service.LogService;\nimport me.zbl.common.utils.HttpContextUtils;\nimport me.zbl.common.utils.IPUtils;\nimport me.zbl.common.utils.JSONUtils;\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.system.domain.UserDO;\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.aspectj.lang.reflect.MethodSignature;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.lang.reflect.Method;\nimport java.util.Date;\n\n@Aspect\n@Component\npublic class LogAspect {\n\n  private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);\n\n  @Autowired\n  LogService logService;\n\n\n  @Pointcut(\"@annotation(me.zbl.common.annotation.Log)\")\n  public void logPointCut() {\n  }\n\n  @Around(\"logPointCut()\")\n  public Object around(ProceedingJoinPoint point) throws Throwable {\n    long beginTime = System.currentTimeMillis();\n    // 执行方法\n    Object result = point.proceed();\n    // 执行时长(毫秒)\n    long time = System.currentTimeMillis() - beginTime;\n    //异步保存日志\n    saveLog(point, time);\n    return result;\n  }\n\n  void saveLog(ProceedingJoinPoint joinPoint, long time) {\n    MethodSignature signature = (MethodSignature) joinPoint.getSignature();\n    Method method = signature.getMethod();\n    LogDO sysLog = new LogDO();\n    Log syslog = method.getAnnotation(Log.class);\n    if (syslog != null) {\n      // 注解上的描述\n      sysLog.setOperation(syslog.value());\n    }\n    // 请求的方法名\n    String className = joinPoint.getTarget().getClass().getName();\n    String methodName = signature.getName();\n    sysLog.setMethod(className + \".\" + methodName + \"()\");\n    // 请求的参数\n    Object[] args = joinPoint.getArgs();\n    try {\n      String params = JSONUtils.beanToJson(args[0]).substring(0, 4999);\n      sysLog.setParams(params);\n    } catch (Exception e) {\n\n    }\n    // 获取request\n    HttpServletRequest request = HttpContextUtils.getHttpServletRequest();\n    // 设置IP地址\n    sysLog.setIp(IPUtils.getIpAddr(request));\n    // 用户名\n    UserDO currUser = ShiroUtils.getUser();\n    if (null == currUser) {\n      if (null != sysLog.getParams()) {\n        sysLog.setUserId(-1L);\n        sysLog.setUsername(sysLog.getParams());\n      } else {\n        sysLog.setUserId(-1L);\n        sysLog.setUsername(\"获取用户信息为空\");\n      }\n    } else {\n      sysLog.setUserId(ShiroUtils.getUserId());\n      sysLog.setUsername(ShiroUtils.getUser().getUsername());\n    }\n    sysLog.setTime((int) time);\n    // 系统当前时间\n    Date date = new Date();\n    sysLog.setGmtCreate(date);\n    // 保存系统日志\n    logService.save(sysLog);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/aspect/WebLogAspect.java",
    "content": "package me.zbl.common.aspect;\n\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.*;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\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;\nimport java.util.Arrays;\n\n@Aspect\n@Component\npublic class WebLogAspect {\n\n  private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);\n\n  @Pointcut(\"execution( * me.zbl..controller.*.*(..))\")//两个..代表所有子目录，最后括号里的两个..代表所有参数\n  public void logPointCut() {\n  }\n\n\n  @Before(\"logPointCut()\")\n  public void doBefore(JoinPoint joinPoint) {\n    // 接收到请求，记录请求内容\n    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();\n    HttpServletRequest request = attributes.getRequest();\n\n    // 记录下请求内容\n    logger.info(\"请求地址 : \" + request.getRequestURL().toString());\n    logger.info(\"HTTP METHOD : \" + request.getMethod());\n    // 获取真实的ip地址\n    //logger.info(\"IP : \" + IPAddressUtil.getClientIpAddress(request));\n    logger.info(\"CLASS_METHOD : \" + joinPoint.getSignature().getDeclaringTypeName() + \".\"\n            + joinPoint.getSignature().getName());\n    logger.info(\"参数 : \" + Arrays.toString(joinPoint.getArgs()));\n    //        loggger.info(\"参数 : \" + joinPoint.getArgs());\n\n  }\n\n  @AfterReturning(returning = \"ret\", pointcut = \"logPointCut()\")// returning的值和doAfterReturning的参数名一致\n  public void doAfterReturning(Object ret) {\n    // 处理完请求，返回内容(返回值太复杂时，打印的是物理存储空间的地址)\n    logger.debug(\"返回值 : \" + ret);\n  }\n\n  @Around(\"logPointCut()\")\n  public Object doAround(ProceedingJoinPoint pjp) throws Throwable {\n    long startTime = System.currentTimeMillis();\n    Object ob = pjp.proceed();// ob 为方法的返回值\n    logger.info(\"耗时 : \" + (System.currentTimeMillis() - startTime));\n    return ob;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/ApplicationContextRegister.java",
    "content": "package me.zbl.common.config;\n\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;\n\n/**\n * @author 郑保乐\n * @date 2017/9/4\n * <p>\n * @email 18333298410@163.dom\n * <p>\n * Describe:\n */\n@Component\npublic class ApplicationContextRegister implements ApplicationContextAware {\n\n  private static Logger logger = LoggerFactory.getLogger(ApplicationContextRegister.class);\n  private static ApplicationContext APPLICATION_CONTEXT;\n\n  /**\n   * 获取容器\n   *\n   * @return\n   */\n  public static ApplicationContext getApplicationContext() {\n    return APPLICATION_CONTEXT;\n  }\n\n  /**\n   * 设置spring上下文\n   *\n   * @param applicationContext spring上下文\n   *\n   * @throws BeansException\n   */\n  @Override\n  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n    logger.debug(\"ApplicationContext registed-->{}\", applicationContext);\n    APPLICATION_CONTEXT = applicationContext;\n  }\n\n  /**\n   * 获取容器对象\n   *\n   * @param type\n   * @param <T>\n   *\n   * @return\n   */\n  public static <T> T getBean(Class<T> type) {\n    return APPLICATION_CONTEXT.getBean(type);\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/config/Constant.java",
    "content": "package me.zbl.common.config;\n\npublic class Constant {\n\n  //演示系统账户\n  public static String DEMO_ACCOUNT = \"test\";\n  //自动去除表前缀\n  public static String AUTO_REOMVE_PRE = \"true\";\n  //停止计划任务\n  public static String STATUS_RUNNING_STOP = \"stop\";\n  //开启计划任务\n  public static String STATUS_RUNNING_START = \"start\";\n  //通知公告阅读状态-未读\n  public static String OA_NOTIFY_READ_NO = \"0\";\n  //通知公告阅读状态-已读\n  public static int OA_NOTIFY_READ_YES = 1;\n  //部门根节点id\n  public static Long DEPT_ROOT_ID = 0l;\n  //缓存方式\n  public static String CACHE_TYPE_REDIS = \"redis\";\n\n  public static String LOG_ERROR = \"error\";\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/DateConverConfig.java",
    "content": "package me.zbl.common.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.convert.converter.Converter;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * @author 郑保乐\n * @date 2017/12/14.\n */\n@Configuration\npublic class DateConverConfig {\n\n  @Bean\n  public Converter<String, Date> stringDateConvert() {\n    return new Converter<String, Date>() {\n      @Override\n      public Date convert(String source) {\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        Date date = null;\n        try {\n          date = sdf.parse(source);\n        } catch (Exception e) {\n          SimpleDateFormat sdfday = new SimpleDateFormat(\"yyyy-MM-dd\");\n          try {\n            date = sdfday.parse(source);\n          } catch (ParseException e1) {\n            e1.printStackTrace();\n          }\n        }\n        return date;\n      }\n    };\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/DruidDBConfig.java",
    "content": "package me.zbl.common.config;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.http.StatViewServlet;\nimport com.alibaba.druid.support.http.WebStatFilter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Value;\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;\nimport org.springframework.context.annotation.Primary;\n\nimport javax.sql.DataSource;\nimport java.sql.SQLException;\n\n/**\n * Created by PrimaryKey on 17/2/4.\n */\n@SuppressWarnings(\"AlibabaRemoveCommentedCode\")\n@Configuration\npublic class DruidDBConfig {\n\n  private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);\n  @Value(\"${spring.datasource.url}\")\n  private String dbUrl;\n\n  @Value(\"${spring.datasource.username}\")\n  private String username;\n\n  @Value(\"${spring.datasource.password}\")\n  private String password;\n\n  @Value(\"${spring.datasource.driverClassName}\")\n  private String driverClassName;\n\n  @Value(\"${spring.datasource.initialSize}\")\n  private int initialSize;\n\n  @Value(\"${spring.datasource.minIdle}\")\n  private int minIdle;\n\n  @Value(\"${spring.datasource.maxActive}\")\n  private int maxActive;\n\n  @Value(\"${spring.datasource.maxWait}\")\n  private int maxWait;\n\n  @Value(\"${spring.datasource.timeBetweenEvictionRunsMillis}\")\n  private int timeBetweenEvictionRunsMillis;\n\n  @Value(\"${spring.datasource.minEvictableIdleTimeMillis}\")\n  private int minEvictableIdleTimeMillis;\n\n  @Value(\"${spring.datasource.validationQuery}\")\n  private String validationQuery;\n\n  @Value(\"${spring.datasource.testWhileIdle}\")\n  private boolean testWhileIdle;\n\n  @Value(\"${spring.datasource.testOnBorrow}\")\n  private boolean testOnBorrow;\n\n  @Value(\"${spring.datasource.testOnReturn}\")\n  private boolean testOnReturn;\n\n  @Value(\"${spring.datasource.poolPreparedStatements}\")\n  private boolean poolPreparedStatements;\n\n  @Value(\"${spring.datasource.maxPoolPreparedStatementPerConnectionSize}\")\n  private int maxPoolPreparedStatementPerConnectionSize;\n\n  @Value(\"${spring.datasource.filters}\")\n  private String filters;\n\n  @Value(\"{spring.datasource.connectionProperties}\")\n  private String connectionProperties;\n\n  @Bean(initMethod = \"init\", destroyMethod = \"close\")   //声明其为Bean实例\n  @Primary  //在同样的DataSource中，首先使用被标注的DataSource\n  public DataSource dataSource() {\n    DruidDataSource datasource = new DruidDataSource();\n\n    datasource.setUrl(this.dbUrl);\n    datasource.setUsername(username);\n    datasource.setPassword(password);\n    datasource.setDriverClassName(driverClassName);\n\n    //configuration\n    datasource.setInitialSize(initialSize);\n    datasource.setMinIdle(minIdle);\n    datasource.setMaxActive(maxActive);\n    datasource.setMaxWait(maxWait);\n    datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n    datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n    datasource.setValidationQuery(validationQuery);\n    datasource.setTestWhileIdle(testWhileIdle);\n    datasource.setTestOnBorrow(testOnBorrow);\n    datasource.setTestOnReturn(testOnReturn);\n    datasource.setPoolPreparedStatements(poolPreparedStatements);\n    datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);\n    try {\n      datasource.setFilters(filters);\n    } catch (SQLException e) {\n      logger.error(\"druid configuration initialization filter\", e);\n    }\n    datasource.setConnectionProperties(connectionProperties);\n\n    return datasource;\n  }\n\n  @Bean\n  public ServletRegistrationBean druidServlet() {\n    ServletRegistrationBean reg = new ServletRegistrationBean();\n    reg.setServlet(new StatViewServlet());\n    reg.addUrlMappings(\"/druid/*\");\n    reg.addInitParameter(\"allow\", \"\"); //白名单\n    return reg;\n  }\n\n  @Bean\n  public FilterRegistrationBean filterRegistrationBean() {\n    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();\n    filterRegistrationBean.setFilter(new WebStatFilter());\n    filterRegistrationBean.addUrlPatterns(\"/*\");\n    filterRegistrationBean.addInitParameter(\"exclusions\", \"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*\");\n    filterRegistrationBean.addInitParameter(\"profileEnable\", \"true\");\n    filterRegistrationBean.addInitParameter(\"principalCookieName\", \"USER_COOKIE\");\n    filterRegistrationBean.addInitParameter(\"principalSessionName\", \"USER_SESSION\");\n    filterRegistrationBean.addInitParameter(\"DruidWebStatFilter\", \"/*\");\n    return filterRegistrationBean;\n  }\n}\n\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/HospitalConfig.java",
    "content": "package me.zbl.common.config;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n@Component\n@ConfigurationProperties(prefix = \"hospital\")\npublic class HospitalConfig {\n\n  //上传路径\n  private String uploadPath;\n\n  public String getUploadPath() {\n    return uploadPath;\n  }\n\n  public void setUploadPath(String uploadPath) {\n    this.uploadPath = uploadPath;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/QuartzConfigration.java",
    "content": "package me.zbl.common.config;\n\nimport me.zbl.common.quartz.factory.JobFactory;\nimport org.quartz.Scheduler;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.config.PropertiesFactoryBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.scheduling.quartz.SchedulerFactoryBean;\n\nimport java.io.IOException;\nimport java.util.Properties;\n\n@Configuration\npublic class QuartzConfigration {\n\n  @Autowired\n  JobFactory jobFactory;\n\n\n  @Bean\n  public SchedulerFactoryBean schedulerFactoryBean() {\n    SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();\n    try {\n      schedulerFactoryBean.setOverwriteExistingJobs(true);\n      schedulerFactoryBean.setQuartzProperties(quartzProperties());\n      schedulerFactoryBean.setJobFactory(jobFactory);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return schedulerFactoryBean;\n  }\n\n  // 指定quartz.properties\n  @Bean\n  public Properties quartzProperties() throws IOException {\n    PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();\n    propertiesFactoryBean.setLocation(new ClassPathResource(\"/config/quartz.properties\"));\n    propertiesFactoryBean.afterPropertiesSet();\n    return propertiesFactoryBean.getObject();\n  }\n\n  // 创建schedule\n  @Bean(name = \"scheduler\")\n  public Scheduler scheduler() {\n    return schedulerFactoryBean().getScheduler();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/SchedulerConf.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.common.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-12\n */\n@Configuration\n@EnableScheduling\npublic class SchedulerConf {\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/config/SpringAsyncConfig.java",
    "content": "package me.zbl.common.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n@Configuration\n@EnableAsync\npublic class SpringAsyncConfig {\n  //    @Bean\n  //    public AsyncTaskExecutor taskExecutor() {\n  //        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n  //        executor.setMaxPoolSize(10);\n  //        return executor;\n  //    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/config/WebConfigurer.java",
    "content": "package me.zbl.common.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\n@Component\nclass WebConfigurer extends WebMvcConfigurerAdapter {\n\n  @Autowired\n  HospitalConfig hospitalConfig;\n\n  @Override\n  public void addResourceHandlers(ResourceHandlerRegistry registry) {\n    registry.addResourceHandler(\"/files/**\").addResourceLocations(\"file:///\" + hospitalConfig.getUploadPath());\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/BaseController.java",
    "content": "package me.zbl.common.controller;\n\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.system.domain.UserDO;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class BaseController {\n\n  public UserDO getUser() {\n    return ShiroUtils.getUser();\n  }\n\n  public Long getUserId() {\n    return getUser().getUserId();\n  }\n\n  public String getUsername() {\n    return getUser().getUsername();\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/DictController.java",
    "content": "package me.zbl.common.controller;\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.domain.DictDO;\nimport me.zbl.common.service.DictService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 字典表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-29 18:28:07\n */\n\n@Controller\n@RequestMapping(\"/common/dict\")\npublic class DictController extends BaseController {\n\n  @Autowired\n  private DictService dictService;\n\n  @GetMapping()\n  @RequiresPermissions(\"common:dict:dict\")\n  String dict() {\n    return \"common/dict/dict\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  @RequiresPermissions(\"common:dict:dict\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    // 查询列表数据\n    Query query = new Query(params);\n    List<DictDO> dictList = dictService.list(query);\n    int total = dictService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(dictList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n  @RequiresPermissions(\"common:dict:add\")\n  String add() {\n    return \"common/dict/add\";\n  }\n\n  @GetMapping(\"/edit/{id}\")\n  @RequiresPermissions(\"common:dict:edit\")\n  String edit(@PathVariable(\"id\") Long id, Model model) {\n    DictDO dict = dictService.get(id);\n    model.addAttribute(\"dict\", dict);\n    return \"common/dict/edit\";\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  @RequiresPermissions(\"common:dict:add\")\n  public R save(DictDO dict) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (dictService.save(dict) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @ResponseBody\n  @RequestMapping(\"/update\")\n  @RequiresPermissions(\"common:dict:edit\")\n  public R update(DictDO dict) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    dictService.update(dict);\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  @RequiresPermissions(\"common:dict:remove\")\n  public R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (dictService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  @RequiresPermissions(\"common:dict:batchRemove\")\n  public R remove(@RequestParam(\"ids[]\") Long[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    dictService.batchRemove(ids);\n    return R.ok();\n  }\n\n  @GetMapping(\"/type\")\n  @ResponseBody\n  public List<DictDO> listType() {\n    return dictService.listType();\n  }\n\n  // 类别已经指定增加\n  @GetMapping(\"/add/{type}/{description}\")\n  @RequiresPermissions(\"common:dict:add\")\n  String addD(Model model, @PathVariable(\"type\") String type, @PathVariable(\"description\") String description) {\n    model.addAttribute(\"type\", type);\n    model.addAttribute(\"description\", description);\n    return \"common/dict/add\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list/{type}\")\n  public List<DictDO> listByType(@PathVariable(\"type\") String type) {\n    // 查询列表数据\n    Map<String, Object> map = new HashMap<>(16);\n    map.put(\"type\", type);\n    List<DictDO> dictList = dictService.list(map);\n    return dictList;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/FileController.java",
    "content": "package me.zbl.common.controller;\n\nimport me.zbl.common.config.HospitalConfig;\nimport me.zbl.common.domain.FileDO;\nimport me.zbl.common.service.FileService;\nimport me.zbl.common.utils.*;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文件上传\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-19 16:02:20\n */\n@Controller\n@RequestMapping(\"/common/sysFile\")\npublic class FileController extends BaseController {\n\n  @Autowired\n  private FileService sysFileService;\n\n  @Autowired\n  private HospitalConfig hospitalConfig;\n\n  @GetMapping()\n  @RequiresPermissions(\"common:sysFile:sysFile\")\n  String sysFile(Model model) {\n    Map<String, Object> params = new HashMap<>(16);\n    return \"common/file/file\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  @RequiresPermissions(\"common:sysFile:sysFile\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    // 查询列表数据\n    Query query = new Query(params);\n    List<FileDO> sysFileList = sysFileService.list(query);\n    int total = sysFileService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(sysFileList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n    // @RequiresPermissions(\"common:bComments\")\n  String add() {\n    return \"common/sysFile/add\";\n  }\n\n  @GetMapping(\"/edit\")\n    // @RequiresPermissions(\"common:bComments\")\n  String edit(Long id, Model model) {\n    FileDO sysFile = sysFileService.get(id);\n    model.addAttribute(\"sysFile\", sysFile);\n    return \"common/sysFile/edit\";\n  }\n\n  /**\n   * 信息\n   */\n  @RequestMapping(\"/info/{id}\")\n  @RequiresPermissions(\"common:info\")\n  public R info(@PathVariable(\"id\") Long id) {\n    FileDO sysFile = sysFileService.get(id);\n    return R.ok().put(\"sysFile\", sysFile);\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  @RequiresPermissions(\"common:save\")\n  public R save(FileDO sysFile) {\n    if (sysFileService.save(sysFile) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @RequestMapping(\"/update\")\n  @RequiresPermissions(\"common:update\")\n  public R update(@RequestBody FileDO sysFile) {\n    sysFileService.update(sysFile);\n\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  // @RequiresPermissions(\"common:remove\")\n  public R remove(Long id, HttpServletRequest request) {\n    if (\"test\".equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    String fileName = hospitalConfig.getUploadPath() + sysFileService.get(id).getUrl().replace(\"/files/\", \"\");\n    if (sysFileService.remove(id) > 0) {\n      boolean b = FileUtil.deleteFile(fileName);\n      if (!b) {\n        return R.error(\"数据库记录删除成功，文件删除失败\");\n      }\n      return R.ok();\n    } else {\n      return R.error();\n    }\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  @RequiresPermissions(\"common:remove\")\n  public R remove(@RequestParam(\"ids[]\") Long[] ids) {\n    if (\"test\".equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    sysFileService.batchRemove(ids);\n    return R.ok();\n  }\n\n  @ResponseBody\n  @PostMapping(\"/upload\")\n  R upload(@RequestParam(\"file\") MultipartFile file, HttpServletRequest request) {\n    if (\"test\".equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    String fileName = file.getOriginalFilename();\n    fileName = FileUtil.renameToUUID(fileName);\n    FileDO sysFile = new FileDO(FileType.fileType(fileName), \"/files/\" + fileName, new Date());\n    try {\n      FileUtil.uploadFile(file.getBytes(), hospitalConfig.getUploadPath(), fileName);\n    } catch (Exception e) {\n      return R.error();\n    }\n\n    if (sysFileService.save(sysFile) > 0) {\n      return R.ok().put(\"fileName\", sysFile.getUrl());\n    }\n    return R.error();\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/GeneratorController.java",
    "content": "package me.zbl.common.controller;\n\nimport com.alibaba.fastjson.JSON;\nimport me.zbl.common.service.GeneratorService;\nimport me.zbl.common.utils.GenUtils;\nimport me.zbl.common.utils.R;\nimport org.apache.commons.configuration.Configuration;\nimport org.apache.commons.configuration.ConfigurationException;\nimport org.apache.commons.configuration.PropertiesConfiguration;\nimport org.apache.commons.io.IOUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@RequestMapping(\"/common/generator\")\n@Controller\npublic class GeneratorController {\n\n  String prefix = \"common/generator\";\n  @Autowired\n  GeneratorService generatorService;\n\n  @GetMapping()\n  String generator() {\n    return prefix + \"/list\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  List<Map<String, Object>> list() {\n    List<Map<String, Object>> list = generatorService.list();\n    return list;\n  }\n\n  @RequestMapping(\"/code/{tableName}\")\n  public void code(HttpServletRequest request, HttpServletResponse response,\n                   @PathVariable(\"tableName\") String tableName) throws IOException {\n    String[] tableNames = new String[]{tableName};\n    byte[] data = generatorService.generatorCode(tableNames);\n    response.reset();\n    response.setHeader(\"Content-Disposition\", \"attachment; filename=\\\"bootdo.zip\\\"\");\n    response.addHeader(\"Content-Length\", \"\" + data.length);\n    response.setContentType(\"application/octet-stream; charset=UTF-8\");\n\n    IOUtils.write(data, response.getOutputStream());\n  }\n\n  @RequestMapping(\"/batchCode\")\n  public void batchCode(HttpServletRequest request, HttpServletResponse response, String tables) throws IOException {\n    String[] tableNames = new String[]{};\n    tableNames = JSON.parseArray(tables).toArray(tableNames);\n    byte[] data = generatorService.generatorCode(tableNames);\n    response.reset();\n    response.setHeader(\"Content-Disposition\", \"attachment; filename=\\\"bootdo.zip\\\"\");\n    response.addHeader(\"Content-Length\", \"\" + data.length);\n    response.setContentType(\"application/octet-stream; charset=UTF-8\");\n\n    IOUtils.write(data, response.getOutputStream());\n  }\n\n  @GetMapping(\"/edit\")\n  public String edit(Model model) {\n    Configuration conf = GenUtils.getConfig();\n    Map<String, Object> property = new HashMap<>(16);\n    property.put(\"author\", conf.getProperty(\"author\"));\n    property.put(\"email\", conf.getProperty(\"email\"));\n    property.put(\"package\", conf.getProperty(\"package\"));\n    property.put(\"autoRemovePre\", conf.getProperty(\"autoRemovePre\"));\n    property.put(\"tablePrefix\", conf.getProperty(\"tablePrefix\"));\n    model.addAttribute(\"property\", property);\n    return prefix + \"/edit\";\n  }\n\n  @ResponseBody\n  @PostMapping(\"/update\")\n  R update(@RequestParam Map<String, Object> map) {\n    try {\n      PropertiesConfiguration conf = new PropertiesConfiguration(\"generator.properties\");\n      conf.setProperty(\"author\", map.get(\"author\"));\n      conf.setProperty(\"email\", map.get(\"email\"));\n      conf.setProperty(\"package\", map.get(\"package\"));\n      conf.setProperty(\"autoRemovePre\", map.get(\"autoRemovePre\"));\n      conf.setProperty(\"tablePrefix\", map.get(\"tablePrefix\"));\n      conf.save();\n    } catch (ConfigurationException e) {\n      return R.error(\"保存配置文件出错\");\n    }\n    return R.ok();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/JobController.java",
    "content": "package me.zbl.common.controller;\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.domain.TaskDO;\nimport me.zbl.common.service.JobService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-26 20:53:48\n */\n@Controller\n@RequestMapping(\"/common/job\")\npublic class JobController extends BaseController {\n\n  @Autowired\n  private JobService taskScheduleJobService;\n\n  @GetMapping()\n  String taskScheduleJob() {\n    return \"common/job/job\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    // 查询列表数据\n    Query query = new Query(params);\n    List<TaskDO> taskScheduleJobList = taskScheduleJobService.list(query);\n    int total = taskScheduleJobService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(taskScheduleJobList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n  String add() {\n    return \"common/job/add\";\n  }\n\n  @GetMapping(\"/edit/{id}\")\n  String edit(@PathVariable(\"id\") Long id, Model model) {\n    TaskDO job = taskScheduleJobService.get(id);\n    model.addAttribute(\"job\", job);\n    return \"common/job/edit\";\n  }\n\n  /**\n   * 信息\n   */\n  @RequestMapping(\"/info/{id}\")\n  public R info(@PathVariable(\"id\") Long id) {\n    TaskDO taskScheduleJob = taskScheduleJobService.get(id);\n    return R.ok().put(\"taskScheduleJob\", taskScheduleJob);\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  public R save(TaskDO taskScheduleJob) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (taskScheduleJobService.save(taskScheduleJob) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @ResponseBody\n  @PostMapping(\"/update\")\n  public R update(TaskDO taskScheduleJob) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    taskScheduleJobService.update(taskScheduleJob);\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  public R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (taskScheduleJobService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  public R remove(@RequestParam(\"ids[]\") Long[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    taskScheduleJobService.batchRemove(ids);\n\n    return R.ok();\n  }\n\n  @PostMapping(value = \"/changeJobStatus\")\n  @ResponseBody\n  public R changeJobStatus(Long id, String cmd) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    String label = \"停止\";\n    if (\"start\".equals(cmd)) {\n      label = \"启动\";\n    } else {\n      label = \"停止\";\n    }\n    try {\n      taskScheduleJobService.changeStatus(id, cmd);\n      return R.ok(\"任务\" + label + \"成功\");\n    } catch (Exception e) {\n      e.printStackTrace();\n    }\n    return R.ok(\"任务\" + label + \"失败\");\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/controller/LogController.java",
    "content": "package me.zbl.common.controller;\n\nimport me.zbl.common.domain.LogDO;\nimport me.zbl.common.domain.PageDO;\nimport me.zbl.common.service.LogService;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Map;\n\n@RequestMapping(\"/common/log\")\n@Controller\npublic class LogController {\n\n  @Autowired\n  LogService logService;\n  String prefix = \"common/log\";\n\n  @GetMapping()\n  String log() {\n    return prefix + \"/log\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  PageDO<LogDO> list(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    PageDO<LogDO> page = logService.queryList(query);\n    return page;\n  }\n\n  @ResponseBody\n  @PostMapping(\"/remove\")\n  R remove(Long id) {\n    if (logService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  @ResponseBody\n  @PostMapping(\"/batchRemove\")\n  R batchRemove(@RequestParam(\"ids[]\") Long[] ids) {\n    int r = logService.batchRemove(ids);\n    if (r > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/dao/DictDao.java",
    "content": "package me.zbl.common.dao;\n\nimport me.zbl.common.domain.DictDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 字典表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 15:45:42\n */\n@Mapper\npublic interface DictDao {\n\n  DictDO get(Long id);\n\n  List<DictDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(DictDO dict);\n\n  int update(DictDO dict);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  List<DictDO> listType();\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/dao/FileDao.java",
    "content": "package me.zbl.common.dao;\n\nimport me.zbl.common.domain.FileDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文件上传\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 15:45:42\n */\n@Mapper\npublic interface FileDao {\n\n  FileDO get(Long id);\n\n  List<FileDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(FileDO file);\n\n  int update(FileDO file);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/dao/GeneratorMapper.java",
    "content": "package me.zbl.common.dao;\n\nimport org.apache.ibatis.annotations.Select;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface GeneratorMapper {\n\n  @Select(\"select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables\"\n                  + \" where table_schema = (select database())\")\n  List<Map<String, Object>> list();\n\n  @Select(\"select count(*) from information_schema.tables where table_schema = (select database())\")\n  int count(Map<String, Object> map);\n\n  @Select(\"select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables \\r\\n\"\n                  + \"\twhere table_schema = (select database()) and table_name = #{tableName}\")\n  Map<String, String> get(String tableName);\n\n  @Select(\"select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns\\r\\n\"\n                  + \" where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position\")\n  List<Map<String, String>> listColumns(String tableName);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/dao/LogDao.java",
    "content": "package me.zbl.common.dao;\n\nimport me.zbl.common.domain.LogDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 系统日志\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 15:45:42\n */\n@Mapper\npublic interface LogDao {\n\n  LogDO get(Long id);\n\n  List<LogDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(LogDO log);\n\n  int update(LogDO log);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/dao/TaskDao.java",
    "content": "package me.zbl.common.dao;\n\nimport me.zbl.common.domain.TaskDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 15:45:42\n */\n@Mapper\npublic interface TaskDao {\n\n  TaskDO get(Long id);\n\n  List<TaskDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(TaskDO task);\n\n  int update(TaskDO task);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/ColumnDO.java",
    "content": "package me.zbl.common.domain;\n\n/**\n * 列的属性\n */\npublic class ColumnDO {\n\n  // 列名\n  private String columnName;\n  // 列名类型\n  private String dataType;\n  // 列名备注\n  private String comments;\n\n  // 属性名称(第一个字母大写)，如：user_name => UserName\n  private String attrName;\n  // 属性名称(第一个字母小写)，如：user_name => userName\n  private String attrname;\n  // 属性类型\n  private String attrType;\n  // auto_increment\n  private String extra;\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 getDataType() {\n    return dataType;\n  }\n\n  public void setDataType(String dataType) {\n    this.dataType = dataType;\n  }\n\n  public String getComments() {\n    return comments;\n  }\n\n  public void setComments(String comments) {\n    this.comments = comments;\n  }\n\n  public String getAttrname() {\n    return attrname;\n  }\n\n  public void setAttrname(String attrname) {\n    this.attrname = attrname;\n  }\n\n  public String getAttrName() {\n    return attrName;\n  }\n\n  public void setAttrName(String attrName) {\n    this.attrName = attrName;\n  }\n\n  public String getAttrType() {\n    return attrType;\n  }\n\n  public void setAttrType(String attrType) {\n    this.attrType = attrType;\n  }\n\n  public String getExtra() {\n    return extra;\n  }\n\n  public void setExtra(String extra) {\n    this.extra = extra;\n  }\n\n  @Override\n  public String toString() {\n    return \"ColumnDO{\" +\n            \"columnName='\" + columnName + '\\'' +\n            \", dataType='\" + dataType + '\\'' +\n            \", comments='\" + comments + '\\'' +\n            \", attrName='\" + attrName + '\\'' +\n            \", attrname='\" + attrname + '\\'' +\n            \", attrType='\" + attrType + '\\'' +\n            \", extra='\" + extra + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/DictDO.java",
    "content": "package me.zbl.common.domain;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n\n/**\n * 字典表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-29 18:28:07\n */\npublic class DictDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //编号\n  private Long id;\n  //标签名\n  private String name;\n  //数据值\n  private String value;\n  //类型\n  private String type;\n  //描述\n  private String description;\n  //排序（升序）\n  private BigDecimal sort;\n  //父级编号\n  private Long parentId;\n  //创建者\n  private Integer createBy;\n  //创建时间\n  private Date createDate;\n  //更新者\n  private Long updateBy;\n  //更新时间\n  private Date updateDate;\n  //备注信息\n  private String remarks;\n  //删除标记\n  private String delFlag;\n\n  /**\n   * 获取：编号\n   */\n  public Long getId() {\n    return id;\n  }\n\n  /**\n   * 设置：编号\n   */\n  public void setId(Long id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：标签名\n   */\n  public String getName() {\n    return name;\n  }\n\n  /**\n   * 设置：标签名\n   */\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  /**\n   * 获取：数据值\n   */\n  public String getValue() {\n    return value;\n  }\n\n  /**\n   * 设置：数据值\n   */\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  /**\n   * 获取：类型\n   */\n  public String getType() {\n    return type;\n  }\n\n  /**\n   * 设置：类型\n   */\n  public void setType(String type) {\n    this.type = type;\n  }\n\n  /**\n   * 获取：描述\n   */\n  public String getDescription() {\n    return description;\n  }\n\n  /**\n   * 设置：描述\n   */\n  public void setDescription(String description) {\n    this.description = description;\n  }\n\n  /**\n   * 获取：排序（升序）\n   */\n  public BigDecimal getSort() {\n    return sort;\n  }\n\n  /**\n   * 设置：排序（升序）\n   */\n  public void setSort(BigDecimal sort) {\n    this.sort = sort;\n  }\n\n  /**\n   * 获取：父级编号\n   */\n  public Long getParentId() {\n    return parentId;\n  }\n\n  /**\n   * 设置：父级编号\n   */\n  public void setParentId(Long parentId) {\n    this.parentId = parentId;\n  }\n\n  /**\n   * 获取：创建者\n   */\n  public Integer getCreateBy() {\n    return createBy;\n  }\n\n  /**\n   * 设置：创建者\n   */\n  public void setCreateBy(Integer createBy) {\n    this.createBy = createBy;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getCreateDate() {\n    return createDate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setCreateDate(Date createDate) {\n    this.createDate = createDate;\n  }\n\n  /**\n   * 获取：更新者\n   */\n  public Long getUpdateBy() {\n    return updateBy;\n  }\n\n  /**\n   * 设置：更新者\n   */\n  public void setUpdateBy(Long updateBy) {\n    this.updateBy = updateBy;\n  }\n\n  /**\n   * 获取：更新时间\n   */\n  public Date getUpdateDate() {\n    return updateDate;\n  }\n\n  /**\n   * 设置：更新时间\n   */\n  public void setUpdateDate(Date updateDate) {\n    this.updateDate = updateDate;\n  }\n\n  /**\n   * 获取：备注信息\n   */\n  public String getRemarks() {\n    return remarks;\n  }\n\n  /**\n   * 设置：备注信息\n   */\n  public void setRemarks(String remarks) {\n    this.remarks = remarks;\n  }\n\n  /**\n   * 获取：删除标记\n   */\n  public String getDelFlag() {\n    return delFlag;\n  }\n\n  /**\n   * 设置：删除标记\n   */\n  public void setDelFlag(String delFlag) {\n    this.delFlag = delFlag;\n  }\n\n  @Override\n  public String toString() {\n    return \"DictDO{\" +\n            \"id=\" + id +\n            \", name='\" + name + '\\'' +\n            \", value='\" + value + '\\'' +\n            \", type='\" + type + '\\'' +\n            \", description='\" + description + '\\'' +\n            \", sort=\" + sort +\n            \", parentId=\" + parentId +\n            \", createBy=\" + createBy +\n            \", createDate=\" + createDate +\n            \", updateBy=\" + updateBy +\n            \", updateDate=\" + updateDate +\n            \", remarks='\" + remarks + '\\'' +\n            \", delFlag='\" + delFlag + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/FileDO.java",
    "content": "package me.zbl.common.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 文件上传\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-19 16:02:20\n */\npublic class FileDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //\n  private Long id;\n  // 文件类型\n  private Integer type;\n  // URL地址\n  private String url;\n  // 创建时间\n  private Date createDate;\n\n\n  public FileDO() {\n    super();\n  }\n\n\n  public FileDO(Integer type, String url, Date createDate) {\n    super();\n    this.type = type;\n    this.url = url;\n    this.createDate = createDate;\n  }\n\n  /**\n   * 获取：\n   */\n  public Long getId() {\n    return id;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setId(Long id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：文件类型\n   */\n  public Integer getType() {\n    return type;\n  }\n\n  /**\n   * 设置：文件类型\n   */\n  public void setType(Integer type) {\n    this.type = type;\n  }\n\n  /**\n   * 获取：URL地址\n   */\n  public String getUrl() {\n    return url;\n  }\n\n  /**\n   * 设置：URL地址\n   */\n  public void setUrl(String url) {\n    this.url = url;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getCreateDate() {\n    return createDate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setCreateDate(Date createDate) {\n    this.createDate = createDate;\n  }\n\n  @Override\n  public String toString() {\n    return \"FileDO{\" +\n            \"id=\" + id +\n            \", type=\" + type +\n            \", url='\" + url + '\\'' +\n            \", createDate=\" + createDate +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/LogDO.java",
    "content": "package me.zbl.common.domain;\n\nimport com.fasterxml.jackson.annotation.JsonFormat;\n\nimport java.util.Date;\n\npublic class LogDO {\n\n  private Long id;\n\n  private Long userId;\n\n  private String username;\n\n  private String operation;\n\n  private Integer time;\n\n  private String method;\n\n  private String params;\n\n  private String ip;\n  @JsonFormat(timezone = \"GMT+8\", pattern = \"yyyy-MM-dd HH:mm:ss\")\n  private Date gmtCreate;\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 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 String getOperation() {\n    return operation;\n  }\n\n  public void setOperation(String operation) {\n    this.operation = operation == null ? null : operation.trim();\n  }\n\n  public Integer getTime() {\n    return time;\n  }\n\n  public void setTime(Integer time) {\n    this.time = time;\n  }\n\n  public String getMethod() {\n    return method;\n  }\n\n  public void setMethod(String method) {\n    this.method = method == null ? null : method.trim();\n  }\n\n  public String getParams() {\n    return params;\n  }\n\n  public void setParams(String params) {\n    this.params = params == null ? null : params.trim();\n  }\n\n  public String getIp() {\n    return ip;\n  }\n\n  public void setIp(String ip) {\n    this.ip = ip == null ? null : ip.trim();\n  }\n\n  public Date getGmtCreate() {\n    return gmtCreate;\n  }\n\n  public void setGmtCreate(Date gmtCreate) {\n    this.gmtCreate = gmtCreate;\n  }\n\n  @Override\n  public String toString() {\n    return \"LogDO{\" +\n            \"id=\" + id +\n            \", userId=\" + userId +\n            \", username='\" + username + '\\'' +\n            \", operation='\" + operation + '\\'' +\n            \", time=\" + time +\n            \", method='\" + method + '\\'' +\n            \", params='\" + params + '\\'' +\n            \", ip='\" + ip + '\\'' +\n            \", gmtCreate=\" + gmtCreate +\n            '}';\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/PageDO.java",
    "content": "package me.zbl.common.domain;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class PageDO<T> {\n\n  private int offset;\n  private int limit;\n  private int total;\n  private Map<String, Object> params;\n  private String param;\n  private List<T> rows;\n\n  public PageDO() {\n    super();\n    this.offset = 0;\n    this.limit = 10;\n    this.total = 1;\n    this.params = new HashMap<>();\n    this.param = \"\";\n    this.rows = new ArrayList<>();\n  }\n\n  public int getOffset() {\n    return offset;\n  }\n\n  public void setOffset(int offset) {\n    this.offset = offset;\n  }\n\n  public int getLimit() {\n    return limit;\n  }\n\n  public void setLimit(int limit) {\n    this.limit = limit;\n  }\n\n  public int getTotal() {\n    return total;\n  }\n\n  public void setTotal(int total) {\n    this.total = total;\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  public List<T> getRows() {\n    return rows;\n  }\n\n  public void setRows(List<T> rows) {\n    this.rows = rows;\n  }\n\n  public String getParam() {\n    return param;\n  }\n\n  public void setParam(String param) {\n    this.param = param;\n  }\n\n  @Override\n  public String toString() {\n    return \"PageDO{\" +\n            \"offset=\" + offset +\n            \", limit=\" + limit +\n            \", total=\" + total +\n            \", params=\" + params +\n            \", param='\" + param + '\\'' +\n            \", rows=\" + rows +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/ScheduleJob.java",
    "content": "package me.zbl.common.domain;\n\nimport org.quartz.Job;\nimport org.quartz.JobExecutionContext;\n\nimport java.io.Serializable;\n\n@SuppressWarnings(\"serial\")\npublic class ScheduleJob implements Serializable, Job {\n\n  public static final String STATUS_RUNNING = \"1\";\n  public static final String STATUS_NOT_RUNNING = \"0\";\n  public static final String CONCURRENT_IS = \"1\";\n  public static final String CONCURRENT_NOT = \"0\";\n\n  /**\n   * 任务名称\n   */\n  private String jobName;\n  /**\n   * 任务分组\n   */\n  private String jobGroup;\n  /**\n   * 任务状态 是否启动任务\n   */\n  private String jobStatus;\n  /**\n   * cron表达式\n   */\n  private String cronExpression;\n  /**\n   * 描述\n   */\n  private String description;\n  /**\n   * 任务执行时调用哪个类的方法 包名+类名\n   */\n  private String beanClass;\n  /**\n   * 任务是否有状态\n   */\n  private String isConcurrent;\n\n  /**\n   * Spring bean\n   */\n  private String springBean;\n\n  /**\n   * 任务调用的方法名\n   */\n  private String methodName;\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 getJobStatus() {\n    return jobStatus;\n  }\n\n  public void setJobStatus(String jobStatus) {\n    this.jobStatus = jobStatus;\n  }\n\n  public String getCronExpression() {\n    return cronExpression;\n  }\n\n  public void setCronExpression(String cronExpression) {\n    this.cronExpression = cronExpression;\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 String getBeanClass() {\n    return beanClass;\n  }\n\n  public void setBeanClass(String beanClass) {\n    this.beanClass = beanClass;\n  }\n\n  public String getIsConcurrent() {\n    return isConcurrent;\n  }\n\n  public void setIsConcurrent(String isConcurrent) {\n    this.isConcurrent = isConcurrent;\n  }\n\n  public String getMethodName() {\n    return methodName;\n  }\n\n  public void setMethodName(String methodName) {\n    this.methodName = methodName;\n  }\n\n  public String getSpringBean() {\n    return springBean;\n  }\n\n  public void setSpringBean(String springBean) {\n    this.springBean = springBean;\n  }\n\n  @Override\n  public void execute(JobExecutionContext context) {\n    // TODO Auto-generated method stub\n\n  }\n\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/TableDO.java",
    "content": "package me.zbl.common.domain;\n\nimport java.util.List;\n\n/**\n * 表数据\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2016年12月20日 上午12:02:55\n */\npublic class TableDO {\n\n  //表的名称\n  private String tableName;\n  //表的备注\n  private String comments;\n  //表的主键\n  private ColumnDO pk;\n  //表的列名(不包含主键)\n  private List<ColumnDO> columns;\n\n  //类名(第一个字母大写)，如：sys_user => SysUser\n  private String className;\n  //类名(第一个字母小写)，如：sys_user => sysUser\n  private String classname;\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 getComments() {\n    return comments;\n  }\n\n  public void setComments(String comments) {\n    this.comments = comments;\n  }\n\n  public ColumnDO getPk() {\n    return pk;\n  }\n\n  public void setPk(ColumnDO pk) {\n    this.pk = pk;\n  }\n\n  public List<ColumnDO> getColumns() {\n    return columns;\n  }\n\n  public void setColumns(List<ColumnDO> columns) {\n    this.columns = columns;\n  }\n\n  public String getClassName() {\n    return className;\n  }\n\n  public void setClassName(String className) {\n    this.className = className;\n  }\n\n  public String getClassname() {\n    return classname;\n  }\n\n  public void setClassname(String classname) {\n    this.classname = classname;\n  }\n\n  @Override\n  public String toString() {\n    return \"TableDO{\" +\n            \"tableName='\" + tableName + '\\'' +\n            \", comments='\" + comments + '\\'' +\n            \", pk=\" + pk +\n            \", columns=\" + columns +\n            \", className='\" + className + '\\'' +\n            \", classname='\" + classname + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/TaskDO.java",
    "content": "package me.zbl.common.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-25 15:09:21\n */\npublic class TaskDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //\n  private Long id;\n  // cron表达式\n  private String cronExpression;\n  // 任务调用的方法名\n  private String methodName;\n  // 任务是否有状态\n  private String isConcurrent;\n  // 任务描述\n  private String description;\n  // 更新者\n  private String updateBy;\n  // 任务执行时调用哪个类的方法 包名+类名\n  private String beanClass;\n  // 创建时间\n  private Date createDate;\n  // 任务状态\n  private String jobStatus;\n  // 任务分组\n  private String jobGroup;\n  // 更新时间\n  private Date updateDate;\n  // 创建者\n  private String createBy;\n  // Spring bean\n  private String springBean;\n  // 任务名\n  private String jobName;\n\n  /**\n   * 获取：\n   */\n  public Long getId() {\n    return id;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setId(Long id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：cron表达式\n   */\n  public String getCronExpression() {\n    return cronExpression;\n  }\n\n  /**\n   * 设置：cron表达式\n   */\n  public void setCronExpression(String cronExpression) {\n    this.cronExpression = cronExpression;\n  }\n\n  /**\n   * 获取：任务调用的方法名\n   */\n  public String getMethodName() {\n    return methodName;\n  }\n\n  /**\n   * 设置：任务调用的方法名\n   */\n  public void setMethodName(String methodName) {\n    this.methodName = methodName;\n  }\n\n  /**\n   * 获取：任务是否有状态\n   */\n  public String getIsConcurrent() {\n    return isConcurrent;\n  }\n\n  /**\n   * 设置：任务是否有状态\n   */\n  public void setIsConcurrent(String isConcurrent) {\n    this.isConcurrent = isConcurrent;\n  }\n\n  /**\n   * 获取：任务描述\n   */\n  public String getDescription() {\n    return description;\n  }\n\n  /**\n   * 设置：任务描述\n   */\n  public void setDescription(String description) {\n    this.description = description;\n  }\n\n  /**\n   * 获取：更新者\n   */\n  public String getUpdateBy() {\n    return updateBy;\n  }\n\n  /**\n   * 设置：更新者\n   */\n  public void setUpdateBy(String updateBy) {\n    this.updateBy = updateBy;\n  }\n\n  /**\n   * 获取：任务执行时调用哪个类的方法 包名+类名\n   */\n  public String getBeanClass() {\n    return beanClass;\n  }\n\n  /**\n   * 设置：任务执行时调用哪个类的方法 包名+类名\n   */\n  public void setBeanClass(String beanClass) {\n    this.beanClass = beanClass;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getCreateDate() {\n    return createDate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setCreateDate(Date createDate) {\n    this.createDate = createDate;\n  }\n\n  /**\n   * 获取：任务状态\n   */\n  public String getJobStatus() {\n    return jobStatus;\n  }\n\n  /**\n   * 设置：任务状态\n   */\n  public void setJobStatus(String jobStatus) {\n    this.jobStatus = jobStatus;\n  }\n\n  /**\n   * 获取：任务分组\n   */\n  public String getJobGroup() {\n    return jobGroup;\n  }\n\n  /**\n   * 设置：任务分组\n   */\n  public void setJobGroup(String jobGroup) {\n    this.jobGroup = jobGroup;\n  }\n\n  /**\n   * 获取：更新时间\n   */\n  public Date getUpdateDate() {\n    return updateDate;\n  }\n\n  /**\n   * 设置：更新时间\n   */\n  public void setUpdateDate(Date updateDate) {\n    this.updateDate = updateDate;\n  }\n\n  /**\n   * 获取：创建者\n   */\n  public String getCreateBy() {\n    return createBy;\n  }\n\n  /**\n   * 设置：创建者\n   */\n  public void setCreateBy(String createBy) {\n    this.createBy = createBy;\n  }\n\n  /**\n   * 获取：Spring bean\n   */\n  public String getSpringBean() {\n    return springBean;\n  }\n\n  /**\n   * 设置：Spring bean\n   */\n  public void setSpringBean(String springBean) {\n    this.springBean = springBean;\n  }\n\n  /**\n   * 获取：任务名\n   */\n  public String getJobName() {\n    return jobName;\n  }\n\n  /**\n   * 设置：任务名\n   */\n  public void setJobName(String jobName) {\n    this.jobName = jobName;\n  }\n\n  @Override\n  public String toString() {\n    return \"TaskDO{\" +\n            \"id=\" + id +\n            \", cronExpression='\" + cronExpression + '\\'' +\n            \", methodName='\" + methodName + '\\'' +\n            \", isConcurrent='\" + isConcurrent + '\\'' +\n            \", description='\" + description + '\\'' +\n            \", updateBy='\" + updateBy + '\\'' +\n            \", beanClass='\" + beanClass + '\\'' +\n            \", createDate=\" + createDate +\n            \", jobStatus='\" + jobStatus + '\\'' +\n            \", jobGroup='\" + jobGroup + '\\'' +\n            \", updateDate=\" + updateDate +\n            \", createBy='\" + createBy + '\\'' +\n            \", springBean='\" + springBean + '\\'' +\n            \", jobName='\" + jobName + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/domain/Tree.java",
    "content": "package me.zbl.common.domain;\n\nimport com.alibaba.fastjson.JSON;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * tree TODO <br>\n *\n * @author 郑保乐\n */\npublic class Tree<T> {\n\n  /**\n   * 节点ID\n   */\n  private String id;\n  /**\n   * 显示节点文本\n   */\n  private String text;\n  /**\n   * 节点状态，open closed\n   */\n  private Map<String, Object> state;\n  /**\n   * 节点是否被选中 true false\n   */\n  private boolean checked = false;\n  /**\n   * 节点属性\n   */\n  private Map<String, Object> attributes;\n\n  /**\n   * 节点的子节点\n   */\n  private List<Tree<T>> children = new ArrayList<Tree<T>>();\n\n  /**\n   * 父ID\n   */\n  private String parentId;\n  /**\n   * 是否有父节点\n   */\n  private boolean hasParent = false;\n  /**\n   * 是否有子节点\n   */\n  private boolean hasChildren = false;\n\n  public Tree(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes,\n              List<Tree<T>> children, boolean isParent, boolean isChildren, String parentID) {\n    super();\n    this.id = id;\n    this.text = text;\n    this.state = state;\n    this.checked = checked;\n    this.attributes = attributes;\n    this.children = children;\n    this.hasParent = isParent;\n    this.hasChildren = isChildren;\n    this.parentId = parentID;\n  }\n\n  public Tree() {\n    super();\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String id) {\n    this.id = id;\n  }\n\n  public String getText() {\n    return text;\n  }\n\n  public void setText(String text) {\n    this.text = text;\n  }\n\n  public Map<String, Object> getState() {\n    return state;\n  }\n\n  public void setState(Map<String, Object> state) {\n    this.state = state;\n  }\n\n  public boolean isChecked() {\n    return checked;\n  }\n\n  public void setChecked(boolean checked) {\n    this.checked = checked;\n  }\n\n  public Map<String, Object> getAttributes() {\n    return attributes;\n  }\n\n  public void setAttributes(Map<String, Object> attributes) {\n    this.attributes = attributes;\n  }\n\n  public List<Tree<T>> getChildren() {\n    return children;\n  }\n\n  public void setChildren(boolean isChildren) {\n    this.hasChildren = isChildren;\n  }\n\n  public void setChildren(List<Tree<T>> children) {\n    this.children = children;\n  }\n\n  public boolean isHasParent() {\n    return hasParent;\n  }\n\n  public void setHasParent(boolean isParent) {\n    this.hasParent = isParent;\n  }\n\n  public boolean isHasChildren() {\n    return hasChildren;\n  }\n\n  public String getParentId() {\n    return parentId;\n  }\n\n  public void setParentId(String parentId) {\n    this.parentId = parentId;\n  }\n\n  @Override\n  public String toString() {\n\n    return JSON.toJSONString(this);\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/exception/BDException.java",
    "content": "package me.zbl.common.exception;\n\n/**\n * 自定义异常\n */\npublic class BDException extends RuntimeException {\n\n  private static final long serialVersionUID = 1L;\n\n  private String msg;\n  private int code = 500;\n\n  public BDException(String msg) {\n    super(msg);\n    this.msg = msg;\n  }\n\n  public BDException(String msg, Throwable e) {\n    super(msg, e);\n    this.msg = msg;\n  }\n\n  public BDException(String msg, int code) {\n    super(msg);\n    this.msg = msg;\n    this.code = code;\n  }\n\n  public BDException(String msg, int code, Throwable e) {\n    super(msg, e);\n    this.msg = msg;\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 int getCode() {\n    return code;\n  }\n\n  public void setCode(int code) {\n    this.code = code;\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/exception/BDExceptionHandler.java",
    "content": "package me.zbl.common.exception;\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.domain.LogDO;\nimport me.zbl.common.service.LogService;\nimport me.zbl.common.utils.HttpServletUtils;\nimport me.zbl.common.utils.R;\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.system.domain.UserDO;\nimport org.apache.shiro.authz.AuthorizationException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\n\n/**\n * 异常处理器\n */\n@RestControllerAdvice\npublic class BDExceptionHandler {\n\n  @Autowired\n  LogService logService;\n  private Logger logger = LoggerFactory.getLogger(getClass());\n  //\n  //    /**\n  //     * 自定义异常\n  //     */\n  //    @ExceptionHandler(BDException.class)\n  //    public R handleBDException(BDException e) {\n  //        logger.error(e.getMessage(), e);\n  //        R r = new R();\n  //        r.put(\"code\", e.getCode());\n  //        r.put(\"msg\", e.getMessage());\n  //        return r;\n  //    }\n  //\n  //    @ExceptionHandler(DuplicateKeyException.class)\n  //    public R handleDuplicateKeyException(DuplicateKeyException e) {\n  //        logger.error(e.getMessage(), e);\n  //        return R.error(\"数据库中已存在该记录\");\n  //    }\n  //\n  //    @ExceptionHandler(org.springframework.web.servlet.NoHandlerFoundException.class)\n  //    public R noHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException e) {\n  //        logger.error(e.getMessage(), e);\n  //        return R.error(404, \"没找找到页面\");\n  //    }\n\n  @ExceptionHandler(AuthorizationException.class)\n  public Object handleAuthorizationException(AuthorizationException e, HttpServletRequest request) {\n    logger.error(e.getMessage(), e);\n    if (HttpServletUtils.jsAjax(request)) {\n      return R.error(403, \"未授权\");\n    }\n    return new ModelAndView(\"error/403\");\n  }\n\n\n  @ExceptionHandler({Exception.class})\n  public Object handleException(Exception e, HttpServletRequest request) {\n    LogDO logDO = new LogDO();\n    logDO.setGmtCreate(new Date());\n    logDO.setOperation(Constant.LOG_ERROR);\n    logDO.setMethod(request.getRequestURL().toString());\n    logDO.setParams(e.toString());\n    UserDO current = ShiroUtils.getUser();\n    if (null != current) {\n      logDO.setUserId(current.getUserId());\n      logDO.setUsername(current.getUsername());\n    }\n    logService.save(logDO);\n    logger.error(e.getMessage(), e);\n    if (HttpServletUtils.jsAjax(request)) {\n      return R.error(500, \"服务器错误，请联系管理员\");\n    }\n    return new ModelAndView(\"error/500\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/exception/MainsiteErrorController.java",
    "content": "package me.zbl.common.exception;\n\n\nimport me.zbl.common.utils.R;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.web.ErrorAttributes;\nimport org.springframework.boot.autoconfigure.web.ErrorController;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n@RestController\npublic class MainsiteErrorController implements ErrorController {\n\n  private static final String ERROR_PATH = \"/error\";\n  @Autowired\n  ErrorAttributes errorAttributes;\n  private Logger logger = LoggerFactory.getLogger(getClass());\n\n  @RequestMapping(\n          value = {ERROR_PATH},\n          produces = {\"text/html\"}\n  )\n  public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {\n    int code = response.getStatus();\n    if (404 == code) {\n      return new ModelAndView(\"error/404\");\n    } else if (403 == code) {\n      return new ModelAndView(\"error/403\");\n    } else if (401 == code) {\n      return new ModelAndView(\"login\");\n    } else {\n      return new ModelAndView(\"error/500\");\n    }\n\n  }\n\n  @RequestMapping(value = ERROR_PATH)\n  public R handleError(HttpServletRequest request, HttpServletResponse response) {\n    response.setStatus(200);\n    int code = response.getStatus();\n    if (404 == code) {\n      return R.error(404, \"未找到资源\");\n    } else if (403 == code) {\n      return R.error(403, \"没有访问权限\");\n    } else if (401 == code) {\n      return R.error(403, \"登录过期\");\n    } else {\n      return R.error(500, \"服务器错误\");\n    }\n  }\n\n  @Override\n  public String getErrorPath() {\n    return ERROR_PATH;\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/listenner/ScheduleJobInitListener.java",
    "content": "package me.zbl.common.listenner;\n\nimport me.zbl.common.quartz.utils.QuartzManager;\nimport me.zbl.common.service.JobService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.stereotype.Component;\n\n@Component\n@Order(value = 1)\npublic class ScheduleJobInitListener implements CommandLineRunner {\n\n  @Autowired\n  JobService scheduleJobService;\n\n  @Autowired\n  QuartzManager quartzManager;\n\n  @Override\n  public void run(String... arg0) {\n    try {\n      scheduleJobService.initSchedule();\n    } catch (Exception e) {\n      e.printStackTrace();\n    }\n\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/quartz/factory/JobFactory.java",
    "content": "package me.zbl.common.quartz.factory;\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 JobFactory extends AdaptableJobFactory {\n\n  @Autowired\n  private AutowireCapableBeanFactory capableBeanFactory;\n\n  @Override\n  protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {\n    //调用父类的方法\n    Object jobInstance = super.createJobInstance(bundle);\n    //进行注入\n    capableBeanFactory.autowireBean(jobInstance);\n    return jobInstance;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/quartz/utils/QuartzManager.java",
    "content": "package me.zbl.common.quartz.utils;\n\nimport me.zbl.common.domain.ScheduleJob;\nimport org.apache.log4j.Logger;\nimport org.quartz.*;\nimport org.quartz.DateBuilder.IntervalUnit;\nimport org.quartz.impl.matchers.GroupMatcher;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @title: QuartzManager.java\n * @description: 计划任务管理\n */\n@Service\npublic class QuartzManager {\n\n  public final Logger log = Logger.getLogger(this.getClass());\n  // private SchedulerFactoryBean schedulerFactoryBean\n  // =SpringContextHolder.getBean(SchedulerFactoryBean.class);\n  // @Autowired\n  // @Qualifier(\"schedulerFactoryBean\")\n  // private SchedulerFactoryBean schedulerFactoryBean;\n  @Autowired\n  private Scheduler scheduler;\n\n  /**\n   * 添加任务\n   *\n   * @param job\n   *\n   * @throws SchedulerException\n   */\n\n  public void addJob(ScheduleJob job) {\n    try {\n      // 创建jobDetail实例，绑定Job实现类\n      // 指明job的名称，所在组的名称，以及绑定job类\n\n      Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(job.getBeanClass()).newInstance()\n              .getClass());\n      JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(job.getJobName(), job.getJobGroup())// 任务名称和组构成任务key\n              .build();\n      // 定义调度触发规则\n      // 使用cornTrigger规则\n      Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())// 触发器key\n              .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))\n              .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).startNow().build();\n      // 把作业和触发器注册到任务调度中\n      scheduler.scheduleJob(jobDetail, trigger);\n      // 启动\n      if (!scheduler.isShutdown()) {\n        scheduler.start();\n      }\n    } catch (Exception e) {\n      e.printStackTrace();\n    }\n  }\n\n  /**\n   * 获取所有计划中的任务列表\n   *\n   * @return\n   *\n   * @throws SchedulerException\n   */\n  public List<ScheduleJob> getAllJob() throws SchedulerException {\n    GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();\n    Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);\n    List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();\n    for (JobKey jobKey : jobKeys) {\n      List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);\n      for (Trigger trigger : triggers) {\n        ScheduleJob job = new ScheduleJob();\n        job.setJobName(jobKey.getName());\n        job.setJobGroup(jobKey.getGroup());\n        job.setDescription(\"触发器:\" + trigger.getKey());\n        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());\n        job.setJobStatus(triggerState.name());\n        if (trigger instanceof CronTrigger) {\n          CronTrigger cronTrigger = (CronTrigger) trigger;\n          String cronExpression = cronTrigger.getCronExpression();\n          job.setCronExpression(cronExpression);\n        }\n        jobList.add(job);\n      }\n    }\n    return jobList;\n  }\n\n  /**\n   * 所有正在运行的job\n   *\n   * @return\n   *\n   * @throws SchedulerException\n   */\n  public List<ScheduleJob> getRunningJob() throws SchedulerException {\n    List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();\n    List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());\n    for (JobExecutionContext executingJob : executingJobs) {\n      ScheduleJob job = new ScheduleJob();\n      JobDetail jobDetail = executingJob.getJobDetail();\n      JobKey jobKey = jobDetail.getKey();\n      Trigger trigger = executingJob.getTrigger();\n      job.setJobName(jobKey.getName());\n      job.setJobGroup(jobKey.getGroup());\n      job.setDescription(\"触发器:\" + trigger.getKey());\n      Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());\n      job.setJobStatus(triggerState.name());\n      if (trigger instanceof CronTrigger) {\n        CronTrigger cronTrigger = (CronTrigger) trigger;\n        String cronExpression = cronTrigger.getCronExpression();\n        job.setCronExpression(cronExpression);\n      }\n      jobList.add(job);\n    }\n    return jobList;\n  }\n\n  /**\n   * 暂停一个job\n   *\n   * @param scheduleJob\n   *\n   * @throws SchedulerException\n   */\n  public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException {\n    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());\n    scheduler.pauseJob(jobKey);\n  }\n\n  /**\n   * 恢复一个job\n   *\n   * @param scheduleJob\n   *\n   * @throws SchedulerException\n   */\n  public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException {\n    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());\n    scheduler.resumeJob(jobKey);\n  }\n\n  /**\n   * 删除一个job\n   *\n   * @param scheduleJob\n   *\n   * @throws SchedulerException\n   */\n  public void deleteJob(ScheduleJob scheduleJob) throws SchedulerException {\n    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());\n    scheduler.deleteJob(jobKey);\n\n  }\n\n  /**\n   * 立即执行job\n   *\n   * @param scheduleJob\n   *\n   * @throws SchedulerException\n   */\n  public void runAJobNow(ScheduleJob scheduleJob) throws SchedulerException {\n    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());\n    scheduler.triggerJob(jobKey);\n  }\n\n  /**\n   * 更新job时间表达式\n   *\n   * @param scheduleJob\n   *\n   * @throws SchedulerException\n   */\n  public void updateJobCron(ScheduleJob scheduleJob) throws SchedulerException {\n\n    TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());\n\n    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);\n\n    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());\n\n    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();\n\n    scheduler.rescheduleJob(triggerKey, trigger);\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/redis/shiro/RedisCache.java",
    "content": "package me.zbl.common.redis.shiro;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\n\nimport org.apache.shiro.cache.Cache;\nimport org.apache.shiro.cache.CacheException;\nimport org.apache.shiro.util.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.*;\n\npublic class RedisCache<K, V> implements Cache<K, V> {\n\n  private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  /**\n   * The wrapped Jedis instance.\n   */\n  private RedisManager cache;\n\n  /**\n   * The Redis key prefix for the sessions\n   */\n  private String keyPrefix = \"shiro_redis_session:\";\n\n  /**\n   * 通过一个JedisManager实例构造RedisCache\n   */\n  public RedisCache(RedisManager cache) {\n    if (cache == null) {\n      throw new IllegalArgumentException(\"Cache argument cannot be null.\");\n    }\n    this.cache = cache;\n  }\n\n  /**\n   * Constructs a cache instance with the specified\n   * Redis manager and using a custom key prefix.\n   *\n   * @param cache  The cache manager instance\n   * @param prefix The Redis key prefix\n   */\n  public RedisCache(RedisManager cache,\n                    String prefix) {\n\n    this(cache);\n\n    // set the prefix\n    this.keyPrefix = prefix;\n  }\n\n  /**\n   * Returns the Redis session keys\n   * prefix.\n   *\n   * @return The prefix\n   */\n  public String getKeyPrefix() {\n    return keyPrefix;\n  }\n\n  /**\n   * Sets the Redis sessions key\n   * prefix.\n   *\n   * @param keyPrefix The prefix\n   */\n  public void setKeyPrefix(String keyPrefix) {\n    this.keyPrefix = keyPrefix;\n  }\n\n  /**\n   * 获得byte[]型的key\n   *\n   * @param key\n   *\n   * @return\n   */\n  private byte[] getByteKey(K key) {\n    if (key instanceof String) {\n      String preKey = this.keyPrefix + key;\n      return preKey.getBytes();\n    } else {\n      return SerializeUtils.serialize(key);\n    }\n  }\n\n  @Override\n  public V get(K key) throws CacheException {\n    logger.debug(\"根据key从Redis中获取对象 key [\" + key + \"]\");\n    try {\n      if (key == null) {\n        return null;\n      } else {\n        byte[] rawValue = cache.get(getByteKey(key));\n        @SuppressWarnings(\"unchecked\")\n        V value = (V) SerializeUtils.deserialize(rawValue);\n        return value;\n      }\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n\n  }\n\n  @Override\n  public V put(K key, V value) throws CacheException {\n    logger.debug(\"根据key从存储 key [\" + key + \"]\");\n    try {\n      cache.set(getByteKey(key), SerializeUtils.serialize(value));\n      return value;\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n  @Override\n  public V remove(K key) throws CacheException {\n    logger.debug(\"从redis中删除 key [\" + key + \"]\");\n    try {\n      V previous = get(key);\n      cache.del(getByteKey(key));\n      return previous;\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n  @Override\n  public void clear() throws CacheException {\n    logger.debug(\"从redis中删除所有元素\");\n    try {\n      cache.flushDB();\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n  @Override\n  public int size() {\n    try {\n      Long longSize = new Long(cache.dbSize());\n      return longSize.intValue();\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Override\n  public Set<K> keys() {\n    try {\n      Set<byte[]> keys = cache.keys(this.keyPrefix + \"*\");\n      if (CollectionUtils.isEmpty(keys)) {\n        return Collections.emptySet();\n      } else {\n        Set<K> newKeys = new HashSet<K>();\n        for (byte[] key : keys) {\n          newKeys.add((K) key);\n        }\n        return newKeys;\n      }\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n  @Override\n  public Collection<V> values() {\n    try {\n      Set<byte[]> keys = cache.keys(this.keyPrefix + \"*\");\n      if (!CollectionUtils.isEmpty(keys)) {\n        List<V> values = new ArrayList<V>(keys.size());\n        for (byte[] key : keys) {\n          @SuppressWarnings(\"unchecked\")\n          V value = get((K) key);\n          if (value != null) {\n            values.add(value);\n          }\n        }\n        return Collections.unmodifiableList(values);\n      } else {\n        return Collections.emptyList();\n      }\n    } catch (Throwable t) {\n      throw new CacheException(t);\n    }\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/redis/shiro/RedisCacheManager.java",
    "content": "package me.zbl.common.redis.shiro;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\n\nimport org.apache.shiro.cache.Cache;\nimport org.apache.shiro.cache.CacheException;\nimport org.apache.shiro.cache.CacheManager;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic class RedisCacheManager implements CacheManager {\n\n  private static final Logger logger = LoggerFactory\n          .getLogger(RedisCacheManager.class);\n\n  // fast lookup by name map\n  private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();\n\n  private RedisManager redisManager;\n\n  /**\n   * The Redis key prefix for caches\n   */\n  private String keyPrefix = \"shiro_redis_cache:\";\n\n  /**\n   * Returns the Redis session keys\n   * prefix.\n   *\n   * @return The prefix\n   */\n  public String getKeyPrefix() {\n    return keyPrefix;\n  }\n\n  /**\n   * Sets the Redis sessions key\n   * prefix.\n   *\n   * @param keyPrefix The prefix\n   */\n  public void setKeyPrefix(String keyPrefix) {\n    this.keyPrefix = keyPrefix;\n  }\n\n  @Override\n  public <K, V> Cache<K, V> getCache(String name) throws CacheException {\n    logger.debug(\"获取名称为: \" + name + \" 的RedisCache实例\");\n\n    Cache c = caches.get(name);\n\n    if (c == null) {\n\n      // initialize the Redis manager instance\n      redisManager.init();\n\n      // create a new cache instance\n      c = new RedisCache<K, V>(redisManager, keyPrefix);\n\n      // add it to the cache collection\n      caches.put(name, c);\n    }\n    return c;\n  }\n\n  public RedisManager getRedisManager() {\n    return redisManager;\n  }\n\n  public void setRedisManager(RedisManager redisManager) {\n    this.redisManager = redisManager;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/redis/shiro/RedisManager.java",
    "content": "package me.zbl.common.redis.shiro;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\n\nimport org.springframework.beans.factory.annotation.Value;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.JedisPoolConfig;\n\nimport java.util.Set;\n\n/**\n *\n */\npublic class RedisManager {\n\n  private static JedisPool jedisPool = null;\n  @Value(\"${spring.redis.host}\")\n  private String host = \"127.0.0.1\";\n  @Value(\"${spring.redis.port}\")\n  private int port = 6379;\n  // 0 - never expire\n  private int expire = 0;\n  //timeout for jedis try to connect to redis server, not expire time! In milliseconds\n  @Value(\"${spring.redis.timeout}\")\n  private int timeout = 0;\n  @Value(\"${spring.redis.password}\")\n  private String password = \"\";\n\n  public RedisManager() {\n\n  }\n\n  /**\n   * 初始化方法\n   */\n  public void init() {\n    if (jedisPool == null) {\n      if (password != null && !\"\".equals(password)) {\n        jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout, password);\n      } else if (timeout != 0) {\n        jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout);\n      } else {\n        jedisPool = new JedisPool(new JedisPoolConfig(), host, port);\n      }\n\n    }\n  }\n\n  /**\n   * get value from redis\n   *\n   * @param key\n   *\n   * @return\n   */\n  public byte[] get(byte[] key) {\n    byte[] value = null;\n    Jedis jedis = jedisPool.getResource();\n    try {\n      value = jedis.get(key);\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n    return value;\n  }\n\n  /**\n   * set\n   *\n   * @param key\n   * @param value\n   *\n   * @return\n   */\n  public byte[] set(byte[] key, byte[] value) {\n    Jedis jedis = jedisPool.getResource();\n    try {\n      jedis.set(key, value);\n      if (this.expire != 0) {\n        jedis.expire(key, this.expire);\n      }\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n    return value;\n  }\n\n  /**\n   * set\n   *\n   * @param key\n   * @param value\n   * @param expire\n   *\n   * @return\n   */\n  public byte[] set(byte[] key, byte[] value, int expire) {\n    Jedis jedis = jedisPool.getResource();\n    try {\n      jedis.set(key, value);\n      if (expire != 0) {\n        jedis.expire(key, expire);\n      }\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n    return value;\n  }\n\n  /**\n   * del\n   *\n   * @param key\n   */\n  public void del(byte[] key) {\n    Jedis jedis = jedisPool.getResource();\n    try {\n      jedis.del(key);\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n  }\n\n  /**\n   * flush\n   */\n  public void flushDB() {\n    Jedis jedis = jedisPool.getResource();\n    try {\n      jedis.flushDB();\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n  }\n\n  /**\n   * size\n   */\n  public Long dbSize() {\n    Long dbSize = 0L;\n    Jedis jedis = jedisPool.getResource();\n    try {\n      dbSize = jedis.dbSize();\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n    return dbSize;\n  }\n\n  /**\n   * keys\n   *\n   * @param regex\n   *\n   * @return\n   */\n  public Set<byte[]> keys(String pattern) {\n    Set<byte[]> keys = null;\n    Jedis jedis = jedisPool.getResource();\n    try {\n      keys = jedis.keys(pattern.getBytes());\n    } finally {\n      if (jedis != null) {\n        jedis.close();\n      }\n    }\n    return keys;\n  }\n\n  public String getHost() {\n    return host;\n  }\n\n  public void setHost(String host) {\n    this.host = host;\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 getExpire() {\n    return expire;\n  }\n\n  public void setExpire(int expire) {\n    this.expire = expire;\n  }\n\n  public int getTimeout() {\n    return timeout;\n  }\n\n  public void setTimeout(int timeout) {\n    this.timeout = timeout;\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"
  },
  {
    "path": "src/main/java/me/zbl/common/redis/shiro/RedisSessionDAO.java",
    "content": "package me.zbl.common.redis.shiro;\n\nimport org.apache.shiro.session.Session;\nimport org.apache.shiro.session.UnknownSessionException;\nimport org.apache.shiro.session.mgt.eis.AbstractSessionDAO;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.Serializable;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\npublic class RedisSessionDAO extends AbstractSessionDAO {\n\n  private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);\n  /**\n   * shiro-redis的session对象前缀\n   */\n  private RedisManager redisManager;\n\n  /**\n   * The Redis key prefix for the sessions\n   */\n  private String keyPrefix = \"shiro_redis_session:\";\n\n  @Override\n  public void update(Session session) throws UnknownSessionException {\n    this.saveSession(session);\n  }\n\n  /**\n   * save session\n   *\n   * @param session\n   *\n   * @throws UnknownSessionException\n   */\n  private void saveSession(Session session) throws UnknownSessionException {\n    if (session == null || session.getId() == null) {\n      logger.error(\"session or session id is null\");\n      return;\n    }\n\n    byte[] key = getByteKey(session.getId());\n    byte[] value = SerializeUtils.serialize(session);\n    session.setTimeout(redisManager.getExpire() * 1000);\n    this.redisManager.set(key, value, redisManager.getExpire());\n  }\n\n  @Override\n  public void delete(Session session) {\n    if (session == null || session.getId() == null) {\n      logger.error(\"session or session id is null\");\n      return;\n    }\n    redisManager.del(this.getByteKey(session.getId()));\n\n  }\n\n  @Override\n  public Collection<Session> getActiveSessions() {\n    Set<Session> sessions = new HashSet<Session>();\n\n    Set<byte[]> keys = redisManager.keys(this.keyPrefix + \"*\");\n    if (keys != null && keys.size() > 0) {\n      for (byte[] key : keys) {\n        Session s = (Session) SerializeUtils.deserialize(redisManager.get(key));\n        sessions.add(s);\n      }\n    }\n\n    return sessions;\n  }\n\n  @Override\n  protected Serializable doCreate(Session session) {\n    Serializable sessionId = this.generateSessionId(session);\n    this.assignSessionId(session, sessionId);\n    this.saveSession(session);\n    return sessionId;\n  }\n\n  @Override\n  protected Session doReadSession(Serializable sessionId) {\n    if (sessionId == null) {\n      logger.error(\"session id is null\");\n      return null;\n    }\n\n    Session s = (Session) SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId)));\n    return s;\n  }\n\n  /**\n   * 获得byte[]型的key\n   *\n   * @param key\n   *\n   * @return\n   */\n  private byte[] getByteKey(Serializable sessionId) {\n    String preKey = this.keyPrefix + sessionId;\n    return preKey.getBytes();\n  }\n\n  public RedisManager getRedisManager() {\n    return redisManager;\n  }\n\n  public void setRedisManager(RedisManager redisManager) {\n    this.redisManager = redisManager;\n\n    /**\n     * 初始化redisManager\n     */\n    this.redisManager.init();\n  }\n\n  /**\n   * Returns the Redis session keys\n   * prefix.\n   *\n   * @return The prefix\n   */\n  public String getKeyPrefix() {\n    return keyPrefix;\n  }\n\n  /**\n   * Sets the Redis sessions key\n   * prefix.\n   *\n   * @param keyPrefix The prefix\n   */\n  public void setKeyPrefix(String keyPrefix) {\n    this.keyPrefix = keyPrefix;\n  }\n\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/redis/shiro/SerializeUtils.java",
    "content": "package me.zbl.common.redis.shiro;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.*;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\npublic class SerializeUtils {\n\n  private static Logger logger = LoggerFactory.getLogger(SerializeUtils.class);\n\n  /**\n   * 反序列化\n   *\n   * @param bytes\n   *\n   * @return\n   */\n  public static Object deserialize(byte[] bytes) {\n\n    Object result = null;\n\n    if (isEmpty(bytes)) {\n      return null;\n    }\n\n    try {\n      ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);\n      try {\n        ObjectInputStream objectInputStream = new ObjectInputStream(byteStream);\n        try {\n          result = objectInputStream.readObject();\n        } catch (ClassNotFoundException ex) {\n          throw new Exception(\"Failed to deserialize object type\", ex);\n        }\n      } catch (Throwable ex) {\n        throw new Exception(\"Failed to deserialize\", ex);\n      }\n    } catch (Exception e) {\n      logger.error(\"Failed to deserialize\", e);\n    }\n    return result;\n  }\n\n  public static boolean isEmpty(byte[] data) {\n    return (data == null || data.length == 0);\n  }\n\n  /**\n   * 序列化\n   *\n   * @param object\n   *\n   * @return\n   */\n  public static byte[] serialize(Object object) {\n\n    byte[] result = null;\n\n    if (object == null) {\n      return new byte[0];\n    }\n    try {\n      ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);\n      try {\n        if (!(object instanceof Serializable)) {\n          throw new IllegalArgumentException(SerializeUtils.class.getSimpleName() + \" requires a Serializable payload \" +\n                  \"but received an object of type [\" + object.getClass().getName() + \"]\");\n        }\n        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);\n        objectOutputStream.writeObject(object);\n        objectOutputStream.flush();\n        result = byteStream.toByteArray();\n      } catch (Throwable ex) {\n        throw new Exception(\"Failed to serialize\", ex);\n      }\n    } catch (Exception ex) {\n      logger.error(\"Failed to serialize\", ex);\n    }\n    return result;\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/service/DictService.java",
    "content": "package me.zbl.common.service;\n\nimport me.zbl.common.domain.DictDO;\nimport me.zbl.system.domain.UserDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 字典表\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-29 18:28:07\n */\npublic interface DictService {\n\n  DictDO get(Long id);\n\n  List<DictDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(DictDO dict);\n\n  int update(DictDO dict);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  List<DictDO> listType();\n\n  String getName(String type, String value);\n\n  /**\n   * 获取爱好列表\n   *\n   * @param userDO\n   *\n   * @return\n   */\n  List<DictDO> getHobbyList(UserDO userDO);\n\n  /**\n   * 获取性别列表\n   *\n   * @return\n   */\n  List<DictDO> getSexList();\n\n  /**\n   * 根据type获取数据\n   *\n   * @param map\n   *\n   * @return\n   */\n  List<DictDO> listByType(String type);\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/FileService.java",
    "content": "package me.zbl.common.service;\n\nimport me.zbl.common.domain.FileDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 文件上传\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-19 16:02:20\n */\npublic interface FileService {\n\n  FileDO get(Long id);\n\n  List<FileDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(FileDO sysFile);\n\n  int update(FileDO sysFile);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  /**\n   * 判断一个文件是否存在\n   *\n   * @param url FileDO中存的路径\n   *\n   * @return\n   */\n  Boolean isExist(String url);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/GeneratorService.java",
    "content": "/**\n *\n */\npackage me.zbl.common.service;\n\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n * @Time 2017年9月6日\n * @description\n */\n@Service\npublic interface GeneratorService {\n\n  List<Map<String, Object>> list();\n\n  byte[] generatorCode(String[] tableNames);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/JobService.java",
    "content": "package me.zbl.common.service;\n\nimport me.zbl.common.domain.TaskDO;\nimport org.quartz.SchedulerException;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-26 20:53:48\n */\npublic interface JobService {\n\n  TaskDO get(Long id);\n\n  List<TaskDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(TaskDO taskScheduleJob);\n\n  int update(TaskDO taskScheduleJob);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  void initSchedule() throws SchedulerException;\n\n  void changeStatus(Long jobId, String cmd) throws SchedulerException;\n\n  void updateCron(Long jobId) throws SchedulerException;\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/LogService.java",
    "content": "package me.zbl.common.service;\n\nimport me.zbl.common.domain.LogDO;\nimport me.zbl.common.domain.PageDO;\nimport me.zbl.common.utils.Query;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic interface LogService {\n\n  void save(LogDO logDO);\n\n  PageDO<LogDO> queryList(Query query);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/impl/DictServiceImpl.java",
    "content": "package me.zbl.common.service.impl;\n\nimport me.zbl.common.dao.DictDao;\nimport me.zbl.common.domain.DictDO;\nimport me.zbl.common.service.DictService;\nimport me.zbl.common.utils.StringUtils;\nimport me.zbl.system.domain.UserDO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n\n@Service\npublic class DictServiceImpl implements DictService {\n\n  @Autowired\n  private DictDao dictDao;\n\n  @Override\n  public DictDO get(Long id) {\n    return dictDao.get(id);\n  }\n\n  @Override\n  public List<DictDO> list(Map<String, Object> map) {\n    return dictDao.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return dictDao.count(map);\n  }\n\n  @Override\n  public int save(DictDO dict) {\n    return dictDao.save(dict);\n  }\n\n  @Override\n  public int update(DictDO dict) {\n    return dictDao.update(dict);\n  }\n\n  @Override\n  public int remove(Long id) {\n    return dictDao.remove(id);\n  }\n\n  @Override\n  public int batchRemove(Long[] ids) {\n    return dictDao.batchRemove(ids);\n  }\n\n  @Override\n\n  public List<DictDO> listType() {\n    return dictDao.listType();\n  }\n\n  @Override\n  public String getName(String type, String value) {\n    Map<String, Object> param = new HashMap<String, Object>(16);\n    param.put(\"type\", type);\n    param.put(\"value\", value);\n    String rString = dictDao.list(param).get(0).getName();\n    return rString;\n  }\n\n  @Override\n  public List<DictDO> getHobbyList(UserDO userDO) {\n    Map<String, Object> param = new HashMap<>(16);\n    param.put(\"type\", \"hobby\");\n    List<DictDO> hobbyList = dictDao.list(param);\n\n    if (StringUtils.isNotEmpty(userDO.getHobby())) {\n      String userHobbys[] = userDO.getHobby().split(\";\");\n      for (String userHobby : userHobbys) {\n        for (DictDO hobby : hobbyList) {\n          if (!Objects.equals(userHobby, hobby.getId().toString())) {\n            continue;\n          }\n          hobby.setRemarks(\"true\");\n          break;\n        }\n      }\n    }\n\n    return hobbyList;\n  }\n\n  @Override\n  public List<DictDO> getSexList() {\n    Map<String, Object> param = new HashMap<>(16);\n    param.put(\"type\", \"sex\");\n    return dictDao.list(param);\n  }\n\n  @Override\n  public List<DictDO> listByType(String type) {\n    Map<String, Object> param = new HashMap<>(16);\n    param.put(\"type\", type);\n    return dictDao.list(param);\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/impl/FileServiceImpl.java",
    "content": "package me.zbl.common.service.impl;\n\nimport me.zbl.common.config.HospitalConfig;\nimport me.zbl.common.dao.FileDao;\nimport me.zbl.common.domain.FileDO;\nimport me.zbl.common.service.FileService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.StringUtils;\n\nimport java.io.File;\nimport java.util.List;\nimport java.util.Map;\n\n\n@Service\npublic class FileServiceImpl implements FileService {\n\n  @Autowired\n  private FileDao sysFileMapper;\n\n  @Autowired\n  private HospitalConfig hospitalConfig;\n\n  @Override\n  public FileDO get(Long id) {\n    return sysFileMapper.get(id);\n  }\n\n  @Override\n  public List<FileDO> list(Map<String, Object> map) {\n    return sysFileMapper.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return sysFileMapper.count(map);\n  }\n\n  @Override\n  public int save(FileDO sysFile) {\n    return sysFileMapper.save(sysFile);\n  }\n\n  @Override\n  public int update(FileDO sysFile) {\n    return sysFileMapper.update(sysFile);\n  }\n\n  @Override\n  public int remove(Long id) {\n    return sysFileMapper.remove(id);\n  }\n\n  @Override\n  public int batchRemove(Long[] ids) {\n    return sysFileMapper.batchRemove(ids);\n  }\n\n  @Override\n  public Boolean isExist(String url) {\n    Boolean isExist = false;\n    if (!StringUtils.isEmpty(url)) {\n      String filePath = url.replace(\"/files/\", \"\");\n      filePath = hospitalConfig.getUploadPath() + filePath;\n      File file = new File(filePath);\n      if (file.exists()) {\n        isExist = true;\n      }\n    }\n    return isExist;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/impl/GeneratorServiceImpl.java",
    "content": "package me.zbl.common.service.impl;\n\nimport me.zbl.common.dao.GeneratorMapper;\nimport me.zbl.common.service.GeneratorService;\nimport me.zbl.common.utils.GenUtils;\nimport org.apache.commons.io.IOUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.io.ByteArrayOutputStream;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.zip.ZipOutputStream;\n\n\n@Service\npublic class GeneratorServiceImpl implements GeneratorService {\n\n  @Autowired\n  GeneratorMapper generatorMapper;\n\n  @Override\n  public List<Map<String, Object>> list() {\n    List<Map<String, Object>> list = generatorMapper.list();\n    return list;\n  }\n\n  @Override\n  public byte[] generatorCode(String[] tableNames) {\n    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();\n    ZipOutputStream zip = new ZipOutputStream(outputStream);\n    for (String tableName : tableNames) {\n      //查询表信息\n      Map<String, String> table = generatorMapper.get(tableName);\n      //查询列信息\n      List<Map<String, String>> columns = generatorMapper.listColumns(tableName);\n      //生成代码\n      GenUtils.generatorCode(table, columns, zip);\n    }\n    IOUtils.closeQuietly(zip);\n    return outputStream.toByteArray();\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/impl/JobServiceImpl.java",
    "content": "package me.zbl.common.service.impl;\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.dao.TaskDao;\nimport me.zbl.common.domain.ScheduleJob;\nimport me.zbl.common.domain.TaskDO;\nimport me.zbl.common.quartz.utils.QuartzManager;\nimport me.zbl.common.service.JobService;\nimport me.zbl.common.utils.ScheduleJobUtils;\nimport org.quartz.SchedulerException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\npublic class JobServiceImpl implements JobService {\n\n  @Autowired\n  QuartzManager quartzManager;\n  @Autowired\n  private TaskDao taskScheduleJobMapper;\n\n  @Override\n  public TaskDO get(Long id) {\n    return taskScheduleJobMapper.get(id);\n  }\n\n  @Override\n  public List<TaskDO> list(Map<String, Object> map) {\n    return taskScheduleJobMapper.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return taskScheduleJobMapper.count(map);\n  }\n\n  @Override\n  public int save(TaskDO taskScheduleJob) {\n    return taskScheduleJobMapper.save(taskScheduleJob);\n  }\n\n  @Override\n  public int update(TaskDO taskScheduleJob) {\n    return taskScheduleJobMapper.update(taskScheduleJob);\n  }\n\n  @Override\n  public int remove(Long id) {\n    try {\n      TaskDO scheduleJob = get(id);\n      quartzManager.deleteJob(ScheduleJobUtils.entityToData(scheduleJob));\n      return taskScheduleJobMapper.remove(id);\n    } catch (SchedulerException e) {\n      e.printStackTrace();\n      return 0;\n    }\n\n  }\n\n  @Override\n  public int batchRemove(Long[] ids) {\n    for (Long id : ids) {\n      try {\n        TaskDO scheduleJob = get(id);\n        quartzManager.deleteJob(ScheduleJobUtils.entityToData(scheduleJob));\n      } catch (SchedulerException e) {\n        e.printStackTrace();\n        return 0;\n      }\n    }\n    return taskScheduleJobMapper.batchRemove(ids);\n  }\n\n  @Override\n  public void initSchedule() {\n    // 这里获取任务信息数据\n    List<TaskDO> jobList = taskScheduleJobMapper.list(new HashMap<String, Object>(16));\n    for (TaskDO scheduleJob : jobList) {\n      if (\"1\".equals(scheduleJob.getJobStatus())) {\n        ScheduleJob job = ScheduleJobUtils.entityToData(scheduleJob);\n        quartzManager.addJob(job);\n      }\n\n    }\n  }\n\n  @Override\n  public void changeStatus(Long jobId, String cmd) throws SchedulerException {\n    TaskDO scheduleJob = get(jobId);\n    if (scheduleJob == null) {\n      return;\n    }\n    if (Constant.STATUS_RUNNING_STOP.equals(cmd)) {\n      quartzManager.deleteJob(ScheduleJobUtils.entityToData(scheduleJob));\n      scheduleJob.setJobStatus(ScheduleJob.STATUS_NOT_RUNNING);\n    } else {\n      if (!Constant.STATUS_RUNNING_START.equals(cmd)) {\n      } else {\n        scheduleJob.setJobStatus(ScheduleJob.STATUS_RUNNING);\n        quartzManager.addJob(ScheduleJobUtils.entityToData(scheduleJob));\n      }\n    }\n    update(scheduleJob);\n  }\n\n  @Override\n  public void updateCron(Long jobId) throws SchedulerException {\n    TaskDO scheduleJob = get(jobId);\n    if (scheduleJob == null) {\n      return;\n    }\n    if (ScheduleJob.STATUS_RUNNING.equals(scheduleJob.getJobStatus())) {\n      quartzManager.updateJobCron(ScheduleJobUtils.entityToData(scheduleJob));\n    }\n    update(scheduleJob);\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/service/impl/LogServiceImpl.java",
    "content": "package me.zbl.common.service.impl;\n\nimport me.zbl.common.dao.LogDao;\nimport me.zbl.common.domain.LogDO;\nimport me.zbl.common.domain.PageDO;\nimport me.zbl.common.service.LogService;\nimport me.zbl.common.utils.Query;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class LogServiceImpl implements LogService {\n\n  @Autowired\n  LogDao logMapper;\n\n  @Async\n  @Override\n  public void save(LogDO logDO) {\n    logMapper.save(logDO);\n  }\n\n  @Override\n  public PageDO<LogDO> queryList(Query query) {\n    int total = logMapper.count(query);\n    List<LogDO> logs = logMapper.list(query);\n    PageDO<LogDO> page = new PageDO<>();\n    page.setTotal(total);\n    page.setRows(logs);\n    return page;\n  }\n\n  @Override\n  public int remove(Long id) {\n    int count = logMapper.remove(id);\n    return count;\n  }\n\n  @Override\n  public int batchRemove(Long[] ids) {\n    return logMapper.batchRemove(ids);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/task/WelcomeJob.java",
    "content": "package me.zbl.common.task;\n\nimport me.zbl.oa.domain.Response;\nimport org.quartz.Job;\nimport org.quartz.JobExecutionContext;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.messaging.simp.SimpMessagingTemplate;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class WelcomeJob implements Job {\n\n  @Autowired\n  SimpMessagingTemplate template;\n\n  @Override\n  public void execute(JobExecutionContext arg0) {\n    template.convertAndSend(\"/topic/getResponse\", new Response(\"欢迎体验bootdo,这是一个任务计划，使用了websocket和quzrtz技术，可以在计划列表中取消，欢迎您加入qq群交流学习!\"));\n\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/BDException.java",
    "content": "package me.zbl.common.utils;\n\n/**\n * 自定义异常\n */\npublic class BDException extends RuntimeException {\n\n  private static final long serialVersionUID = 1L;\n\n  private String msg;\n  private int code = 500;\n\n  public BDException(String msg) {\n    super(msg);\n    this.msg = msg;\n  }\n\n  public BDException(String msg, Throwable e) {\n    super(msg, e);\n    this.msg = msg;\n  }\n\n  public BDException(String msg, int code) {\n    super(msg);\n    this.msg = msg;\n    this.code = code;\n  }\n\n  public BDException(String msg, int code, Throwable e) {\n    super(msg, e);\n    this.msg = msg;\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 int getCode() {\n    return code;\n  }\n\n  public void setCode(int code) {\n    this.code = code;\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/Base64Utils.java",
    "content": "package me.zbl.common.utils;\n\npublic class Base64Utils {\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/BuildTree.java",
    "content": "package me.zbl.common.utils;\n\nimport me.zbl.common.domain.Tree;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class BuildTree {\n\n  public static <T> Tree<T> build(List<Tree<T>> nodes) {\n\n    if (nodes == null) {\n      return null;\n    }\n    List<Tree<T>> topNodes = new ArrayList<Tree<T>>();\n\n    for (Tree<T> children : nodes) {\n\n      String pid = children.getParentId();\n      if (pid == null || \"0\".equals(pid)) {\n        topNodes.add(children);\n\n        continue;\n      }\n\n      for (Tree<T> parent : nodes) {\n        String id = parent.getId();\n        if (id != null && id.equals(pid)) {\n          parent.getChildren().add(children);\n          children.setHasParent(true);\n          parent.setChildren(true);\n          continue;\n        }\n      }\n\n    }\n\n    Tree<T> root = new Tree<T>();\n    if (topNodes.size() == 1) {\n      root = topNodes.get(0);\n    } else {\n      root.setId(\"-1\");\n      root.setParentId(\"\");\n      root.setHasParent(false);\n      root.setChildren(true);\n      root.setChecked(true);\n      root.setChildren(topNodes);\n      root.setText(\"顶级节点\");\n      Map<String, Object> state = new HashMap<>(16);\n      state.put(\"opened\", true);\n      root.setState(state);\n    }\n\n    return root;\n  }\n\n  public static <T> List<Tree<T>> buildList(List<Tree<T>> nodes, String idParam) {\n    if (nodes == null) {\n      return null;\n    }\n    List<Tree<T>> topNodes = new ArrayList<Tree<T>>();\n\n    for (Tree<T> children : nodes) {\n\n      String pid = children.getParentId();\n      if (pid == null || idParam.equals(pid)) {\n        topNodes.add(children);\n\n        continue;\n      }\n\n      for (Tree<T> parent : nodes) {\n        String id = parent.getId();\n        if (id != null && id.equals(pid)) {\n          parent.getChildren().add(children);\n          children.setHasParent(true);\n          parent.setChildren(true);\n\n          continue;\n        }\n      }\n\n    }\n    return topNodes;\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/DateUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * 日期处理\n */\npublic class DateUtils {\n\n  /**\n   * 时间格式(yyyy-MM-dd)\n   */\n  public final static String DATE_PATTERN = \"yyyy-MM-dd\";\n  /**\n   * 时间格式(yyyy-MM-dd HH:mm:ss)\n   */\n  public final static String DATE_TIME_PATTERN = \"yyyy-MM-dd HH:mm:ss\";\n  private final static Logger logger = LoggerFactory.getLogger(DateUtils.class);\n\n  public static String format(Date date) {\n    return format(date, DATE_PATTERN);\n  }\n\n  public static String format(Date date, String pattern) {\n    if (date != null) {\n      SimpleDateFormat df = new SimpleDateFormat(pattern);\n      return df.format(date);\n    }\n    return null;\n  }\n\n  /**\n   * 计算距离现在多久，非精确\n   *\n   * @param date\n   *\n   * @return\n   */\n  public static String getTimeBefore(Date date) {\n    Date now = new Date();\n    long l = now.getTime() - date.getTime();\n    long day = l / (24 * 60 * 60 * 1000);\n    long hour = (l / (60 * 60 * 1000) - day * 24);\n    long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);\n    long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);\n    String r = \"\";\n    if (day > 0) {\n      r += day + \"天\";\n    } else if (hour > 0) {\n      r += hour + \"小时\";\n    } else if (min > 0) {\n      r += min + \"分\";\n    } else if (s > 0) {\n      r += s + \"秒\";\n    }\n    r += \"前\";\n    return r;\n  }\n\n  /**\n   * 计算距离现在多久，精确\n   *\n   * @param date\n   *\n   * @return\n   */\n  public static String getTimeBeforeAccurate(Date date) {\n    Date now = new Date();\n    long l = now.getTime() - date.getTime();\n    long day = l / (24 * 60 * 60 * 1000);\n    long hour = (l / (60 * 60 * 1000) - day * 24);\n    long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);\n    long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);\n    String r = \"\";\n    if (day > 0) {\n      r += day + \"天\";\n    }\n    if (hour > 0) {\n      r += hour + \"小时\";\n    }\n    if (min > 0) {\n      r += min + \"分\";\n    }\n    if (s > 0) {\n      r += s + \"秒\";\n    }\n    r += \"前\";\n    return r;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/ExceptionUtils.java",
    "content": "package me.zbl.common.utils;\n\npublic class ExceptionUtils {\n\n  public static String getExceptionAllinformation(Exception ex) {\n    String sOut = \"\";\n    StackTraceElement[] trace = ex.getStackTrace();\n    for (StackTraceElement s : trace) {\n      sOut += \"\\tat \" + s + \"\\r\\n\";\n    }\n    return sOut;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/FileType.java",
    "content": "package me.zbl.common.utils;\n\n/* author：zss\n * 日期：2017年3月31日\n * 功能：根据文件名称判断类型\n * 接受参数类型：String\n * 返回参数类型：String\n * 备注：文件类型不完善，有需要的自行添加\n */\npublic class FileType {\n\n  public static int fileType(String fileName) {\n    if (fileName == null) {\n      fileName = \"文件名为空！\";\n      return 500;\n\n    } else {\n      // 获取文件后缀名并转化为写，用于后续比较\n      String fileType = fileName.substring(fileName.lastIndexOf(\".\") + 1, fileName.length()).toLowerCase();\n      // 创建图片类型数组0\n      String[] img = {\"bmp\", \"jpg\", \"jpeg\", \"png\", \"tiff\", \"gif\", \"pcx\", \"tga\", \"exif\", \"fpx\", \"svg\", \"psd\",\n              \"cdr\", \"pcd\", \"dxf\", \"ufo\", \"eps\", \"ai\", \"raw\", \"wmf\"};\n      for (int i = 0; i < img.length; i++) {\n        if (img[i].equals(fileType)) {\n          return 0;\n        }\n      }\n\n      // 创建文档类型数组1\n      String[] document = {\"txt\", \"doc\", \"docx\", \"xls\", \"htm\", \"html\", \"jsp\", \"rtf\", \"wpd\", \"pdf\", \"ppt\"};\n      for (int i = 0; i < document.length; i++) {\n        if (document[i].equals(fileType)) {\n          return 1;\n        }\n      }\n      // 创建视频类型数组2\n      String[] video = {\"mp4\", \"avi\", \"mov\", \"wmv\", \"asf\", \"navi\", \"3gp\", \"mkv\", \"f4v\", \"rmvb\", \"webm\"};\n      for (int i = 0; i < video.length; i++) {\n        if (video[i].equals(fileType)) {\n          return 2;\n        }\n      }\n      // 创建音乐类型数组3\n      String[] music = {\"mp3\", \"wma\", \"wav\", \"mod\", \"ra\", \"cd\", \"md\", \"asf\", \"aac\", \"vqf\", \"ape\", \"mid\", \"ogg\",\n              \"m4a\", \"vqf\"};\n      for (int i = 0; i < music.length; i++) {\n        if (music[i].equals(fileType)) {\n          return 3;\n        }\n      }\n\n    }\n    //4\n    return 99;\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/FileUtil.java",
    "content": "package me.zbl.common.utils;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.util.UUID;\n\npublic class FileUtil {\n\n  public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {\n    File targetFile = new File(filePath);\n    if (!targetFile.exists()) {\n      targetFile.mkdirs();\n    }\n    FileOutputStream out = new FileOutputStream(filePath + fileName);\n    out.write(file);\n    out.flush();\n    out.close();\n  }\n\n  public static boolean deleteFile(String fileName) {\n    File file = new File(fileName);\n    // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除\n    if (file.exists() && file.isFile()) {\n      return file.delete();\n    } else {\n      return false;\n    }\n  }\n\n  public static String renameToUUID(String fileName) {\n    return UUID.randomUUID() + \".\" + fileName.substring(fileName.lastIndexOf(\".\") + 1);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/GenUtils.java",
    "content": "package me.zbl.common.utils;\n\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.domain.ColumnDO;\nimport me.zbl.common.domain.TableDO;\nimport org.apache.commons.configuration.Configuration;\nimport org.apache.commons.configuration.ConfigurationException;\nimport org.apache.commons.configuration.PropertiesConfiguration;\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.WordUtils;\nimport org.apache.velocity.Template;\nimport org.apache.velocity.VelocityContext;\nimport org.apache.velocity.app.Velocity;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.util.*;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipOutputStream;\n\n/**\n * 代码生成器   工具类\n */\npublic class GenUtils {\n\n\n  public static List<String> getTemplates() {\n    List<String> templates = new ArrayList<String>();\n    templates.add(\"templates/common/generator/domain.java.vm\");\n    templates.add(\"templates/common/generator/Dao.java.vm\");\n    //templates.add(\"templates/common/generator/Mapper.java.vm\");\n    templates.add(\"templates/common/generator/Mapper.xml.vm\");\n    templates.add(\"templates/common/generator/Service.java.vm\");\n    templates.add(\"templates/common/generator/ServiceImpl.java.vm\");\n    templates.add(\"templates/common/generator/Controller.java.vm\");\n    templates.add(\"templates/common/generator/list.html.vm\");\n    templates.add(\"templates/common/generator/add.html.vm\");\n    templates.add(\"templates/common/generator/edit.html.vm\");\n    templates.add(\"templates/common/generator/list.js.vm\");\n    templates.add(\"templates/common/generator/add.js.vm\");\n    templates.add(\"templates/common/generator/edit.js.vm\");\n    //templates.add(\"templates/common/generator/menu.sql.vm\");\n    return templates;\n  }\n\n  /**\n   * 生成代码\n   */\n\n\n  public static void generatorCode(Map<String, String> table,\n                                   List<Map<String, String>> columns, ZipOutputStream zip) {\n    //配置信息\n    Configuration config = getConfig();\n    //表信息\n    TableDO tableDO = new TableDO();\n    tableDO.setTableName(table.get(\"tableName\"));\n    tableDO.setComments(table.get(\"tableComment\"));\n    //表名转换成Java类名\n    String className = tableToJava(tableDO.getTableName(), config.getString(\"tablePrefix\"), config.getString(\"autoRemovePre\"));\n    tableDO.setClassName(className);\n    tableDO.setClassname(StringUtils.uncapitalize(className));\n\n    //列信息\n    List<ColumnDO> columsList = new ArrayList<>();\n    for (Map<String, String> column : columns) {\n      ColumnDO columnDO = new ColumnDO();\n      columnDO.setColumnName(column.get(\"columnName\"));\n      columnDO.setDataType(column.get(\"dataType\"));\n      columnDO.setComments(column.get(\"columnComment\"));\n      columnDO.setExtra(column.get(\"extra\"));\n\n      //列名转换成Java属性名\n      String attrName = columnToJava(columnDO.getColumnName());\n      columnDO.setAttrName(attrName);\n      columnDO.setAttrname(StringUtils.uncapitalize(attrName));\n\n      //列的数据类型，转换成Java类型\n      String attrType = config.getString(columnDO.getDataType(), \"unknowType\");\n      columnDO.setAttrType(attrType);\n\n      //是否主键\n      if (\"PRI\".equalsIgnoreCase(column.get(\"columnKey\")) && tableDO.getPk() == null) {\n        tableDO.setPk(columnDO);\n      }\n\n      columsList.add(columnDO);\n    }\n    tableDO.setColumns(columsList);\n\n    //没主键，则第一个字段为主键\n    if (tableDO.getPk() == null) {\n      tableDO.setPk(tableDO.getColumns().get(0));\n    }\n\n    //设置velocity资源加载器\n    Properties prop = new Properties();\n    prop.put(\"file.resource.loader.class\", \"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader\");\n    Velocity.init(prop);\n\n    //封装模板数据\n    Map<String, Object> map = new HashMap<>(16);\n    map.put(\"tableName\", tableDO.getTableName());\n    map.put(\"comments\", tableDO.getComments());\n    map.put(\"pk\", tableDO.getPk());\n    map.put(\"className\", tableDO.getClassName());\n    map.put(\"classname\", tableDO.getClassname());\n    map.put(\"pathName\", config.getString(\"package\").substring(config.getString(\"package\").lastIndexOf(\".\") + 1));\n    map.put(\"columns\", tableDO.getColumns());\n    map.put(\"package\", config.getString(\"package\"));\n    map.put(\"author\", config.getString(\"author\"));\n    map.put(\"email\", config.getString(\"email\"));\n    map.put(\"datetime\", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));\n    VelocityContext context = new VelocityContext(map);\n\n    //获取模板列表\n    List<String> templates = getTemplates();\n    for (String template : templates) {\n      //渲染模板\n      StringWriter sw = new StringWriter();\n      Template tpl = Velocity.getTemplate(template, \"UTF-8\");\n      tpl.merge(context, sw);\n\n      try {\n        //添加到zip\n        zip.putNextEntry(new ZipEntry(getFileName(template, tableDO.getClassname(), tableDO.getClassName(), config.getString(\"package\").substring(config.getString(\"package\").lastIndexOf(\".\") + 1))));\n        IOUtils.write(sw.toString(), zip, \"UTF-8\");\n        IOUtils.closeQuietly(sw);\n        zip.closeEntry();\n      } catch (IOException e) {\n        throw new BDException(\"渲染模板失败，表名：\" + tableDO.getTableName(), e);\n      }\n    }\n  }\n\n\n  /**\n   * 列名转换成Java属性名\n   */\n  public static String columnToJava(String columnName) {\n    return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace(\"_\", \"\");\n  }\n\n  /**\n   * 表名转换成Java类名\n   */\n  public static String tableToJava(String tableName, String tablePrefix, String autoRemovePre) {\n    if (Constant.AUTO_REOMVE_PRE.equals(autoRemovePre)) {\n      tableName = tableName.substring(tableName.indexOf(\"_\") + 1);\n    }\n    if (StringUtils.isNotBlank(tablePrefix)) {\n      tableName = tableName.replace(tablePrefix, \"\");\n    }\n\n    return columnToJava(tableName);\n  }\n\n  /**\n   * 获取配置信息\n   */\n  public static Configuration getConfig() {\n    try {\n      return new PropertiesConfiguration(\"generator.properties\");\n    } catch (ConfigurationException e) {\n      throw new BDException(\"获取配置文件失败，\", e);\n    }\n  }\n\n  /**\n   * 获取文件名\n   */\n  public static String getFileName(String template, String classname, String className, String packageName) {\n    String packagePath = \"main\" + File.separator + \"java\" + File.separator;\n    //String modulesname=config.getString(\"packageName\");\n    if (StringUtils.isNotBlank(packageName)) {\n      packagePath += packageName.replace(\".\", File.separator) + File.separator;\n    }\n\n    if (template.contains(\"domain.java.vm\")) {\n      return packagePath + \"domain\" + File.separator + className + \"DO.java\";\n    }\n\n    if (template.contains(\"Dao.java.vm\")) {\n      return packagePath + \"repo\" + File.separator + className + \"Dao.java\";\n    }\n\n    //\t\tif(template.contains(\"Mapper.java.vm\")){\n    //\t\t\treturn packagePath + \"repo\" + File.separator + className + \"Mapper.java\";\n    //\t\t}\n\n    if (template.contains(\"Service.java.vm\")) {\n      return packagePath + \"service\" + File.separator + className + \"Service.java\";\n    }\n\n    if (template.contains(\"ServiceImpl.java.vm\")) {\n      return packagePath + \"service\" + File.separator + \"impl\" + File.separator + className + \"ServiceImpl.java\";\n    }\n\n    if (template.contains(\"Controller.java.vm\")) {\n      return packagePath + \"controller\" + File.separator + className + \"Controller.java\";\n    }\n\n    if (template.contains(\"Mapper.xml.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"mapper\" + File.separator + packageName + File.separator + className + \"Mapper.xml\";\n    }\n\n    if (template.contains(\"list.html.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"templates\" + File.separator\n              + packageName + File.separator + classname + File.separator + classname + \".html\";\n      //\t\t\t\t+ \"modules\" + File.separator + \"generator\" + File.separator + className.toLowerCase() + \".html\";\n    }\n    if (template.contains(\"add.html.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"templates\" + File.separator\n              + packageName + File.separator + classname + File.separator + \"add.html\";\n    }\n    if (template.contains(\"edit.html.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"templates\" + File.separator\n              + packageName + File.separator + classname + File.separator + \"edit.html\";\n    }\n\n    if (template.contains(\"list.js.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"static\" + File.separator + \"js\" + File.separator\n              + \"appjs\" + File.separator + packageName + File.separator + classname + File.separator + classname + \".js\";\n      //\t\t+ \"modules\" + File.separator + \"generator\" + File.separator + className.toLowerCase() + \".js\";\n    }\n    if (template.contains(\"add.js.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"static\" + File.separator + \"js\" + File.separator\n              + \"appjs\" + File.separator + packageName + File.separator + classname + File.separator + \"add.js\";\n    }\n    if (template.contains(\"edit.js.vm\")) {\n      return \"main\" + File.separator + \"resources\" + File.separator + \"static\" + File.separator + \"js\" + File.separator\n              + \"appjs\" + File.separator + packageName + File.separator + classname + File.separator + \"edit.js\";\n    }\n\n    //\t\tif(template.contains(\"menu.sql.vm\")){\n    //\t\t\treturn className.toLowerCase() + \"_menu.sql\";\n    //\t\t}\n\n    return null;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/HttpContextUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.servlet.http.HttpServletRequest;\n\npublic class HttpContextUtils {\n\n  public static HttpServletRequest getHttpServletRequest() {\n    return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/HttpServletUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport javax.servlet.http.HttpServletRequest;\n\npublic class HttpServletUtils {\n\n  public static boolean jsAjax(HttpServletRequest req) {\n    //判断是否为ajax请求，默认不是\n    boolean isAjaxRequest = false;\n    if (!StringUtils.isBlank(req.getHeader(\"x-requested-with\")) && req.getHeader(\"x-requested-with\").equals(\"XMLHttpRequest\")) {\n      isAjaxRequest = true;\n    }\n    return isAjaxRequest;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/IPUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.http.HttpServletRequest;\n\npublic class IPUtils {\n\n  private static Logger logger = LoggerFactory.getLogger(IPUtils.class);\n\n  /**\n   * 获取IP地址\n   * <p>\n   * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址\n   * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址\n   */\n  public static String getIpAddr(HttpServletRequest request) {\n\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 \"0:0:0:0:0:0:0:1\".equals(ip) ? \"127.0.0.1\" : ip;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/ImageUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.imageio.ImageIO;\nimport javax.imageio.ImageReadParam;\nimport javax.imageio.ImageReader;\nimport javax.imageio.stream.ImageInputStream;\nimport java.awt.*;\nimport java.awt.image.BufferedImage;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Iterator;\n\n/**\n * @author 郑保乐\n * @date 2017/12/18.\n */\npublic class ImageUtils {\n\n  /***\n   * 剪裁图片\n   * @param file 图片\n   * @param x  起点横坐标\n   * @param y  纵坐标\n   * @param w  长\n   * @param h  高\n   * @throws IOException\n   * @date\n   */\n  public static BufferedImage cutImage(MultipartFile file, int x, int y, int w, int h, String prefix) {\n\n    Iterator iterator = ImageIO.getImageReadersByFormatName(prefix);\n    try {\n      ImageReader reader = (ImageReader) iterator.next();\n      //转换成输入流\n      InputStream in = file.getInputStream();\n      ImageInputStream iis = ImageIO.createImageInputStream(in);\n      reader.setInput(iis, true);\n      ImageReadParam param = reader.getDefaultReadParam();\n      Rectangle rect = new Rectangle(x, y, w, h);\n      param.setSourceRegion(rect);\n      BufferedImage bi = reader.read(0, param);\n      return bi;\n    } catch (Exception ignored) {\n    }\n    return null;\n  }\n\n  /***\n   * 图片旋转指定角度\n   * @param bufferedimage 图像\n   * @param degree      角度\n   * @return\n   * @date\n   */\n  public static BufferedImage rotateImage(BufferedImage bufferedimage, int degree) {\n    int w = bufferedimage.getWidth();\n    int h = bufferedimage.getHeight();\n    int type = bufferedimage.getColorModel().getTransparency();\n    BufferedImage img;\n    Graphics2D graphics2d;\n    (graphics2d = (img = new BufferedImage(w, h, type))\n            .createGraphics()).setRenderingHint(\n            RenderingHints.KEY_INTERPOLATION,\n            RenderingHints.VALUE_INTERPOLATION_BILINEAR);\n    graphics2d.setPaint(Color.WHITE);\n    graphics2d.fillRect(0, 0, w, h);\n    graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);\n    graphics2d.drawImage(bufferedimage, 0, 0, Color.WHITE, null);\n    graphics2d.dispose();\n    return img;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/JSONUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class JSONUtils {\n\n  /**\n   * Bean对象转JSON\n   *\n   * @param object\n   * @param dataFormatString\n   *\n   * @return\n   */\n  public static String beanToJson(Object object, String dataFormatString) {\n    if (object != null) {\n      if (StringUtils.isEmpty(dataFormatString)) {\n        return JSONObject.toJSONString(object);\n      }\n      return JSON.toJSONStringWithDateFormat(object, dataFormatString);\n    } else {\n      return null;\n    }\n  }\n\n  /**\n   * Bean对象转JSON\n   *\n   * @param object\n   *\n   * @return\n   */\n  public static String beanToJson(Object object) {\n    if (object != null) {\n      return JSON.toJSONString(object);\n    } else {\n      return null;\n    }\n  }\n\n  /**\n   * String转JSON字符串\n   *\n   * @param key\n   * @param value\n   *\n   * @return\n   */\n  public static String stringToJsonByFastjson(String key, String value) {\n    if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {\n      return null;\n    }\n    Map<String, String> map = new HashMap<String, String>(16);\n    map.put(key, value);\n    return beanToJson(map, null);\n  }\n\n  /**\n   * 将json字符串转换成对象\n   *\n   * @param json\n   * @param clazz\n   *\n   * @return\n   */\n  public static Object jsonToBean(String json, Object clazz) {\n    if (StringUtils.isEmpty(json) || clazz == null) {\n      return null;\n    }\n    return JSON.parseObject(json, clazz.getClass());\n  }\n\n  /**\n   * json字符串转map\n   *\n   * @param json\n   *\n   * @return\n   */\n  @SuppressWarnings(\"unchecked\")\n  public static Map<String, Object> jsonToMap(String json) {\n    if (StringUtils.isEmpty(json)) {\n      return null;\n    }\n    return JSON.parseObject(json, Map.class);\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/MD5Utils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.apache.shiro.crypto.hash.SimpleHash;\nimport org.apache.shiro.util.ByteSource;\n\npublic class MD5Utils {\n\n  private static final String SALT = \"1qazxsw2\";\n\n  private static final String ALGORITH_NAME = \"md5\";\n\n  private static final int HASH_ITERATIONS = 2;\n\n  public static String encrypt(String pswd) {\n    String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(SALT), HASH_ITERATIONS).toHex();\n    return newPassword;\n  }\n\n  public static String encrypt(String username, String pswd) {\n    String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(username + SALT),\n            HASH_ITERATIONS).toHex();\n    return newPassword;\n  }\n\n  public static void main(String[] args) {\n\n    //System.out.println(MD5Utils.encrypt(\"admin\", \"1\"));\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/PageWrapper.java",
    "content": "package me.zbl.common.utils;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * @author 郑保乐\n */\npublic class PageWrapper implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n  private int total;\n  private List<?> rows;\n\n  public PageWrapper(List<?> list, int total) {\n    this.rows = list;\n    this.total = total;\n  }\n\n  public int getTotal() {\n    return total;\n  }\n\n  public void setTotal(int total) {\n    this.total = total;\n  }\n\n  public List<?> getRows() {\n    return rows;\n  }\n\n  public void setRows(List<?> rows) {\n    this.rows = rows;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/Query.java",
    "content": "package me.zbl.common.utils;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * 查询参数\n */\npublic class Query extends LinkedHashMap<String, Object> {\n\n  private static final long serialVersionUID = 1L;\n  //\n  private int offset;\n  // 每页条数\n  private int limit;\n\n  public Query(Map<String, Object> params) {\n    this.putAll(params);\n    // 分页参数\n    this.offset = Integer.parseInt(params.get(\"offset\").toString());\n    this.limit = Integer.parseInt(params.get(\"limit\").toString());\n    this.put(\"offset\", offset);\n    this.put(\"page\", offset / limit + 1);\n    this.put(\"limit\", limit);\n  }\n\n  public int getOffset() {\n    return offset;\n  }\n\n  public void setOffset(int offset) {\n    this.put(\"offset\", offset);\n  }\n\n  public int getLimit() {\n    return limit;\n  }\n\n  public void setLimit(int limit) {\n    this.limit = limit;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/R.java",
    "content": "package me.zbl.common.utils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class R extends HashMap<String, Object> {\n\n  private static final long serialVersionUID = 1L;\n\n  public R() {\n    put(\"code\", 0);\n    put(\"msg\", \"操作成功\");\n  }\n\n  public static R error() {\n    return error(1, \"操作失败\");\n  }\n\n  public static R error(String msg) {\n    return error(500, msg);\n  }\n\n  public static R error(int code, String msg) {\n    R r = new R();\n    r.put(\"code\", code);\n    r.put(\"msg\", msg);\n    return r;\n  }\n\n  public static R ok(String msg) {\n    R r = new R();\n    r.put(\"msg\", msg);\n    return r;\n  }\n\n  public static R ok(Map<String, Object> map) {\n    R r = new R();\n    r.putAll(map);\n    return r;\n  }\n\n  public static R ok() {\n    return new R();\n  }\n\n  @Override\n  public R put(String key, Object value) {\n    super.put(key, value);\n    return this;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/ScheduleJobUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport me.zbl.common.domain.ScheduleJob;\nimport me.zbl.common.domain.TaskDO;\n\npublic class ScheduleJobUtils {\n\n  public static ScheduleJob entityToData(TaskDO scheduleJobEntity) {\n    ScheduleJob scheduleJob = new ScheduleJob();\n    scheduleJob.setBeanClass(scheduleJobEntity.getBeanClass());\n    scheduleJob.setCronExpression(scheduleJobEntity.getCronExpression());\n    scheduleJob.setDescription(scheduleJobEntity.getDescription());\n    scheduleJob.setIsConcurrent(scheduleJobEntity.getIsConcurrent());\n    scheduleJob.setJobName(scheduleJobEntity.getJobName());\n    scheduleJob.setJobGroup(scheduleJobEntity.getJobGroup());\n    scheduleJob.setJobStatus(scheduleJobEntity.getJobStatus());\n    scheduleJob.setMethodName(scheduleJobEntity.getMethodName());\n    scheduleJob.setSpringBean(scheduleJobEntity.getSpringBean());\n    return scheduleJob;\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/ShiroUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport me.zbl.system.domain.UserDO;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.session.Session;\nimport org.apache.shiro.session.mgt.eis.SessionDAO;\nimport org.apache.shiro.subject.Subject;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.security.Principal;\nimport java.util.Collection;\nimport java.util.List;\n\npublic class ShiroUtils {\n\n  @Autowired\n  private static SessionDAO sessionDAO;\n\n  public static Subject getSubjct() {\n    return SecurityUtils.getSubject();\n  }\n\n  public static UserDO getUser() {\n    Object object = getSubjct().getPrincipal();\n    return (UserDO) object;\n  }\n\n  public static Long getUserId() {\n    return getUser().getUserId();\n  }\n\n  public static void logout() {\n    getSubjct().logout();\n  }\n\n  public static List<Principal> getPrinciples() {\n    List<Principal> principals = null;\n    Collection<Session> sessions = sessionDAO.getActiveSessions();\n    return principals;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/StringUtils.java",
    "content": "package me.zbl.common.utils;\n\n/**\n * @author 郑保乐\n */\npublic class StringUtils extends org.apache.commons.lang3.StringUtils {\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/TimeUtils.java",
    "content": "package me.zbl.common.utils;\n\nimport org.apache.commons.lang3.time.DateFormatUtils;\n\nimport java.util.Arrays;\nimport java.util.Date;\n\n/**\n * 时间计算工具类\n */\npublic class TimeUtils {\n\n  /**\n   * 时间字段常量，表示“秒”\n   */\n  public final static int SECOND = 0;\n  /**\n   * 时间字段常量，表示“分”\n   */\n  public final static int MINUTE = 1;\n  /**\n   * 时间字段常量，表示“时”\n   */\n  public final static int HOUR = 2;\n  /**\n   * 时间字段常量，表示“天”\n   */\n  public final static int DAY = 3;\n  /**\n   * 各常量允许的最大值\n   */\n  private final int[] maxFields = {59, 59, 23, Integer.MAX_VALUE - 1};\n  /**\n   * 各常量允许的最小值\n   */\n  private final int[] minFields = {0, 0, 0, Integer.MIN_VALUE};\n  /**\n   * 默认的字符串格式时间分隔符\n   */\n  private String timeSeparator = \":\";\n  /**\n   * 时间数据容器\n   */\n  private int[] fields = new int[4];\n\n  /**\n   * 无参构造，将各字段置为 0\n   */\n  public TimeUtils() {\n    this(0, 0, 0, 0);\n  }\n\n  /**\n   * 使用时、分构造一个时间\n   *\n   * @param hour   小时\n   * @param minute 分钟\n   */\n  public TimeUtils(int hour, int minute) {\n    this(0, hour, minute, 0);\n  }\n\n  /**\n   * 使用时、分、秒构造一个时间\n   *\n   * @param hour   小时\n   * @param minute 分钟\n   * @param second 秒\n   */\n  public TimeUtils(int hour, int minute, int second) {\n    this(0, hour, minute, second);\n  }\n\n  /**\n   * 使用一个字符串构造时间<br/>\n   * Time time = new Time(\"14:22:23\");\n   *\n   * @param time 字符串格式的时间，默认采用“:”作为分隔符\n   */\n  public TimeUtils(String time) {\n    this(time, null);\n  }\n\n  /**\n   * 使用时间毫秒构建时间\n   *\n   * @param time\n   */\n  public TimeUtils(long time) {\n    this(new Date(time));\n  }\n\n  /**\n   * 使用日期对象构造时间\n   *\n   * @param date\n   */\n  public TimeUtils(Date date) {\n    this(DateFormatUtils.formatUTC(date, \"HH:mm:ss\"));\n  }\n\n  /**\n   * 使用天、时、分、秒构造时间，进行全字符的构造\n   *\n   * @param day    天\n   * @param hour   时\n   * @param minute 分\n   * @param second 秒\n   */\n  public TimeUtils(int day, int hour, int minute, int second) {\n    initialize(day, hour, minute, second);\n  }\n\n  /**\n   * 使用一个字符串构造时间，指定分隔符<br/>\n   * Time time = new Time(\"14-22-23\", \"-\");\n   *\n   * @param time 字符串格式的时间\n   */\n  public TimeUtils(String time, String timeSeparator) {\n    if (timeSeparator != null) {\n      setTimeSeparator(timeSeparator);\n    }\n    parseTime(time);\n  }\n\n  public static String toTimeString(long time) {\n    TimeUtils t = new TimeUtils(time);\n    int day = t.get(TimeUtils.DAY);\n    int hour = t.get(TimeUtils.HOUR);\n    int minute = t.get(TimeUtils.MINUTE);\n    int second = t.get(TimeUtils.SECOND);\n    StringBuilder sb = new StringBuilder();\n    if (day > 0) {\n      sb.append(day).append(\"天\");\n    }\n    if (hour > 0) {\n      sb.append(hour).append(\"时\");\n    }\n    if (minute > 0) {\n      sb.append(minute).append(\"分\");\n    }\n    if (second > 0) {\n      sb.append(second).append(\"秒\");\n    }\n    return sb.toString();\n  }\n\n  /**\n   * 设置时间字段的值\n   *\n   * @param field 时间字段常量\n   * @param value 时间字段的值\n   */\n  public void set(int field, int value) {\n    if (value < minFields[field]) {\n      throw new IllegalArgumentException(value + \", time value must be positive.\");\n    }\n    fields[field] = value % (maxFields[field] + 1);\n    // 进行进位计算\n    int carry = value / (maxFields[field] + 1);\n    if (carry > 0) {\n      int upFieldValue = get(field + 1);\n      set(field + 1, upFieldValue + carry);\n    }\n  }\n\n  /**\n   * 获得时间字段的值\n   *\n   * @param field 时间字段常量\n   *\n   * @return 该时间字段的值\n   */\n  public int get(int field) {\n    if (field < 0 || field > fields.length - 1) {\n      throw new IllegalArgumentException(field + \", field value is error.\");\n    }\n    return fields[field];\n  }\n\n  /**\n   * 将时间进行“加”运算，即加上一个时间\n   *\n   * @param time 需要加的时间\n   *\n   * @return 运算后的时间\n   */\n  public TimeUtils addTime(TimeUtils time) {\n    TimeUtils result = new TimeUtils();\n    int up = 0;     // 进位标志\n    for (int i = 0; i < fields.length; i++) {\n      int sum = fields[i] + time.fields[i] + up;\n      up = sum / (maxFields[i] + 1);\n      result.fields[i] = sum % (maxFields[i] + 1);\n    }\n    return result;\n  }\n\n  /**\n   * 将时间进行“减”运算，即减去一个时间\n   *\n   * @param time 需要减的时间\n   *\n   * @return 运算后的时间\n   */\n  public TimeUtils subtractTime(TimeUtils time) {\n    TimeUtils result = new TimeUtils();\n    int down = 0;       // 退位标志\n    for (int i = 0, k = fields.length - 1; i < k; i++) {\n      int difference = fields[i] + down;\n      if (difference >= time.fields[i]) {\n        difference -= time.fields[i];\n        down = 0;\n      } else {\n        difference += maxFields[i] + 1 - time.fields[i];\n        down = -1;\n      }\n      result.fields[i] = difference;\n    }\n    result.fields[DAY] = fields[DAY] - time.fields[DAY] + down;\n    return result;\n  }\n\n  /**\n   * 获得时间字段的分隔符\n   *\n   * @return\n   */\n  public String getTimeSeparator() {\n    return timeSeparator;\n  }\n\n  /**\n   * 设置时间字段的分隔符（用于字符串格式的时间）\n   *\n   * @param timeSeparator 分隔符字符串\n   */\n  public void setTimeSeparator(String timeSeparator) {\n    this.timeSeparator = timeSeparator;\n  }\n\n  private void initialize(int day, int hour, int minute, int second) {\n    set(DAY, day);\n    set(HOUR, hour);\n    set(MINUTE, minute);\n    set(SECOND, second);\n  }\n\n  private void parseTime(String time) {\n    if (time == null) {\n      initialize(0, 0, 0, 0);\n      return;\n    }\n    String t = time;\n    int field = DAY;\n    set(field--, 0);\n    int p = -1;\n    while ((p = t.indexOf(timeSeparator)) > -1) {\n      parseTimeField(time, t.substring(0, p), field--);\n      t = t.substring(p + timeSeparator.length());\n    }\n    parseTimeField(time, t, field--);\n  }\n\n  private void parseTimeField(String time, String t, int field) {\n    if (field < SECOND || t.length() < 1) {\n      parseTimeException(time);\n    }\n    char[] chs = t.toCharArray();\n    int n = 0;\n    for (int i = 0; i < chs.length; i++) {\n      if (chs[i] <= ' ') {\n        continue;\n      }\n      if (chs[i] >= '0' && chs[i] <= '9') {\n        n = n * 10 + chs[i] - '0';\n        continue;\n      }\n      parseTimeException(time);\n    }\n    set(field, n);\n  }\n\n  private void parseTimeException(String time) {\n    throw new IllegalArgumentException(time + \", time format error, HH\"\n            + this.timeSeparator + \"mm\" + this.timeSeparator + \"ss\");\n  }\n\n  @Override\n  public String toString() {\n    StringBuilder sb = new StringBuilder(16);\n    sb.append(fields[DAY]).append(',').append(' ');\n    buildString(sb, HOUR).append(timeSeparator);\n    buildString(sb, MINUTE).append(timeSeparator);\n    buildString(sb, SECOND);\n    return sb.toString();\n  }\n\n  private StringBuilder buildString(StringBuilder sb, int field) {\n    if (fields[field] < 10) {\n      sb.append('0');\n    }\n    return sb.append(fields[field]);\n  }\n\n  public int hashCode() {\n    final int PRIME = 31;\n    int result = 1;\n    result = PRIME * result + Arrays.hashCode(fields);\n    return result;\n  }\n\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    final TimeUtils other = (TimeUtils) obj;\n    return Arrays.equals(fields, other.fields);\n  }\n\n}"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/UploadUtils.java",
    "content": "package me.zbl.common.utils;\n\npublic class UploadUtils {\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/common/utils/xss/JsoupUtil.java",
    "content": "package me.zbl.common.utils.xss;\n\nimport org.jsoup.Jsoup;\nimport org.jsoup.nodes.Document;\nimport org.jsoup.safety.Whitelist;\n\n/**\n * xss非法标签过滤\n * {@link http://www.jianshu.com/p/32abc12a175a?nomobile=yes}\n *\n * @author 郑保乐\n * @version v2.0\n * @time 2017年4月27日 下午5:47:09\n */\npublic class JsoupUtil {\n\n  /**\n   * 使用自带的basicWithImages 白名单\n   * 允许的便签有a,b,blockquote,br,cite,code,dd,dl,dt,em,i,li,ol,p,pre,q,small,span,\n   * strike,strong,sub,sup,u,ul,img\n   * 以及a标签的href,img标签的src,align,alt,height,width,title属性\n   */\n  private static final Whitelist whitelist = Whitelist.basicWithImages();\n  /** 配置过滤化参数,不对代码进行格式化 */\n  private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);\n\n  static {\n    // 富文本编辑时一些样式是使用style来进行实现的\n    // 比如红色字体 style=\"color:red;\"\n    // 所以需要给所有标签添加style属性\n    whitelist.addAttributes(\":all\", \"style\");\n  }\n\n  public static String clean(String content) {\n    return Jsoup.clean(content, \"\", whitelist, outputSettings);\n  }\n\n  public static void main(String[] args) {\n    String text = \"<a href=\\\"http://www.baidu.com/a\\\" onclick=\\\"alert(1);\\\">sss</a><script>alert(0);</script>sss\";\n    System.out.println(clean(text));\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/config/WebSocketConfig.java",
    "content": "package me.zbl.oa.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.messaging.simp.config.MessageBrokerRegistry;\nimport org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;\nimport org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;\nimport org.springframework.web.socket.config.annotation.StompEndpointRegistry;\n\n/**\n * 通过EnableWebSocketMessageBroker 开启使用STOMP协议来传输基于代理(message broker)的消息,此时浏览器支持使用@MessageMapping 就像支持@RequestMapping一样。\n */\n@Configuration\n@EnableWebSocketMessageBroker\npublic class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {\n\n  //    /**\n  //     * endPoint 注册协议节点,并映射指定的URl\n  //     *\n  //     * @param registry\n  //     */\n  //    @Override\n  //    public void registerStompEndpoints(StompEndpointRegistry registry) {\n  //        //注册一个Stomp 协议的endpoint,并指定 SockJS协议。\n  //        registry.addEndpoint(\"/endpointWisely\").withSockJS();\n  //    }\n  //\n  //    /**\n  //     * 配置消息代理(message broker)\n  //     *\n  //     * @param registry\n  //     */\n  //    @Override\n  //    public void configureMessageBroker(MessageBrokerRegistry registry) {\n  //        //广播式应配置一个/topic 消息代理\n  //        registry.enableSimpleBroker(\"/topic\");\n  //    }\n  @Override\n  public void registerStompEndpoints(StompEndpointRegistry registry) { //endPoint 注册协议节点,并映射指定的URl\n\n    //注册一个名字为\"endpointChat\" 的endpoint,并指定 SockJS协议。   点对点-用\n    registry.addEndpoint(\"/endpointChat\").withSockJS();\n  }\n\n\n  @Override\n  public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(message broker)\n    //点对点式增加一个/queue 消息代理\n    registry.enableSimpleBroker(\"/queue\", \"/topic\");\n\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/controller/NotifyController.java",
    "content": "package me.zbl.oa.controller;\n\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.domain.DictDO;\nimport me.zbl.common.service.DictService;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport me.zbl.oa.domain.NotifyDO;\nimport me.zbl.oa.domain.NotifyRecordDO;\nimport me.zbl.oa.service.NotifyRecordService;\nimport me.zbl.oa.service.NotifyService;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 通知通告\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-05 17:11:16\n */\n\n@Controller\n@RequestMapping(\"/oa/notify\")\npublic class NotifyController extends BaseController {\n\n  @Autowired\n  private NotifyService notifyService;\n  @Autowired\n  private NotifyRecordService notifyRecordService;\n  @Autowired\n  private DictService dictService;\n\n  @GetMapping()\n  @RequiresPermissions(\"oa:notify:notify\")\n  String oaNotify() {\n    return \"oa/notify/notify\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/list\")\n  @RequiresPermissions(\"oa:notify:notify\")\n  public PageWrapper list(@RequestParam Map<String, Object> params) {\n    // 查询列表数据\n    Query query = new Query(params);\n    List<NotifyDO> notifyList = notifyService.list(query);\n    int total = notifyService.count(query);\n    PageWrapper pageWrapper = new PageWrapper(notifyList, total);\n    return pageWrapper;\n  }\n\n  @GetMapping(\"/add\")\n  @RequiresPermissions(\"oa:notify:add\")\n  String add() {\n    return \"oa/notify/add\";\n  }\n\n  @GetMapping(\"/edit/{id}\")\n  @RequiresPermissions(\"oa:notify:edit\")\n  String edit(@PathVariable(\"id\") Long id, Model model) {\n    NotifyDO notify = notifyService.get(id);\n    List<DictDO> dictDOS = dictService.listByType(\"oa_notify_type\");\n    String type = notify.getType();\n    for (DictDO dictDO : dictDOS) {\n      if (type.equals(dictDO.getValue())) {\n        dictDO.setRemarks(\"checked\");\n      }\n    }\n    model.addAttribute(\"oaNotifyTypes\", dictDOS);\n    model.addAttribute(\"notify\", notify);\n    return \"oa/notify/edit\";\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  @RequiresPermissions(\"oa:notify:add\")\n  public R save(NotifyDO notify) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    notify.setCreateBy(getUserId());\n    if (notifyService.save(notify) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @ResponseBody\n  @RequestMapping(\"/update\")\n  @RequiresPermissions(\"oa:notify:edit\")\n  public R update(NotifyDO notify) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    notifyService.update(notify);\n    return R.ok();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  @RequiresPermissions(\"oa:notify:remove\")\n  public R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (notifyService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  @RequiresPermissions(\"oa:notify:batchRemove\")\n  public R remove(@RequestParam(\"ids[]\") Long[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    notifyService.batchRemove(ids);\n    return R.ok();\n  }\n\n  @ResponseBody\n  @GetMapping(\"/message\")\n  PageWrapper message() {\n    Map<String, Object> params = new HashMap<>(16);\n    params.put(\"offset\", 0);\n    params.put(\"limit\", 3);\n    Query query = new Query(params);\n    query.put(\"userId\", getUserId());\n    query.put(\"isRead\", Constant.OA_NOTIFY_READ_NO);\n    return notifyService.selfList(query);\n  }\n\n  @GetMapping(\"/selfNotify\")\n  String selefNotify() {\n    return \"oa/notify/selfNotify\";\n  }\n\n  @ResponseBody\n  @GetMapping(\"/selfList\")\n  PageWrapper selfList(@RequestParam Map<String, Object> params) {\n    Query query = new Query(params);\n    query.put(\"userId\", getUserId());\n\n    return notifyService.selfList(query);\n  }\n\n  @GetMapping(\"/read/{id}\")\n  @RequiresPermissions(\"oa:notify:edit\")\n  String read(@PathVariable(\"id\") Long id, Model model) {\n    NotifyDO notify = notifyService.get(id);\n    //更改阅读状态\n    NotifyRecordDO notifyRecordDO = new NotifyRecordDO();\n    notifyRecordDO.setNotifyId(id);\n    notifyRecordDO.setUserId(getUserId());\n    notifyRecordDO.setReadDate(new Date());\n    notifyRecordDO.setIsRead(Constant.OA_NOTIFY_READ_YES);\n    notifyRecordService.changeRead(notifyRecordDO);\n    model.addAttribute(\"notify\", notify);\n    return \"oa/notify/read\";\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/controller/WebSocketController.java",
    "content": "package me.zbl.oa.controller;\n\nimport me.zbl.system.service.SessionService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.messaging.simp.SimpMessagingTemplate;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class WebSocketController {\n\n  @Autowired\n  SimpMessagingTemplate template;\n\n  @Autowired\n  SessionService sessionService;\n\n\t/*@Autowired\n\tWelcomeTask welcomeTask;\n\n\t@MessageMapping(\"/welcome\") // 浏览器发送请求通过@messageMapping 映射/welcome 这个地址。\n\t@SendTo(\"/topic/getResponse\") // 服务器端有消息时,会订阅@SendTo 中的路径的浏览器发送消息。\n\tpublic Response say(Message message) throws Exception {\n\t\tThread.sleep(1000);\n\t\treturn new Response(\"Welcome, \" + message.getName() + \"!\");\n\t}\n\n\t@GetMapping(\"/test\")\n\tString test() {\n\t\treturn \"test\";\n\t}\n\n\t@RequestMapping(\"/welcome\")\n\t@ResponseBody\n\tpublic R say02() {\n\t\ttry {\n\t\t\twelcomeTask.sayWelcome();\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn R.ok();\n\t}*/\n  //    @ResponseBody\n  //    @GetMapping(\"/chat\")\n  //    public String  handleChat(Principal principal, String msg) {\n  //        template.convertAndSendToUser(sessionService.listPrincipal().get(0).toString(), \"/queue/notifications\", principal.getName() + \"给您发来了消息：\" + msg);\n  //        return sessionService.listPrincipal().get(0).toString();\n  //    }\n}"
  },
  {
    "path": "src/main/java/me/zbl/oa/dao/NotifyDao.java",
    "content": "package me.zbl.oa.dao;\n\nimport me.zbl.oa.domain.NotifyDO;\nimport me.zbl.oa.domain.NotifyDTO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 通知通告\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-05 17:11:16\n */\n@Mapper\npublic interface NotifyDao {\n\n  NotifyDO get(Long id);\n\n  List<NotifyDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(NotifyDO notify);\n\n  int update(NotifyDO notify);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  List<NotifyDO> listByIds(Long[] ids);\n\n  int countDTO(Map<String, Object> map);\n\n  List<NotifyDTO> listDTO(Map<String, Object> map);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/dao/NotifyRecordDao.java",
    "content": "package me.zbl.oa.dao;\n\nimport me.zbl.oa.domain.NotifyRecordDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 通知通告发送记录\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-09 17:18:45\n */\n@Mapper\npublic interface NotifyRecordDao {\n\n  NotifyRecordDO get(Long id);\n\n  List<NotifyRecordDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(NotifyRecordDO notifyRecord);\n\n  int update(NotifyRecordDO notifyRecord);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  int batchSave(List<NotifyRecordDO> records);\n\n  Long[] listNotifyIds(Map<String, Object> map);\n\n  int removeByNotifbyId(Long notifyId);\n\n  int batchRemoveByNotifbyId(Long[] notifyIds);\n\n  int changeRead(NotifyRecordDO notifyRecord);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/domain/Message.java",
    "content": "package me.zbl.oa.domain;\n\npublic class Message {\n\n  private String name;\n\n  public String getName() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/domain/NotifyDO.java",
    "content": "package me.zbl.oa.domain;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.Date;\n\n\n/**\n * 通知通告\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-05 17:11:16\n */\npublic class NotifyDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //编号\n  private Long id;\n  //类型\n  private String type;\n  //标题\n  private String title;\n  //内容\n  private String content;\n  //附件\n  private String files;\n  //状态\n  private String status;\n  //创建者\n  private Long createBy;\n  //创建时间\n  private Date createDate;\n  //更新者\n  private String updateBy;\n  //更新时间\n  private Date updateDate;\n  //备注信息\n  private String remarks;\n  //删除标记\n  private String delFlag;\n\n  private Long[] userIds;\n\n  /**\n   * 获取：编号\n   */\n  public Long getId() {\n    return id;\n  }\n\n  /**\n   * 设置：编号\n   */\n  public void setId(Long id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：类型\n   */\n  public String getType() {\n    return type;\n  }\n\n  /**\n   * 设置：类型\n   */\n  public void setType(String type) {\n    this.type = type;\n  }\n\n  /**\n   * 获取：标题\n   */\n  public String getTitle() {\n    return title;\n  }\n\n  /**\n   * 设置：标题\n   */\n  public void setTitle(String title) {\n    this.title = title;\n  }\n\n  /**\n   * 获取：内容\n   */\n  public String getContent() {\n    return content;\n  }\n\n  /**\n   * 设置：内容\n   */\n  public void setContent(String content) {\n    this.content = content;\n  }\n\n  /**\n   * 获取：附件\n   */\n  public String getFiles() {\n    return files;\n  }\n\n  /**\n   * 设置：附件\n   */\n  public void setFiles(String files) {\n    this.files = files;\n  }\n\n  /**\n   * 获取：状态\n   */\n  public String getStatus() {\n    return status;\n  }\n\n  /**\n   * 设置：状态\n   */\n  public void setStatus(String status) {\n    this.status = status;\n  }\n\n  /**\n   * 获取：创建者\n   */\n  public Long getCreateBy() {\n    return createBy;\n  }\n\n  /**\n   * 设置：创建者\n   */\n  public void setCreateBy(Long createBy) {\n    this.createBy = createBy;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getCreateDate() {\n    return createDate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setCreateDate(Date createDate) {\n    this.createDate = createDate;\n  }\n\n  /**\n   * 获取：更新者\n   */\n  public String getUpdateBy() {\n    return updateBy;\n  }\n\n  /**\n   * 设置：更新者\n   */\n  public void setUpdateBy(String updateBy) {\n    this.updateBy = updateBy;\n  }\n\n  /**\n   * 获取：更新时间\n   */\n  public Date getUpdateDate() {\n    return updateDate;\n  }\n\n  /**\n   * 设置：更新时间\n   */\n  public void setUpdateDate(Date updateDate) {\n    this.updateDate = updateDate;\n  }\n\n  /**\n   * 获取：备注信息\n   */\n  public String getRemarks() {\n    return remarks;\n  }\n\n  /**\n   * 设置：备注信息\n   */\n  public void setRemarks(String remarks) {\n    this.remarks = remarks;\n  }\n\n  /**\n   * 获取：删除标记\n   */\n  public String getDelFlag() {\n    return delFlag;\n  }\n\n  /**\n   * 设置：删除标记\n   */\n  public void setDelFlag(String delFlag) {\n    this.delFlag = delFlag;\n  }\n\n  public Long[] getUserIds() {\n    return userIds;\n  }\n\n  public void setUserIds(Long[] userIds) {\n    this.userIds = userIds;\n  }\n\n  @Override\n  public String toString() {\n    return \"NotifyDO{\" +\n            \"id=\" + id +\n            \", type='\" + type + '\\'' +\n            \", title='\" + title + '\\'' +\n            \", content='\" + content + '\\'' +\n            \", files='\" + files + '\\'' +\n            \", status='\" + status + '\\'' +\n            \", createBy=\" + createBy +\n            \", createDate=\" + createDate +\n            \", updateBy='\" + updateBy + '\\'' +\n            \", updateDate=\" + updateDate +\n            \", remarks='\" + remarks + '\\'' +\n            \", delFlag='\" + delFlag + '\\'' +\n            \", userIds=\" + Arrays.toString(userIds) +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/domain/NotifyDTO.java",
    "content": "package me.zbl.oa.domain;\n\npublic class NotifyDTO extends NotifyDO {\n\n  private static final long serialVersionUID = 1L;\n\n  private String isRead;\n\n  private String before;\n\n  private String sender;\n\n  public String getIsRead() {\n    return isRead;\n  }\n\n  public void setIsRead(String isRead) {\n    this.isRead = isRead;\n  }\n\n  public String getBefore() {\n    return before;\n  }\n\n  public void setBefore(String before) {\n    this.before = before;\n  }\n\n  public String getSender() {\n    return sender;\n  }\n\n  public void setSender(String sender) {\n    this.sender = sender;\n  }\n\n  @Override\n  public String toString() {\n    return \"NotifyDTO{\" +\n            \"isRead='\" + isRead + '\\'' +\n            \", before='\" + before + '\\'' +\n            \", sender='\" + sender + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/domain/NotifyRecordDO.java",
    "content": "package me.zbl.oa.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n\n/**\n * 通知通告发送记录\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-10 11:08:06\n */\npublic class NotifyRecordDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  /**\n   * 编号\n   */\n  private Long id;\n  //通知通告ID\n  private Long notifyId;\n  //接受人\n  private Long userId;\n  //阅读标记\n  private Integer isRead;\n  //阅读时间\n  private Date readDate;\n\n  /**\n   * 获取：编号\n   */\n  public Long getId() {\n    return id;\n  }\n\n  /**\n   * 设置：编号\n   */\n  public void setId(Long id) {\n    this.id = id;\n  }\n\n  /**\n   * 获取：通知通告ID\n   */\n  public Long getNotifyId() {\n    return notifyId;\n  }\n\n  /**\n   * 设置：通知通告ID\n   */\n  public void setNotifyId(Long notifyId) {\n    this.notifyId = notifyId;\n  }\n\n  /**\n   * 获取：接受人\n   */\n  public Long getUserId() {\n    return userId;\n  }\n\n  /**\n   * 设置：接受人\n   */\n  public void setUserId(Long userId) {\n    this.userId = userId;\n  }\n\n  /**\n   * 获取：阅读标记\n   */\n  public Integer getIsRead() {\n    return isRead;\n  }\n\n  /**\n   * 设置：阅读标记\n   */\n  public void setIsRead(Integer isRead) {\n    this.isRead = isRead;\n  }\n\n  /**\n   * 获取：阅读时间\n   */\n  public Date getReadDate() {\n    return readDate;\n  }\n\n  /**\n   * 设置：阅读时间\n   */\n  public void setReadDate(Date readDate) {\n    this.readDate = readDate;\n  }\n\n  @Override\n  public String toString() {\n    return \"NotifyRecordDO{\" +\n            \"id=\" + id +\n            \", notifyId=\" + notifyId +\n            \", userId=\" + userId +\n            \", isRead=\" + isRead +\n            \", readDate=\" + readDate +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/domain/Response.java",
    "content": "package me.zbl.oa.domain;\n\npublic class Response {\n\n  private String responseMessage;\n\n  public Response(String responseMessage) {\n    this.responseMessage = responseMessage;\n  }\n\n  public String getResponseMessage() {\n    return responseMessage;\n  }\n\n  public void setResponseMessage(String responseMessage) {\n    this.responseMessage = responseMessage;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/service/NotifyRecordService.java",
    "content": "package me.zbl.oa.service;\n\nimport me.zbl.oa.domain.NotifyRecordDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 通知通告发送记录\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-09 17:18:45\n */\npublic interface NotifyRecordService {\n\n  NotifyRecordDO get(Long id);\n\n  List<NotifyRecordDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(NotifyRecordDO notifyRecord);\n\n  int update(NotifyRecordDO notifyRecord);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  /**\n   * 更改阅读状态\n   *\n   * @return\n   */\n  int changeRead(NotifyRecordDO notifyRecord);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/service/NotifyService.java",
    "content": "package me.zbl.oa.service;\n\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.oa.domain.NotifyDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 通知通告\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-05 17:11:16\n */\npublic interface NotifyService {\n\n  NotifyDO get(Long id);\n\n  List<NotifyDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(NotifyDO notify);\n\n  int update(NotifyDO notify);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  //\tMap<String, Object> message(Long userId);\n\n  PageWrapper selfList(Map<String, Object> map);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/service/impl/NotifyRecordServiceImpl.java",
    "content": "package me.zbl.oa.service.impl;\n\nimport me.zbl.oa.dao.NotifyRecordDao;\nimport me.zbl.oa.domain.NotifyRecordDO;\nimport me.zbl.oa.service.NotifyRecordService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n\n@Service\npublic class NotifyRecordServiceImpl implements NotifyRecordService {\n\n  @Autowired\n  private NotifyRecordDao notifyRecordDao;\n\n  @Override\n  public NotifyRecordDO get(Long id) {\n    return notifyRecordDao.get(id);\n  }\n\n  @Override\n  public List<NotifyRecordDO> list(Map<String, Object> map) {\n    return notifyRecordDao.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return notifyRecordDao.count(map);\n  }\n\n  @Override\n  public int save(NotifyRecordDO notifyRecord) {\n    return notifyRecordDao.save(notifyRecord);\n  }\n\n  @Override\n  public int update(NotifyRecordDO notifyRecord) {\n    return notifyRecordDao.update(notifyRecord);\n  }\n\n  @Override\n  public int remove(Long id) {\n    return notifyRecordDao.remove(id);\n  }\n\n  @Override\n  public int batchRemove(Long[] ids) {\n    return notifyRecordDao.batchRemove(ids);\n  }\n\n  @Override\n  public int changeRead(NotifyRecordDO notifyRecord) {\n    return notifyRecordDao.changeRead(notifyRecord);\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/oa/service/impl/NotifyServiceImpl.java",
    "content": "package me.zbl.oa.service.impl;\n\nimport me.zbl.common.service.DictService;\nimport me.zbl.common.utils.DateUtils;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.oa.dao.NotifyDao;\nimport me.zbl.oa.dao.NotifyRecordDao;\nimport me.zbl.oa.domain.NotifyDO;\nimport me.zbl.oa.domain.NotifyDTO;\nimport me.zbl.oa.domain.NotifyRecordDO;\nimport me.zbl.oa.service.NotifyService;\nimport me.zbl.system.dao.UserDao;\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.service.SessionService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.messaging.simp.SimpMessagingTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.LinkedBlockingDeque;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n@Service\npublic class NotifyServiceImpl implements NotifyService {\n\n  @Autowired\n  private NotifyDao notifyDao;\n  @Autowired\n  private NotifyRecordDao recordDao;\n  @Autowired\n  private UserDao userDao;\n  @Autowired\n  private DictService dictService;\n  @Autowired\n  private SessionService sessionService;\n  @Autowired\n  private SimpMessagingTemplate template;\n\n  @Override\n  public NotifyDO get(Long id) {\n    NotifyDO rDO = notifyDao.get(id);\n    rDO.setType(dictService.getName(\"oa_notify_type\", rDO.getType()));\n    return rDO;\n  }\n\n  @Override\n  public List<NotifyDO> list(Map<String, Object> map) {\n    List<NotifyDO> notifys = notifyDao.list(map);\n    for (NotifyDO notifyDO : notifys) {\n      notifyDO.setType(dictService.getName(\"oa_notify_type\", notifyDO.getType()));\n    }\n    return notifys;\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return notifyDao.count(map);\n  }\n\n  @Transactional(rollbackFor = Exception.class)\n  @Override\n  public int save(NotifyDO notify) {\n    notify.setUpdateDate(new Date());\n    int r = notifyDao.save(notify);\n    // 保存到接受者列表中\n    Long[] userIds = notify.getUserIds();\n    Long notifyId = notify.getId();\n    List<NotifyRecordDO> records = new ArrayList<>();\n    for (Long userId : userIds) {\n      NotifyRecordDO record = new NotifyRecordDO();\n      record.setNotifyId(notifyId);\n      record.setUserId(userId);\n      record.setIsRead(0);\n      records.add(record);\n    }\n    recordDao.batchSave(records);\n    //给在线用户发送通知\n    ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());\n    executor.execute(new Runnable() {\n      @Override\n      public void run() {\n        for (UserDO userDO : sessionService.listOnlineUser()) {\n          for (Long userId : userIds) {\n            if (userId.equals(userDO.getUserId())) {\n              template.convertAndSendToUser(userDO.toString(), \"/queue/notifications\", \"新消息：\" + notify.getTitle());\n            }\n          }\n        }\n      }\n    });\n    executor.shutdown();\n    return r;\n  }\n\n  @Override\n  public int update(NotifyDO notify) {\n    return notifyDao.update(notify);\n  }\n\n  @Transactional\n  @Override\n  public int remove(Long id) {\n    recordDao.removeByNotifbyId(id);\n    return notifyDao.remove(id);\n  }\n\n  @Transactional\n  @Override\n  public int batchRemove(Long[] ids) {\n    recordDao.batchRemoveByNotifbyId(ids);\n    return notifyDao.batchRemove(ids);\n  }\n\n\n  @Override\n  public PageWrapper selfList(Map<String, Object> map) {\n    List<NotifyDTO> rows = notifyDao.listDTO(map);\n    for (NotifyDTO notifyDTO : rows) {\n      notifyDTO.setBefore(DateUtils.getTimeBefore(notifyDTO.getUpdateDate()));\n      notifyDTO.setSender(userDao.get(notifyDTO.getCreateBy()).getName());\n    }\n    PageWrapper page = new PageWrapper(rows, notifyDao.countDTO(map));\n    return page;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/config/BDSessionListener.java",
    "content": "package me.zbl.system.config;\n\nimport org.apache.shiro.session.Session;\nimport org.apache.shiro.session.SessionListener;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class BDSessionListener implements SessionListener {\n\n  private final AtomicInteger sessionCount = new AtomicInteger(0);\n\n  @Override\n  public void onStart(Session session) {\n    sessionCount.incrementAndGet();\n  }\n\n  @Override\n  public void onStop(Session session) {\n    sessionCount.decrementAndGet();\n  }\n\n  @Override\n  public void onExpiration(Session session) {\n    sessionCount.decrementAndGet();\n\n  }\n\n  public int getSessionCount() {\n    return sessionCount.get();\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/config/ShiroConfig.java",
    "content": "package me.zbl.system.config;\n\nimport at.pollux.thymeleaf.shiro.dialect.ShiroDialect;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.redis.shiro.RedisCacheManager;\nimport me.zbl.common.redis.shiro.RedisManager;\nimport me.zbl.common.redis.shiro.RedisSessionDAO;\nimport me.zbl.system.shiro.UserRealm;\nimport org.apache.shiro.cache.ehcache.EhCacheManager;\nimport org.apache.shiro.mgt.SecurityManager;\nimport org.apache.shiro.session.SessionListener;\nimport org.apache.shiro.session.mgt.eis.MemorySessionDAO;\nimport org.apache.shiro.session.mgt.eis.SessionDAO;\nimport org.apache.shiro.spring.LifecycleBeanPostProcessor;\nimport org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;\nimport org.apache.shiro.spring.web.ShiroFilterFactoryBean;\nimport org.apache.shiro.web.mgt.DefaultWebSecurityManager;\nimport org.apache.shiro.web.session.mgt.DefaultWebSessionManager;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedHashMap;\n\n/**\n * @author 郑保乐\n */\n@Configuration\npublic class ShiroConfig {\n\n  @Value(\"${spring.redis.host}\")\n  private String host;\n  @Value(\"${spring.redis.password}\")\n  private String password;\n  @Value(\"${spring.redis.port}\")\n  private int port;\n  @Value(\"${spring.redis.timeout}\")\n  private int timeout;\n\n  @Value(\"${cacheType}\")\n  private String cacheType;\n\n  @Value(\"${server.session-timeout}\")\n  private int tomcatTimeout;\n\n  @Bean\n  public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {\n    return new LifecycleBeanPostProcessor();\n  }\n\n  /**\n   * ShiroDialect，为了在thymeleaf里使用shiro的标签的bean\n   *\n   * @return\n   */\n  @Bean\n  public ShiroDialect shiroDialect() {\n    return new ShiroDialect();\n  }\n\n  @Bean\n  ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {\n    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();\n    shiroFilterFactoryBean.setSecurityManager(securityManager);\n    shiroFilterFactoryBean.setLoginUrl(\"/login\");\n    shiroFilterFactoryBean.setSuccessUrl(\"/index\");\n    shiroFilterFactoryBean.setUnauthorizedUrl(\"/403\");\n    LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();\n    filterChainDefinitionMap.put(\"/favicon.ico\", \"anon\");\n    filterChainDefinitionMap.put(\"/css/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/js/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/fonts/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/img/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/docs/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/druid/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/upload/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/files/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/logout\", \"logout\");\n    filterChainDefinitionMap.put(\"/\", \"anon\");\n    filterChainDefinitionMap.put(\"/blog\", \"anon\");\n    filterChainDefinitionMap.put(\"/blog/open/**\", \"anon\");\n    filterChainDefinitionMap.put(\"/**\", \"authc\");\n    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);\n    return shiroFilterFactoryBean;\n  }\n\n\n  @Bean\n  public SecurityManager securityManager() {\n    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();\n    //设置realm.\n    securityManager.setRealm(userRealm());\n    // 自定义缓存实现 使用redis\n    if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {\n      securityManager.setCacheManager(cacheManager());\n    } else {\n      securityManager.setCacheManager(ehCacheManager());\n    }\n    securityManager.setSessionManager(sessionManager());\n    return securityManager;\n  }\n\n  @Bean\n  UserRealm userRealm() {\n    UserRealm userRealm = new UserRealm();\n    return userRealm;\n  }\n\n  /**\n   * 开启shiro aop注解支持.\n   * 使用代理方式;所以需要开启代码支持;\n   *\n   * @param securityManager\n   *\n   * @return\n   */\n  @Bean\n  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {\n    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();\n    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);\n    return authorizationAttributeSourceAdvisor;\n  }\n\n  /**\n   * 配置shiro redisManager\n   *\n   * @return\n   */\n  @Bean\n  public RedisManager redisManager() {\n    RedisManager redisManager = new RedisManager();\n    redisManager.setHost(host);\n    redisManager.setPort(port);\n    redisManager.setExpire(1800);// 配置缓存过期时间\n    //redisManager.setTimeout(1800);\n    redisManager.setPassword(password);\n    return redisManager;\n  }\n\n  /**\n   * cacheManager 缓存 redis实现\n   * 使用的是shiro-redis开源插件\n   *\n   * @return\n   */\n  public RedisCacheManager cacheManager() {\n    RedisCacheManager redisCacheManager = new RedisCacheManager();\n    redisCacheManager.setRedisManager(redisManager());\n    return redisCacheManager;\n  }\n\n\n  /**\n   * RedisSessionDAO shiro sessionDao层的实现 通过redis\n   * 使用的是shiro-redis开源插件\n   */\n  @Bean\n  public RedisSessionDAO redisSessionDAO() {\n    RedisSessionDAO redisSessionDAO = new RedisSessionDAO();\n    redisSessionDAO.setRedisManager(redisManager());\n    return redisSessionDAO;\n  }\n\n  @Bean\n  public SessionDAO sessionDAO() {\n    if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {\n      return redisSessionDAO();\n    } else {\n      return new MemorySessionDAO();\n    }\n  }\n\n  /**\n   * shiro session的管理\n   */\n  @Bean\n  public DefaultWebSessionManager sessionManager() {\n    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();\n    sessionManager.setGlobalSessionTimeout(tomcatTimeout * 1000);\n    sessionManager.setSessionDAO(sessionDAO());\n    Collection<SessionListener> listeners = new ArrayList<SessionListener>();\n    listeners.add(new BDSessionListener());\n    sessionManager.setSessionListeners(listeners);\n    return sessionManager;\n  }\n\n  @Bean\n  public EhCacheManager ehCacheManager() {\n    EhCacheManager em = new EhCacheManager();\n    em.setCacheManagerConfigFile(\"classpath:config/ehcache.xml\");\n    return em;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/config/Swagger2Config.java",
    "content": "package me.zbl.system.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 * ${DESCRIPTION}\n *\n * @author 郑保乐\n * @create 2017-01-02 23:53\n */\n@EnableSwagger2\n@Configuration\npublic class Swagger2Config {\n\n  @Bean\n  public Docket createRestApi() {\n    return new Docket(DocumentationType.SWAGGER_2)\n            .apiInfo(apiInfo())\n            .select()\n            //为当前包路径\n            .apis(RequestHandlerSelectors.any())\n            .paths(PathSelectors.any())\n            .build();\n  }\n\n  //构建 api文档的详细信息函数\n  private ApiInfo apiInfo() {\n    return new ApiInfoBuilder()\n            //页面标题\n            .title(\"功能测试\")\n            //创建人\n            .contact(new Contact(\"Edison\", \"xxx@qq.com\", \"xxx@qq.com\"))\n            //版本号\n            .version(\"1.0\")\n            //描述\n            .description(\"API 描述\")\n            .build();\n  }\n}"
  },
  {
    "path": "src/main/java/me/zbl/system/config/XssConfig.java",
    "content": "package me.zbl.system.config;\n\nimport com.google.common.collect.Maps;\nimport me.zbl.system.filter.XssFilter;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport java.util.Map;\n\n@Configuration\npublic class XssConfig {\n\n  /**\n   * xss过滤拦截器\n   */\n  @Bean\n  public FilterRegistrationBean xssFilterRegistrationBean() {\n    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();\n    filterRegistrationBean.setFilter(new XssFilter());\n    filterRegistrationBean.setOrder(1);\n    filterRegistrationBean.setEnabled(false);\n    filterRegistrationBean.addUrlPatterns(\"/*\");\n    Map<String, String> initParameters = Maps.newHashMap();\n    initParameters.put(\"excludes\", \"/favicon.ico,/img/*,/js/*,/css/*\");\n    initParameters.put(\"isIncludeRichText\", \"true\");\n    filterRegistrationBean.setInitParameters(initParameters);\n    return filterRegistrationBean;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/DeptController.java",
    "content": "package me.zbl.system.controller;\n\nimport io.swagger.annotations.ApiOperation;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.utils.R;\nimport me.zbl.system.domain.DeptDO;\nimport me.zbl.system.service.DeptService;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 部门管理\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-27 14:40:36\n */\n\n@Controller\n@RequestMapping(\"/system/sysDept\")\npublic class DeptController extends BaseController {\n\n  private String prefix = \"system/dept\";\n  @Autowired\n  private DeptService sysDeptService;\n\n  @GetMapping()\n  @RequiresPermissions(\"system:sysDept:sysDept\")\n  String dept() {\n    return prefix + \"/dept\";\n  }\n\n  @ApiOperation(value = \"获取部门列表\", notes = \"\")\n  @ResponseBody\n  @GetMapping(\"/list\")\n  @RequiresPermissions(\"system:sysDept:sysDept\")\n  public List<DeptDO> list() {\n    Map<String, Object> query = new HashMap<>(16);\n    List<DeptDO> sysDeptList = sysDeptService.list(query);\n    return sysDeptList;\n  }\n\n  @GetMapping(\"/add/{pId}\")\n  @RequiresPermissions(\"system:sysDept:add\")\n  String add(@PathVariable(\"pId\") Long pId, Model model) {\n    model.addAttribute(\"pId\", pId);\n    if (pId == 0) {\n      model.addAttribute(\"pName\", \"总部门\");\n    } else {\n      model.addAttribute(\"pName\", sysDeptService.get(pId).getName());\n    }\n    return prefix + \"/add\";\n  }\n\n  @GetMapping(\"/edit/{deptId}\")\n  @RequiresPermissions(\"system:sysDept:edit\")\n  String edit(@PathVariable(\"deptId\") Long deptId, Model model) {\n    DeptDO sysDept = sysDeptService.get(deptId);\n    model.addAttribute(\"sysDept\", sysDept);\n    if (Constant.DEPT_ROOT_ID.equals(sysDept.getParentId())) {\n      model.addAttribute(\"parentDeptName\", \"无\");\n    } else {\n      DeptDO parDept = sysDeptService.get(sysDept.getParentId());\n      model.addAttribute(\"parentDeptName\", parDept.getName());\n    }\n    return prefix + \"/edit\";\n  }\n\n  /**\n   * 保存\n   */\n  @ResponseBody\n  @PostMapping(\"/save\")\n  @RequiresPermissions(\"system:sysDept:add\")\n  public R save(DeptDO sysDept) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (sysDeptService.save(sysDept) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 修改\n   */\n  @ResponseBody\n  @RequestMapping(\"/update\")\n  @RequiresPermissions(\"system:sysDept:edit\")\n  public R update(DeptDO sysDept) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (sysDeptService.update(sysDept) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  @RequiresPermissions(\"system:sysDept:remove\")\n  public R remove(Long deptId) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    Map<String, Object> map = new HashMap<String, Object>();\n    map.put(\"parentId\", deptId);\n    if (sysDeptService.count(map) > 0) {\n      return R.error(1, \"包含下级部门,不允许修改\");\n    }\n    if (sysDeptService.checkDeptHasUser(deptId)) {\n      if (sysDeptService.remove(deptId) > 0) {\n        return R.ok();\n      }\n    } else {\n      return R.error(1, \"部门包含用户,不允许修改\");\n    }\n    return R.error();\n  }\n\n  /**\n   * 删除\n   */\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  @RequiresPermissions(\"system:sysDept:batchRemove\")\n  public R remove(@RequestParam(\"ids[]\") Long[] deptIds) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    sysDeptService.batchRemove(deptIds);\n    return R.ok();\n  }\n\n  @GetMapping(\"/tree\")\n  @ResponseBody\n  public Tree<DeptDO> tree() {\n    Tree<DeptDO> tree = new Tree<DeptDO>();\n    tree = sysDeptService.getTree();\n    return tree;\n  }\n\n  @GetMapping(\"/treeView\")\n  String treeView() {\n    return prefix + \"/deptTree\";\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/LoginController.java",
    "content": "package me.zbl.system.controller;\n\nimport me.zbl.common.annotation.Log;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.domain.FileDO;\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.service.FileService;\nimport me.zbl.common.utils.MD5Utils;\nimport me.zbl.common.utils.R;\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.system.domain.MenuDO;\nimport me.zbl.system.service.MenuService;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.AuthenticationException;\nimport org.apache.shiro.authc.UsernamePasswordToken;\nimport org.apache.shiro.subject.Subject;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\n\n@Controller\npublic class LoginController extends BaseController {\n\n  private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  @Autowired\n  MenuService menuService;\n  @Autowired\n  FileService fileService;\n\n  @GetMapping({\"/\", \"\"})\n  String welcome(Model model) {\n\n    return \"redirect:/login\";\n  }\n\n  @Log(\"请求访问主页\")\n  @GetMapping({\"/index\"})\n  String index(Model model) {\n    List<Tree<MenuDO>> menus = menuService.listMenuTree(getUserId());\n    model.addAttribute(\"menus\", menus);\n    model.addAttribute(\"name\", getUser().getName());\n    FileDO fileDO = fileService.get(getUser().getPicId());\n    if (fileDO != null && fileDO.getUrl() != null) {\n      if (fileService.isExist(fileDO.getUrl())) {\n        model.addAttribute(\"picUrl\", fileDO.getUrl());\n      } else {\n        model.addAttribute(\"picUrl\", \"/img/photo_s.jpg\");\n      }\n    } else {\n      model.addAttribute(\"picUrl\", \"/img/photo_s.jpg\");\n    }\n    model.addAttribute(\"username\", getUser().getUsername());\n    return \"index_v1\";\n  }\n\n  @GetMapping(\"/login\")\n  String login() {\n    return \"login\";\n  }\n\n  @Log(\"登录\")\n  @PostMapping(\"/login\")\n  @ResponseBody\n  R ajaxLogin(String username, String password) {\n\n    password = MD5Utils.encrypt(username, password);\n    UsernamePasswordToken token = new UsernamePasswordToken(username, password);\n    Subject subject = SecurityUtils.getSubject();\n    try {\n      subject.login(token);\n      return R.ok();\n    } catch (AuthenticationException e) {\n      return R.error(\"用户或密码错误\");\n    }\n  }\n\n  @GetMapping(\"/logout\")\n  String logout() {\n    ShiroUtils.logout();\n    return \"redirect:/login\";\n  }\n\n  @GetMapping(\"/main\")\n  String main() {\n    return \"main\";\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/MenuController.java",
    "content": "package me.zbl.system.controller;\n\nimport me.zbl.common.annotation.Log;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.utils.R;\nimport me.zbl.system.domain.MenuDO;\nimport me.zbl.system.service.MenuService;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n */\n@RequestMapping(\"/sys/menu\")\n@Controller\npublic class MenuController extends BaseController {\n\n  String prefix = \"system/menu\";\n  @Autowired\n  MenuService menuService;\n\n  @RequiresPermissions(\"sys:menu:menu\")\n  @GetMapping()\n  String menu(Model model) {\n    return prefix + \"/menu\";\n  }\n\n  @RequiresPermissions(\"sys:menu:menu\")\n  @RequestMapping(\"/list\")\n  @ResponseBody\n  List<MenuDO> list(@RequestParam Map<String, Object> params) {\n    List<MenuDO> menus = menuService.list(params);\n    return menus;\n  }\n\n  @Log(\"添加菜单\")\n  @RequiresPermissions(\"sys:menu:add\")\n  @GetMapping(\"/add/{pId}\")\n  String add(Model model, @PathVariable(\"pId\") Long pId) {\n    model.addAttribute(\"pId\", pId);\n    if (pId == 0) {\n      model.addAttribute(\"pName\", \"根目录\");\n    } else {\n      model.addAttribute(\"pName\", menuService.get(pId).getName());\n    }\n    return prefix + \"/add\";\n  }\n\n  @Log(\"编辑菜单\")\n  @RequiresPermissions(\"sys:menu:edit\")\n  @GetMapping(\"/edit/{id}\")\n  String edit(Model model, @PathVariable(\"id\") Long id) {\n    MenuDO mdo = menuService.get(id);\n    Long pId = mdo.getParentId();\n    model.addAttribute(\"pId\", pId);\n    if (pId == 0) {\n      model.addAttribute(\"pName\", \"根目录\");\n    } else {\n      model.addAttribute(\"pName\", menuService.get(pId).getName());\n    }\n    model.addAttribute(\"menu\", mdo);\n    return prefix + \"/edit\";\n  }\n\n  @Log(\"保存菜单\")\n  @RequiresPermissions(\"sys:menu:add\")\n  @PostMapping(\"/save\")\n  @ResponseBody\n  R save(MenuDO menu) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (menuService.save(menu) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"保存失败\");\n    }\n  }\n\n  @Log(\"更新菜单\")\n  @RequiresPermissions(\"sys:menu:edit\")\n  @PostMapping(\"/update\")\n  @ResponseBody\n  R update(MenuDO menu) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (menuService.update(menu) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"更新失败\");\n    }\n  }\n\n  @Log(\"删除菜单\")\n  @RequiresPermissions(\"sys:menu:remove\")\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (menuService.remove(id) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"删除失败\");\n    }\n  }\n\n  @GetMapping(\"/tree\")\n  @ResponseBody\n  Tree<MenuDO> tree() {\n    Tree<MenuDO> tree = new Tree<MenuDO>();\n    tree = menuService.getTree();\n    return tree;\n  }\n\n  @GetMapping(\"/tree/{roleId}\")\n  @ResponseBody\n  Tree<MenuDO> tree(@PathVariable(\"roleId\") Long roleId) {\n    Tree<MenuDO> tree = new Tree<MenuDO>();\n    tree = menuService.getTree(roleId);\n    return tree;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/RoleController.java",
    "content": "package me.zbl.system.controller;\n\nimport me.zbl.common.annotation.Log;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.utils.R;\nimport me.zbl.system.domain.RoleDO;\nimport me.zbl.system.service.RoleService;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n@RequestMapping(\"/sys/role\")\n@Controller\npublic class RoleController extends BaseController {\n\n  String prefix = \"system/role\";\n  @Autowired\n  RoleService roleService;\n\n  @RequiresPermissions(\"sys:role:role\")\n  @GetMapping()\n  String role() {\n    return prefix + \"/role\";\n  }\n\n  @RequiresPermissions(\"sys:role:role\")\n  @GetMapping(\"/list\")\n  @ResponseBody()\n  List<RoleDO> list() {\n    List<RoleDO> roles = roleService.list();\n    return roles;\n  }\n\n  @Log(\"添加角色\")\n  @RequiresPermissions(\"sys:role:add\")\n  @GetMapping(\"/add\")\n  String add() {\n    return prefix + \"/add\";\n  }\n\n  @Log(\"编辑角色\")\n  @RequiresPermissions(\"sys:role:edit\")\n  @GetMapping(\"/edit/{id}\")\n  String edit(@PathVariable(\"id\") Long id, Model model) {\n    RoleDO roleDO = roleService.get(id);\n    model.addAttribute(\"role\", roleDO);\n    return prefix + \"/edit\";\n  }\n\n  @Log(\"保存角色\")\n  @RequiresPermissions(\"sys:role:add\")\n  @PostMapping(\"/save\")\n  @ResponseBody()\n  R save(RoleDO role) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (roleService.save(role) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"保存失败\");\n    }\n  }\n\n  @Log(\"更新角色\")\n  @RequiresPermissions(\"sys:role:edit\")\n  @PostMapping(\"/update\")\n  @ResponseBody()\n  R update(RoleDO role) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (roleService.update(role) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"保存失败\");\n    }\n  }\n\n  @Log(\"删除角色\")\n  @RequiresPermissions(\"sys:role:remove\")\n  @PostMapping(\"/remove\")\n  @ResponseBody()\n  R save(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (roleService.remove(id) > 0) {\n      return R.ok();\n    } else {\n      return R.error(1, \"删除失败\");\n    }\n  }\n\n  @RequiresPermissions(\"sys:role:batchRemove\")\n  @Log(\"批量删除角色\")\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  R batchRemove(@RequestParam(\"ids[]\") Long[] ids) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    int r = roleService.batchremove(ids);\n    if (r > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/SessionController.java",
    "content": "package me.zbl.system.controller;\n\nimport me.zbl.common.utils.R;\nimport me.zbl.system.domain.UserOnline;\nimport me.zbl.system.service.SessionService;\nimport org.apache.shiro.session.Session;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\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.ResponseBody;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\n\nimport java.util.Collection;\nimport java.util.List;\n\n@RequestMapping(\"/sys/online\")\n@Controller\npublic class SessionController {\n\n  @Autowired\n  SessionService sessionService;\n\n  @GetMapping()\n  public String online() {\n    return \"system/online/online\";\n  }\n\n  @ResponseBody\n  @RequestMapping(\"/list\")\n  public List<UserOnline> list() {\n    return sessionService.list();\n  }\n\n  @ResponseBody\n  @RequestMapping(\"/forceLogout/{sessionId}\")\n  public R forceLogout(@PathVariable(\"sessionId\") String sessionId, RedirectAttributes redirectAttributes) {\n    try {\n      sessionService.forceLogout(sessionId);\n      return R.ok();\n    } catch (Exception e) {\n      e.printStackTrace();\n      return R.error();\n    }\n\n  }\n\n  @ResponseBody\n  @RequestMapping(\"/sessionList\")\n  public Collection<Session> sessionList() {\n    return sessionService.sessionList();\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/controller/UserController.java",
    "content": "package me.zbl.system.controller;\n\nimport me.zbl.common.annotation.Log;\nimport me.zbl.common.config.Constant;\nimport me.zbl.common.controller.BaseController;\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.service.DictService;\nimport me.zbl.common.utils.MD5Utils;\nimport me.zbl.common.utils.PageWrapper;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\nimport me.zbl.system.domain.DeptDO;\nimport me.zbl.system.domain.RoleDO;\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.service.RoleService;\nimport me.zbl.system.service.UserService;\nimport me.zbl.system.vo.UserVO;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@RequestMapping(\"/sys/user\")\n@Controller\npublic class UserController extends BaseController {\n\n  @Autowired\n  UserService userService;\n  @Autowired\n  RoleService roleService;\n  @Autowired\n  DictService dictService;\n  private String prefix = \"system/user\";\n\n  @RequiresPermissions(\"sys:user:user\")\n  @GetMapping(\"\")\n  String user(Model model) {\n    return prefix + \"/user\";\n  }\n\n  @GetMapping(\"/list\")\n  @ResponseBody\n  PageWrapper list(@RequestParam Map<String, Object> params) {\n    // 查询列表数据\n    Query query = new Query(params);\n    List<UserDO> sysUserList = userService.list(query);\n    int total = userService.count(query);\n    PageWrapper pageUtil = new PageWrapper(sysUserList, total);\n    return pageUtil;\n  }\n\n  @RequiresPermissions(\"sys:user:add\")\n  @Log(\"添加用户\")\n  @GetMapping(\"/add\")\n  String add(Model model) {\n    List<RoleDO> roles = roleService.list();\n    model.addAttribute(\"roles\", roles);\n    return prefix + \"/add\";\n  }\n\n  @RequiresPermissions(\"sys:user:edit\")\n  @Log(\"编辑用户\")\n  @GetMapping(\"/edit/{id}\")\n  String edit(Model model, @PathVariable(\"id\") Long id) {\n    UserDO userDO = userService.get(id);\n    model.addAttribute(\"user\", userDO);\n    List<RoleDO> roles = roleService.list(id);\n    model.addAttribute(\"roles\", roles);\n    return prefix + \"/edit\";\n  }\n\n  @RequiresPermissions(\"sys:user:add\")\n  @Log(\"保存用户\")\n  @PostMapping(\"/save\")\n  @ResponseBody\n  R save(UserDO user) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    user.setPassword(MD5Utils.encrypt(user.getUsername(), user.getPassword()));\n    if (userService.save(user) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  @RequiresPermissions(\"sys:user:edit\")\n  @Log(\"更新用户\")\n  @PostMapping(\"/update\")\n  @ResponseBody\n  R update(UserDO user) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (userService.update(user) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n\n  @RequiresPermissions(\"sys:user:edit\")\n  @Log(\"更新用户\")\n  @PostMapping(\"/updatePeronal\")\n  @ResponseBody\n  R updatePeronal(UserDO user) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (userService.updatePersonal(user) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n\n  @RequiresPermissions(\"sys:user:remove\")\n  @Log(\"删除用户\")\n  @PostMapping(\"/remove\")\n  @ResponseBody\n  R remove(Long id) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    if (userService.remove(id) > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  @RequiresPermissions(\"sys:user:batchRemove\")\n  @Log(\"批量删除用户\")\n  @PostMapping(\"/batchRemove\")\n  @ResponseBody\n  R batchRemove(@RequestParam(\"ids[]\") Long[] userIds) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    int r = userService.batchremove(userIds);\n    if (r > 0) {\n      return R.ok();\n    }\n    return R.error();\n  }\n\n  @PostMapping(\"/exit\")\n  @ResponseBody\n  boolean exit(@RequestParam Map<String, Object> params) {\n    // 存在，不通过，false\n    return !userService.exit(params);\n  }\n\n  @RequiresPermissions(\"sys:user:resetPwd\")\n  @Log(\"请求更改用户密码\")\n  @GetMapping(\"/resetPwd/{id}\")\n  String resetPwd(@PathVariable(\"id\") Long userId, Model model) {\n\n    UserDO userDO = new UserDO();\n    userDO.setUserId(userId);\n    model.addAttribute(\"user\", userDO);\n    return prefix + \"/reset_pwd\";\n  }\n\n  @Log(\"提交更改用户密码\")\n  @PostMapping(\"/resetPwd\")\n  @ResponseBody\n  R resetPwd(UserVO userVO) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    try {\n      userService.resetPwd(userVO, getUser());\n      return R.ok();\n    } catch (Exception e) {\n      return R.error(1, e.getMessage());\n    }\n\n  }\n\n  @RequiresPermissions(\"sys:user:resetPwd\")\n  @Log(\"admin提交更改用户密码\")\n  @PostMapping(\"/adminResetPwd\")\n  @ResponseBody\n  R adminResetPwd(UserVO userVO) {\n    if (Constant.DEMO_ACCOUNT.equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    try {\n      userService.adminResetPwd(userVO);\n      return R.ok();\n    } catch (Exception e) {\n      return R.error(1, e.getMessage());\n    }\n\n  }\n\n  @GetMapping(\"/tree\")\n  @ResponseBody\n  public Tree<DeptDO> tree() {\n    Tree<DeptDO> tree = new Tree<DeptDO>();\n    tree = userService.getTree();\n    return tree;\n  }\n\n  @GetMapping(\"/treeView\")\n  String treeView() {\n    return prefix + \"/userTree\";\n  }\n\n  @GetMapping(\"/personal\")\n  String personal(Model model) {\n    UserDO userDO = userService.get(getUserId());\n    model.addAttribute(\"user\", userDO);\n    model.addAttribute(\"hobbyList\", dictService.getHobbyList(userDO));\n    model.addAttribute(\"sexList\", dictService.getSexList());\n    return prefix + \"/personal\";\n  }\n\n  @ResponseBody\n  @PostMapping(\"/uploadImg\")\n  R uploadImg(@RequestParam(\"avatar_file\") MultipartFile file, String avatar_data, HttpServletRequest request) {\n    if (\"test\".equals(getUsername())) {\n      return R.error(1, \"演示系统不允许修改,完整体验请部署程序\");\n    }\n    Map<String, Object> result = new HashMap<>();\n    try {\n      result = userService.updatePersonalImg(file, avatar_data, getUserId());\n    } catch (Exception e) {\n      return R.error(\"更新图像失败！\");\n    }\n    if (result != null && result.size() > 0) {\n      return R.ok(result);\n    } else {\n      return R.error(\"更新图像失败！\");\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/DeptDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.DeptDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 部门管理\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 15:35:39\n */\n@Mapper\npublic interface DeptDao {\n\n  DeptDO get(Long deptId);\n\n  List<DeptDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(DeptDO dept);\n\n  int update(DeptDO dept);\n\n  int remove(Long deptId);\n\n  int batchRemove(Long[] deptIds);\n\n  Long[] listParentDept();\n\n  int getDeptUserNumber(Long deptId);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/MenuDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.MenuDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 菜单管理\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 09:45:09\n */\n@Mapper\npublic interface MenuDao {\n\n  MenuDO get(Long menuId);\n\n  List<MenuDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(MenuDO menu);\n\n  int update(MenuDO menu);\n\n  int remove(Long menuId);\n\n  int batchRemove(Long[] menuIds);\n\n  List<MenuDO> listMenuByUserId(Long id);\n\n  List<String> listUserPerms(Long id);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/RoleDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.RoleDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 角色\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-02 20:24:47\n */\n@Mapper\npublic interface RoleDao {\n\n  RoleDO get(Long roleId);\n\n  List<RoleDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(RoleDO role);\n\n  int update(RoleDO role);\n\n  int remove(Long roleId);\n\n  int batchRemove(Long[] roleIds);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/RoleMenuDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.RoleMenuDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 角色与菜单对应关系\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 11:08:59\n */\n@Mapper\npublic interface RoleMenuDao {\n\n  RoleMenuDO get(Long id);\n\n  List<RoleMenuDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(RoleMenuDO roleMenu);\n\n  int update(RoleMenuDO roleMenu);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  List<Long> listMenuIdByRoleId(Long roleId);\n\n  int removeByRoleId(Long roleId);\n\n  int removeByMenuId(Long menuId);\n\n  int batchSave(List<RoleMenuDO> list);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/UserDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.UserDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 09:45:11\n */\n@Mapper\npublic interface UserDao {\n\n  UserDO get(Long userId);\n\n  List<UserDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(UserDO user);\n\n  int update(UserDO user);\n\n  int remove(Long userId);\n\n  int batchRemove(Long[] userIds);\n\n  Long[] listAllDept();\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/dao/UserRoleDao.java",
    "content": "package me.zbl.system.dao;\n\nimport me.zbl.system.domain.UserRoleDO;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 用户与角色对应关系\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-10-03 11:08:59\n */\n@Mapper\npublic interface UserRoleDao {\n\n  UserRoleDO get(Long id);\n\n  List<UserRoleDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(UserRoleDO userRole);\n\n  int update(UserRoleDO userRole);\n\n  int remove(Long id);\n\n  int batchRemove(Long[] ids);\n\n  List<Long> listRoleId(Long userId);\n\n  int removeByUserId(Long userId);\n\n  int removeByRoleId(Long roleId);\n\n  int batchSave(List<UserRoleDO> list);\n\n  int batchRemoveByUserId(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/DeptDO.java",
    "content": "package me.zbl.system.domain;\n\nimport java.io.Serializable;\n\n\n/**\n * 部门管理\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-27 14:28:36\n */\npublic class DeptDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  //\n  private Long deptId;\n  //上级部门ID，一级部门为0\n  private Long parentId;\n  //部门名称\n  private String name;\n  //排序\n  private Integer orderNum;\n  //是否删除  -1：已删除  0：正常\n  private Integer delFlag;\n\n  /**\n   * 获取：\n   */\n  public Long getDeptId() {\n    return deptId;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setDeptId(Long deptId) {\n    this.deptId = deptId;\n  }\n\n  /**\n   * 获取：上级部门ID，一级部门为0\n   */\n  public Long getParentId() {\n    return parentId;\n  }\n\n  /**\n   * 设置：上级部门ID，一级部门为0\n   */\n  public void setParentId(Long parentId) {\n    this.parentId = parentId;\n  }\n\n  /**\n   * 获取：部门名称\n   */\n  public String getName() {\n    return name;\n  }\n\n  /**\n   * 设置：部门名称\n   */\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  /**\n   * 获取：排序\n   */\n  public Integer getOrderNum() {\n    return orderNum;\n  }\n\n  /**\n   * 设置：排序\n   */\n  public void setOrderNum(Integer orderNum) {\n    this.orderNum = orderNum;\n  }\n\n  /**\n   * 获取：是否删除  -1：已删除  0：正常\n   */\n  public Integer getDelFlag() {\n    return delFlag;\n  }\n\n  /**\n   * 设置：是否删除  -1：已删除  0：正常\n   */\n  public void setDelFlag(Integer delFlag) {\n    this.delFlag = delFlag;\n  }\n\n  @Override\n  public String toString() {\n    return \"DeptDO{\" +\n            \"deptId=\" + deptId +\n            \", parentId=\" + parentId +\n            \", name='\" + name + '\\'' +\n            \", orderNum=\" + orderNum +\n            \", delFlag=\" + delFlag +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/MenuDO.java",
    "content": "package me.zbl.system.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\npublic class MenuDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n  //\n  private Long menuId;\n  // 父菜单ID，一级菜单为0\n  private Long parentId;\n  // 菜单名称\n  private String name;\n  // 菜单URL\n  private String url;\n  // 授权(多个用逗号分隔，如：user:list,user:create)\n  private String perms;\n  // 类型 0：目录 1：菜单 2：按钮\n  private Integer type;\n  // 菜单图标\n  private String icon;\n  // 排序\n  private Integer orderNum;\n  // 创建时间\n  private Date gmtCreate;\n  // 修改时间\n  private Date gmtModified;\n\n  /**\n   * 获取：\n   */\n  public Long getMenuId() {\n    return menuId;\n  }\n\n  /**\n   * 设置：\n   */\n  public void setMenuId(Long menuId) {\n    this.menuId = menuId;\n  }\n\n  /**\n   * 获取：父菜单ID，一级菜单为0\n   */\n  public Long getParentId() {\n    return parentId;\n  }\n\n  /**\n   * 设置：父菜单ID，一级菜单为0\n   */\n  public void setParentId(Long parentId) {\n    this.parentId = parentId;\n  }\n\n  /**\n   * 获取：菜单名称\n   */\n  public String getName() {\n    return name;\n  }\n\n  /**\n   * 设置：菜单名称\n   */\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  /**\n   * 获取：菜单URL\n   */\n  public String getUrl() {\n    return url;\n  }\n\n  /**\n   * 设置：菜单URL\n   */\n  public void setUrl(String url) {\n    this.url = url;\n  }\n\n  /**\n   * 获取：授权(多个用逗号分隔，如：user:list,user:create)\n   */\n  public String getPerms() {\n    return perms;\n  }\n\n  /**\n   * 设置：授权(多个用逗号分隔，如：user:list,user:create)\n   */\n  public void setPerms(String perms) {\n    this.perms = perms;\n  }\n\n  /**\n   * 获取：类型 0：目录 1：菜单 2：按钮\n   */\n  public Integer getType() {\n    return type;\n  }\n\n  /**\n   * 设置：类型 0：目录 1：菜单 2：按钮\n   */\n  public void setType(Integer type) {\n    this.type = type;\n  }\n\n  /**\n   * 获取：菜单图标\n   */\n  public String getIcon() {\n    return icon;\n  }\n\n  /**\n   * 设置：菜单图标\n   */\n  public void setIcon(String icon) {\n    this.icon = icon;\n  }\n\n  /**\n   * 获取：排序\n   */\n  public Integer getOrderNum() {\n    return orderNum;\n  }\n\n  /**\n   * 设置：排序\n   */\n  public void setOrderNum(Integer orderNum) {\n    this.orderNum = orderNum;\n  }\n\n  /**\n   * 获取：创建时间\n   */\n  public Date getGmtCreate() {\n    return gmtCreate;\n  }\n\n  /**\n   * 设置：创建时间\n   */\n  public void setGmtCreate(Date gmtCreate) {\n    this.gmtCreate = gmtCreate;\n  }\n\n  /**\n   * 获取：修改时间\n   */\n  public Date getGmtModified() {\n    return gmtModified;\n  }\n\n  /**\n   * 设置：修改时间\n   */\n  public void setGmtModified(Date gmtModified) {\n    this.gmtModified = gmtModified;\n  }\n\n  @Override\n  public String toString() {\n    return \"MenuDO{\" +\n            \"menuId=\" + menuId +\n            \", parentId=\" + parentId +\n            \", name='\" + name + '\\'' +\n            \", url='\" + url + '\\'' +\n            \", perms='\" + perms + '\\'' +\n            \", type=\" + type +\n            \", icon='\" + icon + '\\'' +\n            \", orderNum=\" + orderNum +\n            \", gmtCreate=\" + gmtCreate +\n            \", gmtModified=\" + gmtModified +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/RoleDO.java",
    "content": "package me.zbl.system.domain;\n\nimport java.sql.Timestamp;\nimport java.util.List;\n\npublic class RoleDO {\n\n  private Long roleId;\n  private String roleName;\n  private String roleSign;\n  private String remark;\n  private Long userIdCreate;\n  private Timestamp gmtCreate;\n  private Timestamp gmtModified;\n  private List<Long> menuIds;\n\n  public Long getRoleId() {\n    return roleId;\n  }\n\n  public void setRoleId(Long roleId) {\n    this.roleId = roleId;\n  }\n\n  public String getRoleName() {\n    return roleName;\n  }\n\n  public void setRoleName(String roleName) {\n    this.roleName = roleName;\n  }\n\n  public String getRoleSign() {\n    return roleSign;\n  }\n\n  public void setRoleSign(String roleSign) {\n    this.roleSign = roleSign;\n  }\n\n  public String getRemark() {\n    return remark;\n  }\n\n  public void setRemark(String remark) {\n    this.remark = remark;\n  }\n\n  public Long getUserIdCreate() {\n    return userIdCreate;\n  }\n\n  public void setUserIdCreate(Long userIdCreate) {\n    this.userIdCreate = userIdCreate;\n  }\n\n  public Timestamp getGmtCreate() {\n    return gmtCreate;\n  }\n\n  public void setGmtCreate(Timestamp gmtCreate) {\n    this.gmtCreate = gmtCreate;\n  }\n\n  public Timestamp getGmtModified() {\n    return gmtModified;\n  }\n\n  public void setGmtModified(Timestamp gmtModified) {\n    this.gmtModified = gmtModified;\n  }\n\n  public List<Long> getMenuIds() {\n    return menuIds;\n  }\n\n  public void setMenuIds(List<Long> menuIds) {\n    this.menuIds = menuIds;\n  }\n\n  @Override\n  public String toString() {\n    return \"RoleDO{\" +\n            \"roleId=\" + roleId +\n            \", roleName='\" + roleName + '\\'' +\n            \", roleSign='\" + roleSign + '\\'' +\n            \", remark='\" + remark + '\\'' +\n            \", userIdCreate=\" + userIdCreate +\n            \", gmtCreate=\" + gmtCreate +\n            \", gmtModified=\" + gmtModified +\n            \", menuIds=\" + menuIds +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/RoleMenuDO.java",
    "content": "package me.zbl.system.domain;\n\npublic class RoleMenuDO {\n\n  private Long id;\n  private Long roleId;\n  private Long menuId;\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 getRoleId() {\n    return roleId;\n  }\n\n  public void setRoleId(Long roleId) {\n    this.roleId = roleId;\n  }\n\n  public Long getMenuId() {\n    return menuId;\n  }\n\n  public void setMenuId(Long menuId) {\n    this.menuId = menuId;\n  }\n\n  @Override\n  public String toString() {\n    return \"RoleMenuDO{\" +\n            \"id=\" + id +\n            \", roleId=\" + roleId +\n            \", menuId=\" + menuId +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/UserDO.java",
    "content": "package me.zbl.system.domain;\n\nimport org.springframework.format.annotation.DateTimeFormat;\n\nimport java.io.Serializable;\nimport java.util.Date;\nimport java.util.List;\n\npublic class UserDO implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n  //\n  private Long userId;\n  // 用户名\n  private String username;\n  // 用户真实姓名\n  private String name;\n  // 密码\n  private String password;\n  // 部门\n  private Long deptId;\n  private String deptName;\n  // 邮箱\n  private String email;\n  // 手机号\n  private String mobile;\n  // 状态 0:禁用，1:正常\n  private Integer status;\n  // 创建用户id\n  private Long userIdCreate;\n  // 创建时间\n  private Date gmtCreate;\n  // 修改时间\n  private Date gmtModified;\n  //角色\n  private List<Long> roleIds;\n  //性别\n  private Long sex;\n  //出身日期\n  @DateTimeFormat(pattern = \"yyyy-MM-dd\")\n  private Date birth;\n  //图片ID\n  private Long picId;\n  //现居住地\n  private String liveAddress;\n  //爱好\n  private String hobby;\n  //省份\n  private String province;\n  //所在城市\n  private String city;\n  //所在地区\n  private String district;\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 getUsername() {\n    return username;\n  }\n\n  public void setUsername(String username) {\n    this.username = username;\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 getPassword() {\n    return password;\n  }\n\n  public void setPassword(String password) {\n    this.password = password;\n  }\n\n  public Long getDeptId() {\n    return deptId;\n  }\n\n  public void setDeptId(Long deptId) {\n    this.deptId = deptId;\n  }\n\n  public String getDeptName() {\n    return deptName;\n  }\n\n  public void setDeptName(String deptName) {\n    this.deptName = deptName;\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 Integer getStatus() {\n    return status;\n  }\n\n  public void setStatus(Integer status) {\n    this.status = status;\n  }\n\n  public Long getUserIdCreate() {\n    return userIdCreate;\n  }\n\n  public void setUserIdCreate(Long userIdCreate) {\n    this.userIdCreate = userIdCreate;\n  }\n\n  public Date getGmtCreate() {\n    return gmtCreate;\n  }\n\n  public void setGmtCreate(Date gmtCreate) {\n    this.gmtCreate = gmtCreate;\n  }\n\n  public Date getGmtModified() {\n    return gmtModified;\n  }\n\n  public void setGmtModified(Date gmtModified) {\n    this.gmtModified = gmtModified;\n  }\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  public Long getSex() {\n    return sex;\n  }\n\n  public void setSex(Long sex) {\n    this.sex = sex;\n  }\n\n  public Date getBirth() {\n    return birth;\n  }\n\n  public void setBirth(Date birth) {\n    this.birth = birth;\n  }\n\n  public Long getPicId() {\n    return picId;\n  }\n\n  public void setPicId(Long picId) {\n    this.picId = picId;\n  }\n\n  public String getLiveAddress() {\n    return liveAddress;\n  }\n\n  public void setLiveAddress(String liveAddress) {\n    this.liveAddress = liveAddress;\n  }\n\n  public String getHobby() {\n    return hobby;\n  }\n\n  public void setHobby(String hobby) {\n    this.hobby = hobby;\n  }\n\n  public String getProvince() {\n    return province;\n  }\n\n  public void setProvince(String province) {\n    this.province = province;\n  }\n\n  public String getCity() {\n    return city;\n  }\n\n  public void setCity(String city) {\n    this.city = city;\n  }\n\n  public String getDistrict() {\n    return district;\n  }\n\n  public void setDistrict(String district) {\n    this.district = district;\n  }\n\n  @Override\n  public String toString() {\n    return \"UserDO{\" +\n            \"userId=\" + userId +\n            \", username='\" + username + '\\'' +\n            \", name='\" + name + '\\'' +\n            \", password='\" + password + '\\'' +\n            \", deptId=\" + deptId +\n            \", deptName='\" + deptName + '\\'' +\n            \", email='\" + email + '\\'' +\n            \", mobile='\" + mobile + '\\'' +\n            \", status=\" + status +\n            \", userIdCreate=\" + userIdCreate +\n            \", gmtCreate=\" + gmtCreate +\n            \", gmtModified=\" + gmtModified +\n            \", roleIds=\" + roleIds +\n            \", sex=\" + sex +\n            \", birth=\" + birth +\n            \", picId=\" + picId +\n            \", liveAddress='\" + liveAddress + '\\'' +\n            \", hobby='\" + hobby + '\\'' +\n            \", province='\" + province + '\\'' +\n            \", city='\" + city + '\\'' +\n            \", district='\" + district + '\\'' +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/UserOnline.java",
    "content": "package me.zbl.system.domain;\n\nimport java.util.Date;\n\n/**\n *\n *\n */\npublic class UserOnline {\n\n  /**\n   */\n  private String id;\n\n  private String userId;\n\n  private String username;\n\n  /**\n   * 用户主机地址\n   */\n  private String host;\n\n  /**\n   * 用户登录时系统IP\n   */\n  private String systemHost;\n\n  /**\n   * 用户浏览器类型\n   */\n  private String userAgent;\n\n  /**\n   * 在线状态\n   */\n  private String status = \"on_line\";\n\n  /**\n   * session创建时间\n   */\n  private Date startTimestamp;\n  /**\n   * session最后访问时间\n   */\n  private Date lastAccessTime;\n\n  /**\n   * 超时时间\n   */\n  private Long timeout;\n\n  /**\n   * 备份的当前用户会话\n   */\n  private String onlineSession;\n\n\n  public String getId() {\n    return id;\n  }\n\n  public void setId(String id) {\n    this.id = id;\n  }\n\n  public Date getStartTimestamp() {\n    return startTimestamp;\n  }\n\n  public void setStartTimestamp(Date startTimestamp) {\n    this.startTimestamp = startTimestamp;\n  }\n\n  public Date getLastAccessTime() {\n    return lastAccessTime;\n  }\n\n  public void setLastAccessTime(Date lastAccessTime) {\n    this.lastAccessTime = lastAccessTime;\n  }\n\n  public Long getTimeout() {\n    return timeout;\n  }\n\n  public void setTimeout(Long timeout) {\n    this.timeout = timeout;\n  }\n\n  public String getHost() {\n    return host;\n  }\n\n  public void setHost(String host) {\n    this.host = host;\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 getUsername() {\n    return username;\n  }\n\n  public void setUsername(String username) {\n    this.username = username;\n  }\n\n  public String getUserAgent() {\n    return userAgent;\n  }\n\n  public void setUserAgent(String userAgent) {\n    this.userAgent = userAgent;\n  }\n\n  public String getStatus() {\n    return status;\n  }\n\n  public void setStatus(String status) {\n    this.status = status;\n  }\n\n  public String getOnlineSession() {\n    return onlineSession;\n  }\n\n  public void setOnlineSession(String onlineSession) {\n    this.onlineSession = onlineSession;\n  }\n\n\n  public String getSystemHost() {\n    return systemHost;\n  }\n\n  public void setSystemHost(String systemHost) {\n    this.systemHost = systemHost;\n  }\n\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/UserRoleDO.java",
    "content": "package me.zbl.system.domain;\n\npublic class UserRoleDO {\n\n  private Long id;\n  private Long userId;\n  private Long roleId;\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 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 \"UserRoleDO{\" +\n            \"id=\" + id +\n            \", userId=\" + userId +\n            \", roleId=\" + roleId +\n            '}';\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/domain/UserToken.java",
    "content": "package me.zbl.system.domain;\n\nimport java.io.Serializable;\n\n/**\n * @author 郑保乐\n * @version V1.0\n */\npublic class UserToken implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n  private Long userId;\n  private String username;\n  private String name;\n  private String password;\n  private Long deptId;\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 getUsername() {\n    return username;\n  }\n\n  public void setUsername(String username) {\n    this.username = username;\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 getPassword() {\n    return password;\n  }\n\n  public void setPassword(String password) {\n    this.password = password;\n  }\n\n  public Long getDeptId() {\n    return deptId;\n  }\n\n  public void setDeptId(Long deptId) {\n    this.deptId = deptId;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/filter/XssFilter.java",
    "content": "package me.zbl.system.filter;\n\nimport org.apache.commons.lang3.BooleanUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * 拦截防止xss注入\n * 通过Jsoup过滤请求参数内的特定字符\n *\n * @author 郑保乐\n */\npublic class XssFilter implements Filter {\n\n  private static Logger logger = LoggerFactory.getLogger(XssFilter.class);\n\n  /**\n   * 是否过滤富文本内容\n   */\n  private static boolean IS_INCLUDE_RICH_TEXT = false;\n\n  public List<String> excludes = new ArrayList<>();\n\n  @Override\n  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {\n    if (logger.isDebugEnabled()) {\n      logger.debug(\"xss filter is open\");\n    }\n\n    HttpServletRequest req = (HttpServletRequest) request;\n    HttpServletResponse resp = (HttpServletResponse) response;\n    if (handleExcludeURL(req, resp)) {\n      filterChain.doFilter(request, response);\n      return;\n    }\n\n    XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request, IS_INCLUDE_RICH_TEXT);\n    filterChain.doFilter(xssRequest, response);\n  }\n\n  private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {\n\n    if (excludes == null || excludes.isEmpty()) {\n      return false;\n    }\n\n    String url = request.getServletPath();\n    for (String pattern : excludes) {\n      Pattern p = Pattern.compile(\"^\" + pattern);\n      Matcher m = p.matcher(url);\n      if (m.find()) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  @Override\n  public void init(FilterConfig filterConfig) {\n    if (logger.isDebugEnabled()) {\n      logger.debug(\"xss filter init~~~~~~~~~~~~\");\n    }\n    String isIncludeRichText = filterConfig.getInitParameter(\"isIncludeRichText\");\n    if (StringUtils.isNotBlank(isIncludeRichText)) {\n      IS_INCLUDE_RICH_TEXT = BooleanUtils.toBoolean(isIncludeRichText);\n    }\n\n    String temp = filterConfig.getInitParameter(\"excludes\");\n    if (temp != null) {\n      String[] url = temp.split(\",\");\n      for (int i = 0; url != null && i < url.length; i++) {\n        excludes.add(url[i]);\n      }\n    }\n  }\n\n  @Override\n  public void destroy() {\n  }\n\n}  \n"
  },
  {
    "path": "src/main/java/me/zbl/system/filter/XssHttpServletRequestWrapper.java",
    "content": "package me.zbl.system.filter;\n\nimport me.zbl.common.utils.xss.JsoupUtil;\nimport org.apache.commons.lang3.StringUtils;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletRequestWrapper;\n\n\n/**\n * <code>{@link XssHttpServletRequestWrapper}</code>\n *\n * @author 郑保乐\n */\npublic class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {\n\n  HttpServletRequest orgRequest = null;\n  private boolean isIncludeRichText = false;\n\n  public XssHttpServletRequestWrapper(HttpServletRequest request, boolean isIncludeRichText) {\n    super(request);\n    orgRequest = request;\n    this.isIncludeRichText = isIncludeRichText;\n  }\n\n  /**\n   * 获取最原始的request的静态方法\n   *\n   * @return\n   */\n  public static HttpServletRequest getOrgRequest(HttpServletRequest req) {\n    if (req instanceof XssHttpServletRequestWrapper) {\n      return ((XssHttpServletRequestWrapper) req).getOrgRequest();\n    }\n\n    return req;\n  }\n\n  /**\n   * 覆盖getParameter方法，将参数名和参数值都做xss过滤。<br/>\n   * 如果需要获得原始的值，则通过super.getParameterValues(name)来获取<br/>\n   * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖\n   */\n  @Override\n  public String getParameter(String name) {\n    Boolean flag = (\"content\".equals(name) || name.endsWith(\"WithHtml\"));\n    if (flag && !isIncludeRichText) {\n      return super.getParameter(name);\n    }\n    name = JsoupUtil.clean(name);\n    String value = super.getParameter(name);\n    if (StringUtils.isNotBlank(value)) {\n      value = JsoupUtil.clean(value);\n    }\n    return value;\n  }\n\n  @Override\n  public String[] getParameterValues(String name) {\n    String[] arr = super.getParameterValues(name);\n    if (arr != null) {\n      for (int i = 0; i < arr.length; i++) {\n        arr[i] = JsoupUtil.clean(arr[i]);\n      }\n    }\n    return arr;\n  }\n\n  /**\n   * 覆盖getHeader方法，将参数名和参数值都做xss过滤。<br/>\n   * 如果需要获得原始的值，则通过super.getHeaders(name)来获取<br/>\n   * getHeaderNames 也可能需要覆盖\n   */\n  @Override\n  public String getHeader(String name) {\n    name = JsoupUtil.clean(name);\n    String value = super.getHeader(name);\n    if (StringUtils.isNotBlank(value)) {\n      value = JsoupUtil.clean(value);\n    }\n    return value;\n  }\n\n  /**\n   * 获取最原始的request\n   *\n   * @return\n   */\n  public HttpServletRequest getOrgRequest() {\n    return orgRequest;\n  }\n\n}  \n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/DeptService.java",
    "content": "package me.zbl.system.service;\n\nimport me.zbl.common.domain.Tree;\nimport me.zbl.system.domain.DeptDO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 部门管理\n *\n * @author 郑保乐\n * @email 18333298410@163.com\n * @date 2017-09-27 14:28:36\n */\npublic interface DeptService {\n\n  DeptDO get(Long deptId);\n\n  List<DeptDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(DeptDO sysDept);\n\n  int update(DeptDO sysDept);\n\n  int remove(Long deptId);\n\n  int batchRemove(Long[] deptIds);\n\n  Tree<DeptDO> getTree();\n\n  boolean checkDeptHasUser(Long deptId);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/MenuService.java",
    "content": "package me.zbl.system.service;\n\nimport me.zbl.common.domain.Tree;\nimport me.zbl.system.domain.MenuDO;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n@Service\npublic interface MenuService {\n\n  Tree<MenuDO> getSysMenuTree(Long id);\n\n  List<Tree<MenuDO>> listMenuTree(Long id);\n\n  Tree<MenuDO> getTree();\n\n  Tree<MenuDO> getTree(Long id);\n\n  List<MenuDO> list(Map<String, Object> params);\n\n  int remove(Long id);\n\n  int save(MenuDO menu);\n\n  int update(MenuDO menu);\n\n  MenuDO get(Long id);\n\n  Set<String> listPerms(Long userId);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/RoleService.java",
    "content": "package me.zbl.system.service;\n\nimport me.zbl.system.domain.RoleDO;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic interface RoleService {\n\n  RoleDO get(Long id);\n\n  List<RoleDO> list();\n\n  int save(RoleDO role);\n\n  int update(RoleDO role);\n\n  int remove(Long id);\n\n  List<RoleDO> list(Long userId);\n\n  int batchremove(Long[] ids);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/SessionService.java",
    "content": "package me.zbl.system.service;\n\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.domain.UserOnline;\nimport org.apache.shiro.session.Session;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collection;\nimport java.util.List;\n\n@Service\npublic interface SessionService {\n\n  List<UserOnline> list();\n\n  List<UserDO> listOnlineUser();\n\n  Collection<Session> sessionList();\n\n  boolean forceLogout(String sessionId);\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/UserService.java",
    "content": "package me.zbl.system.service;\n\nimport me.zbl.common.domain.Tree;\nimport me.zbl.system.domain.DeptDO;\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.vo.UserVO;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n@Service\npublic interface UserService {\n\n  UserDO get(Long id);\n\n  List<UserDO> list(Map<String, Object> map);\n\n  int count(Map<String, Object> map);\n\n  int save(UserDO user);\n\n  int update(UserDO user);\n\n  int remove(Long userId);\n\n  int batchremove(Long[] userIds);\n\n  boolean exit(Map<String, Object> params);\n\n  Set<String> listRoles(Long userId);\n\n  int resetPwd(UserVO userVO, UserDO userDO) throws Exception;\n\n  int adminResetPwd(UserVO userVO) throws Exception;\n\n  Tree<DeptDO> getTree();\n\n  /**\n   * 更新个人信息\n   *\n   * @param userDO\n   *\n   * @return\n   */\n  int updatePersonal(UserDO userDO);\n\n  /**\n   * 更新个人图片\n   *\n   * @param file        图片\n   * @param avatar_data 裁剪信息\n   * @param userId      用户ID\n   *\n   * @throws Exception\n   */\n  Map<String, Object> updatePersonalImg(MultipartFile file, String avatar_data, Long userId) throws Exception;\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/impl/DeptServiceImpl.java",
    "content": "package me.zbl.system.service.impl;\n\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.utils.BuildTree;\nimport me.zbl.system.dao.DeptDao;\nimport me.zbl.system.domain.DeptDO;\nimport me.zbl.system.service.DeptService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n\n@Service\npublic class DeptServiceImpl implements DeptService {\n\n  @Autowired\n  private DeptDao sysDeptMapper;\n\n  @Override\n  public DeptDO get(Long deptId) {\n    return sysDeptMapper.get(deptId);\n  }\n\n  @Override\n  public List<DeptDO> list(Map<String, Object> map) {\n    return sysDeptMapper.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return sysDeptMapper.count(map);\n  }\n\n  @Override\n  public int save(DeptDO sysDept) {\n    return sysDeptMapper.save(sysDept);\n  }\n\n  @Override\n  public int update(DeptDO sysDept) {\n    return sysDeptMapper.update(sysDept);\n  }\n\n  @Override\n  public int remove(Long deptId) {\n    return sysDeptMapper.remove(deptId);\n  }\n\n  @Override\n  public int batchRemove(Long[] deptIds) {\n    return sysDeptMapper.batchRemove(deptIds);\n  }\n\n  @Override\n  public Tree<DeptDO> getTree() {\n    List<Tree<DeptDO>> trees = new ArrayList<Tree<DeptDO>>();\n    List<DeptDO> sysDepts = sysDeptMapper.list(new HashMap<String, Object>(16));\n    for (DeptDO sysDept : sysDepts) {\n      Tree<DeptDO> tree = new Tree<DeptDO>();\n      tree.setId(sysDept.getDeptId().toString());\n      tree.setParentId(sysDept.getParentId().toString());\n      tree.setText(sysDept.getName());\n      Map<String, Object> state = new HashMap<>(16);\n      state.put(\"opened\", true);\n      tree.setState(state);\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    Tree<DeptDO> t = BuildTree.build(trees);\n    return t;\n  }\n\n  @Override\n  public boolean checkDeptHasUser(Long deptId) {\n    //查询部门以及此部门的下级部门\n    int result = sysDeptMapper.getDeptUserNumber(deptId);\n    return result == 0;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/impl/MenuServiceImpl.java",
    "content": "package me.zbl.system.service.impl;\n\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.utils.BuildTree;\nimport me.zbl.system.dao.MenuDao;\nimport me.zbl.system.dao.RoleMenuDao;\nimport me.zbl.system.domain.MenuDO;\nimport me.zbl.system.service.MenuService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.*;\n\n@SuppressWarnings(\"AlibabaRemoveCommentedCode\")\n@Service\n@Transactional(readOnly = true, rollbackFor = Exception.class)\npublic class MenuServiceImpl implements MenuService {\n\n  @Autowired\n  MenuDao menuMapper;\n  @Autowired\n  RoleMenuDao roleMenuMapper;\n\n  /**\n   * @param\n   *\n   * @return 树形菜单\n   */\n  @Cacheable\n  @Override\n  public Tree<MenuDO> getSysMenuTree(Long id) {\n    List<Tree<MenuDO>> trees = new ArrayList<Tree<MenuDO>>();\n    List<MenuDO> menuDOs = menuMapper.listMenuByUserId(id);\n    for (MenuDO sysMenuDO : menuDOs) {\n      Tree<MenuDO> tree = new Tree<MenuDO>();\n      tree.setId(sysMenuDO.getMenuId().toString());\n      tree.setParentId(sysMenuDO.getParentId().toString());\n      tree.setText(sysMenuDO.getName());\n      Map<String, Object> attributes = new HashMap<>(16);\n      attributes.put(\"url\", sysMenuDO.getUrl());\n      attributes.put(\"icon\", sysMenuDO.getIcon());\n      tree.setAttributes(attributes);\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    Tree<MenuDO> t = BuildTree.build(trees);\n    return t;\n  }\n\n  @Override\n  public List<MenuDO> list(Map<String, Object> params) {\n    List<MenuDO> menus = menuMapper.list(params);\n    return menus;\n  }\n\n  @Transactional(readOnly = false, rollbackFor = Exception.class)\n  @Override\n  public int remove(Long id) {\n    int result = menuMapper.remove(id);\n    return result;\n  }\n\n  @Transactional(readOnly = false, rollbackFor = Exception.class)\n  @Override\n  public int save(MenuDO menu) {\n    int r = menuMapper.save(menu);\n    return r;\n  }\n\n  @Transactional(readOnly = false, rollbackFor = Exception.class)\n  @Override\n  public int update(MenuDO menu) {\n    int r = menuMapper.update(menu);\n    return r;\n  }\n\n  @Override\n  public MenuDO get(Long id) {\n    MenuDO menuDO = menuMapper.get(id);\n    return menuDO;\n  }\n\n  @Override\n  public Tree<MenuDO> getTree() {\n    List<Tree<MenuDO>> trees = new ArrayList<Tree<MenuDO>>();\n    List<MenuDO> menuDOs = menuMapper.list(new HashMap<>(16));\n    for (MenuDO sysMenuDO : menuDOs) {\n      Tree<MenuDO> tree = new Tree<MenuDO>();\n      tree.setId(sysMenuDO.getMenuId().toString());\n      tree.setParentId(sysMenuDO.getParentId().toString());\n      tree.setText(sysMenuDO.getName());\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    Tree<MenuDO> t = BuildTree.build(trees);\n    return t;\n  }\n\n  @Override\n  public Tree<MenuDO> getTree(Long id) {\n    // 根据roleId查询权限\n    List<MenuDO> menus = menuMapper.list(new HashMap<String, Object>(16));\n    List<Long> menuIds = roleMenuMapper.listMenuIdByRoleId(id);\n    List<Long> temp = menuIds;\n    for (MenuDO menu : menus) {\n      if (temp.contains(menu.getParentId())) {\n        menuIds.remove(menu.getParentId());\n      }\n    }\n    List<Tree<MenuDO>> trees = new ArrayList<Tree<MenuDO>>();\n    List<MenuDO> menuDOs = menuMapper.list(new HashMap<String, Object>(16));\n    for (MenuDO sysMenuDO : menuDOs) {\n      Tree<MenuDO> tree = new Tree<MenuDO>();\n      tree.setId(sysMenuDO.getMenuId().toString());\n      tree.setParentId(sysMenuDO.getParentId().toString());\n      tree.setText(sysMenuDO.getName());\n      Map<String, Object> state = new HashMap<>(16);\n      Long menuId = sysMenuDO.getMenuId();\n      if (menuIds.contains(menuId)) {\n        state.put(\"selected\", true);\n      } else {\n        state.put(\"selected\", false);\n      }\n      tree.setState(state);\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    Tree<MenuDO> t = BuildTree.build(trees);\n    return t;\n  }\n\n  @Override\n  public Set<String> listPerms(Long userId) {\n    List<String> perms = menuMapper.listUserPerms(userId);\n    Set<String> permsSet = new HashSet<>();\n    for (String perm : perms) {\n      if (StringUtils.isNotBlank(perm)) {\n        permsSet.addAll(Arrays.asList(perm.trim().split(\",\")));\n      }\n    }\n    return permsSet;\n  }\n\n  @Override\n  public List<Tree<MenuDO>> listMenuTree(Long id) {\n    List<Tree<MenuDO>> trees = new ArrayList<Tree<MenuDO>>();\n    List<MenuDO> menuDOs = menuMapper.listMenuByUserId(id);\n    for (MenuDO sysMenuDO : menuDOs) {\n      Tree<MenuDO> tree = new Tree<MenuDO>();\n      tree.setId(sysMenuDO.getMenuId().toString());\n      tree.setParentId(sysMenuDO.getParentId().toString());\n      tree.setText(sysMenuDO.getName());\n      Map<String, Object> attributes = new HashMap<>(16);\n      attributes.put(\"url\", sysMenuDO.getUrl());\n      attributes.put(\"icon\", sysMenuDO.getIcon());\n      tree.setAttributes(attributes);\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    List<Tree<MenuDO>> list = BuildTree.buildList(trees, \"0\");\n    return list;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/impl/RoleServiceImpl.java",
    "content": "package me.zbl.system.service.impl;\n\nimport me.zbl.system.dao.RoleDao;\nimport me.zbl.system.dao.RoleMenuDao;\nimport me.zbl.system.dao.UserDao;\nimport me.zbl.system.dao.UserRoleDao;\nimport me.zbl.system.domain.RoleDO;\nimport me.zbl.system.domain.RoleMenuDO;\nimport me.zbl.system.service.RoleService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Objects;\n\n\n@Service\npublic class RoleServiceImpl implements RoleService {\n\n  public static final String ROLE_ALL_KEY = \"\\\"role_all\\\"\";\n\n  public static final String DEMO_CACHE_NAME = \"role\";\n\n  @Autowired\n  RoleDao roleMapper;\n  @Autowired\n  RoleMenuDao roleMenuMapper;\n  @Autowired\n  UserDao userMapper;\n  @Autowired\n  UserRoleDao userRoleMapper;\n\n  @Override\n  public List<RoleDO> list() {\n    List<RoleDO> roles = roleMapper.list(new HashMap<>(16));\n    return roles;\n  }\n\n\n  @Override\n  public List<RoleDO> list(Long userId) {\n    List<Long> rolesIds = userRoleMapper.listRoleId(userId);\n    List<RoleDO> roles = roleMapper.list(new HashMap<>(16));\n    for (RoleDO roleDO : roles) {\n      roleDO.setRoleSign(\"false\");\n      for (Long roleId : rolesIds) {\n        if (Objects.equals(roleDO.getRoleId(), roleId)) {\n          roleDO.setRoleSign(\"true\");\n          break;\n        }\n      }\n    }\n    return roles;\n  }\n\n  @Transactional\n  @Override\n  public int save(RoleDO role) {\n    int count = roleMapper.save(role);\n    List<Long> menuIds = role.getMenuIds();\n    Long roleId = role.getRoleId();\n    List<RoleMenuDO> rms = new ArrayList<>();\n    for (Long menuId : menuIds) {\n      RoleMenuDO rmDo = new RoleMenuDO();\n      rmDo.setRoleId(roleId);\n      rmDo.setMenuId(menuId);\n      rms.add(rmDo);\n    }\n    roleMenuMapper.removeByRoleId(roleId);\n    if (rms.size() > 0) {\n      roleMenuMapper.batchSave(rms);\n    }\n    return count;\n  }\n\n  @Transactional\n  @Override\n  public int remove(Long id) {\n    int count = roleMapper.remove(id);\n    userRoleMapper.removeByRoleId(id);\n    roleMenuMapper.removeByRoleId(id);\n    return count;\n  }\n\n  @Override\n  public RoleDO get(Long id) {\n    RoleDO roleDO = roleMapper.get(id);\n    return roleDO;\n  }\n\n  @Override\n  public int update(RoleDO role) {\n    int r = roleMapper.update(role);\n    List<Long> menuIds = role.getMenuIds();\n    Long roleId = role.getRoleId();\n    roleMenuMapper.removeByRoleId(roleId);\n    List<RoleMenuDO> rms = new ArrayList<>();\n    for (Long menuId : menuIds) {\n      RoleMenuDO rmDo = new RoleMenuDO();\n      rmDo.setRoleId(roleId);\n      rmDo.setMenuId(menuId);\n      rms.add(rmDo);\n    }\n    if (rms.size() > 0) {\n      roleMenuMapper.batchSave(rms);\n    }\n    return r;\n  }\n\n  @Override\n  public int batchremove(Long[] ids) {\n    int r = roleMapper.batchRemove(ids);\n    return r;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/impl/SessionServiceImpl.java",
    "content": "package me.zbl.system.service.impl;\n\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.domain.UserOnline;\nimport me.zbl.system.service.SessionService;\nimport org.apache.shiro.session.Session;\nimport org.apache.shiro.session.mgt.eis.SessionDAO;\nimport org.apache.shiro.subject.SimplePrincipalCollection;\nimport org.apache.shiro.subject.support.DefaultSubjectContext;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * 待完善\n *\n * @author 郑保乐\n */\n@Service\npublic class SessionServiceImpl implements SessionService {\n\n  private final SessionDAO sessionDAO;\n\n  @Autowired\n  public SessionServiceImpl(SessionDAO sessionDAO) {\n    this.sessionDAO = sessionDAO;\n  }\n\n  @Override\n  public List<UserOnline> list() {\n    List<UserOnline> list = new ArrayList<>();\n    Collection<Session> sessions = sessionDAO.getActiveSessions();\n    for (Session session : sessions) {\n      UserOnline userOnline = new UserOnline();\n      if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {\n        continue;\n      } else {\n        SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) session\n                .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);\n        UserDO userDO = (UserDO) principalCollection.getPrimaryPrincipal();\n        userOnline.setUsername(userDO.getUsername());\n      }\n      userOnline.setId((String) session.getId());\n      userOnline.setHost(session.getHost());\n      userOnline.setStartTimestamp(session.getStartTimestamp());\n      userOnline.setLastAccessTime(session.getLastAccessTime());\n      userOnline.setTimeout(session.getTimeout());\n      list.add(userOnline);\n    }\n    return list;\n  }\n\n  @Override\n  public List<UserDO> listOnlineUser() {\n    List<UserDO> list = new ArrayList<>();\n    UserDO userDO;\n    Collection<Session> sessions = sessionDAO.getActiveSessions();\n    for (Session session : sessions) {\n      SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();\n      if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {\n        continue;\n      } else {\n        principalCollection = (SimplePrincipalCollection) session\n                .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);\n        userDO = (UserDO) principalCollection.getPrimaryPrincipal();\n        list.add(userDO);\n      }\n    }\n    return list;\n  }\n\n  @Override\n  public Collection<Session> sessionList() {\n    return sessionDAO.getActiveSessions();\n  }\n\n  @Override\n  public boolean forceLogout(String sessionId) {\n    Session session = sessionDAO.readSession(sessionId);\n    session.setTimeout(0);\n    return true;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/service/impl/UserServiceImpl.java",
    "content": "package me.zbl.system.service.impl;\n\nimport me.zbl.common.config.HospitalConfig;\nimport me.zbl.common.domain.FileDO;\nimport me.zbl.common.domain.Tree;\nimport me.zbl.common.service.FileService;\nimport me.zbl.common.utils.*;\nimport me.zbl.system.dao.DeptDao;\nimport me.zbl.system.dao.UserDao;\nimport me.zbl.system.dao.UserRoleDao;\nimport me.zbl.system.domain.DeptDO;\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.domain.UserRoleDO;\nimport me.zbl.system.service.UserService;\nimport me.zbl.system.vo.UserVO;\nimport org.apache.commons.lang.ArrayUtils;\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.web.multipart.MultipartFile;\n\nimport javax.imageio.ImageIO;\nimport java.awt.image.BufferedImage;\nimport java.io.ByteArrayOutputStream;\nimport java.util.*;\n\n@Transactional\n@Service\npublic class UserServiceImpl implements UserService {\n\n  private static final Logger logger = LoggerFactory.getLogger(UserService.class);\n  @Autowired\n  UserDao userMapper;\n  @Autowired\n  UserRoleDao userRoleMapper;\n  @Autowired\n  DeptDao deptMapper;\n  @Autowired\n  private FileService sysFileService;\n  @Autowired\n  private HospitalConfig hospitalConfig;\n\n  @Override\n  public UserDO get(Long id) {\n    List<Long> roleIds = userRoleMapper.listRoleId(id);\n    UserDO user = userMapper.get(id);\n    user.setDeptName(deptMapper.get(user.getDeptId()).getName());\n    user.setRoleIds(roleIds);\n    return user;\n  }\n\n  @Override\n  public List<UserDO> list(Map<String, Object> map) {\n    return userMapper.list(map);\n  }\n\n  @Override\n  public int count(Map<String, Object> map) {\n    return userMapper.count(map);\n  }\n\n  @Transactional\n  @Override\n  public int save(UserDO user) {\n    int count = userMapper.save(user);\n    Long userId = user.getUserId();\n    List<Long> roles = user.getRoleIds();\n    userRoleMapper.removeByUserId(userId);\n    List<UserRoleDO> list = new ArrayList<>();\n    for (Long roleId : roles) {\n      UserRoleDO ur = new UserRoleDO();\n      ur.setUserId(userId);\n      ur.setRoleId(roleId);\n      list.add(ur);\n    }\n    if (list.size() > 0) {\n      userRoleMapper.batchSave(list);\n    }\n    return count;\n  }\n\n  @Override\n  public int update(UserDO user) {\n    int r = userMapper.update(user);\n    Long userId = user.getUserId();\n    List<Long> roles = user.getRoleIds();\n    userRoleMapper.removeByUserId(userId);\n    List<UserRoleDO> list = new ArrayList<>();\n    for (Long roleId : roles) {\n      UserRoleDO ur = new UserRoleDO();\n      ur.setUserId(userId);\n      ur.setRoleId(roleId);\n      list.add(ur);\n    }\n    if (list.size() > 0) {\n      userRoleMapper.batchSave(list);\n    }\n    return r;\n  }\n\n  @Override\n  public int remove(Long userId) {\n    userRoleMapper.removeByUserId(userId);\n    return userMapper.remove(userId);\n  }\n\n  @Override\n  public boolean exit(Map<String, Object> params) {\n    boolean exit;\n    exit = userMapper.list(params).size() > 0;\n    return exit;\n  }\n\n  @Override\n  public Set<String> listRoles(Long userId) {\n    return null;\n  }\n\n  @Override\n  public int resetPwd(UserVO userVO, UserDO userDO) throws Exception {\n    if (Objects.equals(userVO.getUserDO().getUserId(), userDO.getUserId())) {\n      if (Objects.equals(MD5Utils.encrypt(userDO.getUsername(), userVO.getPwdOld()), userDO.getPassword())) {\n        userDO.setPassword(MD5Utils.encrypt(userDO.getUsername(), userVO.getPwdNew()));\n        return userMapper.update(userDO);\n      } else {\n        throw new Exception(\"输入的旧密码有误！\");\n      }\n    } else {\n      throw new Exception(\"你修改的不是你登录的账号！\");\n    }\n  }\n\n  @Override\n  public int adminResetPwd(UserVO userVO) throws Exception {\n    UserDO userDO = get(userVO.getUserDO().getUserId());\n    if (\"admin\".equals(userDO.getUsername())) {\n      throw new Exception(\"超级管理员的账号不允许直接重置！\");\n    }\n    userDO.setPassword(MD5Utils.encrypt(userDO.getUsername(), userVO.getPwdNew()));\n    return userMapper.update(userDO);\n\n\n  }\n\n  @Transactional\n  @Override\n  public int batchremove(Long[] userIds) {\n    int count = userMapper.batchRemove(userIds);\n    userRoleMapper.batchRemoveByUserId(userIds);\n    return count;\n  }\n\n  @Override\n  public Tree<DeptDO> getTree() {\n    List<Tree<DeptDO>> trees = new ArrayList<Tree<DeptDO>>();\n    List<DeptDO> depts = deptMapper.list(new HashMap<String, Object>(16));\n    Long[] pDepts = deptMapper.listParentDept();\n    Long[] uDepts = userMapper.listAllDept();\n    Long[] allDepts = (Long[]) ArrayUtils.addAll(pDepts, uDepts);\n    for (DeptDO dept : depts) {\n      if (!ArrayUtils.contains(allDepts, dept.getDeptId())) {\n        continue;\n      }\n      Tree<DeptDO> tree = new Tree<DeptDO>();\n      tree.setId(dept.getDeptId().toString());\n      tree.setParentId(dept.getParentId().toString());\n      tree.setText(dept.getName());\n      Map<String, Object> state = new HashMap<>(16);\n      state.put(\"opened\", true);\n      state.put(\"mType\", \"dept\");\n      tree.setState(state);\n      trees.add(tree);\n    }\n    List<UserDO> users = userMapper.list(new HashMap<String, Object>(16));\n    for (UserDO user : users) {\n      Tree<DeptDO> tree = new Tree<DeptDO>();\n      tree.setId(user.getUserId().toString());\n      tree.setParentId(user.getDeptId().toString());\n      tree.setText(user.getName());\n      Map<String, Object> state = new HashMap<>(16);\n      state.put(\"opened\", true);\n      state.put(\"mType\", \"user\");\n      tree.setState(state);\n      trees.add(tree);\n    }\n    // 默认顶级菜单为０，根据数据库实际情况调整\n    Tree<DeptDO> t = BuildTree.build(trees);\n    return t;\n  }\n\n  @Override\n  public int updatePersonal(UserDO userDO) {\n    return userMapper.update(userDO);\n  }\n\n  @Override\n  public Map<String, Object> updatePersonalImg(MultipartFile file, String avatar_data, Long userId) throws Exception {\n    String fileName = file.getOriginalFilename();\n    fileName = FileUtil.renameToUUID(fileName);\n    FileDO sysFile = new FileDO(FileType.fileType(fileName), \"/files/\" + fileName, new Date());\n    //获取图片后缀\n    String prefix = fileName.substring((fileName.lastIndexOf(\".\") + 1));\n    String[] str = avatar_data.split(\",\");\n    //获取截取的x坐标\n    int x = (int) Math.floor(Double.parseDouble(str[0].split(\":\")[1]));\n    //获取截取的y坐标\n    int y = (int) Math.floor(Double.parseDouble(str[1].split(\":\")[1]));\n    //获取截取的高度\n    int h = (int) Math.floor(Double.parseDouble(str[2].split(\":\")[1]));\n    //获取截取的宽度\n    int w = (int) Math.floor(Double.parseDouble(str[3].split(\":\")[1]));\n    //获取旋转的角度\n    int r = Integer.parseInt(str[4].split(\":\")[1].replaceAll(\"}\", \"\"));\n    try {\n      BufferedImage cutImage = ImageUtils.cutImage(file, x, y, w, h, prefix);\n      BufferedImage rotateImage = ImageUtils.rotateImage(cutImage, r);\n      ByteArrayOutputStream out = new ByteArrayOutputStream();\n      boolean flag = ImageIO.write(rotateImage, prefix, out);\n      //转换后存入数据库\n      byte[] b = out.toByteArray();\n      FileUtil.uploadFile(b, hospitalConfig.getUploadPath(), fileName);\n    } catch (Exception e) {\n      throw new Exception(\"图片裁剪错误！！\");\n    }\n    Map<String, Object> result = new HashMap<>();\n    if (sysFileService.save(sysFile) > 0) {\n      UserDO userDO = new UserDO();\n      userDO.setUserId(userId);\n      userDO.setPicId(sysFile.getId());\n      if (userMapper.update(userDO) > 0) {\n        result.put(\"url\", sysFile.getUrl());\n      }\n    }\n    return result;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/shiro/UserRealm.java",
    "content": "package me.zbl.system.shiro;\n\nimport me.zbl.common.config.ApplicationContextRegister;\nimport me.zbl.common.utils.ShiroUtils;\nimport me.zbl.system.dao.UserDao;\nimport me.zbl.system.domain.UserDO;\nimport me.zbl.system.service.MenuService;\nimport org.apache.shiro.authc.*;\nimport org.apache.shiro.authz.AuthorizationInfo;\nimport org.apache.shiro.authz.SimpleAuthorizationInfo;\nimport org.apache.shiro.realm.AuthorizingRealm;\nimport org.apache.shiro.subject.PrincipalCollection;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class UserRealm extends AuthorizingRealm {\n/*\t@Autowired\n\tUserDao userMapper;\n\t@Autowired\n\tMenuService menuService;*/\n\n  @Override\n  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {\n    Long userId = ShiroUtils.getUserId();\n    MenuService menuService = ApplicationContextRegister.getBean(MenuService.class);\n    Set<String> perms = menuService.listPerms(userId);\n    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();\n    info.setStringPermissions(perms);\n    return info;\n  }\n\n  @Override\n  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {\n    String username = (String) token.getPrincipal();\n    Map<String, Object> map = new HashMap<>(16);\n    map.put(\"username\", username);\n    String password = new String((char[]) token.getCredentials());\n\n    UserDao userMapper = ApplicationContextRegister.getBean(UserDao.class);\n    // 查询用户信息\n    UserDO user = userMapper.list(map).get(0);\n\n    // 账号不存在\n    if (user == null) {\n      throw new UnknownAccountException(\"账号或密码不正确\");\n    }\n\n    // 密码错误\n    if (!password.equals(user.getPassword())) {\n      throw new IncorrectCredentialsException(\"账号或密码不正确\");\n    }\n\n    // 账号锁定\n    if (user.getStatus() == 0) {\n      throw new LockedAccountException(\"账号已被锁定,请联系管理员\");\n    }\n    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());\n    return info;\n  }\n\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/system/vo/UserVO.java",
    "content": "package me.zbl.system.vo;\n\nimport me.zbl.system.domain.UserDO;\n\n/**\n * @author 郑保乐\n * @date 2017/12/15.\n */\npublic class UserVO {\n\n  /**\n   * 更新的用户对象\n   */\n  private UserDO userDO = new UserDO();\n  /**\n   * 旧密码\n   */\n  private String pwdOld;\n  /**\n   * 新密码\n   */\n  private String pwdNew;\n\n  public UserDO getUserDO() {\n    return userDO;\n  }\n\n  public void setUserDO(UserDO userDO) {\n    this.userDO = userDO;\n  }\n\n  public String getPwdOld() {\n    return pwdOld;\n  }\n\n  public void setPwdOld(String pwdOld) {\n    this.pwdOld = pwdOld;\n  }\n\n  public String getPwdNew() {\n    return pwdNew;\n  }\n\n  public void setPwdNew(String pwdNew) {\n    this.pwdNew = pwdNew;\n  }\n}\n"
  },
  {
    "path": "src/main/java/me/zbl/util/PageUtil.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.util;\n\nimport com.github.pagehelper.ISelect;\nimport com.github.pagehelper.Page;\nimport com.github.pagehelper.PageHelper;\n\nimport java.util.Map;\nimport java.util.Optional;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-06-24\n */\npublic class PageUtil {\n\n  public static <E> Page<E> page(Map<String, Object> params, ISelect select) {\n    Optional<String> orderby = Optional.ofNullable((String) (params.get(\"orderby\")));\n    Page<Object> page = PageHelper.offsetPage(\n            (Integer) params.get(\"offset\"),\n            (Integer) params.get(\"limit\"));\n    orderby.ifPresent(page::setOrderBy);\n    return page.doSelectPage(select);\n  }\n}\n"
  },
  {
    "path": "src/main/resources/application-dev.yml",
    "content": "hospital:\n  uploadPath: D:/var/uploaded_files/\nlogging:\n  level:\n    root: info\n    me.zbl: debug\nspring:\n  datasource:\n    type: com.alibaba.druid.pool.DruidDataSource\n    driverClassName: com.mysql.jdbc.Driver\n    url: jdbc:mysql://47.93.187.44:3306/hospital-drug?useUnicode=true&characterEncoding=utf8\n    username: dev\n    password: 19961120\n    initialSize: 1\n    minIdle: 3\n    maxActive: 20\n    # 配置获取连接等待超时的时间\n    maxWait: 60000\n    # 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒\n    timeBetweenEvictionRunsMillis: 60000\n    # 配置一个连接在池中最小生存的时间，单位是毫秒\n    minEvictableIdleTimeMillis: 30000\n    validationQuery: select 'x'\n    testWhileIdle: true\n    testOnBorrow: false\n    testOnReturn: false\n    # 打开PSCache，并且指定每个连接上PSCache的大小\n    poolPreparedStatements: true\n    maxPoolPreparedStatementPerConnectionSize: 20\n    # 配置监控统计拦截的filters，去掉后监控界面sql无法统计，'wall'用于防火墙\n    filters: stat,wall,slf4j\n    # 通过connectProperties属性来打开mergeSql功能；慢SQL记录\n    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000\n    # 合并多个DruidDataSource的监控数据\n    #useGlobalDataSourceStat: true\n  redis:\n      host: localhost\n      port: 6379\n      password:\n      # 连接超时时间（毫秒）\n      timeout: 10000\n      pool:\n        # 连接池中的最大空闲连接\n        max-idle: 8\n        # 连接池中的最小空闲连接\n        min-idle: 10\n        # 连接池最大连接数（使用负值表示没有限制）\n        max-active: 100\n        # 连接池最大阻塞等待时间（使用负值表示没有限制）\n        max-wait: -1"
  },
  {
    "path": "src/main/resources/application-pro.yml",
    "content": "hospital:\n  uploadPath: drug-sys/uploaded_files/\nlogging:\n  level:\n    root: error\n    me.zbl: info\nspring:\n  datasource:\n    type: com.alibaba.druid.pool.DruidDataSource\n    driverClassName: com.mysql.jdbc.Driver\n    url: jdbc:mysql://47.93.187.44:3306/hospital-drug?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC\n    username: dev\n    password: 19961120\n    initialSize: 1\n    minIdle: 3\n    maxActive: 20\n    # 配置获取连接等待超时的时间\n    maxWait: 60000\n    # 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒\n    timeBetweenEvictionRunsMillis: 60000\n    # 配置一个连接在池中最小生存的时间，单位是毫秒\n    minEvictableIdleTimeMillis: 30000\n    validationQuery: select 'x'\n    testWhileIdle: true\n    testOnBorrow: false\n    testOnReturn: false\n    # 打开PSCache，并且指定每个连接上PSCache的大小\n    poolPreparedStatements: true\n    maxPoolPreparedStatementPerConnectionSize: 20\n    # 配置监控统计拦截的filters，去掉后监控界面sql无法统计，'wall'用于防火墙\n    filters: stat,wall,slf4j\n    # 通过connectProperties属性来打开mergeSql功能；慢SQL记录\n    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000\n    # 合并多个DruidDataSource的监控数据\n    #useGlobalDataSourceStat: true\n  redis:\n      host: localhost\n      port: 6379\n      password:\n      # 连接超时时间（毫秒）\n      timeout: 10000\n      pool:\n        # 连接池中的最大空闲连接\n        max-idle: 8\n        # 连接池中的最小空闲连接\n        min-idle: 10\n        # 连接池最大连接数（使用负值表示没有限制）\n        max-active: 100\n        # 连接池最大阻塞等待时间（使用负值表示没有限制）\n        max-wait: -1"
  },
  {
    "path": "src/main/resources/application.yml",
    "content": "server:\n  port: 8086\n  session-timeout: 36000\n  tomcat:\n    uri-encoding: utf-8\n    # max-threads: 1000\n    # min-spare-threads: 30\nsecurity:\n  basic:\n    enabled: false\nspring:\n  thymeleaf:\n    mode: LEGACYHTML5\n    cache: false\n  jackson:\n    time-zone: GMT+8\n    date-format: yyyy-MM-dd HH:mm:ss\n  profiles: \n    active: dev\n  http:\n    multipart:\n      max-file-size: 30Mb\n      max-request-size: 30Mb\n  devtools:\n    restart:\n      enabled: true    \nmybatis: \n  configuration:\n    map-underscore-to-camel-case: true\n  mapper-locations: mybatis/**/*Mapper.xml\n  typeAliasesPackage: me.zbl.**.domain\n#配置缓存和session存储方式，默认ehcache,可选redis\ncacheType: ehcache\n"
  },
  {
    "path": "src/main/resources/config/ehcache.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ehcache xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:noNamespaceSchemaLocation=\"http://ehcache.org/ehcache.xsd\"\n\tupdateCheck=\"false\">\n\t<diskStore path=\"java.io.tmpdir/Tmp_EhCache\" />\n\t<defaultCache eternal=\"false\" maxElementsInMemory=\"1000\"\n\t\toverflowToDisk=\"false\" diskPersistent=\"false\" timeToIdleSeconds=\"0\"\n\t\ttimeToLiveSeconds=\"600\" memoryStoreEvictionPolicy=\"LRU\" />\n\t<cache name=\"role\" eternal=\"false\" maxElementsInMemory=\"10000\"\n\t\toverflowToDisk=\"false\" diskPersistent=\"false\" timeToIdleSeconds=\"0\"\n\t\ttimeToLiveSeconds=\"0\" memoryStoreEvictionPolicy=\"LFU\" />\n</ehcache>"
  },
  {
    "path": "src/main/resources/config/quartz.properties",
    "content": ""
  },
  {
    "path": "src/main/resources/generatorConfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE generatorConfiguration\n        PUBLIC \"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd\">\n\n<generatorConfiguration>\n    <!--<classPathEntry location=\"/Program Files/IBM/SQLLIB/java/db2java.zip\" />-->\n\n    <!--<selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">-->\n    <!--SELECT REPLACE(UUID(),'-','') AS ID FROM DUAL-->\n    <!--</selectKey>-->\n\n    <context id=\"MySQLTables\" targetRuntime=\"MyBatis3\">\n        <commentGenerator>\n            <property name=\"suppressAllComments\" value=\"true\"/>\n        </commentGenerator>\n        <jdbcConnection driverClass=\"com.mysql.jdbc.Driver\"\n                        connectionURL=\"jdbc:mysql://47.93.187.44:3306/hospital-drug\"\n                        userId=\"root\"\n                        password=\"root\">\n        </jdbcConnection>\n\n        <javaTypeResolver>\n            <property name=\"forceBigDecimals\" value=\"false\"/>\n        </javaTypeResolver>\n\n        <javaModelGenerator targetPackage=\"me.zbl.app.domain\" targetProject=\"src/main/java\">\n            <property name=\"enableSubPackages\" value=\"true\"/>\n            <property name=\"trimStrings\" value=\"true\"/>\n        </javaModelGenerator>\n\n        <sqlMapGenerator targetPackage=\"mybatis/app\" targetProject=\"src/main/resources\">\n            <property name=\"enableSubPackages\" value=\"true\"/>\n        </sqlMapGenerator>\n\n        <javaClientGenerator type=\"XMLMAPPER\" targetPackage=\"me.zbl.app.dao\" targetProject=\"src/main/java\">\n            <property name=\"enableSubPackages\" value=\"true\"/>\n        </javaClientGenerator>\n\n        <!-- 药品表 -->\n        <table tableName=\"app_drug\" domainObjectName=\"Drug\" modelType=\"conditional\" enableSelectByExample=\"false\"\n               enableCountByExample=\"false\" enableDeleteByExample=\"false\" enableUpdateByExample=\"false\">\n            <generatedKey column=\"ID\" sqlStatement=\"select replace(uuid(),'-','') from dual\" type=\"pre\"/>\n        </table>\n\n        <!-- 顾客表 -->\n        <table tableName=\"app_consumer\" domainObjectName=\"Consumer\" modelType=\"conditional\" enableSelectByExample=\"false\"\n               enableCountByExample=\"false\" enableDeleteByExample=\"false\" enableUpdateByExample=\"false\">\n            <generatedKey column=\"ID\" sqlStatement=\"select replace(uuid(),'-','') from dual\" type=\"pre\"/>\n        </table>\n\n        <!-- 过期时间记录表 -->\n        <table tableName=\"app_expire\" domainObjectName=\"Expire\" modelType=\"conditional\" enableSelectByExample=\"false\"\n               enableCountByExample=\"false\" enableDeleteByExample=\"false\" enableUpdateByExample=\"false\">\n            <generatedKey column=\"ID\" sqlStatement=\"select replace(uuid(),'-','') from dual\" type=\"pre\"/>\n        </table>\n\n        <!-- 仓储记录表 -->\n        <table tableName=\"app_inventory_record\" domainObjectName=\"Inventory\" modelType=\"conditional\" enableSelectByExample=\"false\"\n               enableCountByExample=\"false\" enableDeleteByExample=\"false\" enableUpdateByExample=\"false\">\n            <generatedKey column=\"ID\" sqlStatement=\"select replace(uuid(),'-','') from dual\" type=\"pre\"/>\n        </table>\n\n        <!-- 供应商表 -->\n        <table tableName=\"app_supplier\" domainObjectName=\"Supplier\" modelType=\"conditional\" enableSelectByExample=\"false\"\n               enableCountByExample=\"false\" enableDeleteByExample=\"false\" enableUpdateByExample=\"false\">\n            <generatedKey column=\"ID\" sqlStatement=\"select replace(uuid(),'-','') from dual\" type=\"pre\"/>\n        </table>\n\n    </context>\n</generatorConfiguration>"
  },
  {
    "path": "src/main/resources/logback-spring.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration  scan=\"true\" scanPeriod=\"60 seconds\" debug=\"false\">\n    <contextName>logback</contextName>\n    <!--输出到控制台-->\n    <appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <!--按天生成日志-->\n    <appender name=\"logFile\"  class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <Prudent>true</Prudent>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <FileNamePattern>\n                applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log\n            </FileNamePattern>\n        </rollingPolicy>\n        <layout class=\"ch.qos.logback.classic.PatternLayout\">\n            <Pattern>\n                %d{yyyy-MM-dd HH:mm:ss} -%msg%n\n            </Pattern>\n        </layout>\n    </appender>\n\n    <logger name=\"me.zbl\" additivity=\"false\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"logFile\" />\n    </logger>\n\n    <root level=\"error\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"logFile\" />\n    </root>\n\n</configuration>\n"
  },
  {
    "path": "src/main/resources/mybatis/activiti/SalaryMapper.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\n<mapper namespace=\"me.zbl.activity.dao.SalaryDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.activity.domain.SalaryDO\">\n\t\tselect `id`,`PROC_INS_ID`,`USER_ID`,`OFFICE_ID`,`POST`,`AGE`,`EDU`,`CONTENT`,`OLDA`,`OLDB`,`OLDC`,`NEWA`,`NEWB`,`NEWC`,`ADD_NUM`,`EXE_DATE`,`HR_TEXT`,`LEAD_TEXT`,`MAIN_LEAD_TEXT`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag` from salary where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.activity.domain.SalaryDO\">\n\t\tselect `id`,`PROC_INS_ID`,`USER_ID`,`OFFICE_ID`,`POST`,`AGE`,`EDU`,`CONTENT`,`OLDA`,`OLDB`,`OLDC`,`NEWA`,`NEWB`,`NEWC`,`ADD_NUM`,`EXE_DATE`,`HR_TEXT`,`LEAD_TEXT`,`MAIN_LEAD_TEXT`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag` from salary\n        <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"procInsId != null and procInsId != ''\"> and PROC_INS_ID = #{procInsId} </if>\n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and USER_ID = #{userId} </if>\n\t\t  \t\t  <if test=\"officeId != null and officeId != ''\"> and OFFICE_ID = #{officeId} </if>\n\t\t  \t\t  <if test=\"post != null and post != ''\"> and POST = #{post} </if>\n\t\t  \t\t  <if test=\"age != null and age != ''\"> and AGE = #{age} </if>\n\t\t  \t\t  <if test=\"edu != null and edu != ''\"> and EDU = #{edu} </if>\n\t\t  \t\t  <if test=\"content != null and content != ''\"> and CONTENT = #{content} </if>\n\t\t  \t\t  <if test=\"olda != null and olda != ''\"> and OLDA = #{olda} </if>\n\t\t  \t\t  <if test=\"oldb != null and oldb != ''\"> and OLDB = #{oldb} </if>\n\t\t  \t\t  <if test=\"oldc != null and oldc != ''\"> and OLDC = #{oldc} </if>\n\t\t  \t\t  <if test=\"newa != null and newa != ''\"> and NEWA = #{newa} </if>\n\t\t  \t\t  <if test=\"newb != null and newb != ''\"> and NEWB = #{newb} </if>\n\t\t  \t\t  <if test=\"newc != null and newc != ''\"> and NEWC = #{newc} </if>\n\t\t  \t\t  <if test=\"addNum != null and addNum != ''\"> and ADD_NUM = #{addNum} </if>\n\t\t  \t\t  <if test=\"exeDate != null and exeDate != ''\"> and EXE_DATE = #{exeDate} </if>\n\t\t  \t\t  <if test=\"hrText != null and hrText != ''\"> and HR_TEXT = #{hrText} </if>\n\t\t  \t\t  <if test=\"leadText != null and leadText != ''\"> and LEAD_TEXT = #{leadText} </if>\n\t\t  \t\t  <if test=\"mainLeadText != null and mainLeadText != ''\"> and MAIN_LEAD_TEXT = #{mainLeadText} </if>\n\t\t  \t\t  <if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t  <if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t  \t\t  <if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t  \t\t  <if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t  \t\t  <if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by id desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from salary\n\t\t <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"procInsId != null and procInsId != ''\"> and PROC_INS_ID = #{procInsId} </if>\n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and USER_ID = #{userId} </if>\n\t\t  \t\t  <if test=\"officeId != null and officeId != ''\"> and OFFICE_ID = #{officeId} </if>\n\t\t  \t\t  <if test=\"post != null and post != ''\"> and POST = #{post} </if>\n\t\t  \t\t  <if test=\"age != null and age != ''\"> and AGE = #{age} </if>\n\t\t  \t\t  <if test=\"edu != null and edu != ''\"> and EDU = #{edu} </if>\n\t\t  \t\t  <if test=\"content != null and content != ''\"> and CONTENT = #{content} </if>\n\t\t  \t\t  <if test=\"olda != null and olda != ''\"> and OLDA = #{olda} </if>\n\t\t  \t\t  <if test=\"oldb != null and oldb != ''\"> and OLDB = #{oldb} </if>\n\t\t  \t\t  <if test=\"oldc != null and oldc != ''\"> and OLDC = #{oldc} </if>\n\t\t  \t\t  <if test=\"newa != null and newa != ''\"> and NEWA = #{newa} </if>\n\t\t  \t\t  <if test=\"newb != null and newb != ''\"> and NEWB = #{newb} </if>\n\t\t  \t\t  <if test=\"newc != null and newc != ''\"> and NEWC = #{newc} </if>\n\t\t  \t\t  <if test=\"addNum != null and addNum != ''\"> and ADD_NUM = #{addNum} </if>\n\t\t  \t\t  <if test=\"exeDate != null and exeDate != ''\"> and EXE_DATE = #{exeDate} </if>\n\t\t  \t\t  <if test=\"hrText != null and hrText != ''\"> and HR_TEXT = #{hrText} </if>\n\t\t  \t\t  <if test=\"leadText != null and leadText != ''\"> and LEAD_TEXT = #{leadText} </if>\n\t\t  \t\t  <if test=\"mainLeadText != null and mainLeadText != ''\"> and MAIN_LEAD_TEXT = #{mainLeadText} </if>\n\t\t  \t\t  <if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t  <if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t  \t\t  <if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t  \t\t  <if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t  \t\t  <if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.activity.domain.SalaryDO\">\n\t\tinsert into salary\n\t\t(\n\t\t\t`id`, \n\t\t\t`PROC_INS_ID`, \n\t\t\t`USER_ID`, \n\t\t\t`OFFICE_ID`, \n\t\t\t`POST`, \n\t\t\t`AGE`, \n\t\t\t`EDU`, \n\t\t\t`CONTENT`, \n\t\t\t`OLDA`, \n\t\t\t`OLDB`, \n\t\t\t`OLDC`, \n\t\t\t`NEWA`, \n\t\t\t`NEWB`, \n\t\t\t`NEWC`, \n\t\t\t`ADD_NUM`, \n\t\t\t`EXE_DATE`, \n\t\t\t`HR_TEXT`, \n\t\t\t`LEAD_TEXT`, \n\t\t\t`MAIN_LEAD_TEXT`, \n\t\t\t`create_by`, \n\t\t\t`create_date`, \n\t\t\t`update_by`, \n\t\t\t`update_date`, \n\t\t\t`remarks`, \n\t\t\t`del_flag`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{id}, \n\t\t\t#{procInsId}, \n\t\t\t#{userId}, \n\t\t\t#{officeId}, \n\t\t\t#{post}, \n\t\t\t#{age}, \n\t\t\t#{edu}, \n\t\t\t#{content}, \n\t\t\t#{olda}, \n\t\t\t#{oldb}, \n\t\t\t#{oldc}, \n\t\t\t#{newa}, \n\t\t\t#{newb}, \n\t\t\t#{newc}, \n\t\t\t#{addNum}, \n\t\t\t#{exeDate}, \n\t\t\t#{hrText}, \n\t\t\t#{leadText}, \n\t\t\t#{mainLeadText}, \n\t\t\t#{createBy}, \n\t\t\t#{createDate}, \n\t\t\t#{updateBy}, \n\t\t\t#{updateDate}, \n\t\t\t#{remarks}, \n\t\t\t#{delFlag}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.activity.domain.SalaryDO\">\n\t\tupdate salary \n\t\t<set>\n\t\t\t<if test=\"procInsId != null\">`PROC_INS_ID` = #{procInsId}, </if>\n\t\t\t<if test=\"userId != null\">`USER_ID` = #{userId}, </if>\n\t\t\t<if test=\"officeId != null\">`OFFICE_ID` = #{officeId}, </if>\n\t\t\t<if test=\"post != null\">`POST` = #{post}, </if>\n\t\t\t<if test=\"age != null\">`AGE` = #{age}, </if>\n\t\t\t<if test=\"edu != null\">`EDU` = #{edu}, </if>\n\t\t\t<if test=\"content != null\">`CONTENT` = #{content}, </if>\n\t\t\t<if test=\"olda != null\">`OLDA` = #{olda}, </if>\n\t\t\t<if test=\"oldb != null\">`OLDB` = #{oldb}, </if>\n\t\t\t<if test=\"oldc != null\">`OLDC` = #{oldc}, </if>\n\t\t\t<if test=\"newa != null\">`NEWA` = #{newa}, </if>\n\t\t\t<if test=\"newb != null\">`NEWB` = #{newb}, </if>\n\t\t\t<if test=\"newc != null\">`NEWC` = #{newc}, </if>\n\t\t\t<if test=\"addNum != null\">`ADD_NUM` = #{addNum}, </if>\n\t\t\t<if test=\"exeDate != null\">`EXE_DATE` = #{exeDate}, </if>\n\t\t\t<if test=\"hrText != null\">`HR_TEXT` = #{hrText}, </if>\n\t\t\t<if test=\"leadText != null\">`LEAD_TEXT` = #{leadText}, </if>\n\t\t\t<if test=\"mainLeadText != null\">`MAIN_LEAD_TEXT` = #{mainLeadText}, </if>\n\t\t\t<if test=\"createBy != null\">`create_by` = #{createBy}, </if>\n\t\t\t<if test=\"createDate != null\">`create_date` = #{createDate}, </if>\n\t\t\t<if test=\"updateBy != null\">`update_by` = #{updateBy}, </if>\n\t\t\t<if test=\"updateDate != null\">`update_date` = #{updateDate}, </if>\n\t\t\t<if test=\"remarks != null\">`remarks` = #{remarks}, </if>\n\t\t\t<if test=\"delFlag != null\">`del_flag` = #{delFlag}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from salary where id = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from salary where id in \n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/app/ConsumerMapper.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=\"me.zbl.app.dao.ConsumerMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"me.zbl.app.domain.Consumer\">\n        <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\"/>\n        <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n        <result column=\"tel\" jdbcType=\"VARCHAR\" property=\"tel\"/>\n    </resultMap>\n    <sql id=\"Base_Column_List\">\n        id, name, tel\n    </sql>\n    <!-- selectConsumerByTel -->\n    <select id=\"selectConsumerByTel\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from app_consumer\n        where tel = #{tel}\n    </select>\n    <!-- selectAllConsumer -->\n    <select id=\"selectAllConsumer\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from app_consumer\n        <if test=\"offset != null and limit != null\">\n            limit ${offset}, ${limit}\n        </if>\n    </select>\n    <!-- count -->\n    <select id=\"count\" resultType=\"int\">\n        select count(*)\n        from app_consumer\n    </select>\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from app_consumer\n        where id = #{id,jdbcType=VARCHAR}\n    </select>\n    <select id=\"selectByName\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from app_consumer\n        where name like CONCAT(CONCAT('%',#{name},'%'))\n    </select>\n    <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n        delete from app_consumer\n        where id = #{id,jdbcType=VARCHAR}\n    </delete>\n    <insert id=\"insert\" parameterType=\"me.zbl.app.domain.Consumer\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_consumer (id, name, tel\n        )\n        values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{tel,jdbcType=VARCHAR}\n        )\n    </insert>\n    <insert id=\"insertSelective\" parameterType=\"me.zbl.app.domain.Consumer\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_consumer\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            id,\n            <if test=\"name != null\">\n                name,\n            </if>\n            <if test=\"tel != null\">\n                tel,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            #{id,jdbcType=VARCHAR},\n            <if test=\"name != null\">\n                #{name,jdbcType=VARCHAR},\n            </if>\n            <if test=\"tel != null\">\n                #{tel,jdbcType=VARCHAR},\n            </if>\n        </trim>\n    </insert>\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"me.zbl.app.domain.Consumer\">\n        update app_consumer\n        <set>\n            <if test=\"name != null\">\n                name = #{name,jdbcType=VARCHAR},\n            </if>\n            <if test=\"tel != null\">\n                tel = #{tel,jdbcType=VARCHAR},\n            </if>\n        </set>\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n    <update id=\"updateByPrimaryKey\" parameterType=\"me.zbl.app.domain.Consumer\">\n        update app_consumer\n        set name = #{name,jdbcType=VARCHAR},\n        tel = #{tel,jdbcType=VARCHAR}\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/app/DrugMapper.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=\"me.zbl.app.dao.DrugMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"me.zbl.app.domain.Drug\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\" />\n    <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\" />\n    <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\" />\n    <result column=\"invalid\" jdbcType=\"VARCHAR\" property=\"invalid\" />\n    <result column=\"quality_guarantee_period\" jdbcType=\"INTEGER\" property=\"qualityGuaranteePeriod\" />\n    <result column=\"lower_limit\" jdbcType=\"INTEGER\" property=\"lowerLimit\" />\n    <result column=\"supplier_id\" jdbcType=\"VARCHAR\" property=\"supplierId\" />\n    <result column=\"specification\" jdbcType=\"VARCHAR\" property=\"specification\" />\n  </resultMap>\n\n  <resultMap id=\"DrugListResultMap\" type=\"me.zbl.app.domain.DrugDO\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\" />\n    <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\" />\n    <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\" />\n    <result column=\"invalid\" jdbcType=\"VARCHAR\" property=\"invalid\" />\n    <result column=\"quality_guarantee_period\" jdbcType=\"INTEGER\" property=\"qualityGuaranteePeriod\" />\n    <result column=\"lower_limit\" jdbcType=\"INTEGER\" property=\"lowerLimit\" />\n    <result column=\"supplier_id\" jdbcType=\"VARCHAR\" property=\"supplierId\" />\n    <result column=\"specification\" jdbcType=\"VARCHAR\" property=\"specification\" />\n    <result column=\"supplier\" jdbcType=\"VARCHAR\" property=\"supplier\" />\n  </resultMap>\n\n  <sql id=\"Base_Column_List\">\n    id, name, quantity, price, invalid, quality_guarantee_period, lower_limit, supplier_id,\n    specification\n  </sql>\n  <!-- selectAllDrug -->\n  <select id=\"selectAllDrug\" parameterType=\"java.util.Map\" resultMap=\"DrugListResultMap\">\n    select\n    app_drug.id, app_drug.name, quantity, price, invalid, quality_guarantee_period, lower_limit, supplier_id,\n    specification,\n    s.name as supplier\n    from app_drug join app_supplier s on app_drug.supplier_id = s.id\n    <if test=\"offset != null and limit != null\">\n      limit ${offset}, ${limit}\n    </if>\n  </select>\n  <!-- count -->\n  <select id=\"count\" resultType=\"int\">\n    select count(*)\n    from app_drug\n  </select>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select\n    <include refid=\"Base_Column_List\" />\n    from app_drug\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n\n  <select id=\"selectByExpireDate\" parameterType=\"java.util.Date\" resultMap=\"BaseResultMap\">\n    select\n    app_drug.id, name, quantity, price, invalid, quality_guarantee_period, lower_limit, supplier_id,\n    specification\n    from app_drug, app_expire\n    where app_drug.id = app_expire.drug_id and\n    expired_date = DATE_FORMAT(#{date,jdbcType=TIMESTAMP},'%y-%m-%d');\n  </select>\n\n  <select id=\"selectOverLowerLimit\" resultMap=\"BaseResultMap\">\n    select\n    <include refid=\"Base_Column_List\" />\n    from app_drug\n    WHERE quantity <![CDATA[\n      <=\n    ]]>\n    lower_limit\n  </select>\n\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from app_drug\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"me.zbl.app.domain.Drug\">\n    insert into app_drug (id, name, quantity,\n      price, invalid, quality_guarantee_period,\n      lower_limit, supplier_id, specification\n      )\n    values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{quantity,jdbcType=INTEGER},\n      #{price,jdbcType=DECIMAL}, #{invalid,jdbcType=VARCHAR}, #{qualityGuaranteePeriod,jdbcType=INTEGER},\n      #{lowerLimit,jdbcType=INTEGER}, #{supplierId,jdbcType=VARCHAR}, #{specification,jdbcType=VARCHAR}\n      )\n  </insert>\n  <insert id=\"insertSelective\" parameterType=\"me.zbl.app.domain.Drug\">\n    insert into app_drug\n    <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n      id,\n      <if test=\"name != null\">\n        name,\n      </if>\n      <if test=\"quantity != null\">\n        quantity,\n      </if>\n      <if test=\"price != null\">\n        price,\n      </if>\n      <if test=\"invalid != null\">\n        invalid,\n      </if>\n      <if test=\"qualityGuaranteePeriod != null\">\n        quality_guarantee_period,\n      </if>\n      <if test=\"lowerLimit != null\">\n        lower_limit,\n      </if>\n      <if test=\"supplierId != null\">\n        supplier_id,\n      </if>\n      <if test=\"specification != null\">\n        specification,\n      </if>\n    </trim>\n    <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n      #{id,jdbcType=VARCHAR},\n      <if test=\"name != null\">\n        #{name,jdbcType=VARCHAR},\n      </if>\n      <if test=\"quantity != null\">\n        #{quantity,jdbcType=INTEGER},\n      </if>\n      <if test=\"price != null\">\n        #{price,jdbcType=DECIMAL},\n      </if>\n      <if test=\"invalid != null\">\n        #{invalid,jdbcType=VARCHAR},\n      </if>\n      <if test=\"qualityGuaranteePeriod != null\">\n        #{qualityGuaranteePeriod,jdbcType=INTEGER},\n      </if>\n      <if test=\"lowerLimit != null\">\n        #{lowerLimit,jdbcType=INTEGER},\n      </if>\n      <if test=\"supplierId != null\">\n        #{supplierId,jdbcType=VARCHAR},\n      </if>\n      <if test=\"specification != null\">\n        #{specification,jdbcType=VARCHAR},\n      </if>\n    </trim>\n  </insert>\n\n  <!-- increaseAndDecreaseQuantity -->\n  <update id=\"increaseAndDecreaseQuantity\" parameterType=\"java.util.Map\">\n    update app_drug set quantity = quantity + #{quantity,jdbcType=INTEGER} where id = #{drugId,jdbcType=VARCHAR}\n  </update>\n\n  <update id=\"updateByPrimaryKeySelective\" parameterType=\"me.zbl.app.domain.Drug\">\n    update app_drug\n    <set>\n      <if test=\"name != null\">\n        name = #{name,jdbcType=VARCHAR},\n      </if>\n      <if test=\"quantity != null\">\n        quantity = #{quantity,jdbcType=INTEGER},\n      </if>\n      <if test=\"price != null\">\n        price = #{price,jdbcType=DECIMAL},\n      </if>\n      <if test=\"invalid != null\">\n        invalid = #{invalid,jdbcType=VARCHAR},\n      </if>\n      <if test=\"qualityGuaranteePeriod != null\">\n        quality_guarantee_period = #{qualityGuaranteePeriod,jdbcType=INTEGER},\n      </if>\n      <if test=\"lowerLimit != null\">\n        lower_limit = #{lowerLimit,jdbcType=INTEGER},\n      </if>\n      <if test=\"supplierId != null\">\n        supplier_id = #{supplierId,jdbcType=VARCHAR},\n      </if>\n      <if test=\"specification != null\">\n        specification = #{specification,jdbcType=VARCHAR},\n      </if>\n    </set>\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <update id=\"updateByPrimaryKey\" parameterType=\"me.zbl.app.domain.Drug\">\n    update app_drug\n    set name = #{name,jdbcType=VARCHAR},\n      quantity = #{quantity,jdbcType=INTEGER},\n      price = #{price,jdbcType=DECIMAL},\n      invalid = #{invalid,jdbcType=VARCHAR},\n      quality_guarantee_period = #{qualityGuaranteePeriod,jdbcType=INTEGER},\n      lower_limit = #{lowerLimit,jdbcType=INTEGER},\n      supplier_id = #{supplierId,jdbcType=VARCHAR},\n      specification = #{specification,jdbcType=VARCHAR}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/app/ExpireMapper.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=\"me.zbl.app.dao.ExpireMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"me.zbl.app.domain.Expire\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"drug_id\" jdbcType=\"VARCHAR\" property=\"drugId\" />\n    <result column=\"expired_date\" jdbcType=\"DATE\" property=\"expiredDate\" />\n  </resultMap>\n  <sql id=\"Base_Column_List\">\n    id, drug_id, expired_date\n  </sql>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select \n    <include refid=\"Base_Column_List\" />\n    from app_expire\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n\n  <!-- select expire on target date -->\n  <select id=\"selectByDate\" parameterType=\"java.util.Date\" resultMap=\"BaseResultMap\">\n    select\n    <include refid=\"Base_Column_List\" />\n    from app_expire\n    where expired_date = DATE_FORMAT(#{date,jdbcType=TIMESTAMP},'%y-%m-%d');\n  </select>\n\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from app_expire\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"me.zbl.app.domain.Expire\">\n    <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n      select replace(uuid(),'-','') from dual\n    </selectKey>\n    insert into app_expire (id, drug_id, expired_date\n      )\n    values (#{id,jdbcType=VARCHAR}, #{drugId,jdbcType=VARCHAR}, #{expiredDate,jdbcType=DATE}\n      )\n  </insert>\n  <insert id=\"insertSelective\" parameterType=\"me.zbl.app.domain.Expire\">\n    <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n      select replace(uuid(),'-','') from dual\n    </selectKey>\n    insert into app_expire\n    <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n      id,\n      <if test=\"drugId != null\">\n        drug_id,\n      </if>\n      <if test=\"expiredDate != null\">\n        expired_date,\n      </if>\n    </trim>\n    <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n      #{id,jdbcType=VARCHAR},\n      <if test=\"drugId != null\">\n        #{drugId,jdbcType=VARCHAR},\n      </if>\n      <if test=\"expiredDate != null\">\n        #{expiredDate,jdbcType=DATE},\n      </if>\n    </trim>\n  </insert>\n  <update id=\"updateByPrimaryKeySelective\" parameterType=\"me.zbl.app.domain.Expire\">\n    update app_expire\n    <set>\n      <if test=\"drugId != null\">\n        drug_id = #{drugId,jdbcType=VARCHAR},\n      </if>\n      <if test=\"expiredDate != null\">\n        expired_date = #{expiredDate,jdbcType=DATE},\n      </if>\n    </set>\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <update id=\"updateByPrimaryKey\" parameterType=\"me.zbl.app.domain.Expire\">\n    update app_expire\n    set drug_id = #{drugId,jdbcType=VARCHAR},\n      expired_date = #{expiredDate,jdbcType=DATE}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/app/InventoryMapper.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=\"me.zbl.app.dao.InventoryMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"me.zbl.app.domain.Inventory\">\n        <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\"/>\n        <result column=\"consumer_id\" jdbcType=\"VARCHAR\" property=\"consumerId\"/>\n        <result column=\"drug_id\" jdbcType=\"VARCHAR\" property=\"drugId\"/>\n        <result column=\"type\" jdbcType=\"VARCHAR\" property=\"type\"/>\n        <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\"/>\n        <result column=\"ammount\" jdbcType=\"DECIMAL\" property=\"ammount\"/>\n        <result column=\"comment\" jdbcType=\"VARCHAR\" property=\"comment\"/>\n        <result column=\"manager\" jdbcType=\"VARCHAR\" property=\"manager\"/>\n        <result column=\"gmt_created\" jdbcType=\"TIMESTAMP\" property=\"gmtCreated\"/>\n        <result column=\"gmt_modified\" jdbcType=\"TIMESTAMP\" property=\"gmtModified\"/>\n    </resultMap>\n    <resultMap id=\"DrugInResultMap\" type=\"me.zbl.app.domain.DrugInDO\">\n        <result column=\"type\" jdbcType=\"VARCHAR\" property=\"type\"/>\n        <result column=\"manager\" jdbcType=\"VARCHAR\" property=\"manager\"/>\n        <result column=\"quantityNow\" jdbcType=\"INTEGER\" property=\"quantityNow\"/>\n        <result column=\"drugId\" jdbcType=\"VARCHAR\" property=\"drugId\"/>\n        <result column=\"drugName\" jdbcType=\"VARCHAR\" property=\"drugName\"/>\n        <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\"/>\n        <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\"/>\n        <result column=\"specification\" jdbcType=\"VARCHAR\" property=\"specification\"/>\n        <result column=\"ammount\" jdbcType=\"DECIMAL\" property=\"ammount\"/>\n        <result column=\"supplierName\" jdbcType=\"VARCHAR\" property=\"supplierName\"/>\n        <result column=\"gmt_created\" jdbcType=\"TIMESTAMP\" property=\"gmtCreated\"/>\n    </resultMap>\n    <resultMap id=\"DrugOutResultMap\" type=\"me.zbl.app.domain.DrugOutDO\">\n        <result column=\"type\" jdbcType=\"VARCHAR\" property=\"type\"/>\n        <result column=\"manager\" jdbcType=\"VARCHAR\" property=\"manager\"/>\n        <result column=\"quantityNow\" jdbcType=\"INTEGER\" property=\"quantityNow\"/>\n        <result column=\"drugId\" jdbcType=\"VARCHAR\" property=\"drugId\"/>\n        <result column=\"drugName\" jdbcType=\"VARCHAR\" property=\"drugName\"/>\n        <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\"/>\n        <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\"/>\n        <result column=\"specification\" jdbcType=\"VARCHAR\" property=\"specification\"/>\n        <result column=\"comment\" jdbcType=\"VARCHAR\" property=\"comment\"/>\n        <result column=\"ammount\" jdbcType=\"DECIMAL\" property=\"ammount\"/>\n        <result column=\"supplierName\" jdbcType=\"VARCHAR\" property=\"supplierName\"/>\n        <result column=\"gmt_created\" jdbcType=\"TIMESTAMP\" property=\"gmtCreated\"/>\n    </resultMap>\n    <resultMap id=\"SaleResultMap\" type=\"me.zbl.app.domain.SaleDO\">\n        <result column=\"order_id\" jdbcType=\"VARCHAR\" property=\"orderId\"/>\n        <result column=\"type\" jdbcType=\"VARCHAR\" property=\"type\"/>\n        <result column=\"manager\" jdbcType=\"VARCHAR\" property=\"manager\"/>\n        <result column=\"quantityNow\" jdbcType=\"INTEGER\" property=\"quantityNow\"/>\n        <result column=\"drugId\" jdbcType=\"VARCHAR\" property=\"drugId\"/>\n        <result column=\"drugName\" jdbcType=\"VARCHAR\" property=\"drugName\"/>\n        <result column=\"quantity\" jdbcType=\"INTEGER\" property=\"quantity\"/>\n        <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\"/>\n        <result column=\"specification\" jdbcType=\"VARCHAR\" property=\"specification\"/>\n        <result column=\"comment\" jdbcType=\"VARCHAR\" property=\"comment\"/>\n        <result column=\"ammount\" jdbcType=\"DECIMAL\" property=\"ammount\"/>\n        <result column=\"supplierName\" jdbcType=\"VARCHAR\" property=\"supplierName\"/>\n        <result column=\"consumer\" jdbcType=\"VARCHAR\" property=\"consumer\"/>\n        <result column=\"gmt_created\" jdbcType=\"TIMESTAMP\" property=\"gmtCreated\"/>\n    </resultMap>\n    <resultMap id=\"StaSaleResultMap\" type=\"me.zbl.app.domain.StaSaleDO\">\n        <result column=\"R_DATE_UNIT\" jdbcType=\"VARCHAR\" property=\"dateUnit\"/>\n        <result column=\"R_SUM_QUANTITY\" jdbcType=\"DECIMAL\" property=\"saleCount\"/>\n    </resultMap>\n    <sql id=\"Base_Column_List\">\n        id, consumer_id, drug_id, type, quantity, ammount, comment, manager,\n        gmt_created, gmt_modified\n    </sql>\n\n    <!-- staSaleDay -->\n    <select id=\"staSaleDay\" resultMap=\"StaSaleResultMap\">\n        SELECT\n            DATE_FORMAT(T_TMP.F_DATE, '%c月%e日') AS R_DATE_UNIT,\n            IFNULL(SUM(T_INVEN.quantity), 0)    AS R_SUM_QUANTITY\n        FROM\n            (\n                SELECT @cdate := DATE_SUB(@cdate, INTERVAL 1 DAY) AS F_DATE\n                FROM\n                    (SELECT @cdate := DATE_ADD(CURRENT_DATE, INTERVAL 1 DAY)\n                     FROM app_inventory_record) T_TMP2\n                LIMIT 30\n            ) T_TMP\n            LEFT JOIN app_inventory_record T_INVEN\n                ON DATE(T_TMP.F_DATE) = DATE(T_INVEN.gmt_created)\n                   AND T_INVEN.TYPE = '3'\n        GROUP BY\n            T_TMP.F_DATE\n        ORDER BY\n            T_TMP.F_DATE ASC;\n    </select>\n\n    <!-- staSaleMonth -->\n    <select id=\"staSaleMonth\" resultMap=\"StaSaleResultMap\">\n        SELECT\n            DATE_FORMAT(T_TMP.F_DATE, '%c月') AS R_DATE_UNIT,\n            IFNULL(SUM(T_INVEN.quantity), 0) AS R_SUM_QUANTITY\n        FROM\n            (\n                SELECT @cdate := DATE_SUB(@cdate, INTERVAL 1 MONTH) AS F_DATE\n                FROM\n                    (SELECT @cdate := DATE_ADD(CURRENT_DATE, INTERVAL 1 MONTH)\n                     FROM app_inventory_record) T_TMP2\n                WHERE YEAR(@cdate) = YEAR(CURRENT_DATE)\n                LIMIT 12\n            ) T_TMP\n            LEFT JOIN app_inventory_record T_INVEN\n                ON YEAR(T_TMP.F_DATE) = YEAR(T_INVEN.gmt_created)\n                   AND MONTH(T_TMP.F_DATE) = MONTH(T_INVEN.gmt_created)\n                   AND T_INVEN.TYPE = '3'\n        WHERE YEAR(T_TMP.F_DATE) = YEAR(CURRENT_DATE)\n        GROUP BY\n            T_TMP.F_DATE\n        ORDER BY\n            T_TMP.F_DATE ASC;\n    </select>\n\n    <!-- staSaleYear -->\n    <select id=\"staSaleYear\" resultMap=\"StaSaleResultMap\">\n        SELECT\n            DATE_FORMAT(T_TMP.F_DATE, '%Y年') AS R_DATE_UNIT,\n            IFNULL(SUM(T_INVEN.quantity), 0) AS R_SUM_QUANTITY\n        FROM\n            (\n                SELECT @cdate := DATE_SUB(@cdate, INTERVAL 1 YEAR) AS F_DATE\n                FROM\n                    (SELECT @cdate := DATE_ADD(CURRENT_DATE, INTERVAL 1 YEAR)\n                     FROM app_inventory_record) T_TMP2\n                LIMIT 5\n            ) T_TMP\n            LEFT JOIN app_inventory_record T_INVEN\n                ON YEAR(T_TMP.F_DATE) = YEAR(T_INVEN.gmt_created)\n                   AND T_INVEN.TYPE = '3'\n        GROUP BY\n            T_TMP.F_DATE\n        ORDER BY\n            T_TMP.F_DATE ASC;\n    </select>\n\n    <!-- countIn -->\n    <select id=\"countIn\" resultType=\"int\">\n        select count(*)\n        from app_inventory_record\n        where type in ('1', '2')\n    </select>\n\n    <!-- countOut -->\n    <select id=\"countOut\" resultType=\"int\">\n        select count(*)\n        from app_inventory_record\n        where type in ('3', '4')\n    </select>\n\n    <!-- countSale -->\n    <select id=\"countSale\" resultType=\"int\">\n        select count(*)\n        from app_inventory_record\n        where type = '3'\n    </select>\n\n    <!--inList-->\n    <select id=\"inList\" parameterType=\"java.util.Map\" resultMap=\"DrugInResultMap\">\n        select\n        i.type, i.manager, d.quantity as quantityNow, d.id as drugId, d.`name` as\n        drugName,d.price,d.specification,i.quantity,i.ammount,s.name as supplierName,i.gmt_created\n        from app_inventory_record i,app_drug d,app_supplier s\n        where\n        i.drug_id = d.id and d.supplier_id = s.id\n        and i.type in('1','2')\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n            <otherwise>\n                order by gmt_created desc\n            </otherwise>\n        </choose>\n        <if test=\"offset != null and limit != null\">\n            limit ${offset}, ${limit}\n        </if>\n    </select>\n\n    <!--outList-->\n    <select id=\"outList\" parameterType=\"java.util.Map\" resultMap=\"DrugOutResultMap\">\n        select\n        i.comment, i.type, i.manager, d.quantity as quantityNow, d.id as drugId, d.`name` as\n        drugName,d.price,d.specification,i.quantity,i.ammount,s.name as supplierName,i.gmt_created\n        from app_inventory_record i,app_drug d,app_supplier s\n        where\n        i.drug_id = d.id and d.supplier_id = s.id\n        and i.type in('3','4')\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n            <otherwise>\n                order by gmt_created desc\n            </otherwise>\n        </choose>\n        <if test=\"offset != null and limit != null\">\n            limit ${offset}, ${limit}\n        </if>\n    </select>\n\n    <!--saleList-->\n    <select id=\"saleList\" parameterType=\"java.util.Map\" resultMap=\"SaleResultMap\">\n        select\n            i.id       as order_id,\n            i.comment,\n            i.type,\n            i.manager,\n            d.quantity as quantityNow,\n            d.id       as drugId,\n            d.`name`   as\n                          drugName,\n            d.price,\n            d.specification,\n            i.quantity,\n            i.ammount,\n            s.name     as supplierName,\n            i.gmt_created,\n            c.name     as consumer\n        from app_inventory_record i, app_drug d, app_supplier s, app_consumer c\n        where\n            i.drug_id = d.id and d.supplier_id = s.id and i.consumer_id = c.id\n            and i.type = '3'\n        order by gmt_created desc\n    </select>\n\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from app_inventory_record\n        where id = #{id,jdbcType=VARCHAR}\n    </select>\n    <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n        delete from app_inventory_record\n        where id = #{id,jdbcType=VARCHAR}\n    </delete>\n\n    <!-- drugInSave -->\n    <insert id=\"drugInSave\" parameterType=\"me.zbl.app.domain.DrugInFormDO\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_inventory_record (id,\n        drug_id, type, quantity,\n        ammount, comment, manager)\n        values (#{id,jdbcType=VARCHAR}, #{drugId,jdbcType=VARCHAR},\n        '1', #{quantity,jdbcType=INTEGER}, #{ammount,jdbcType=INTEGER},\n        '进货入库', #{manager,jdbcType=VARCHAR})\n    </insert>\n\n    <!-- drugOutSave -->\n    <insert id=\"drugOutSave\" parameterType=\"me.zbl.app.domain.DrugOutFormDO\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_inventory_record (id,\n        drug_id, type, quantity,\n        ammount, comment, manager)\n        values (#{id,jdbcType=VARCHAR}, #{drugId,jdbcType=VARCHAR},\n        '4', #{quantity,jdbcType=INTEGER}, #{ammount,jdbcType=INTEGER},\n        #{comment,jdbcType=VARCHAR}, #{manager,jdbcType=VARCHAR})\n    </insert>\n\n    <!-- saleSave -->\n    <insert id=\"saleSave\" parameterType=\"me.zbl.app.domain.DrugOutFormDO\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_inventory_record (id,\n        drug_id, type, quantity,\n        ammount, comment, manager, consumer_id)\n        values (#{id,jdbcType=VARCHAR}, #{drugId,jdbcType=VARCHAR},\n        '3', #{quantity,jdbcType=INTEGER}, #{ammount,jdbcType=INTEGER},\n        #{comment,jdbcType=VARCHAR}, #{manager,jdbcType=VARCHAR}, #{consumer})\n    </insert>\n\n    <insert id=\"insert\" parameterType=\"me.zbl.app.domain.Inventory\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_inventory_record (id, consumer_id,\n        drug_id, type, quantity,\n        ammount, comment, manager,\n        gmt_created, gmt_modified)\n        values (#{id,jdbcType=VARCHAR}, #{consumerId,jdbcType=VARCHAR},\n        #{drugId,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{quantity,jdbcType=INTEGER},\n        #{ammount,jdbcType=DECIMAL}, #{comment,jdbcType=VARCHAR}, #{manager,jdbcType=VARCHAR},\n        #{gmtCreated,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP})\n    </insert>\n    <insert id=\"insertSelective\" parameterType=\"me.zbl.app.domain.Inventory\">\n        <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n            select replace(uuid(),'-','') from dual\n        </selectKey>\n        insert into app_inventory_record\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            id,\n            <if test=\"consumerId != null\">\n                consumer_id,\n            </if>\n            <if test=\"drugId != null\">\n                drug_id,\n            </if>\n            <if test=\"type != null\">\n                type,\n            </if>\n            <if test=\"quantity != null\">\n                quantity,\n            </if>\n            <if test=\"ammount != null\">\n                ammount,\n            </if>\n            <if test=\"comment != null\">\n                comment,\n            </if>\n            <if test=\"manager != null\">\n                manager,\n            </if>\n            <if test=\"gmtCreated != null\">\n                gmt_created,\n            </if>\n            <if test=\"gmtModified != null\">\n                gmt_modified,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            #{id,jdbcType=VARCHAR},\n            <if test=\"consumerId != null\">\n                #{consumerId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"drugId != null\">\n                #{drugId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"type != null\">\n                #{type,jdbcType=VARCHAR},\n            </if>\n            <if test=\"quantity != null\">\n                #{quantity,jdbcType=INTEGER},\n            </if>\n            <if test=\"ammount != null\">\n                #{ammount,jdbcType=DECIMAL},\n            </if>\n            <if test=\"comment != null\">\n                #{comment,jdbcType=VARCHAR},\n            </if>\n            <if test=\"manager != null\">\n                #{manager,jdbcType=VARCHAR},\n            </if>\n            <if test=\"gmtCreated != null\">\n                #{gmtCreated,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"gmtModified != null\">\n                #{gmtModified,jdbcType=TIMESTAMP},\n            </if>\n        </trim>\n    </insert>\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"me.zbl.app.domain.Inventory\">\n        update app_inventory_record\n        <set>\n            <if test=\"consumerId != null\">\n                consumer_id = #{consumerId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"drugId != null\">\n                drug_id = #{drugId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"type != null\">\n                type = #{type,jdbcType=VARCHAR},\n            </if>\n            <if test=\"quantity != null\">\n                quantity = #{quantity,jdbcType=INTEGER},\n            </if>\n            <if test=\"ammount != null\">\n                ammount = #{ammount,jdbcType=DECIMAL},\n            </if>\n            <if test=\"comment != null\">\n                comment = #{comment,jdbcType=VARCHAR},\n            </if>\n            <if test=\"manager != null\">\n                manager = #{manager,jdbcType=VARCHAR},\n            </if>\n            <if test=\"gmtCreated != null\">\n                gmt_created = #{gmtCreated,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"gmtModified != null\">\n                gmt_modified = #{gmtModified,jdbcType=TIMESTAMP},\n            </if>\n        </set>\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n    <update id=\"updateByPrimaryKey\" parameterType=\"me.zbl.app.domain.Inventory\">\n        update app_inventory_record\n        set consumer_id  = #{consumerId,jdbcType=VARCHAR},\n            drug_id      = #{drugId,jdbcType=VARCHAR},\n            type         = #{type,jdbcType=VARCHAR},\n            quantity     = #{quantity,jdbcType=INTEGER},\n            ammount      = #{ammount,jdbcType=DECIMAL},\n            comment      = #{comment,jdbcType=VARCHAR},\n            manager      = #{manager,jdbcType=VARCHAR},\n            gmt_created  = #{gmtCreated,jdbcType=TIMESTAMP},\n            gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/app/SupplierMapper.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=\"me.zbl.app.dao.SupplierMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"me.zbl.app.domain.Supplier\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\" />\n  </resultMap>\n  <sql id=\"Base_Column_List\">\n    id, name\n  </sql>\n  <!-- selectAllSupplier -->\n  <select id=\"selectAllSupplier\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n    select\n    <include refid=\"Base_Column_List\" />\n    from app_supplier\n    <if test=\"offset != null and limit != null\">\n      limit ${offset}, ${limit}\n    </if>\n  </select>\n  <!-- count -->\n  <select id=\"count\" resultType=\"int\">\n    select count(*) from app_supplier\n  </select>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select \n    <include refid=\"Base_Column_List\" />\n    from app_supplier\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from app_supplier\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"me.zbl.app.domain.Supplier\">\n    <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">\n      select replace(uuid(),'-','') from dual\n    </selectKey>\n    insert into app_supplier (id, name)\n    values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR})\n  </insert>\n  <insert id=\"insertSelective\" parameterType=\"me.zbl.app.domain.Supplier\">\n    <!--<selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"java.lang.String\">-->\n      <!--select replace(uuid(),'-','') from dual-->\n    <!--</selectKey>-->\n    insert into app_supplier\n    <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n      id,\n      <if test=\"name != null\">\n        name,\n      </if>\n    </trim>\n    <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n      #{id,jdbcType=VARCHAR},\n      <if test=\"name != null\">\n        #{name,jdbcType=VARCHAR},\n      </if>\n    </trim>\n  </insert>\n  <update id=\"updateByPrimaryKeySelective\" parameterType=\"me.zbl.app.domain.Supplier\">\n    update app_supplier\n    <set>\n      <if test=\"name != null\">\n        name = #{name,jdbcType=VARCHAR},\n      </if>\n    </set>\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <update id=\"updateByPrimaryKey\" parameterType=\"me.zbl.app.domain.Supplier\">\n    update app_supplier\n    set name = #{name,jdbcType=VARCHAR}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/blog/ContentMapper.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\n<mapper namespace=\"me.zbl.blog.dao.ContentDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.blog.domain.ContentDO\">\n\t\tselect `cid`,`title`,`slug`,`created`,`modified`,`content`,`type`,`tags`,`categories`,`hits`,`comments_num`,`allow_comment`,`allow_ping`,`allow_feed`,`status`,`author`,`gtm_create`,`gtm_modified` from blog_content where cid = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.blog.domain.ContentDO\">\n\t\tselect `cid`,`title`,`slug`,`created`,`modified`,`content`,`type`,`tags`,`categories`,`hits`,`comments_num`,`allow_comment`,`allow_ping`,`allow_feed`,`status`,`author`,`gtm_create`,`gtm_modified` from blog_content\n        <where>  \n\t\t  \t\t  <if test=\"cid != null and cid != ''\"> and cid = #{cid} </if>\n\t\t  \t\t  <if test=\"title != null and title != ''\"> and title = #{title} </if>\n\t\t  \t\t  <if test=\"slug != null and slug != ''\"> and slug = #{slug} </if>\n\t\t  \t\t  <if test=\"created != null and created != ''\"> and created = #{created} </if>\n\t\t  \t\t  <if test=\"modified != null and modified != ''\"> and modified = #{modified} </if>\n\t\t  \t\t  <if test=\"content != null and content != ''\"> and content = #{content} </if>\n\t\t  \t\t  <if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t  \t\t  <if test=\"tags != null and tags != ''\"> and tags = #{tags} </if>\n\t\t  \t\t  <if test=\"categories != null and categories != ''\"> and categories = #{categories} </if>\n\t\t  \t\t  <if test=\"hits != null and hits != ''\"> and hits = #{hits} </if>\n\t\t  \t\t  <if test=\"commentsNum != null and commentsNum != ''\"> and comments_num = #{commentsNum} </if>\n\t\t  \t\t  <if test=\"allowComment != null and allowComment != ''\"> and allow_comment = #{allowComment} </if>\n\t\t  \t\t  <if test=\"allowPing != null and allowPing != ''\"> and allow_ping = #{allowPing} </if>\n\t\t  \t\t  <if test=\"allowFeed != null and allowFeed != ''\"> and allow_feed = #{allowFeed} </if>\n\t\t  \t\t  <if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t  \t\t  <if test=\"author != null and author != ''\"> and author = #{author} </if>\n\t\t  \t\t  <if test=\"gtmCreate != null and gtmCreate != ''\"> and gtm_create = #{gtmCreate} </if>\n\t\t  \t\t  <if test=\"gtmModified != null and gtmModified != ''\"> and gtm_modified = #{gtmModified} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by cid desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit ${offset}, ${limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from blog_content\n\t\t <where>  \n\t\t  \t\t  <if test=\"cid != null and cid != ''\"> and cid = #{cid} </if>\n\t\t  \t\t  <if test=\"title != null and title != ''\"> and title = #{title} </if>\n\t\t  \t\t  <if test=\"slug != null and slug != ''\"> and slug = #{slug} </if>\n\t\t  \t\t  <if test=\"created != null and created != ''\"> and created = #{created} </if>\n\t\t  \t\t  <if test=\"modified != null and modified != ''\"> and modified = #{modified} </if>\n\t\t  \t\t  <if test=\"content != null and content != ''\"> and content = #{content} </if>\n\t\t  \t\t  <if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t  \t\t  <if test=\"tags != null and tags != ''\"> and tags = #{tags} </if>\n\t\t  \t\t  <if test=\"categories != null and categories != ''\"> and categories = #{categories} </if>\n\t\t  \t\t  <if test=\"hits != null and hits != ''\"> and hits = #{hits} </if>\n\t\t  \t\t  <if test=\"commentsNum != null and commentsNum != ''\"> and comments_num = #{commentsNum} </if>\n\t\t  \t\t  <if test=\"allowComment != null and allowComment != ''\"> and allow_comment = #{allowComment} </if>\n\t\t  \t\t  <if test=\"allowPing != null and allowPing != ''\"> and allow_ping = #{allowPing} </if>\n\t\t  \t\t  <if test=\"allowFeed != null and allowFeed != ''\"> and allow_feed = #{allowFeed} </if>\n\t\t  \t\t  <if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t  \t\t  <if test=\"author != null and author != ''\"> and author = #{author} </if>\n\t\t  \t\t  <if test=\"gtmCreate != null and gtmCreate != ''\"> and gtm_create = #{gtmCreate} </if>\n\t\t  \t\t  <if test=\"gtmModified != null and gtmModified != ''\"> and gtm_modified = #{gtmModified} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.blog.domain.ContentDO\" useGeneratedKeys=\"true\" keyProperty=\"cid\">\n\t\tinsert into blog_content\n\t\t(\n\t\t\t`title`, \n\t\t\t`slug`, \n\t\t\t`created`, \n\t\t\t`modified`, \n\t\t\t`content`, \n\t\t\t`type`, \n\t\t\t`tags`, \n\t\t\t`categories`, \n\t\t\t`hits`, \n\t\t\t`comments_num`, \n\t\t\t`allow_comment`, \n\t\t\t`allow_ping`, \n\t\t\t`allow_feed`, \n\t\t\t`status`, \n\t\t\t`author`, \n\t\t\t`gtm_create`, \n\t\t\t`gtm_modified`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{title}, \n\t\t\t#{slug}, \n\t\t\t#{created}, \n\t\t\t#{modified}, \n\t\t\t#{content}, \n\t\t\t#{type}, \n\t\t\t#{tags}, \n\t\t\t#{categories}, \n\t\t\t#{hits}, \n\t\t\t#{commentsNum}, \n\t\t\t#{allowComment}, \n\t\t\t#{allowPing}, \n\t\t\t#{allowFeed}, \n\t\t\t#{status}, \n\t\t\t#{author}, \n\t\t\t#{gtmCreate}, \n\t\t\t#{gtmModified}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.blog.domain.ContentDO\">\n\t\tupdate blog_content \n\t\t<set>\n\t\t\t<if test=\"title != null\">`title` = #{title}, </if>\n\t\t\t<if test=\"slug != null\">`slug` = #{slug}, </if>\n\t\t\t<if test=\"created != null\">`created` = #{created}, </if>\n\t\t\t<if test=\"modified != null\">`modified` = #{modified}, </if>\n\t\t\t<if test=\"content != null\">`content` = #{content}, </if>\n\t\t\t<if test=\"type != null\">`type` = #{type}, </if>\n\t\t\t<if test=\"tags != null\">`tags` = #{tags}, </if>\n\t\t\t<if test=\"categories != null\">`categories` = #{categories}, </if>\n\t\t\t<if test=\"hits != null\">`hits` = #{hits}, </if>\n\t\t\t<if test=\"commentsNum != null\">`comments_num` = #{commentsNum}, </if>\n\t\t\t<if test=\"allowComment != null\">`allow_comment` = #{allowComment}, </if>\n\t\t\t<if test=\"allowPing != null\">`allow_ping` = #{allowPing}, </if>\n\t\t\t<if test=\"allowFeed != null\">`allow_feed` = #{allowFeed}, </if>\n\t\t\t<if test=\"status != null\">`status` = #{status}, </if>\n\t\t\t<if test=\"author != null\">`author` = #{author}, </if>\n\t\t\t<if test=\"gtmCreate != null\">`gtm_create` = #{gtmCreate}, </if>\n\t\t\t<if test=\"gtmModified != null\">`gtm_modified` = #{gtmModified}</if>\n\t\t</set>\n\t\twhere cid = #{cid}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from blog_content where cid = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from blog_content where cid in \n\t\t<foreach item=\"cid\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{cid}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/common/DictMapper.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\n<mapper namespace=\"me.zbl.common.dao.DictDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.common.domain.DictDO\">\n\t\tselect\n\t\t`id`,`name`,`value`,`type`,`description`,`sort`,`parent_id`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom sys_dict where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.common.domain.DictDO\">\n\t\tselect\n\t\t`id`,`name`,`value`,`type`,`description`,`sort`,`parent_id`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom sys_dict\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"value != null and value != ''\"> and value = #{value} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"description != null and description != ''\"> and description = #{description} </if>\n\t\t\t<if test=\"sort != null and sort != ''\"> and sort = #{sort} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t\t<if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t\t<if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t\t<if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t\t<if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_dict\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"value != null and value != ''\"> and value = #{value} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"description != null and description != ''\"> and description = #{description} </if>\n\t\t\t<if test=\"sort != null and sort != ''\"> and sort = #{sort} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t\t<if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t\t<if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t\t<if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t\t<if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.common.domain.DictDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_dict\n\t\t(\n\t\t`name`,\n\t\t`value`,\n\t\t`type`,\n\t\t`description`,\n\t\t`sort`,\n\t\t`parent_id`,\n\t\t`create_by`,\n\t\t`create_date`,\n\t\t`update_by`,\n\t\t`update_date`,\n\t\t`remarks`,\n\t\t`del_flag`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{name},\n\t\t#{value},\n\t\t#{type},\n\t\t#{description},\n\t\t#{sort},\n\t\t#{parentId},\n\t\t#{createBy},\n\t\t#{createDate},\n\t\t#{updateBy},\n\t\t#{updateDate},\n\t\t#{remarks},\n\t\t#{delFlag}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.common.domain.DictDO\">\n\t\tupdate sys_dict\n\t\t<set>\n\t\t\t<if test=\"name != null\">`name` = #{name}, </if>\n\t\t\t<if test=\"value != null\">`value` = #{value}, </if>\n\t\t\t<if test=\"type != null\">`type` = #{type}, </if>\n\t\t\t<if test=\"description != null\">`description` = #{description}, </if>\n\t\t\t<if test=\"sort != null\">`sort` = #{sort}, </if>\n\t\t\t<if test=\"parentId != null\">`parent_id` = #{parentId}, </if>\n\t\t\t<if test=\"createBy != null\">`create_by` = #{createBy}, </if>\n\t\t\t<if test=\"createDate != null\">`create_date` = #{createDate}, </if>\n\t\t\t<if test=\"updateBy != null\">`update_by` = #{updateBy}, </if>\n\t\t\t<if test=\"updateDate != null\">`update_date` = #{updateDate}, </if>\n\t\t\t<if test=\"remarks != null\">`remarks` = #{remarks}, </if>\n\t\t\t<if test=\"delFlag != null\">`del_flag` = #{delFlag}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_dict where id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_dict where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listType\" resultType=\"me.zbl.common.domain.DictDO\">\n\t\tselect distinct `type` , description from sys_dict\n\t</select>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/common/FileMapper.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\n<mapper namespace=\"me.zbl.common.dao.FileDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.common.domain.FileDO\">\n\t\tselect `id`,`type`,`url`,`create_date` from sys_file where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.common.domain.FileDO\">\n\t\tselect `id`,`type`,`url`,`create_date` from sys_file\n        <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t  \t\t  <if test=\"url != null and url != ''\"> and url = #{url} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by id desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_file\n\t\t <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t  \t\t  <if test=\"url != null and url != ''\"> and url = #{url} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.common.domain.FileDO\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_file\n\t\t(\n\t\t\t`type`, \n\t\t\t`url`, \n\t\t\t`create_date`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{type}, \n\t\t\t#{url}, \n\t\t\t#{createDate}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.common.domain.FileDO\">\n\t\tupdate sys_file \n\t\t<set>\n\t\t\t<if test=\"type != null\">`type` = #{type}, </if>\n\t\t\t<if test=\"url != null\">`url` = #{url}, </if>\n\t\t\t<if test=\"createDate != null\">`create_date` = #{createDate}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from sys_file where id = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_file where id in \n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/common/LogMapper.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\n<mapper namespace=\"me.zbl.common.dao.LogDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.common.domain.LogDO\">\n\t\tselect `id`,`user_id`,`username`,`operation`,`time`,`method`,`params`,`ip`,`gmt_create` from sys_log where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.common.domain.LogDO\">\n\t\tselect `id`,`user_id`,`username`,`operation`,`time`,`method`,`params`,`ip`,`gmt_create` from sys_log\n        <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t  \t\t  <if test=\"username != null and username != ''\"> and username = #{username} </if>\n\t\t  \t\t  <if test=\"operation != null and operation != ''\"> and operation = #{operation} </if>\n\t\t  \t\t  <if test=\"time != null and time != ''\"> and time = #{time} </if>\n\t\t  \t\t  <if test=\"method != null and method != ''\"> and method = #{method} </if>\n\t\t  \t\t  <if test=\"params != null and params != ''\"> and params = #{params} </if>\n\t\t  \t\t  <if test=\"ip != null and ip != ''\"> and ip = #{ip} </if>\n\t\t  \t\t  <if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by id desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_log\n\t\t <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t  \t\t  <if test=\"username != null and username != ''\"> and username = #{username} </if>\n\t\t  \t\t  <if test=\"operation != null and operation != ''\"> and operation = #{operation} </if>\n\t\t  \t\t  <if test=\"time != null and time != ''\"> and time = #{time} </if>\n\t\t  \t\t  <if test=\"method != null and method != ''\"> and method = #{method} </if>\n\t\t  \t\t  <if test=\"params != null and params != ''\"> and params = #{params} </if>\n\t\t  \t\t  <if test=\"ip != null and ip != ''\"> and ip = #{ip} </if>\n\t\t  \t\t  <if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.common.domain.LogDO\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_log\n\t\t(\n\t\t\t`user_id`, \n\t\t\t`username`, \n\t\t\t`operation`, \n\t\t\t`time`, \n\t\t\t`method`, \n\t\t\t`params`, \n\t\t\t`ip`, \n\t\t\t`gmt_create`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{userId}, \n\t\t\t#{username}, \n\t\t\t#{operation}, \n\t\t\t#{time}, \n\t\t\t#{method}, \n\t\t\t#{params}, \n\t\t\t#{ip}, \n\t\t\t#{gmtCreate}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.common.domain.LogDO\">\n\t\tupdate sys_log \n\t\t<set>\n\t\t\t<if test=\"userId != null\">`user_id` = #{userId}, </if>\n\t\t\t<if test=\"username != null\">`username` = #{username}, </if>\n\t\t\t<if test=\"operation != null\">`operation` = #{operation}, </if>\n\t\t\t<if test=\"time != null\">`time` = #{time}, </if>\n\t\t\t<if test=\"method != null\">`method` = #{method}, </if>\n\t\t\t<if test=\"params != null\">`params` = #{params}, </if>\n\t\t\t<if test=\"ip != null\">`ip` = #{ip}, </if>\n\t\t\t<if test=\"gmtCreate != null\">`gmt_create` = #{gmtCreate}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from sys_log where id = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_log where id in \n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/common/TaskMapper.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\n<mapper namespace=\"me.zbl.common.dao.TaskDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.common.domain.TaskDO\">\n\t\tselect `id`,`cron_expression`,`method_name`,`is_concurrent`,`description`,`update_by`,`bean_class`,`create_date`,`job_status`,`job_group`,`update_date`,`create_by`,`spring_bean`,`job_name` from sys_task where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.common.domain.TaskDO\">\n\t\tselect `id`,`cron_expression`,`method_name`,`is_concurrent`,`description`,`update_by`,`bean_class`,`create_date`,`job_status`,`job_group`,`update_date`,`create_by`,`spring_bean`,`job_name` from sys_task\n        <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"cronExpression != null and cronExpression != ''\"> and cron_expression = #{cronExpression} </if>\n\t\t  \t\t  <if test=\"methodName != null and methodName != ''\"> and method_name = #{methodName} </if>\n\t\t  \t\t  <if test=\"isConcurrent != null and isConcurrent != ''\"> and is_concurrent = #{isConcurrent} </if>\n\t\t  \t\t  <if test=\"description != null and description != ''\"> and description = #{description} </if>\n\t\t  \t\t  <if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t  \t\t  <if test=\"beanClass != null and beanClass != ''\"> and bean_class = #{beanClass} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t  <if test=\"jobStatus != null and jobStatus != ''\"> and job_status = #{jobStatus} </if>\n\t\t  \t\t  <if test=\"jobGroup != null and jobGroup != ''\"> and job_group = #{jobGroup} </if>\n\t\t  \t\t  <if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t  \t\t  <if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t  \t\t  <if test=\"springBean != null and springBean != ''\"> and spring_bean = #{springBean} </if>\n\t\t  \t\t  <if test=\"jobName != null and jobName != ''\"> and job_name = #{jobName} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by id desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_task\n\t\t <where>  \n\t\t  \t\t  <if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t  \t\t  <if test=\"cronExpression != null and cronExpression != ''\"> and cron_expression = #{cronExpression} </if>\n\t\t  \t\t  <if test=\"methodName != null and methodName != ''\"> and method_name = #{methodName} </if>\n\t\t  \t\t  <if test=\"isConcurrent != null and isConcurrent != ''\"> and is_concurrent = #{isConcurrent} </if>\n\t\t  \t\t  <if test=\"description != null and description != ''\"> and description = #{description} </if>\n\t\t  \t\t  <if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t  \t\t  <if test=\"beanClass != null and beanClass != ''\"> and bean_class = #{beanClass} </if>\n\t\t  \t\t  <if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t  \t\t  <if test=\"jobStatus != null and jobStatus != ''\"> and job_status = #{jobStatus} </if>\n\t\t  \t\t  <if test=\"jobGroup != null and jobGroup != ''\"> and job_group = #{jobGroup} </if>\n\t\t  \t\t  <if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t  \t\t  <if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t  \t\t  <if test=\"springBean != null and springBean != ''\"> and spring_bean = #{springBean} </if>\n\t\t  \t\t  <if test=\"jobName != null and jobName != ''\"> and job_name = #{jobName} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.common.domain.TaskDO\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_task\n\t\t(\n\t\t\t`cron_expression`, \n\t\t\t`method_name`, \n\t\t\t`is_concurrent`, \n\t\t\t`description`, \n\t\t\t`update_by`, \n\t\t\t`bean_class`, \n\t\t\t`create_date`, \n\t\t\t`job_status`, \n\t\t\t`job_group`, \n\t\t\t`update_date`, \n\t\t\t`create_by`, \n\t\t\t`spring_bean`, \n\t\t\t`job_name`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{cronExpression}, \n\t\t\t#{methodName}, \n\t\t\t#{isConcurrent}, \n\t\t\t#{description}, \n\t\t\t#{updateBy}, \n\t\t\t#{beanClass}, \n\t\t\t#{createDate}, \n\t\t\t#{jobStatus}, \n\t\t\t#{jobGroup}, \n\t\t\t#{updateDate}, \n\t\t\t#{createBy}, \n\t\t\t#{springBean}, \n\t\t\t#{jobName}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.common.domain.TaskDO\">\n\t\tupdate sys_task \n\t\t<set>\n\t\t\t<if test=\"cronExpression != null\">`cron_expression` = #{cronExpression}, </if>\n\t\t\t<if test=\"methodName != null\">`method_name` = #{methodName}, </if>\n\t\t\t<if test=\"isConcurrent != null\">`is_concurrent` = #{isConcurrent}, </if>\n\t\t\t<if test=\"description != null\">`description` = #{description}, </if>\n\t\t\t<if test=\"updateBy != null\">`update_by` = #{updateBy}, </if>\n\t\t\t<if test=\"beanClass != null\">`bean_class` = #{beanClass}, </if>\n\t\t\t<if test=\"createDate != null\">`create_date` = #{createDate}, </if>\n\t\t\t<if test=\"jobStatus != null\">`job_status` = #{jobStatus}, </if>\n\t\t\t<if test=\"jobGroup != null\">`job_group` = #{jobGroup}, </if>\n\t\t\t<if test=\"updateDate != null\">`update_date` = #{updateDate}, </if>\n\t\t\t<if test=\"createBy != null\">`create_by` = #{createBy}, </if>\n\t\t\t<if test=\"springBean != null\">`spring_bean` = #{springBean}, </if>\n\t\t\t<if test=\"jobName != null\">`job_name` = #{jobName}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from sys_task where id = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_task where id in \n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/oa/NotifyMapper.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\n<mapper namespace=\"me.zbl.oa.dao.NotifyDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.oa.domain.NotifyDO\">\n\t\tselect\n\t\t`id`,`type`,`title`,`content`,`files`,`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom oa_notify where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.oa.domain.NotifyDO\">\n\t\tselect\n\t\t`id`,`type`,`title`,`content`,`files`,`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom oa_notify\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"title != null and title != ''\"> and title = #{title} </if>\n\t\t\t<if test=\"content != null and content != ''\"> and content = #{content} </if>\n\t\t\t<if test=\"files != null and files != ''\"> and files = #{files} </if>\n\t\t\t<if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t\t<if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t\t<if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t\t<if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t\t<if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t\t<if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from oa_notify\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"title != null and title != ''\"> and title = #{title} </if>\n\t\t\t<if test=\"content != null and content != ''\"> and content = #{content} </if>\n\t\t\t<if test=\"files != null and files != ''\"> and files = #{files} </if>\n\t\t\t<if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t\t<if test=\"createBy != null and createBy != ''\"> and create_by = #{createBy} </if>\n\t\t\t<if test=\"createDate != null and createDate != ''\"> and create_date = #{createDate} </if>\n\t\t\t<if test=\"updateBy != null and updateBy != ''\"> and update_by = #{updateBy} </if>\n\t\t\t<if test=\"updateDate != null and updateDate != ''\"> and update_date = #{updateDate} </if>\n\t\t\t<if test=\"remarks != null and remarks != ''\"> and remarks = #{remarks} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.oa.domain.NotifyDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into oa_notify\n\t\t(\n\t\t`type`,\n\t\t`title`,\n\t\t`content`,\n\t\t`files`,\n\t\t`status`,\n\t\t`create_by`,\n\t\t`create_date`,\n\t\t`update_by`,\n\t\t`update_date`,\n\t\t`remarks`,\n\t\t`del_flag`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{type},\n\t\t#{title},\n\t\t#{content},\n\t\t#{files},\n\t\t#{status},\n\t\t#{createBy},\n\t\t#{createDate},\n\t\t#{updateBy},\n\t\t#{updateDate},\n\t\t#{remarks},\n\t\t#{delFlag}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.oa.domain.NotifyDO\">\n\t\tupdate oa_notify\n\t\t<set>\n\t\t\t<if test=\"type != null\">`type` = #{type}, </if>\n\t\t\t<if test=\"title != null\">`title` = #{title}, </if>\n\t\t\t<if test=\"content != null\">`content` = #{content}, </if>\n\t\t\t<if test=\"files != null\">`files` = #{files}, </if>\n\t\t\t<if test=\"status != null\">`status` = #{status}, </if>\n\t\t\t<if test=\"createBy != null\">`create_by` = #{createBy}, </if>\n\t\t\t<if test=\"createDate != null\">`create_date` = #{createDate}, </if>\n\t\t\t<if test=\"updateBy != null\">`update_by` = #{updateBy}, </if>\n\t\t\t<if test=\"updateDate != null\">`update_date` = #{updateDate}, </if>\n\t\t\t<if test=\"remarks != null\">`remarks` = #{remarks}, </if>\n\t\t\t<if test=\"delFlag != null\">`del_flag` = #{delFlag}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from oa_notify where id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from oa_notify where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listByIds\" resultType=\"me.zbl.oa.domain.NotifyDO\">\n\t\tselect\n\t\t`id`,`type`,`title`,`content`,`files`,`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom oa_notify where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</select>\n\n\n\t<select id=\"countDTO\" resultType=\"int\">\n\t\tselect count(*)\n\t\tfrom\n\t\toa_notify_record r right JOIN oa_notify n on r.notify_id\n\t\t= n.id where\n\t\tr.user_id =#{userId} and\n\t\tr.is_read = #{isRead}\n\t</select>\n\n\t<select id=\"listDTO\" resultType=\"me.zbl.oa.domain.NotifyDTO\">\n\t\tselect DISTINCT\n\t\tn.id ,`type`,`title`,`content`,`files`,r.is_read,`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`\n\t\tfrom oa_notify_record r right JOIN oa_notify n on r.notify_id = n.id\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and r.id = #{id} </if>\n\t\t\t<if test=\"notifyId != null and notifyId != ''\"> and r.notify_id = #{notifyId} </if>\n\t\t\t<if test=\"isRead != null and isRead != ''\"> and r.is_read = #{isRead} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and r.user_id = #{userId} </if>\n\t\t\t<if test=\"readDate != null and readDate != ''\"> and r.read_date = #{readDate} </if>\n\t\t</where>\n\t\torder by is_read ASC, update_date DESC\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t\t\n\t</select>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/oa/NotifyRecordMapper.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\n<mapper namespace=\"me.zbl.oa.dao.NotifyRecordDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.oa.domain.NotifyRecordDO\">\n\t\tselect\n\t\t`id`,`notify_id`,`user_id`,`is_read`,`read_date` from oa_notify_record\n\t\twhere id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.oa.domain.NotifyRecordDO\">\n\t\tselect `id`,`notify_id`,`user_id`,`is_read`,`read_date` from\n\t\toa_notify_record\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"notifyId != null and notifyId != ''\"> and notify_id = #{notifyId} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t\t<if test=\"isRead != null and isRead != ''\"> and is_read = #{isRead} </if>\n\t\t\t<if test=\"readDate != null and readDate != ''\"> and read_date = #{readDate} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by #{sort} #{order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from oa_notify_record\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"notifyId != null and notifyId != ''\"> and notify_id = #{notifyId} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t\t<if test=\"isRead != null and isRead != ''\"> and is_read = #{isRead} </if>\n\t\t\t<if test=\"readDate != null and readDate != ''\"> and read_date = #{readDate} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.oa.domain.NotifyRecordDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into oa_notify_record\n\t\t(\n\t\t`notify_id`,\n\t\t`user_id`,\n\t\t`is_read`,\n\t\t`read_date`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{notifyId},\n\t\t#{userId},\n\t\t#{isRead},\n\t\t#{readDate}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.oa.domain.NotifyRecordDO\">\n\t\tupdate oa_notify_record\n\t\t<set>\n\t\t\t<if test=\"notifyId != null\">`notify_id` = #{notifyId}, </if>\n\t\t\t<if test=\"userId != null\">`user_id` = #{userId}, </if>\n\t\t\t<if test=\"isRead != null\">`is_read` = #{isRead}, </if>\n\t\t\t<if test=\"readDate != null\">`read_date` = #{readDate}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from oa_notify_record where id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from oa_notify_record where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\n\t<insert id=\"batchSave\" parameterType=\"me.zbl.oa.domain.NotifyRecordDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into oa_notify_record\n\t\t(\n\t\t`notify_id`,\n\t\t`user_id`,\n\t\t`is_read`,\n\t\t`read_date`\n\t\t)\n\t\tvalues\n\t\t<foreach item=\"item\" index=\"index\" collection=\"list\"\n\t\t\tseparator=\",\">\n\t\t\t(\n\t\t\t#{item.notifyId},\n\t\t\t#{item.userId},\n\t\t\t#{item.isRead},\n\t\t\t#{item.readDate}\n\t\t\t)\n\t\t</foreach>\n\t</insert>\n\n\t<select id=\"listNotifyIds\" resultType=\"long\">\n\t\tselect distinct notify_id from oa_notify_record\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"notifyId != null and notifyId != ''\"> and notify_id = #{notifyId} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t\t<if test=\"isRead != null and isRead != ''\"> and is_read = #{isRead} </if>\n\t\t\t<if test=\"readDate != null and readDate != ''\"> and read_date = #{readDate} </if>\n\t\t</where>\n\t</select>\n\n\t<delete id=\"removeByNotifbyId\">\n\t\tdelete from oa_notify_record where notify_id =\n\t\t#{value}\n\t</delete>\n\n\t<delete id=\"batchRemoveByNotifbyId\">\n\t\tdelete from oa_notify_record where notify_id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<update id=\"changeRead\" parameterType=\"me.zbl.oa.domain.NotifyRecordDO\">\n\t\tupdate oa_notify_record\n\t\t<set>\n\t\t\t<if test=\"isRead != null\">`is_read` = #{isRead}, </if>\n\t\t\t<if test=\"readDate != null\">`read_date` = #{readDate}</if>\n\t\t</set>\n\t\twhere notify_id = #{notifyId} and user_id = #{userId}\n\t</update>\n\n\n\n</mapper>\n"
  },
  {
    "path": "src/main/resources/mybatis/system/DeptMapper.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\n<mapper namespace=\"me.zbl.system.dao.DeptDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.DeptDO\">\n\t\tselect\n\t\t`dept_id`,`parent_id`,`name`,`order_num`,`del_flag` from sys_dept\n\t\twhere dept_id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.DeptDO\">\n\t\tselect `dept_id`,`parent_id`,`name`,`order_num`,`del_flag` from\n\t\tsys_dept\n\t\t<where>\n\t\t\t<if test=\"deptId != null and deptId != ''\"> and dept_id = #{deptId} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"orderNum != null and orderNum != ''\"> and order_num = #{orderNum} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by dept_id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_dept\n\t\t<where>\n\t\t\t<if test=\"deptId != null and deptId != ''\"> and dept_id = #{deptId} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"orderNum != null and orderNum != ''\"> and order_num = #{orderNum} </if>\n\t\t\t<if test=\"delFlag != null and delFlag != ''\"> and del_flag = #{delFlag} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.DeptDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"deptId\">\n\t\tinsert into sys_dept\n\t\t(\n\t\t`parent_id`,\n\t\t`name`,\n\t\t`order_num`,\n\t\t`del_flag`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{parentId},\n\t\t#{name},\n\t\t#{orderNum},\n\t\t#{delFlag}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.DeptDO\">\n\t\tupdate sys_dept\n\t\t<set>\n\t\t\t<if test=\"parentId != null\">`parent_id` = #{parentId}, </if>\n\t\t\t<if test=\"name != null\">`name` = #{name}, </if>\n\t\t\t<if test=\"orderNum != null\">`order_num` = #{orderNum}, </if>\n\t\t\t<if test=\"delFlag != null\">`del_flag` = #{delFlag}</if>\n\t\t</set>\n\t\twhere dept_id = #{deptId}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_dept where dept_id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_dept where dept_id in\n\t\t<foreach item=\"deptId\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{deptId}\n\t\t</foreach>\n\t</delete>\n\t\n\t<select id=\"listParentDept\" resultType=\"long\">\n\t\tselect DISTINCT parent_id from sys_dept\n\t</select>\n\n    <select id=\"getDeptUserNumber\" resultType=\"int\">\n\t\tselect count(*) from sys_user where dept_id = #{value}\n\t</select>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/system/MenuMapper.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\n<mapper namespace=\"me.zbl.system.dao.MenuDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.MenuDO\">\n\t\tselect\n\t\t`menu_id`,`parent_id`,`name`,`url`,`perms`,`type`,`icon`,`order_num`,`gmt_create`,`gmt_modified`\n\t\tfrom sys_menu where menu_id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.MenuDO\">\n\t\tselect\n\t\t`menu_id`,`parent_id`,`name`,`url`,`perms`,`type`,`icon`,`order_num`,`gmt_create`,`gmt_modified`\n\t\tfrom sys_menu\n\t\t<where>\n\t\t\t<if test=\"menuId != null and menuId != ''\"> and menu_id = #{menuId} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"url != null and url != ''\"> and url = #{url} </if>\n\t\t\t<if test=\"perms != null and perms != ''\"> and perms = #{perms} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"icon != null and icon != ''\"> and icon = #{icon} </if>\n\t\t\t<if test=\"orderNum != null and orderNum != ''\"> and order_num = #{orderNum} </if>\n\t\t\t<if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t\t<if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by menu_id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_menu\n\t\t<where>\n\t\t\t<if test=\"menuId != null and menuId != ''\"> and menu_id = #{menuId} </if>\n\t\t\t<if test=\"parentId != null and parentId != ''\"> and parent_id = #{parentId} </if>\n\t\t\t<if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t\t<if test=\"url != null and url != ''\"> and url = #{url} </if>\n\t\t\t<if test=\"perms != null and perms != ''\"> and perms = #{perms} </if>\n\t\t\t<if test=\"type != null and type != ''\"> and type = #{type} </if>\n\t\t\t<if test=\"icon != null and icon != ''\"> and icon = #{icon} </if>\n\t\t\t<if test=\"orderNum != null and orderNum != ''\"> and order_num = #{orderNum} </if>\n\t\t\t<if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t\t<if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.MenuDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"menuId\">\n\t\tinsert into sys_menu\n\t\t(\n\t\t`parent_id`,\n\t\t`name`,\n\t\t`url`,\n\t\t`perms`,\n\t\t`type`,\n\t\t`icon`,\n\t\t`order_num`,\n\t\t`gmt_create`,\n\t\t`gmt_modified`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{parentId},\n\t\t#{name},\n\t\t#{url},\n\t\t#{perms},\n\t\t#{type},\n\t\t#{icon},\n\t\t#{orderNum},\n\t\t#{gmtCreate},\n\t\t#{gmtModified}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.MenuDO\">\n\t\tupdate sys_menu\n\t\t<set>\n\t\t\t<if test=\"parentId != null\">`parent_id` = #{parentId}, </if>\n\t\t\t<if test=\"name != null\">`name` = #{name}, </if>\n\t\t\t<if test=\"url != null\">`url` = #{url}, </if>\n\t\t\t<if test=\"perms != null\">`perms` = #{perms}, </if>\n\t\t\t<if test=\"type != null\">`type` = #{type}, </if>\n\t\t\t<if test=\"icon != null\">`icon` = #{icon}, </if>\n\t\t\t<if test=\"orderNum != null\">`order_num` = #{orderNum}, </if>\n\t\t\t<if test=\"gmtCreate != null\">`gmt_create` = #{gmtCreate}, </if>\n\t\t\t<if test=\"gmtModified != null\">`gmt_modified` = #{gmtModified}</if>\n\t\t</set>\n\t\twhere menu_id = #{menuId}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_menu where menu_id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_menu where menu_id in\n\t\t<foreach item=\"menuId\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{menuId}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listMenuByUserId\" resultType=\"me.zbl.system.domain.MenuDO\">\n\t\tselect distinct\n\t\tm.menu_id , parent_id, name, url,\n\t\tperms,`type`,icon,order_num,gmt_create, gmt_modified\n\t\tfrom sys_menu m\n\t\tleft\n\t\tjoin sys_role_menu rm on m.menu_id = rm.menu_id left join\n\t\tsys_user_role ur\n\t\ton rm.role_id =ur.role_id where ur.user_id = #{id}\n\t\tand\n\t\tm.type in(0,1)\n\t\torder by\n\t\tm.order_num\n\t</select>\n\n\t<select id=\"listUserPerms\" resultType=\"string\">\n\t\tselect distinct m.perms\n\t\tfrom sys_menu m left join\n\t\tsys_role_menu rm on m.menu_id = rm.menu_id\n\t\tleft join sys_user_role ur\n\t\ton rm.role_id = ur.role_id where ur.user_id\n\t\t= #{id}\n\t</select>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/system/RoleMapper.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\n<mapper namespace=\"me.zbl.system.dao.RoleDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.RoleDO\">\n\t\tselect\n\t\t`role_id`,`role_name`,`role_sign`,`remark`,`user_id_create`,`gmt_create`,`gmt_modified`\n\t\tfrom sys_role where role_id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.RoleDO\">\n\t\tselect\n\t\t`role_id`,`role_name`,`role_sign`,`remark`,`user_id_create`,`gmt_create`,`gmt_modified`\n\t\tfrom sys_role\n\t\t<where>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t\t<if test=\"roleName != null and roleName != ''\"> and role_name = #{roleName} </if>\n\t\t\t<if test=\"roleSign != null and roleSign != ''\"> and role_sign = #{roleSign} </if>\n\t\t\t<if test=\"remark != null and remark != ''\"> and remark = #{remark} </if>\n\t\t\t<if test=\"userIdCreate != null and userIdCreate != ''\"> and user_id_create = #{userIdCreate} </if>\n\t\t\t<if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t\t<if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by role_id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_role\n\t\t<where>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t\t<if test=\"roleName != null and roleName != ''\"> and role_name = #{roleName} </if>\n\t\t\t<if test=\"roleSign != null and roleSign != ''\"> and role_sign = #{roleSign} </if>\n\t\t\t<if test=\"remark != null and remark != ''\"> and remark = #{remark} </if>\n\t\t\t<if test=\"userIdCreate != null and userIdCreate != ''\"> and user_id_create = #{userIdCreate} </if>\n\t\t\t<if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t\t<if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.RoleDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"roleId\">\n\t\tinsert into sys_role\n\t\t(\n\t\t`role_name`,\n\t\t`role_sign`,\n\t\t`remark`,\n\t\t`user_id_create`,\n\t\t`gmt_create`,\n\t\t`gmt_modified`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{roleName},\n\t\t#{roleSign},\n\t\t#{remark},\n\t\t#{userIdCreate},\n\t\t#{gmtCreate},\n\t\t#{gmtModified}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.RoleDO\">\n\t\tupdate sys_role\n\t\t<set>\n\t\t\t<if test=\"roleName != null\">`role_name` = #{roleName}, </if>\n\t\t\t<if test=\"roleSign != null\">`role_sign` = #{roleSign}, </if>\n\t\t\t<if test=\"remark != null\">`remark` = #{remark}, </if>\n\t\t\t<if test=\"userIdCreate != null\">`user_id_create` = #{userIdCreate}, </if>\n\t\t\t<if test=\"gmtCreate != null\">`gmt_create` = #{gmtCreate}, </if>\n\t\t\t<if test=\"gmtModified != null\">`gmt_modified` = #{gmtModified}</if>\n\t\t</set>\n\t\twhere role_id = #{roleId}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_role where role_id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_role where role_id in\n\t\t<foreach item=\"roleId\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{roleId}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/system/RoleMenuMapper.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\n<mapper namespace=\"me.zbl.system.dao.RoleMenuDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.RoleMenuDO\">\n\t\tselect `id`,`role_id`,`menu_id` from\n\t\tsys_role_menu where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.RoleMenuDO\">\n\t\tselect `id`,`role_id`,`menu_id` from sys_role_menu\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t\t<if test=\"menuId != null and menuId != ''\"> and menu_id = #{menuId} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_role_menu\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t\t<if test=\"menuId != null and menuId != ''\"> and menu_id = #{menuId} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.RoleMenuDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_role_menu\n\t\t(\n\t\t`role_id`,\n\t\t`menu_id`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{roleId},\n\t\t#{menuId}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.RoleMenuDO\">\n\t\tupdate sys_role_menu\n\t\t<set>\n\t\t\t<if test=\"roleId != null\">`role_id` = #{roleId}, </if>\n\t\t\t<if test=\"menuId != null\">`menu_id` = #{menuId}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_role_menu where id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_role_menu where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listMenuIdByRoleId\" resultType=\"long\">\n\t\tselect menu_id from sys_role_menu\n\t\t<where>role_id = #{roleId}</where>\n\t</select>\n\n\t<delete id=\"removeByRoleId\">\n\t\tDELETE FROM sys_role_menu WHERE role_id=#{roleId}\n\t</delete>\n\n\t<delete id=\"removeByMenuId\">\n\t\tDELETE FROM sys_role_menu WHERE menu_id=#{menuId}\n\t</delete>\n\n\t<insert id=\"batchSave\">\n\t\tINSERT INTO sys_role_menu(role_id, menu_id) values\n\t\t<foreach item=\"item\" index=\"index\" collection=\"list\"\n\t\t\tseparator=\",\">\n\t\t\t(#{item.roleId},#{item.menuId})\n\t\t</foreach>\n\t</insert>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/system/UserMapper.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\n<mapper namespace=\"me.zbl.system.dao.UserDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.UserDO\">\n\t\tselect `user_id`,`username`,`name`,`password`,`dept_id`,`email`,`mobile`,`status`,`user_id_create`,`gmt_create`,`gmt_modified`,`sex`,`birth`,`pic_id`,`live_address`,`hobby`,`province`,`city`,`district` from sys_user where user_id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.UserDO\">\n\t\tselect `user_id`,`username`,`name`,`password`,`dept_id`,`email`,`mobile`,`status`,`user_id_create`,`gmt_create`,`gmt_modified`,`sex`,`birth`,`pic_id`,`live_address`,`hobby`,`province`,`city`,`district` from sys_user\n        <where>  \n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t  \t\t  <if test=\"username != null and username != ''\"> and username = #{username} </if>\n\t\t  \t\t  <if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t  \t\t  <if test=\"password != null and password != ''\"> and password = #{password} </if>\n\t\t  \t\t  <if test=\"deptId != null and deptId != ''\"> and dept_id = #{deptId} </if>\n\t\t  \t\t  <if test=\"email != null and email != ''\"> and email = #{email} </if>\n\t\t  \t\t  <if test=\"mobile != null and mobile != ''\"> and mobile = #{mobile} </if>\n\t\t  \t\t  <if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t  \t\t  <if test=\"userIdCreate != null and userIdCreate != ''\"> and user_id_create = #{userIdCreate} </if>\n\t\t  \t\t  <if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t  \t\t  <if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t  \t\t  <if test=\"sex != null and sex != ''\"> and sex = #{sex} </if>\n\t\t  \t\t  <if test=\"birth != null and birth != ''\"> and birth = #{birth} </if>\n\t\t  \t\t  <if test=\"picId != null and picId != ''\"> and pic_id = #{picId} </if>\n\t\t  \t\t  <if test=\"liveAddress != null and liveAddress != ''\"> and live_address = #{liveAddress} </if>\n\t\t  \t\t  <if test=\"hobby != null and hobby != ''\"> and hobby = #{hobby} </if>\n\t\t  \t\t  <if test=\"province != null and province != ''\"> and province = #{province} </if>\n\t\t  \t\t  <if test=\"city != null and city != ''\"> and city = #{city} </if>\n\t\t  \t\t  <if test=\"district != null and district != ''\"> and district = #{district} </if>\n\t\t  \t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by user_id desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_user\n\t\t <where>  \n\t\t  \t\t  <if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t  \t\t  <if test=\"username != null and username != ''\"> and username = #{username} </if>\n\t\t  \t\t  <if test=\"name != null and name != ''\"> and name = #{name} </if>\n\t\t  \t\t  <if test=\"password != null and password != ''\"> and password = #{password} </if>\n\t\t  \t\t  <if test=\"deptId != null and deptId != ''\"> and dept_id = #{deptId} </if>\n\t\t  \t\t  <if test=\"email != null and email != ''\"> and email = #{email} </if>\n\t\t  \t\t  <if test=\"mobile != null and mobile != ''\"> and mobile = #{mobile} </if>\n\t\t  \t\t  <if test=\"status != null and status != ''\"> and status = #{status} </if>\n\t\t  \t\t  <if test=\"userIdCreate != null and userIdCreate != ''\"> and user_id_create = #{userIdCreate} </if>\n\t\t  \t\t  <if test=\"gmtCreate != null and gmtCreate != ''\"> and gmt_create = #{gmtCreate} </if>\n\t\t  \t\t  <if test=\"gmtModified != null and gmtModified != ''\"> and gmt_modified = #{gmtModified} </if>\n\t\t  \t\t  <if test=\"sex != null and sex != ''\"> and sex = #{sex} </if>\n\t\t  \t\t  <if test=\"birth != null and birth != ''\"> and birth = #{birth} </if>\n\t\t  \t\t  <if test=\"picId != null and picId != ''\"> and pic_id = #{picId} </if>\n\t\t  \t\t  <if test=\"liveAddress != null and liveAddress != ''\"> and live_address = #{liveAddress} </if>\n\t\t  \t\t  <if test=\"hobby != null and hobby != ''\"> and hobby = #{hobby} </if>\n\t\t  \t\t  <if test=\"province != null and province != ''\"> and province = #{province} </if>\n\t\t  \t\t  <if test=\"city != null and city != ''\"> and city = #{city} </if>\n\t\t  \t\t  <if test=\"district != null and district != ''\"> and district = #{district} </if>\n\t\t  \t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.UserDO\" useGeneratedKeys=\"true\" keyProperty=\"userId\">\n\t\tinsert into sys_user\n\t\t(\n\t\t\t`username`, \n\t\t\t`name`, \n\t\t\t`password`, \n\t\t\t`dept_id`, \n\t\t\t`email`, \n\t\t\t`mobile`, \n\t\t\t`status`, \n\t\t\t`user_id_create`, \n\t\t\t`gmt_create`, \n\t\t\t`gmt_modified`, \n\t\t\t`sex`, \n\t\t\t`birth`, \n\t\t\t`pic_id`, \n\t\t\t`live_address`, \n\t\t\t`hobby`, \n\t\t\t`province`, \n\t\t\t`city`, \n\t\t\t`district`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t\t#{username}, \n\t\t\t#{name}, \n\t\t\t#{password}, \n\t\t\t#{deptId}, \n\t\t\t#{email}, \n\t\t\t#{mobile}, \n\t\t\t#{status}, \n\t\t\t#{userIdCreate}, \n\t\t\t#{gmtCreate}, \n\t\t\t#{gmtModified}, \n\t\t\t#{sex}, \n\t\t\t#{birth}, \n\t\t\t#{picId}, \n\t\t\t#{liveAddress}, \n\t\t\t#{hobby}, \n\t\t\t#{province}, \n\t\t\t#{city}, \n\t\t\t#{district}\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.UserDO\">\n\t\tupdate sys_user \n\t\t<set>\n\t\t\t<if test=\"username != null\">`username` = #{username}, </if>\n\t\t\t<if test=\"name != null\">`name` = #{name}, </if>\n\t\t\t<if test=\"password != null\">`password` = #{password}, </if>\n\t\t\t<if test=\"deptId != null\">`dept_id` = #{deptId}, </if>\n\t\t\t<if test=\"email != null\">`email` = #{email}, </if>\n\t\t\t<if test=\"mobile != null\">`mobile` = #{mobile}, </if>\n\t\t\t<if test=\"status != null\">`status` = #{status}, </if>\n\t\t\t<if test=\"userIdCreate != null\">`user_id_create` = #{userIdCreate}, </if>\n\t\t\t<if test=\"gmtCreate != null\">`gmt_create` = #{gmtCreate}, </if>\n\t\t\t<if test=\"gmtModified != null\">`gmt_modified` = #{gmtModified}, </if>\n\t\t\t<if test=\"sex != null\">`sex` = #{sex}, </if>\n\t\t\t<if test=\"birth != null\">`birth` = #{birth}, </if>\n\t\t\t<if test=\"picId != null\">`pic_id` = #{picId}, </if>\n\t\t\t<if test=\"liveAddress != null\">`live_address` = #{liveAddress}, </if>\n\t\t\t<if test=\"hobby != null\">`hobby` = #{hobby}, </if>\n\t\t\t<if test=\"province != null\">`province` = #{province}, </if>\n\t\t\t<if test=\"city != null\">`city` = #{city}, </if>\n\t\t\t<if test=\"district != null\">`district` = #{district}</if>\n\t\t</set>\n\t\twhere user_id = #{userId}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from sys_user where user_id = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_user where user_id in \n\t\t<foreach item=\"userId\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{userId}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listAllDept\" resultType=\"long\">\n\t\t\t\tselect DISTINCT dept_id from sys_user\n\t</select>\n</mapper>"
  },
  {
    "path": "src/main/resources/mybatis/system/UserRoleMapper.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\n<mapper namespace=\"me.zbl.system.dao.UserRoleDao\">\n\n\t<select id=\"get\" resultType=\"me.zbl.system.domain.UserRoleDO\">\n\t\tselect `id`,`user_id`,`role_id` from\n\t\tsys_user_role where id = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"me.zbl.system.domain.UserRoleDO\">\n\t\tselect `id`,`user_id`,`role_id` from sys_user_role\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t</where>\n\t\t<choose>\n\t\t\t<when test=\"sort != null and sort.trim() != ''\">\n\t\t\t\torder by ${sort} ${order}\n\t\t\t</when>\n\t\t\t<otherwise>\n\t\t\t\torder by id desc\n\t\t\t</otherwise>\n\t\t</choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from sys_user_role\n\t\t<where>\n\t\t\t<if test=\"id != null and id != ''\"> and id = #{id} </if>\n\t\t\t<if test=\"userId != null and userId != ''\"> and user_id = #{userId} </if>\n\t\t\t<if test=\"roleId != null and roleId != ''\"> and role_id = #{roleId} </if>\n\t\t</where>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"me.zbl.system.domain.UserRoleDO\"\n\t\tuseGeneratedKeys=\"true\" keyProperty=\"id\">\n\t\tinsert into sys_user_role\n\t\t(\n\t\t`user_id`,\n\t\t`role_id`\n\t\t)\n\t\tvalues\n\t\t(\n\t\t#{userId},\n\t\t#{roleId}\n\t\t)\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"me.zbl.system.domain.UserRoleDO\">\n\t\tupdate sys_user_role\n\t\t<set>\n\t\t\t<if test=\"userId != null\">`user_id` = #{userId}, </if>\n\t\t\t<if test=\"roleId != null\">`role_id` = #{roleId}</if>\n\t\t</set>\n\t\twhere id = #{id}\n\t</update>\n\n\t<delete id=\"remove\">\n\t\tdelete from sys_user_role where id = #{value}\n\t</delete>\n\n\t<delete id=\"batchRemove\">\n\t\tdelete from sys_user_role where id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<select id=\"listRoleId\" resultType=\"long\">\n\t\tselect role_id from\n\t\tsys_user_role where\n\t\tuser_id=#{userId}\n\t</select>\n\n\t<delete id=\"removeByUserId\">\n\t\tdelete from sys_user_role where user_id=#{userId}\n\t</delete>\n\n\t<delete id=\"removeByRoleId\">\n\t\tdelete from sys_user_role where role_id=#{roleId}\n\t</delete>\n\n\t<delete id=\"batchRemoveByUserId\">\n\t\tdelete from sys_user_role where user_id in\n\t\t<foreach item=\"id\" collection=\"array\" open=\"(\" separator=\",\"\n\t\t\tclose=\")\">\n\t\t\t#{id}\n\t\t</foreach>\n\t</delete>\n\n\t<insert id=\"batchSave\">\n\t\tINSERT INTO sys_user_role(user_id, role_id) values\n\t\t<foreach item=\"item\" index=\"index\" collection=\"list\"\n\t\t\tseparator=\",\">\n\t\t\t(#{item.userId},#{item.roleId})\n\t\t</foreach>\n\t</insert>\n</mapper>"
  },
  {
    "path": "src/main/resources/public/FontIcoList.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Font Awesome Ico list</title>\n    <link href=\"/css/font-awesome.min.css\" rel=\"stylesheet\">\n    <script src=\"/js/jquery.min.js\"></script>\n    <style type=\"text/css\">\n        .fa{\n            margin: 5px;\n            padding: 5px;\n            cursor:pointer;\n            font-size: 18px;\n             width: 21px;\n             border-radius: 3px;\n        }\n        .fa:hover {\n            background-color: #1d9d74;\n            color: #ffffff;}\n    </style>\n</head>\n<body>\n<div class=\"ico-list\">\n     <i class=\"fa fa-address-book\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-address-book-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-address-card\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-address-card-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-adjust\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-american-sign-language-interpreting\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-anchor\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-archive\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-area-chart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-arrows\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-arrows-h\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-arrows-v\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-asl-interpreting\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-assistive-listening-systems\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-asterisk\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-at\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-audio-description\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-automobile\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-balance-scale\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-ban\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bank\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bar-chart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bar-chart-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-barcode\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bath\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bathtub\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-0\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-1\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-2\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-3\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-4\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-empty\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-full\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-half\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-quarter\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-battery-three-quarters\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bed\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-beer\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bell\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bell-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bell-slash\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bell-slash-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bicycle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-binoculars\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-birthday-cake\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-blind\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bluetooth\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bluetooth-b\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bolt\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bomb\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-book\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bookmark\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bookmark-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-braille\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-briefcase\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bug\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-building\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-building-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bullhorn\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bullseye\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-bus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cab\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calculator\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar-check-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar-minus-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar-plus-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-calendar-times-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-camera\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-camera-retro\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-car\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-caret-square-o-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-caret-square-o-left\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-caret-square-o-right\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-caret-square-o-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cart-arrow-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cart-plus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-certificate\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-check\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-check-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-check-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-check-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-check-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-child\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-circle-o-notch\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-circle-thin\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-clone\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-close\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cloud\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cloud-download\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cloud-upload\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-code\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-coffee\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cog\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cogs\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-comment\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-comment-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-commenting\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-commenting-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-comments\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-comments-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-compass\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-copyright\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-creative-commons\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-credit-card\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-credit-card-alt\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-crop\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-crosshairs\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cube\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cubes\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-cutlery\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-database\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-deaf\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-deafness\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-desktop\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-diamond\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-dot-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-download\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-drivers-license\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-drivers-license-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-edit\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-ellipsis-h\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-ellipsis-v\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-envelope\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-envelope-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-envelope-open\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-envelope-open-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-envelope-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-eraser\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-exchange\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-exclamation\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-exclamation-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-external-link-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-eye\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-eye-slash\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-eyedropper\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-fax\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-feed\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-female\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-fighter-jet\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-archive-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-audio-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-code-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-excel-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-image-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-movie-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-photo-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-picture-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-powerpoint-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-sound-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-video-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-word-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-file-zip-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-film\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-filter\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-fire\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-fire-extinguisher\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-flag\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-flag-checkered\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-flag-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-flash\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-flask\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-folder\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-folder-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-folder-open\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-folder-open-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-frown-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-futbol-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-gamepad\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-gavel\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-gear\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-gears\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-gift\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-glass\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-graduation-cap\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-group\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-grab-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-lizard-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-paper-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-peace-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-pointer-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-rock-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-scissors-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-spock-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hand-stop-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-handshake-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hard-of-hearing\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hashtag\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hdd-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-headphones\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-heart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-heart-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-heartbeat\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-history\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-home\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hotel\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-1\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-2\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-3\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-end\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-half\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-hourglass-start\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-i-cursor\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-id-badge\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-id-card\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-id-card-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-image\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-inbox\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-industry\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-info\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-info-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-institution\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-key\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-keyboard-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-language\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-laptop\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-leaf\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-legal\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-lemon-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-level-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-level-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-life-bouy\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-life-buoy\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-life-ring\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-life-saver\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-lightbulb-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-line-chart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-location-arrow\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-lock\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-low-vision\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-magic\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-magnet\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mail-forward\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mail-reply\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mail-reply-all\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-male\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-map\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-map-marker\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-map-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-map-pin\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-map-signs\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-meh-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-microchip\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-microphone\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-microphone-slash\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-minus-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-minus-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-minus-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mobile\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mobile-phone\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-money\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-moon-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mortar-board\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-motorcycle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-mouse-pointer\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-music\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-navicon\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-newspaper-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-object-group\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-object-ungroup\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-paint-brush\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-paper-plane-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-paw\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-pencil-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-pencil-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-percent\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-phone\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-phone-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-photo\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-picture-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-pie-chart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plane\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plug\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plus-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-plus-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-podcast\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-power-off\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-print\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-puzzle-piece\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-qrcode\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-question\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-question-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-question-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-quote-left\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-quote-right\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-random\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-recycle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-refresh\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-registered\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-remove\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-reorder\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-reply\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-reply-all\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-retweet\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-road\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-rocket\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-rss\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-rss-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-s15\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-search-minus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-search-plus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-send\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-send-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-server\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-share\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-share-alt-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-share-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-share-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-shield\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-ship\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-shopping-bag\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-shopping-basket\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-shopping-cart\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-shower\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sign-in\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sign-language\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-signal\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-signing\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sitemap\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sliders\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-smile-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-snowflake-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-soccer-ball-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-alpha-asc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-alpha-desc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-amount-asc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-amount-desc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-asc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-desc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-numeric-asc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-numeric-desc\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sort-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-space-shuttle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-spinner\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-spoon\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-square\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-square-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star-half\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star-half-empty\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star-half-full\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star-half-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-star-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sticky-note\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sticky-note-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-street-view\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-suitcase\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-sun-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-support\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tablet\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tachometer\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tag\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tags\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tasks\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-taxi\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-television\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-terminal\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-0\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-1\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-2\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-3\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-4\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-empty\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-full\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-half\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-quarter\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thermometer-three-quarters\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thumb-tack\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thumbs-o-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thumbs-o-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-ticket\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-times\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-times-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-times-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-times-rectangle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-times-rectangle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tint\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-left\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-off\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-on\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-right\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-toggle-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-trademark\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-trash\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-trash-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tree\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-trophy\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-truck\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tty\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-tv\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-umbrella\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-universal-access\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-university\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-unlock\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-unlock-alt\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-unsorted\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-upload\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-circle\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-circle-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-plus\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-secret\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-user-times\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-users\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-vcard\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-vcard-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-video-camera\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-volume-control-phone\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-volume-down\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-volume-off\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-volume-up\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-warning\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-wheelchair\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-wheelchair-alt\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-wifi\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-window-close\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-window-close-o\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-window-maximize\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-window-minimize\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-window-restore\" aria-hidden=\"true\"></i>\n\n     <i class=\"fa fa-wrench\" aria-hidden=\"true\"></i>\n\n</div>\n\n<script type=\"text/javascript\">\n    var index = parent.layer.getFrameIndex(window.name);\n    //给父页面传值\n    $('.ico-list i').on('click', function(){\n        parent.$('#icon').val($(this).attr('class'));\n        //parent.layer.tips('Look here', '#parentIframe', {time: 5000});\n        parent.layer.close(index);\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/public/chart/graph_echarts.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n\n    <title>百度ECHarts</title>\n    <meta name=\"keywords\" content=\"\">\n    <meta name=\"description\" content=\"\">\n\n    <link rel=\"shortcut icon\" href=\"favicon.ico\"> <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n\n</head>\n\n<body class=\"gray-bg\">\n    <div class=\"row  border-bottom white-bg dashboard-header\">\n        <div class=\"col-sm-12\">\n            <p>ECharts开源来自百度商业前端数据可视化团队，基于html5 Canvas，是一个纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验，赋予了用户对数据进行挖掘、整合的能力。 <a href=\"http://echarts.baidu.com/doc/about.html\" target=\"_blank\">了解更多</a>\n            </p>\n            <p>ECharts官网：<a href=\"http://echarts.baidu.com/\" target=\"_blank\">http://echarts.baidu.com/</a>\n            </p>\n\n        </div>\n\n    </div>\n    <div class=\"wrapper wrapper-content animated fadeInRight\">\n        <div class=\"row\">\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>折线图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-line-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>柱状图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n\n                        <div class=\"echarts\" id=\"echarts-bar-chart\"></div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <div class=\"row\">\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>散点图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-scatter-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>K线图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-k-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>饼状图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-pie-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>雷达图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-radar-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>和弦图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-chord-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>仪表盘</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-gauge-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>漏斗图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-funnel-chart\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"col-sm-6\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>力导向布局图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div class=\"echarts\" id=\"echarts-force-chart\"></div>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-12\">\n                <div class=\"ibox float-e-margins\">\n                    <div class=\"ibox-title\">\n                        <h5>中国地图</h5>\n                        <div class=\"ibox-tools\">\n                            <a class=\"collapse-link\">\n                                <i class=\"fa fa-chevron-up\"></i>\n                            </a>\n                            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"graph_flot.html#\">\n                                <i class=\"fa fa-wrench\"></i>\n                            </a>\n                            <ul class=\"dropdown-menu dropdown-user\">\n                                <li><a href=\"graph_flot.html#\">选项1</a>\n                                </li>\n                                <li><a href=\"graph_flot.html#\">选项2</a>\n                                </li>\n                            </ul>\n                            <a class=\"close-link\">\n                                <i class=\"fa fa-times\"></i>\n                            </a>\n                        </div>\n                    </div>\n                    <div class=\"ibox-content\">\n                        <div style=\"height:600px\" id=\"echarts-map-chart\"></div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n    <!-- 全局js -->\n    <script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n    <script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n\n    <!-- ECharts -->\n    <script src=\"/js/plugins/echarts/echarts-all.js\"></script>\n\n    <!-- 自定义js -->\n    <script src=\"/js/content.js?v=1.0.0\"></script>\n\n\n    <!-- ECharts demo data -->\n    <script src=\"/js/demo/echarts-demo.js\"></script>\n\n\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/public/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 + \"/act/service/process-instance/{processInstanceId}/highlights?callback=?\",\n    processDefinitionUrl: baseUrl + \"/act/service/process-definition/{processDefinitionId}/diagram-layout?callback=?\",\n    processDefinitionByKeyUrl: baseUrl + \"/act/service/process-definition/{processDefinitionKey}/diagram-layout?callback=?\",\n    processInstanceUrl: baseUrl + \"/act/service/process-instance/{processInstanceId}/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": "src/main/resources/public/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": "src/main/resources/public/diagram-viewer/js/ActivityImpl.js",
    "content": "/**\r * \r * @author 郑保乐\r * @author 郑保乐\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": "src/main/resources/public/diagram-viewer/js/Color.js",
    "content": "/**\n * Web color table\n * \n * @author 郑保乐\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": "src/main/resources/public/diagram-viewer/js/LineBreakMeasurer.js",
    "content": "/**\n * Word wrapping\n * \n * @author 郑保乐\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": "src/main/resources/public/diagram-viewer/js/Polyline.js",
    "content": "/**\n * Class to generate polyline\n *\n * @author 郑保乐\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": "src/main/resources/public/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 郑保乐\n * @author 郑保乐\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": "src/main/resources/public/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 郑保乐\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\t// ���������ʵ����ʱ���׳��쳣���⡣\n\t\tvar url = Lang.sub(ActivitiRest.options.processInstanceUrl, {processInstanceId: processInstanceId});\n\t\tvar _drawHighLights = this._drawHighLights;\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\tActivitiRest.getHighLights(processInstanceId, _drawHighLights);\n\t\t}).fail(function(jqXHR, textStatus){\n\t\t\tconsole.log('Get HighLights['+processInstanceId+'] failure: ', textStatus, jqXHR);\n\t\t});\n\t\t//ActivitiRest.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\t\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": "src/main/resources/public/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 郑保乐\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": "src/main/resources/public/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 common 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 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 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 common 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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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": "src/main/resources/public/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>\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": "src/main/resources/static/css/animate.css",
    "content": "/* @charset \"UTF-8\";\n\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\n\n.animated {\n    -webkit-animation-duration: 1s;\n    animation-duration: 1s;\n    -webkit-animation-fill-mode: both;\n    animation-fill-mode: both;\n    z-index: 100;\n}\n\n.animated.infinite {\n    -webkit-animation-iteration-count: infinite;\n    animation-iteration-count: infinite;\n}\n\n.animated.hinge {\n    -webkit-animation-duration: 2s;\n    animation-duration: 2s;\n}\n\n@-webkit-keyframes bounce {\n    0%, 20%, 50%, 80%, 100% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    40% {\n        -webkit-transform: translateY(-30px);\n        transform: translateY(-30px);\n    }\n\n    60% {\n        -webkit-transform: translateY(-15px);\n        transform: translateY(-15px);\n    }\n}\n\n@keyframes bounce {\n    0%, 20%, 50%, 80%, 100% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    40% {\n        -webkit-transform: translateY(-30px);\n        -ms-transform: translateY(-30px);\n        transform: translateY(-30px);\n    }\n\n    60% {\n        -webkit-transform: translateY(-15px);\n        -ms-transform: translateY(-15px);\n        transform: translateY(-15px);\n    }\n}\n\n.bounce {\n    -webkit-animation-name: bounce;\n    animation-name: bounce;\n}\n\n@-webkit-keyframes flash {\n    0%, 50%, 100% {\n        opacity: 1;\n    }\n\n    25%, 75% {\n        opacity: 0;\n    }\n}\n\n@keyframes flash {\n    0%, 50%, 100% {\n        opacity: 1;\n    }\n\n    25%, 75% {\n        opacity: 0;\n    }\n}\n\n.flash {\n    -webkit-animation-name: flash;\n    animation-name: flash;\n}\n\noriginally authored by Nick Pettit - https://github.com/nickpettit/glide\n\n@-webkit-keyframes pulse {\n    0% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n\n    50% {\n        -webkit-transform: scale(1.1);\n        transform: scale(1.1);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes pulse {\n    0% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n\n    50% {\n        -webkit-transform: scale(1.1);\n        -ms-transform: scale(1.1);\n        transform: scale(1.1);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n.pulse {\n    -webkit-animation-name: pulse;\n    animation-name: pulse;\n}\n\n@-webkit-keyframes rubberBand {\n    0% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n\n    30% {\n        -webkit-transform: scaleX(1.25) scaleY(0.75);\n        transform: scaleX(1.25) scaleY(0.75);\n    }\n\n    40% {\n        -webkit-transform: scaleX(0.75) scaleY(1.25);\n        transform: scaleX(0.75) scaleY(1.25);\n    }\n\n    60% {\n        -webkit-transform: scaleX(1.15) scaleY(0.85);\n        transform: scaleX(1.15) scaleY(0.85);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes rubberBand {\n    0% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n\n    30% {\n        -webkit-transform: scaleX(1.25) scaleY(0.75);\n        -ms-transform: scaleX(1.25) scaleY(0.75);\n        transform: scaleX(1.25) scaleY(0.75);\n    }\n\n    40% {\n        -webkit-transform: scaleX(0.75) scaleY(1.25);\n        -ms-transform: scaleX(0.75) scaleY(1.25);\n        transform: scaleX(0.75) scaleY(1.25);\n    }\n\n    60% {\n        -webkit-transform: scaleX(1.15) scaleY(0.85);\n        -ms-transform: scaleX(1.15) scaleY(0.85);\n        transform: scaleX(1.15) scaleY(0.85);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n.rubberBand {\n    -webkit-animation-name: rubberBand;\n    animation-name: rubberBand;\n}\n\n@-webkit-keyframes shake {\n    0%, 100% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    10%, 30%, 50%, 70%, 90% {\n        -webkit-transform: translateX(-10px);\n        transform: translateX(-10px);\n    }\n\n    20%, 40%, 60%, 80% {\n        -webkit-transform: translateX(10px);\n        transform: translateX(10px);\n    }\n}\n\n@keyframes shake {\n    0%, 100% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    10%, 30%, 50%, 70%, 90% {\n        -webkit-transform: translateX(-10px);\n        -ms-transform: translateX(-10px);\n        transform: translateX(-10px);\n    }\n\n    20%, 40%, 60%, 80% {\n        -webkit-transform: translateX(10px);\n        -ms-transform: translateX(10px);\n        transform: translateX(10px);\n    }\n}\n\n.shake {\n    -webkit-animation-name: shake;\n    animation-name: shake;\n}\n\n@-webkit-keyframes swing {\n    20% {\n        -webkit-transform: rotate(15deg);\n        transform: rotate(15deg);\n    }\n\n    40% {\n        -webkit-transform: rotate(-10deg);\n        transform: rotate(-10deg);\n    }\n\n    60% {\n        -webkit-transform: rotate(5deg);\n        transform: rotate(5deg);\n    }\n\n    80% {\n        -webkit-transform: rotate(-5deg);\n        transform: rotate(-5deg);\n    }\n\n    100% {\n        -webkit-transform: rotate(0deg);\n        transform: rotate(0deg);\n    }\n}\n\n@keyframes swing {\n    20% {\n        -webkit-transform: rotate(15deg);\n        -ms-transform: rotate(15deg);\n        transform: rotate(15deg);\n    }\n\n    40% {\n        -webkit-transform: rotate(-10deg);\n        -ms-transform: rotate(-10deg);\n        transform: rotate(-10deg);\n    }\n\n    60% {\n        -webkit-transform: rotate(5deg);\n        -ms-transform: rotate(5deg);\n        transform: rotate(5deg);\n    }\n\n    80% {\n        -webkit-transform: rotate(-5deg);\n        -ms-transform: rotate(-5deg);\n        transform: rotate(-5deg);\n    }\n\n    100% {\n        -webkit-transform: rotate(0deg);\n        -ms-transform: rotate(0deg);\n        transform: rotate(0deg);\n    }\n}\n\n.swing {\n    -webkit-transform-origin: top center;\n    -ms-transform-origin: top center;\n    transform-origin: top center;\n    -webkit-animation-name: swing;\n    animation-name: swing;\n}\n\n@-webkit-keyframes tada {\n    0% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n\n    10%, 20% {\n        -webkit-transform: scale(0.9) rotate(-3deg);\n        transform: scale(0.9) rotate(-3deg);\n    }\n\n    30%, 50%, 70%, 90% {\n        -webkit-transform: scale(1.1) rotate(3deg);\n        transform: scale(1.1) rotate(3deg);\n    }\n\n    40%, 60%, 80% {\n        -webkit-transform: scale(1.1) rotate(-3deg);\n        transform: scale(1.1) rotate(-3deg);\n    }\n\n    100% {\n        -webkit-transform: scale(1) rotate(0);\n        transform: scale(1) rotate(0);\n    }\n}\n\n@keyframes tada {\n    0% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n\n    10%, 20% {\n        -webkit-transform: scale(0.9) rotate(-3deg);\n        -ms-transform: scale(0.9) rotate(-3deg);\n        transform: scale(0.9) rotate(-3deg);\n    }\n\n    30%, 50%, 70%, 90% {\n        -webkit-transform: scale(1.1) rotate(3deg);\n        -ms-transform: scale(1.1) rotate(3deg);\n        transform: scale(1.1) rotate(3deg);\n    }\n\n    40%, 60%, 80% {\n        -webkit-transform: scale(1.1) rotate(-3deg);\n        -ms-transform: scale(1.1) rotate(-3deg);\n        transform: scale(1.1) rotate(-3deg);\n    }\n\n    100% {\n        -webkit-transform: scale(1) rotate(0);\n        -ms-transform: scale(1) rotate(0);\n        transform: scale(1) rotate(0);\n    }\n}\n\n.tada {\n    -webkit-animation-name: tada;\n    animation-name: tada;\n}\n\noriginally authored by Nick Pettit - https://github.com/nickpettit/glide\n\n@-webkit-keyframes wobble {\n    0% {\n        -webkit-transform: translateX(0%);\n        transform: translateX(0%);\n    }\n\n    15% {\n        -webkit-transform: translateX(-25%) rotate(-5deg);\n        transform: translateX(-25%) rotate(-5deg);\n    }\n\n    30% {\n        -webkit-transform: translateX(20%) rotate(3deg);\n        transform: translateX(20%) rotate(3deg);\n    }\n\n    45% {\n        -webkit-transform: translateX(-15%) rotate(-3deg);\n        transform: translateX(-15%) rotate(-3deg);\n    }\n\n    60% {\n        -webkit-transform: translateX(10%) rotate(2deg);\n        transform: translateX(10%) rotate(2deg);\n    }\n\n    75% {\n        -webkit-transform: translateX(-5%) rotate(-1deg);\n        transform: translateX(-5%) rotate(-1deg);\n    }\n\n    100% {\n        -webkit-transform: translateX(0%);\n        transform: translateX(0%);\n    }\n}\n\n@keyframes wobble {\n    0% {\n        -webkit-transform: translateX(0%);\n        -ms-transform: translateX(0%);\n        transform: translateX(0%);\n    }\n\n    15% {\n        -webkit-transform: translateX(-25%) rotate(-5deg);\n        -ms-transform: translateX(-25%) rotate(-5deg);\n        transform: translateX(-25%) rotate(-5deg);\n    }\n\n    30% {\n        -webkit-transform: translateX(20%) rotate(3deg);\n        -ms-transform: translateX(20%) rotate(3deg);\n        transform: translateX(20%) rotate(3deg);\n    }\n\n    45% {\n        -webkit-transform: translateX(-15%) rotate(-3deg);\n        -ms-transform: translateX(-15%) rotate(-3deg);\n        transform: translateX(-15%) rotate(-3deg);\n    }\n\n    60% {\n        -webkit-transform: translateX(10%) rotate(2deg);\n        -ms-transform: translateX(10%) rotate(2deg);\n        transform: translateX(10%) rotate(2deg);\n    }\n\n    75% {\n        -webkit-transform: translateX(-5%) rotate(-1deg);\n        -ms-transform: translateX(-5%) rotate(-1deg);\n        transform: translateX(-5%) rotate(-1deg);\n    }\n\n    100% {\n        -webkit-transform: translateX(0%);\n        -ms-transform: translateX(0%);\n        transform: translateX(0%);\n    }\n}\n\n.wobble {\n    -webkit-animation-name: wobble;\n    animation-name: wobble;\n}\n\n@-webkit-keyframes bounceIn {\n    0% {\n        opacity: 0;\n        -webkit-transform: scale(.3);\n        transform: scale(.3);\n    }\n\n    50% {\n        opacity: 1;\n        -webkit-transform: scale(1.05);\n        transform: scale(1.05);\n    }\n\n    70% {\n        -webkit-transform: scale(.9);\n        transform: scale(.9);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes bounceIn {\n    0% {\n        opacity: 0;\n        -webkit-transform: scale(.3);\n        -ms-transform: scale(.3);\n        transform: scale(.3);\n    }\n\n    50% {\n        opacity: 1;\n        -webkit-transform: scale(1.05);\n        -ms-transform: scale(1.05);\n        transform: scale(1.05);\n    }\n\n    70% {\n        -webkit-transform: scale(.9);\n        -ms-transform: scale(.9);\n        transform: scale(.9);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n.bounceIn {\n    -webkit-animation-name: bounceIn;\n    animation-name: bounceIn;\n}\n\n@-webkit-keyframes bounceInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateY(30px);\n        transform: translateY(30px);\n    }\n\n    80% {\n        -webkit-transform: translateY(-10px);\n        transform: translateY(-10px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes bounceInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateY(30px);\n        -ms-transform: translateY(30px);\n        transform: translateY(30px);\n    }\n\n    80% {\n        -webkit-transform: translateY(-10px);\n        -ms-transform: translateY(-10px);\n        transform: translateY(-10px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.bounceInDown {\n    -webkit-animation-name: bounceInDown;\n    animation-name: bounceInDown;\n}\n\n@-webkit-keyframes bounceInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateX(30px);\n        transform: translateX(30px);\n    }\n\n    80% {\n        -webkit-transform: translateX(-10px);\n        transform: translateX(-10px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes bounceInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateX(30px);\n        -ms-transform: translateX(30px);\n        transform: translateX(30px);\n    }\n\n    80% {\n        -webkit-transform: translateX(-10px);\n        -ms-transform: translateX(-10px);\n        transform: translateX(-10px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.bounceInLeft {\n    -webkit-animation-name: bounceInLeft;\n    animation-name: bounceInLeft;\n}\n\n@-webkit-keyframes bounceInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateX(-30px);\n        transform: translateX(-30px);\n    }\n\n    80% {\n        -webkit-transform: translateX(10px);\n        transform: translateX(10px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes bounceInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateX(-30px);\n        -ms-transform: translateX(-30px);\n        transform: translateX(-30px);\n    }\n\n    80% {\n        -webkit-transform: translateX(10px);\n        -ms-transform: translateX(10px);\n        transform: translateX(10px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.bounceInRight {\n    -webkit-animation-name: bounceInRight;\n    animation-name: bounceInRight;\n}\n\n@-webkit-keyframes bounceInUp {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateY(-30px);\n        transform: translateY(-30px);\n    }\n\n    80% {\n        -webkit-transform: translateY(10px);\n        transform: translateY(10px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes bounceInUp {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        -ms-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n\n    60% {\n        opacity: 1;\n        -webkit-transform: translateY(-30px);\n        -ms-transform: translateY(-30px);\n        transform: translateY(-30px);\n    }\n\n    80% {\n        -webkit-transform: translateY(10px);\n        -ms-transform: translateY(10px);\n        transform: translateY(10px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.bounceInUp {\n    -webkit-animation-name: bounceInUp;\n    animation-name: bounceInUp;\n}\n\n@-webkit-keyframes bounceOut {\n    0% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n\n    25% {\n        -webkit-transform: scale(.95);\n        transform: scale(.95);\n    }\n\n    50% {\n        opacity: 1;\n        -webkit-transform: scale(1.1);\n        transform: scale(1.1);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: scale(.3);\n        transform: scale(.3);\n    }\n}\n\n@keyframes bounceOut {\n    0% {\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n\n    25% {\n        -webkit-transform: scale(.95);\n        -ms-transform: scale(.95);\n        transform: scale(.95);\n    }\n\n    50% {\n        opacity: 1;\n        -webkit-transform: scale(1.1);\n        -ms-transform: scale(1.1);\n        transform: scale(1.1);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: scale(.3);\n        -ms-transform: scale(.3);\n        transform: scale(.3);\n    }\n}\n\n.bounceOut {\n    -webkit-animation-name: bounceOut;\n    animation-name: bounceOut;\n}\n\n@-webkit-keyframes bounceOutDown {\n    0% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n@keyframes bounceOutDown {\n    0% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateY(-20px);\n        -ms-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        -ms-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n.bounceOutDown {\n    -webkit-animation-name: bounceOutDown;\n    animation-name: bounceOutDown;\n}\n\n@-webkit-keyframes bounceOutLeft {\n    0% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateX(20px);\n        transform: translateX(20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n@keyframes bounceOutLeft {\n    0% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateX(20px);\n        -ms-transform: translateX(20px);\n        transform: translateX(20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n.bounceOutLeft {\n    -webkit-animation-name: bounceOutLeft;\n    animation-name: bounceOutLeft;\n}\n\n@-webkit-keyframes bounceOutRight {\n    0% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n@keyframes bounceOutRight {\n    0% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateX(-20px);\n        -ms-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n.bounceOutRight {\n    -webkit-animation-name: bounceOutRight;\n    animation-name: bounceOutRight;\n}\n\n@-webkit-keyframes bounceOutUp {\n    0% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n@keyframes bounceOutUp {\n    0% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    20% {\n        opacity: 1;\n        -webkit-transform: translateY(20px);\n        -ms-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n.bounceOutUp {\n    -webkit-animation-name: bounceOutUp;\n    animation-name: bounceOutUp;\n}\n\n@-webkit-keyframes fadeIn {\n    0% {\n        opacity: 0;\n    }\n\n    100% {\n        opacity: 1;\n    }\n}\n\n@keyframes fadeIn {\n    0% {\n        opacity: 0;\n    }\n\n    100% {\n        opacity: 1;\n    }\n}\n\n.fadeIn {\n    -webkit-animation-name: fadeIn;\n    animation-name: fadeIn;\n}\n\n@-webkit-keyframes fadeInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes fadeInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-20px);\n        -ms-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.fadeInDown {\n    -webkit-animation-name: fadeInDown;\n    animation-name: fadeInDown;\n}\n\n@-webkit-keyframes fadeInDownBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes fadeInDownBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.fadeInDownBig {\n    -webkit-animation-name: fadeInDownBig;\n    animation-name: fadeInDownBig;\n}\n\n@-webkit-keyframes fadeInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes fadeInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-20px);\n        -ms-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.fadeInLeft {\n    -webkit-animation-name: fadeInLeft;\n    animation-name: fadeInLeft;\n}\n\n@-webkit-keyframes fadeInLeftBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes fadeInLeftBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.fadeInLeftBig {\n    -webkit-animation-name: fadeInLeftBig;\n    animation-name: fadeInLeftBig;\n}\n\n@-webkit-keyframes fadeInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(20px);\n        transform: translateX(20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes fadeInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(40px);\n        -ms-transform: translateX(40px);\n        transform: translateX(40px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.fadeInRight {\n    -webkit-animation-name: fadeInRight;\n    animation-name: fadeInRight;\n}\n\n@-webkit-keyframes fadeInRightBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes fadeInRightBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.fadeInRightBig {\n    -webkit-animation-name: fadeInRightBig;\n    animation-name: fadeInRightBig;\n}\n\n@-webkit-keyframes fadeInUp {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes fadeInUp {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(20px);\n        -ms-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.fadeInUp {\n    -webkit-animation-name: fadeInUp;\n    animation-name: fadeInUp;\n}\n\n@-webkit-keyframes fadeInUpBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes fadeInUpBig {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        -ms-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.fadeInUpBig {\n    -webkit-animation-name: fadeInUpBig;\n    animation-name: fadeInUpBig;\n}\n\n@-webkit-keyframes fadeOut {\n    0% {\n        opacity: 1;\n    }\n\n    100% {\n        opacity: 0;\n    }\n}\n\n@keyframes fadeOut {\n    0% {\n        opacity: 1;\n    }\n\n    100% {\n        opacity: 0;\n    }\n}\n\n.fadeOut {\n    -webkit-animation-name: fadeOut;\n    animation-name: fadeOut;\n}\n\n@-webkit-keyframes fadeOutDown {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n}\n\n@keyframes fadeOutDown {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(20px);\n        -ms-transform: translateY(20px);\n        transform: translateY(20px);\n    }\n}\n\n.fadeOutDown {\n    -webkit-animation-name: fadeOutDown;\n    animation-name: fadeOutDown;\n}\n\n@-webkit-keyframes fadeOutDownBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n@keyframes fadeOutDownBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        -ms-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n.fadeOutDownBig {\n    -webkit-animation-name: fadeOutDownBig;\n    animation-name: fadeOutDownBig;\n}\n\n@-webkit-keyframes fadeOutLeft {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n}\n\n@keyframes fadeOutLeft {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-20px);\n        -ms-transform: translateX(-20px);\n        transform: translateX(-20px);\n    }\n}\n\n.fadeOutLeft {\n    -webkit-animation-name: fadeOutLeft;\n    animation-name: fadeOutLeft;\n}\n\n@-webkit-keyframes fadeOutLeftBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n@keyframes fadeOutLeftBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n.fadeOutLeftBig {\n    -webkit-animation-name: fadeOutLeftBig;\n    animation-name: fadeOutLeftBig;\n}\n\n@-webkit-keyframes fadeOutRight {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(20px);\n        transform: translateX(20px);\n    }\n}\n\n@keyframes fadeOutRight {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(20px);\n        -ms-transform: translateX(20px);\n        transform: translateX(20px);\n    }\n}\n\n.fadeOutRight {\n    -webkit-animation-name: fadeOutRight;\n    animation-name: fadeOutRight;\n}\n\n@-webkit-keyframes fadeOutRightBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n@keyframes fadeOutRightBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n.fadeOutRightBig {\n    -webkit-animation-name: fadeOutRightBig;\n    animation-name: fadeOutRightBig;\n}\n\n@-webkit-keyframes fadeOutUp {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n}\n\n@keyframes fadeOutUp {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-20px);\n        -ms-transform: translateY(-20px);\n        transform: translateY(-20px);\n    }\n}\n\n.fadeOutUp {\n    -webkit-animation-name: fadeOutUp;\n    animation-name: fadeOutUp;\n}\n\n@-webkit-keyframes fadeOutUpBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n@keyframes fadeOutUpBig {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n.fadeOutUpBig {\n    -webkit-animation-name: fadeOutUpBig;\n    animation-name: fadeOutUpBig;\n}\n\n@-webkit-keyframes flip {\n    0% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n        transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n        -webkit-animation-timing-function: ease-out;\n        animation-timing-function: ease-out;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n        transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n        -webkit-animation-timing-function: ease-out;\n        animation-timing-function: ease-out;\n    }\n\n    50% {\n        -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n        transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n\n    80% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n        transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n        transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n}\n\n@keyframes flip {\n    0% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n        -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n        transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n        -webkit-animation-timing-function: ease-out;\n        animation-timing-function: ease-out;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n        -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n        transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n        -webkit-animation-timing-function: ease-out;\n        animation-timing-function: ease-out;\n    }\n\n    50% {\n        -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n        -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n        transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n\n    80% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n        -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n        transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n        -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n        transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n        -webkit-animation-timing-function: ease-in;\n        animation-timing-function: ease-in;\n    }\n}\n\n.animated.flip {\n    -webkit-backface-visibility: visible;\n    -ms-backface-visibility: visible;\n    backface-visibility: visible;\n    -webkit-animation-name: flip;\n    animation-name: flip;\n}\n\n@-webkit-keyframes flipInX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) rotateX(-10deg);\n        transform: perspective(400px) rotateX(-10deg);\n    }\n\n    70% {\n        -webkit-transform: perspective(400px) rotateX(10deg);\n        transform: perspective(400px) rotateX(10deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n\n@keyframes flipInX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        -ms-transform: perspective(400px) rotateX(90deg);\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) rotateX(-10deg);\n        -ms-transform: perspective(400px) rotateX(-10deg);\n        transform: perspective(400px) rotateX(-10deg);\n    }\n\n    70% {\n        -webkit-transform: perspective(400px) rotateX(10deg);\n        -ms-transform: perspective(400px) rotateX(10deg);\n        transform: perspective(400px) rotateX(10deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        -ms-transform: perspective(400px) rotateX(0deg);\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n\n.flipInX {\n    -webkit-backface-visibility: visible !important;\n    -ms-backface-visibility: visible !important;\n    backface-visibility: visible !important;\n    -webkit-animation-name: flipInX;\n    animation-name: flipInX;\n}\n\n@-webkit-keyframes flipInY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) rotateY(-10deg);\n        transform: perspective(400px) rotateY(-10deg);\n    }\n\n    70% {\n        -webkit-transform: perspective(400px) rotateY(10deg);\n        transform: perspective(400px) rotateY(10deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n\n@keyframes flipInY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        -ms-transform: perspective(400px) rotateY(90deg);\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n\n    40% {\n        -webkit-transform: perspective(400px) rotateY(-10deg);\n        -ms-transform: perspective(400px) rotateY(-10deg);\n        transform: perspective(400px) rotateY(-10deg);\n    }\n\n    70% {\n        -webkit-transform: perspective(400px) rotateY(10deg);\n        -ms-transform: perspective(400px) rotateY(10deg);\n        transform: perspective(400px) rotateY(10deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        -ms-transform: perspective(400px) rotateY(0deg);\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n\n.flipInY {\n    -webkit-backface-visibility: visible !important;\n    -ms-backface-visibility: visible !important;\n    backface-visibility: visible !important;\n    -webkit-animation-name: flipInY;\n    animation-name: flipInY;\n}\n\n@-webkit-keyframes flipOutX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes flipOutX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        -ms-transform: perspective(400px) rotateX(0deg);\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        -ms-transform: perspective(400px) rotateX(90deg);\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n.flipOutX {\n    -webkit-animation-name: flipOutX;\n    animation-name: flipOutX;\n    -webkit-backface-visibility: visible !important;\n    -ms-backface-visibility: visible !important;\n    backface-visibility: visible !important;\n}\n\n@-webkit-keyframes flipOutY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes flipOutY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        -ms-transform: perspective(400px) rotateY(0deg);\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        -ms-transform: perspective(400px) rotateY(90deg);\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n\n.flipOutY {\n    -webkit-backface-visibility: visible !important;\n    -ms-backface-visibility: visible !important;\n    backface-visibility: visible !important;\n    -webkit-animation-name: flipOutY;\n    animation-name: flipOutY;\n}\n\n@-webkit-keyframes lightSpeedIn {\n    0% {\n        -webkit-transform: translateX(100%) skewX(-30deg);\n        transform: translateX(100%) skewX(-30deg);\n        opacity: 0;\n    }\n\n    60% {\n        -webkit-transform: translateX(-20%) skewX(30deg);\n        transform: translateX(-20%) skewX(30deg);\n        opacity: 1;\n    }\n\n    80% {\n        -webkit-transform: translateX(0%) skewX(-15deg);\n        transform: translateX(0%) skewX(-15deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateX(0%) skewX(0deg);\n        transform: translateX(0%) skewX(0deg);\n        opacity: 1;\n    }\n}\n\n@keyframes lightSpeedIn {\n    0% {\n        -webkit-transform: translateX(100%) skewX(-30deg);\n        -ms-transform: translateX(100%) skewX(-30deg);\n        transform: translateX(100%) skewX(-30deg);\n        opacity: 0;\n    }\n\n    60% {\n        -webkit-transform: translateX(-20%) skewX(30deg);\n        -ms-transform: translateX(-20%) skewX(30deg);\n        transform: translateX(-20%) skewX(30deg);\n        opacity: 1;\n    }\n\n    80% {\n        -webkit-transform: translateX(0%) skewX(-15deg);\n        -ms-transform: translateX(0%) skewX(-15deg);\n        transform: translateX(0%) skewX(-15deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateX(0%) skewX(0deg);\n        -ms-transform: translateX(0%) skewX(0deg);\n        transform: translateX(0%) skewX(0deg);\n        opacity: 1;\n    }\n}\n\n.lightSpeedIn {\n    -webkit-animation-name: lightSpeedIn;\n    animation-name: lightSpeedIn;\n    -webkit-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n}\n\n@-webkit-keyframes lightSpeedOut {\n    0% {\n        -webkit-transform: translateX(0%) skewX(0deg);\n        transform: translateX(0%) skewX(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateX(100%) skewX(-30deg);\n        transform: translateX(100%) skewX(-30deg);\n        opacity: 0;\n    }\n}\n\n@keyframes lightSpeedOut {\n    0% {\n        -webkit-transform: translateX(0%) skewX(0deg);\n        -ms-transform: translateX(0%) skewX(0deg);\n        transform: translateX(0%) skewX(0deg);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateX(100%) skewX(-30deg);\n        -ms-transform: translateX(100%) skewX(-30deg);\n        transform: translateX(100%) skewX(-30deg);\n        opacity: 0;\n    }\n}\n\n.lightSpeedOut {\n    -webkit-animation-name: lightSpeedOut;\n    animation-name: lightSpeedOut;\n    -webkit-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n}\n\n@-webkit-keyframes rotateIn {\n    0% {\n        -webkit-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(-200deg);\n        transform: rotate(-200deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n@keyframes rotateIn {\n    0% {\n        -webkit-transform-origin: center center;\n        -ms-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(-200deg);\n        -ms-transform: rotate(-200deg);\n        transform: rotate(-200deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: center center;\n        -ms-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n.rotateIn {\n    -webkit-animation-name: rotateIn;\n    animation-name: rotateIn;\n}\n\n@-webkit-keyframes rotateInDownLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n@keyframes rotateInDownLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n.rotateInDownLeft {\n    -webkit-animation-name: rotateInDownLeft;\n    animation-name: rotateInDownLeft;\n}\n\n@-webkit-keyframes rotateInDownRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n@keyframes rotateInDownRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(90deg);\n        -ms-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n.rotateInDownRight {\n    -webkit-animation-name: rotateInDownRight;\n    animation-name: rotateInDownRight;\n}\n\n@-webkit-keyframes rotateInUpLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n@keyframes rotateInUpLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(90deg);\n        -ms-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n.rotateInUpLeft {\n    -webkit-animation-name: rotateInUpLeft;\n    animation-name: rotateInUpLeft;\n}\n\n@-webkit-keyframes rotateInUpRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n@keyframes rotateInUpRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n}\n\n.rotateInUpRight {\n    -webkit-animation-name: rotateInUpRight;\n    animation-name: rotateInUpRight;\n}\n\n@-webkit-keyframes rotateOut {\n    0% {\n        -webkit-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(200deg);\n        transform: rotate(200deg);\n        opacity: 0;\n    }\n}\n\n@keyframes rotateOut {\n    0% {\n        -webkit-transform-origin: center center;\n        -ms-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: center center;\n        -ms-transform-origin: center center;\n        transform-origin: center center;\n        -webkit-transform: rotate(200deg);\n        -ms-transform: rotate(200deg);\n        transform: rotate(200deg);\n        opacity: 0;\n    }\n}\n\n.rotateOut {\n    -webkit-animation-name: rotateOut;\n    animation-name: rotateOut;\n}\n\n@-webkit-keyframes rotateOutDownLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes rotateOutDownLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(90deg);\n        -ms-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n}\n\n.rotateOutDownLeft {\n    -webkit-animation-name: rotateOutDownLeft;\n    animation-name: rotateOutDownLeft;\n}\n\n@-webkit-keyframes rotateOutDownRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes rotateOutDownRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n}\n\n.rotateOutDownRight {\n    -webkit-animation-name: rotateOutDownRight;\n    animation-name: rotateOutDownRight;\n}\n\n@-webkit-keyframes rotateOutUpLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes rotateOutUpLeft {\n    0% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: left bottom;\n        -ms-transform-origin: left bottom;\n        transform-origin: left bottom;\n        -webkit-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n        transform: rotate(-90deg);\n        opacity: 0;\n    }\n}\n\n.rotateOutUpLeft {\n    -webkit-animation-name: rotateOutUpLeft;\n    animation-name: rotateOutUpLeft;\n}\n\n@-webkit-keyframes rotateOutUpRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes rotateOutUpRight {\n    0% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform-origin: right bottom;\n        -ms-transform-origin: right bottom;\n        transform-origin: right bottom;\n        -webkit-transform: rotate(90deg);\n        -ms-transform: rotate(90deg);\n        transform: rotate(90deg);\n        opacity: 0;\n    }\n}\n\n.rotateOutUpRight {\n    -webkit-animation-name: rotateOutUpRight;\n    animation-name: rotateOutUpRight;\n}\n\n@-webkit-keyframes slideInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n@keyframes slideInDown {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n\n    100% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n}\n\n.slideInDown {\n    -webkit-animation-name: slideInDown;\n    animation-name: slideInDown;\n}\n\n@-webkit-keyframes slideInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes slideInLeft {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.slideInLeft {\n    -webkit-animation-name: slideInLeft;\n    animation-name: slideInLeft;\n}\n\n@-webkit-keyframes slideInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n@keyframes slideInRight {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n\n    100% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n}\n\n.slideInRight {\n    -webkit-animation-name: slideInRight;\n    animation-name: slideInRight;\n}\n\n@-webkit-keyframes slideOutLeft {\n    0% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n@keyframes slideOutLeft {\n    0% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(-2000px);\n        -ms-transform: translateX(-2000px);\n        transform: translateX(-2000px);\n    }\n}\n\n.slideOutLeft {\n    -webkit-animation-name: slideOutLeft;\n    animation-name: slideOutLeft;\n}\n\n@-webkit-keyframes slideOutRight {\n    0% {\n        -webkit-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n@keyframes slideOutRight {\n    0% {\n        -webkit-transform: translateX(0);\n        -ms-transform: translateX(0);\n        transform: translateX(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(2000px);\n        -ms-transform: translateX(2000px);\n        transform: translateX(2000px);\n    }\n}\n\n.slideOutRight {\n    -webkit-animation-name: slideOutRight;\n    animation-name: slideOutRight;\n}\n\n@-webkit-keyframes slideOutUp {\n    0% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n@keyframes slideOutUp {\n    0% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(-2000px);\n        -ms-transform: translateY(-2000px);\n        transform: translateY(-2000px);\n    }\n}\n\n.slideOutUp {\n    -webkit-animation-name: slideOutUp;\n    animation-name: slideOutUp;\n}\n\n@-webkit-keyframes slideOutDown {\n    0% {\n        -webkit-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n@keyframes slideOutDown {\n    0% {\n        -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n        transform: translateY(0);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateY(2000px);\n        -ms-transform: translateY(2000px);\n        transform: translateY(2000px);\n    }\n}\n\n.slideOutDown {\n    -webkit-animation-name: slideOutDown;\n    animation-name: slideOutDown;\n}\n\n@-webkit-keyframes hinge {\n    0% {\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n        -webkit-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    20%, 60% {\n        -webkit-transform: rotate(80deg);\n        transform: rotate(80deg);\n        -webkit-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    40% {\n        -webkit-transform: rotate(60deg);\n        transform: rotate(60deg);\n        -webkit-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    80% {\n        -webkit-transform: rotate(60deg) translateY(0);\n        transform: rotate(60deg) translateY(0);\n        -webkit-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateY(700px);\n        transform: translateY(700px);\n        opacity: 0;\n    }\n}\n\n@keyframes hinge {\n    0% {\n        -webkit-transform: rotate(0);\n        -ms-transform: rotate(0);\n        transform: rotate(0);\n        -webkit-transform-origin: top left;\n        -ms-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    20%, 60% {\n        -webkit-transform: rotate(80deg);\n        -ms-transform: rotate(80deg);\n        transform: rotate(80deg);\n        -webkit-transform-origin: top left;\n        -ms-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    40% {\n        -webkit-transform: rotate(60deg);\n        -ms-transform: rotate(60deg);\n        transform: rotate(60deg);\n        -webkit-transform-origin: top left;\n        -ms-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n    }\n\n    80% {\n        -webkit-transform: rotate(60deg) translateY(0);\n        -ms-transform: rotate(60deg) translateY(0);\n        transform: rotate(60deg) translateY(0);\n        -webkit-transform-origin: top left;\n        -ms-transform-origin: top left;\n        transform-origin: top left;\n        -webkit-animation-timing-function: ease-in-out;\n        animation-timing-function: ease-in-out;\n        opacity: 1;\n    }\n\n    100% {\n        -webkit-transform: translateY(700px);\n        -ms-transform: translateY(700px);\n        transform: translateY(700px);\n        opacity: 0;\n    }\n}\n\n.hinge {\n    -webkit-animation-name: hinge;\n    animation-name: hinge;\n}\n\noriginally authored by Nick Pettit - https://github.com/nickpettit/glide\n\n@-webkit-keyframes rollIn {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-100%) rotate(-120deg);\n        transform: translateX(-100%) rotate(-120deg);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0px) rotate(0deg);\n        transform: translateX(0px) rotate(0deg);\n    }\n}\n\n@keyframes rollIn {\n    0% {\n        opacity: 0;\n        -webkit-transform: translateX(-100%) rotate(-120deg);\n        -ms-transform: translateX(-100%) rotate(-120deg);\n        transform: translateX(-100%) rotate(-120deg);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: translateX(0px) rotate(0deg);\n        -ms-transform: translateX(0px) rotate(0deg);\n        transform: translateX(0px) rotate(0deg);\n    }\n}\n\n.rollIn {\n    -webkit-animation-name: rollIn;\n    animation-name: rollIn;\n}\n\noriginally authored by Nick Pettit - https://github.com/nickpettit/glide\n\n@-webkit-keyframes rollOut {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0px) rotate(0deg);\n        transform: translateX(0px) rotate(0deg);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(100%) rotate(120deg);\n        transform: translateX(100%) rotate(120deg);\n    }\n}\n\n@keyframes rollOut {\n    0% {\n        opacity: 1;\n        -webkit-transform: translateX(0px) rotate(0deg);\n        -ms-transform: translateX(0px) rotate(0deg);\n        transform: translateX(0px) rotate(0deg);\n    }\n\n    100% {\n        opacity: 0;\n        -webkit-transform: translateX(100%) rotate(120deg);\n        -ms-transform: translateX(100%) rotate(120deg);\n        transform: translateX(100%) rotate(120deg);\n    }\n}\n\n.rollOut {\n    -webkit-animation-name: rollOut;\n    animation-name: rollOut;\n}\n */"
  },
  {
    "path": "src/main/resources/static/css/blog/clean-blog.css",
    "content": "/*!\n * Clean Blog v1.0.0 (http://startbootstrap.com)\n * Copyright 2014 Start Bootstrap\n * Licensed under Apache 2.0 (https://github.com/IronSummitMedia/startbootstrap/blob/gh-pages/LICENSE)\n */\n\nbody {\n  font-family: 'Lora', 'Times New Roman', serif;\n  font-size: 20px;\n  color: #404040;\n}\np {\n  line-height: 1.5;\n  margin: 30px 0;\n}\np a {\n  text-decoration: underline;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  font-weight: 800;\n}\na {\n  color: #404040;\n}\na:hover,\na:focus {\n  color: #0085a1;\n}\na img:hover,\na img:focus {\n  cursor: zoom-in;\n}\nblockquote {\n  color: #808080;\n  font-style: italic;\n}\nhr.small {\n  max-width: 100px;\n  margin: 15px auto;\n  border-width: 4px;\n  border-color: white;\n}\n.navbar-custom {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  z-index: 3;\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n}\n.navbar-custom .navbar-brand {\n  font-weight: 800;\n}\n.navbar-custom .nav li a {\n  text-transform: uppercase;\n  font-size: 18px;\n  font-weight: 800;\n  letter-spacing: 1px;\n}\n@media only screen and (min-width: 768px) {\n  .navbar-custom {\n    background: transparent;\n    border-bottom: 1px solid transparent;\n  }\n  .navbar-custom .navbar-brand {\n    color: white;\n    padding: 20px;\n  }\n  .navbar-custom .navbar-brand:hover,\n  .navbar-custom .navbar-brand:focus {\n    color: rgba(255, 255, 255, 0.8);\n  }\n  .navbar-custom .nav li a {\n    color: white;\n    padding: 20px;\n  }\n  .navbar-custom .nav li a:hover,\n  .navbar-custom .nav li a:focus {\n    color: rgba(255, 255, 255, 0.8);\n  }\n}\n@media only screen and (min-width: 1170px) {\n  .navbar-custom {\n    -webkit-transition: background-color 0.3s;\n    -moz-transition: background-color 0.3s;\n    transition: background-color 0.3s;\n    /* Force Hardware Acceleration in WebKit */\n    -webkit-transform: translate3d(0, 0, 0);\n    -moz-transform: translate3d(0, 0, 0);\n    -ms-transform: translate3d(0, 0, 0);\n    -o-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n    -webkit-backface-visibility: hidden;\n    backface-visibility: hidden;\n  }\n  .navbar-custom.is-fixed {\n    /* when the user scrolls down, we hide the header right above the viewport */\n    position: fixed;\n    top: -61px;\n    background-color: rgba(255, 255, 255, 0.9);\n    border-bottom: 1px solid #f2f2f2;\n    -webkit-transition: -webkit-transform 0.3s;\n    -moz-transition: -moz-transform 0.3s;\n    transition: transform 0.3s;\n  }\n  .navbar-custom.is-fixed .navbar-brand {\n    color: #404040;\n  }\n  .navbar-custom.is-fixed .navbar-brand:hover,\n  .navbar-custom.is-fixed .navbar-brand:focus {\n    color: #0085a1;\n  }\n  .navbar-custom.is-fixed .nav li a {\n    color: #404040;\n  }\n  .navbar-custom.is-fixed .nav li a:hover,\n  .navbar-custom.is-fixed .nav li a:focus {\n    color: #0085a1;\n  }\n  .navbar-custom.is-visible {\n    /* if the user changes the scrolling direction, we show the header */\n    -webkit-transform: translate3d(0, 100%, 0);\n    -moz-transform: translate3d(0, 100%, 0);\n    -ms-transform: translate3d(0, 100%, 0);\n    -o-transform: translate3d(0, 100%, 0);\n    transform: translate3d(0, 100%, 0);\n  }\n}\n.intro-header {\n  background-color: #808080;\n  background: no-repeat center center;\n  background-attachment: scroll;\n  -webkit-background-size: cover;\n  -moz-background-size: cover;\n  background-size: cover;\n  -o-background-size: cover;\n  margin-bottom: 50px;\n}\n.intro-header .site-heading,\n.intro-header .post-heading,\n.intro-header .page-heading {\n  padding: 100px 0 50px;\n  color: white;\n}\n@media only screen and (min-width: 768px) {\n  .intro-header .site-heading,\n  .intro-header .post-heading,\n  .intro-header .page-heading {\n    padding: 150px 0;\n  }\n}\n.intro-header .site-heading,\n.intro-header .page-heading {\n  text-align: center;\n}\n.intro-header .site-heading h1,\n.intro-header .page-heading h1 {\n  margin-top: 0;\n  font-size: 50px;\n}\n.intro-header .site-heading .subheading,\n.intro-header .page-heading .subheading {\n  font-size: 24px;\n  line-height: 1.1;\n  display: block;\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  font-weight: 300;\n  margin: 10px 0 0;\n}\n@media only screen and (min-width: 768px) {\n  .intro-header .site-heading h1,\n  .intro-header .page-heading h1 {\n    font-size: 80px;\n  }\n}\n.intro-header .post-heading h1 {\n  font-size: 35px;\n}\n.intro-header .post-heading .subheading,\n.intro-header .post-heading .meta {\n  line-height: 1.1;\n  display: block;\n}\n.intro-header .post-heading .subheading {\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  font-size: 24px;\n  margin: 10px 0 30px;\n  font-weight: 600;\n}\n.intro-header .post-heading .meta {\n  font-family: 'Lora', 'Times New Roman', serif;\n  font-style: italic;\n  font-weight: 300;\n  font-size: 20px;\n}\n.intro-header .post-heading .meta a {\n  color: white;\n}\n@media only screen and (min-width: 768px) {\n  .intro-header .post-heading h1 {\n    font-size: 55px;\n  }\n  .intro-header .post-heading .subheading {\n    font-size: 30px;\n  }\n}\n.post-preview > a {\n  color: #404040;\n}\n.post-preview > a:hover,\n.post-preview > a:focus {\n  text-decoration: none;\n  color: #0085a1;\n}\n.post-preview > a > .post-title {\n  font-size: 30px;\n  margin-top: 30px;\n  margin-bottom: 10px;\n}\n.post-preview > a > .post-subtitle {\n  margin: 0;\n  font-weight: 300;\n  margin-bottom: 10px;\n}\n.post-preview > .post-meta {\n  color: #808080;\n  font-size: 18px;\n  font-style: italic;\n  margin-top: 0;\n}\n.post-preview > .post-meta > a {\n  text-decoration: none;\n  color: #404040;\n}\n.post-preview > .post-meta > a:hover,\n.post-preview > .post-meta > a:focus {\n  color: #0085a1;\n  text-decoration: underline;\n}\n@media only screen and (min-width: 768px) {\n  .post-preview > a > .post-title {\n    font-size: 36px;\n  }\n}\n.section-heading {\n  font-size: 36px;\n  margin-top: 60px;\n  font-weight: 700;\n}\n.caption {\n  text-align: center;\n  font-size: 14px;\n  padding: 10px;\n  font-style: italic;\n  margin: 0;\n  display: block;\n  border-bottom-right-radius: 5px;\n  border-bottom-left-radius: 5px;\n}\nfooter {\n  padding: 50px 0 65px;\n}\nfooter .list-inline {\n  margin: 0;\n  padding: 0;\n}\nfooter .copyright {\n  font-size: 14px;\n  text-align: center;\n  margin-bottom: 0;\n}\n.floating-label-form-group {\n  font-size: 14px;\n  position: relative;\n  margin-bottom: 0;\n  padding-bottom: 0.5em;\n  border-bottom: 1px solid #eeeeee;\n}\n.floating-label-form-group input,\n.floating-label-form-group textarea {\n  z-index: 1;\n  position: relative;\n  padding-right: 0;\n  padding-left: 0;\n  border: none;\n  border-radius: 0;\n  font-size: 1.5em;\n  background: none;\n  box-shadow: none !important;\n  resize: none;\n}\n.floating-label-form-group label {\n  display: block;\n  z-index: 0;\n  position: relative;\n  top: 2em;\n  margin: 0;\n  font-size: 0.85em;\n  line-height: 1.764705882em;\n  vertical-align: middle;\n  vertical-align: baseline;\n  opacity: 0;\n  -webkit-transition: top 0.3s ease,opacity 0.3s ease;\n  -moz-transition: top 0.3s ease,opacity 0.3s ease;\n  -ms-transition: top 0.3s ease,opacity 0.3s ease;\n  transition: top 0.3s ease,opacity 0.3s ease;\n}\n.floating-label-form-group::not(:first-child) {\n  padding-left: 14px;\n  border-left: 1px solid #eeeeee;\n}\n.floating-label-form-group-with-value label {\n  top: 0;\n  opacity: 1;\n}\n.floating-label-form-group-with-focus label {\n  color: #0085a1;\n}\nform .row:first-child .floating-label-form-group {\n  border-top: 1px solid #eeeeee;\n}\n.btn {\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  text-transform: uppercase;\n  font-size: 14px;\n  font-weight: 800;\n  letter-spacing: 1px;\n  border-radius: 0;\n  padding: 15px 25px;\n}\n.btn-lg {\n  font-size: 16px;\n  padding: 25px 35px;\n}\n.btn-default:hover,\n.btn-default:focus {\n  background-color: #0085a1;\n  border: 1px solid #0085a1;\n  color: white;\n}\n.pager {\n  margin: 20px 0 0;\n}\n.pager li > a,\n.pager li > span {\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  text-transform: uppercase;\n  font-size: 14px;\n  font-weight: 800;\n  letter-spacing: 1px;\n  padding: 15px 25px;\n  background-color: white;\n  border-radius: 0;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  color: white;\n  background-color: #0085a1;\n  border: 1px solid #0085a1;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #808080;\n  background-color: #404040;\n  cursor: not-allowed;\n}\n::-moz-selection {\n  color: white;\n  text-shadow: none;\n  background: #0085a1;\n}\n::selection {\n  color: white;\n  text-shadow: none;\n  background: #0085a1;\n}\nimg::selection {\n  color: white;\n  background: transparent;\n}\nimg::-moz-selection {\n  color: white;\n  background: transparent;\n}\nbody {\n  webkit-tap-highlight-color: #0085a1;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/bootstrap-rtl.css",
    "content": "/*******************************************************************************\n *              bootstrap-rtl (version 3.3.1)\n *      Author: Morteza Ansarinia (http://github.com/morteza)\n *  Created on: January 21,2015\n *     Project: bootstrap-rtl\n *   Copyright: Unlicensed Public Domain\n *******************************************************************************/\n\nhtml {\n  direction: rtl;\n}\nbody {\n  direction: rtl;\n}\n.list-unstyled {\n  padding-right: 0;\n  padding-left: initial;\n}\n.list-inline {\n  padding-right: 0;\n  padding-left: initial;\n  margin-right: -5px;\n  margin-left: 0;\n}\ndd {\n  margin-right: 0;\n  margin-left: initial;\n}\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: right;\n    clear: right;\n    text-align: left;\n  }\n  .dl-horizontal dd {\n    margin-right: 180px;\n    margin-left: 0;\n  }\n}\nblockquote {\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n.blockquote-reverse,\nblockquote.pull-left {\n  padding-left: 15px;\n  padding-right: 0;\n  border-left: 5px solid #eeeeee;\n  border-right: 0;\n  text-align: left;\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-left: 15px;\n  padding-right: 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: right;\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  left: 100%;\n  right: auto;\n}\n.col-xs-pull-11 {\n  left: 91.66666667%;\n  right: auto;\n}\n.col-xs-pull-10 {\n  left: 83.33333333%;\n  right: auto;\n}\n.col-xs-pull-9 {\n  left: 75%;\n  right: auto;\n}\n.col-xs-pull-8 {\n  left: 66.66666667%;\n  right: auto;\n}\n.col-xs-pull-7 {\n  left: 58.33333333%;\n  right: auto;\n}\n.col-xs-pull-6 {\n  left: 50%;\n  right: auto;\n}\n.col-xs-pull-5 {\n  left: 41.66666667%;\n  right: auto;\n}\n.col-xs-pull-4 {\n  left: 33.33333333%;\n  right: auto;\n}\n.col-xs-pull-3 {\n  left: 25%;\n  right: auto;\n}\n.col-xs-pull-2 {\n  left: 16.66666667%;\n  right: auto;\n}\n.col-xs-pull-1 {\n  left: 8.33333333%;\n  right: auto;\n}\n.col-xs-pull-0 {\n  left: auto;\n  right: auto;\n}\n.col-xs-push-12 {\n  right: 100%;\n  left: 0;\n}\n.col-xs-push-11 {\n  right: 91.66666667%;\n  left: 0;\n}\n.col-xs-push-10 {\n  right: 83.33333333%;\n  left: 0;\n}\n.col-xs-push-9 {\n  right: 75%;\n  left: 0;\n}\n.col-xs-push-8 {\n  right: 66.66666667%;\n  left: 0;\n}\n.col-xs-push-7 {\n  right: 58.33333333%;\n  left: 0;\n}\n.col-xs-push-6 {\n  right: 50%;\n  left: 0;\n}\n.col-xs-push-5 {\n  right: 41.66666667%;\n  left: 0;\n}\n.col-xs-push-4 {\n  right: 33.33333333%;\n  left: 0;\n}\n.col-xs-push-3 {\n  right: 25%;\n  left: 0;\n}\n.col-xs-push-2 {\n  right: 16.66666667%;\n  left: 0;\n}\n.col-xs-push-1 {\n  right: 8.33333333%;\n  left: 0;\n}\n.col-xs-push-0 {\n  right: auto;\n  left: 0;\n}\n.col-xs-offset-12 {\n  margin-right: 100%;\n  margin-left: 0;\n}\n.col-xs-offset-11 {\n  margin-right: 91.66666667%;\n  margin-left: 0;\n}\n.col-xs-offset-10 {\n  margin-right: 83.33333333%;\n  margin-left: 0;\n}\n.col-xs-offset-9 {\n  margin-right: 75%;\n  margin-left: 0;\n}\n.col-xs-offset-8 {\n  margin-right: 66.66666667%;\n  margin-left: 0;\n}\n.col-xs-offset-7 {\n  margin-right: 58.33333333%;\n  margin-left: 0;\n}\n.col-xs-offset-6 {\n  margin-right: 50%;\n  margin-left: 0;\n}\n.col-xs-offset-5 {\n  margin-right: 41.66666667%;\n  margin-left: 0;\n}\n.col-xs-offset-4 {\n  margin-right: 33.33333333%;\n  margin-left: 0;\n}\n.col-xs-offset-3 {\n  margin-right: 25%;\n  margin-left: 0;\n}\n.col-xs-offset-2 {\n  margin-right: 16.66666667%;\n  margin-left: 0;\n}\n.col-xs-offset-1 {\n  margin-right: 8.33333333%;\n  margin-left: 0;\n}\n.col-xs-offset-0 {\n  margin-right: 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: right;\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    left: 100%;\n    right: auto;\n  }\n  .col-sm-pull-11 {\n    left: 91.66666667%;\n    right: auto;\n  }\n  .col-sm-pull-10 {\n    left: 83.33333333%;\n    right: auto;\n  }\n  .col-sm-pull-9 {\n    left: 75%;\n    right: auto;\n  }\n  .col-sm-pull-8 {\n    left: 66.66666667%;\n    right: auto;\n  }\n  .col-sm-pull-7 {\n    left: 58.33333333%;\n    right: auto;\n  }\n  .col-sm-pull-6 {\n    left: 50%;\n    right: auto;\n  }\n  .col-sm-pull-5 {\n    left: 41.66666667%;\n    right: auto;\n  }\n  .col-sm-pull-4 {\n    left: 33.33333333%;\n    right: auto;\n  }\n  .col-sm-pull-3 {\n    left: 25%;\n    right: auto;\n  }\n  .col-sm-pull-2 {\n    left: 16.66666667%;\n    right: auto;\n  }\n  .col-sm-pull-1 {\n    left: 8.33333333%;\n    right: auto;\n  }\n  .col-sm-pull-0 {\n    left: auto;\n    right: auto;\n  }\n  .col-sm-push-12 {\n    right: 100%;\n    left: 0;\n  }\n  .col-sm-push-11 {\n    right: 91.66666667%;\n    left: 0;\n  }\n  .col-sm-push-10 {\n    right: 83.33333333%;\n    left: 0;\n  }\n  .col-sm-push-9 {\n    right: 75%;\n    left: 0;\n  }\n  .col-sm-push-8 {\n    right: 66.66666667%;\n    left: 0;\n  }\n  .col-sm-push-7 {\n    right: 58.33333333%;\n    left: 0;\n  }\n  .col-sm-push-6 {\n    right: 50%;\n    left: 0;\n  }\n  .col-sm-push-5 {\n    right: 41.66666667%;\n    left: 0;\n  }\n  .col-sm-push-4 {\n    right: 33.33333333%;\n    left: 0;\n  }\n  .col-sm-push-3 {\n    right: 25%;\n    left: 0;\n  }\n  .col-sm-push-2 {\n    right: 16.66666667%;\n    left: 0;\n  }\n  .col-sm-push-1 {\n    right: 8.33333333%;\n    left: 0;\n  }\n  .col-sm-push-0 {\n    right: auto;\n    left: 0;\n  }\n  .col-sm-offset-12 {\n    margin-right: 100%;\n    margin-left: 0;\n  }\n  .col-sm-offset-11 {\n    margin-right: 91.66666667%;\n    margin-left: 0;\n  }\n  .col-sm-offset-10 {\n    margin-right: 83.33333333%;\n    margin-left: 0;\n  }\n  .col-sm-offset-9 {\n    margin-right: 75%;\n    margin-left: 0;\n  }\n  .col-sm-offset-8 {\n    margin-right: 66.66666667%;\n    margin-left: 0;\n  }\n  .col-sm-offset-7 {\n    margin-right: 58.33333333%;\n    margin-left: 0;\n  }\n  .col-sm-offset-6 {\n    margin-right: 50%;\n    margin-left: 0;\n  }\n  .col-sm-offset-5 {\n    margin-right: 41.66666667%;\n    margin-left: 0;\n  }\n  .col-sm-offset-4 {\n    margin-right: 33.33333333%;\n    margin-left: 0;\n  }\n  .col-sm-offset-3 {\n    margin-right: 25%;\n    margin-left: 0;\n  }\n  .col-sm-offset-2 {\n    margin-right: 16.66666667%;\n    margin-left: 0;\n  }\n  .col-sm-offset-1 {\n    margin-right: 8.33333333%;\n    margin-left: 0;\n  }\n  .col-sm-offset-0 {\n    margin-right: 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: right;\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    left: 100%;\n    right: auto;\n  }\n  .col-md-pull-11 {\n    left: 91.66666667%;\n    right: auto;\n  }\n  .col-md-pull-10 {\n    left: 83.33333333%;\n    right: auto;\n  }\n  .col-md-pull-9 {\n    left: 75%;\n    right: auto;\n  }\n  .col-md-pull-8 {\n    left: 66.66666667%;\n    right: auto;\n  }\n  .col-md-pull-7 {\n    left: 58.33333333%;\n    right: auto;\n  }\n  .col-md-pull-6 {\n    left: 50%;\n    right: auto;\n  }\n  .col-md-pull-5 {\n    left: 41.66666667%;\n    right: auto;\n  }\n  .col-md-pull-4 {\n    left: 33.33333333%;\n    right: auto;\n  }\n  .col-md-pull-3 {\n    left: 25%;\n    right: auto;\n  }\n  .col-md-pull-2 {\n    left: 16.66666667%;\n    right: auto;\n  }\n  .col-md-pull-1 {\n    left: 8.33333333%;\n    right: auto;\n  }\n  .col-md-pull-0 {\n    left: auto;\n    right: auto;\n  }\n  .col-md-push-12 {\n    right: 100%;\n    left: 0;\n  }\n  .col-md-push-11 {\n    right: 91.66666667%;\n    left: 0;\n  }\n  .col-md-push-10 {\n    right: 83.33333333%;\n    left: 0;\n  }\n  .col-md-push-9 {\n    right: 75%;\n    left: 0;\n  }\n  .col-md-push-8 {\n    right: 66.66666667%;\n    left: 0;\n  }\n  .col-md-push-7 {\n    right: 58.33333333%;\n    left: 0;\n  }\n  .col-md-push-6 {\n    right: 50%;\n    left: 0;\n  }\n  .col-md-push-5 {\n    right: 41.66666667%;\n    left: 0;\n  }\n  .col-md-push-4 {\n    right: 33.33333333%;\n    left: 0;\n  }\n  .col-md-push-3 {\n    right: 25%;\n    left: 0;\n  }\n  .col-md-push-2 {\n    right: 16.66666667%;\n    left: 0;\n  }\n  .col-md-push-1 {\n    right: 8.33333333%;\n    left: 0;\n  }\n  .col-md-push-0 {\n    right: auto;\n    left: 0;\n  }\n  .col-md-offset-12 {\n    margin-right: 100%;\n    margin-left: 0;\n  }\n  .col-md-offset-11 {\n    margin-right: 91.66666667%;\n    margin-left: 0;\n  }\n  .col-md-offset-10 {\n    margin-right: 83.33333333%;\n    margin-left: 0;\n  }\n  .col-md-offset-9 {\n    margin-right: 75%;\n    margin-left: 0;\n  }\n  .col-md-offset-8 {\n    margin-right: 66.66666667%;\n    margin-left: 0;\n  }\n  .col-md-offset-7 {\n    margin-right: 58.33333333%;\n    margin-left: 0;\n  }\n  .col-md-offset-6 {\n    margin-right: 50%;\n    margin-left: 0;\n  }\n  .col-md-offset-5 {\n    margin-right: 41.66666667%;\n    margin-left: 0;\n  }\n  .col-md-offset-4 {\n    margin-right: 33.33333333%;\n    margin-left: 0;\n  }\n  .col-md-offset-3 {\n    margin-right: 25%;\n    margin-left: 0;\n  }\n  .col-md-offset-2 {\n    margin-right: 16.66666667%;\n    margin-left: 0;\n  }\n  .col-md-offset-1 {\n    margin-right: 8.33333333%;\n    margin-left: 0;\n  }\n  .col-md-offset-0 {\n    margin-right: 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: right;\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    left: 100%;\n    right: auto;\n  }\n  .col-lg-pull-11 {\n    left: 91.66666667%;\n    right: auto;\n  }\n  .col-lg-pull-10 {\n    left: 83.33333333%;\n    right: auto;\n  }\n  .col-lg-pull-9 {\n    left: 75%;\n    right: auto;\n  }\n  .col-lg-pull-8 {\n    left: 66.66666667%;\n    right: auto;\n  }\n  .col-lg-pull-7 {\n    left: 58.33333333%;\n    right: auto;\n  }\n  .col-lg-pull-6 {\n    left: 50%;\n    right: auto;\n  }\n  .col-lg-pull-5 {\n    left: 41.66666667%;\n    right: auto;\n  }\n  .col-lg-pull-4 {\n    left: 33.33333333%;\n    right: auto;\n  }\n  .col-lg-pull-3 {\n    left: 25%;\n    right: auto;\n  }\n  .col-lg-pull-2 {\n    left: 16.66666667%;\n    right: auto;\n  }\n  .col-lg-pull-1 {\n    left: 8.33333333%;\n    right: auto;\n  }\n  .col-lg-pull-0 {\n    left: auto;\n    right: auto;\n  }\n  .col-lg-push-12 {\n    right: 100%;\n    left: 0;\n  }\n  .col-lg-push-11 {\n    right: 91.66666667%;\n    left: 0;\n  }\n  .col-lg-push-10 {\n    right: 83.33333333%;\n    left: 0;\n  }\n  .col-lg-push-9 {\n    right: 75%;\n    left: 0;\n  }\n  .col-lg-push-8 {\n    right: 66.66666667%;\n    left: 0;\n  }\n  .col-lg-push-7 {\n    right: 58.33333333%;\n    left: 0;\n  }\n  .col-lg-push-6 {\n    right: 50%;\n    left: 0;\n  }\n  .col-lg-push-5 {\n    right: 41.66666667%;\n    left: 0;\n  }\n  .col-lg-push-4 {\n    right: 33.33333333%;\n    left: 0;\n  }\n  .col-lg-push-3 {\n    right: 25%;\n    left: 0;\n  }\n  .col-lg-push-2 {\n    right: 16.66666667%;\n    left: 0;\n  }\n  .col-lg-push-1 {\n    right: 8.33333333%;\n    left: 0;\n  }\n  .col-lg-push-0 {\n    right: auto;\n    left: 0;\n  }\n  .col-lg-offset-12 {\n    margin-right: 100%;\n    margin-left: 0;\n  }\n  .col-lg-offset-11 {\n    margin-right: 91.66666667%;\n    margin-left: 0;\n  }\n  .col-lg-offset-10 {\n    margin-right: 83.33333333%;\n    margin-left: 0;\n  }\n  .col-lg-offset-9 {\n    margin-right: 75%;\n    margin-left: 0;\n  }\n  .col-lg-offset-8 {\n    margin-right: 66.66666667%;\n    margin-left: 0;\n  }\n  .col-lg-offset-7 {\n    margin-right: 58.33333333%;\n    margin-left: 0;\n  }\n  .col-lg-offset-6 {\n    margin-right: 50%;\n    margin-left: 0;\n  }\n  .col-lg-offset-5 {\n    margin-right: 41.66666667%;\n    margin-left: 0;\n  }\n  .col-lg-offset-4 {\n    margin-right: 33.33333333%;\n    margin-left: 0;\n  }\n  .col-lg-offset-3 {\n    margin-right: 25%;\n    margin-left: 0;\n  }\n  .col-lg-offset-2 {\n    margin-right: 16.66666667%;\n    margin-left: 0;\n  }\n  .col-lg-offset-1 {\n    margin-right: 8.33333333%;\n    margin-left: 0;\n  }\n  .col-lg-offset-0 {\n    margin-right: 0%;\n    margin-left: 0;\n  }\n}\ncaption {\n  text-align: right;\n}\nth {\n  text-align: right;\n}\n@media screen and (max-width: 767px) {\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-right: 0;\n    border-left: initial;\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-left: 0;\n    border-right: initial;\n  }\n}\n.radio label,\n.checkbox label {\n  padding-right: 20px;\n  padding-left: initial;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  margin-right: -20px;\n  margin-left: auto;\n}\n.radio-inline,\n.checkbox-inline {\n  padding-right: 20px;\n  padding-left: 0;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-right: 10px;\n  margin-left: 0;\n}\n.has-feedback .form-control {\n  padding-left: 42.5px;\n  padding-right: 12px;\n}\n.form-control-feedback {\n  left: 0;\n  right: auto;\n}\n@media (min-width: 768px) {\n  .form-inline label {\n    padding-right: 0;\n    padding-left: initial;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    margin-right: 0;\n    margin-left: auto;\n  }\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: left;\n  }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n  left: 15px;\n  right: auto;\n}\n.caret {\n  margin-right: 2px;\n  margin-left: 0;\n}\n.dropdown-menu {\n  right: 0;\n  left: auto;\n  float: left;\n  text-align: right;\n}\n.dropdown-menu.pull-right {\n  left: 0;\n  right: auto;\n  float: right;\n}\n.dropdown-menu-right {\n  left: auto;\n  right: 0;\n}\n.dropdown-menu-left {\n  left: 0;\n  right: auto;\n}\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    left: auto;\n    right: 0;\n  }\n  .navbar-right .dropdown-menu-left {\n    left: 0;\n    right: auto;\n  }\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  float: right;\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-right: -1px;\n  margin-left: 0px;\n}\n.btn-toolbar {\n  margin-right: -5px;\n  margin-left: 0px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n  float: right;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n  margin-right: 5px;\n  margin-left: 0px;\n}\n.btn-group > .btn:first-child {\n  margin-right: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 0;\n  border-top-left-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: 4px;\n  border-bottom-left-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.btn-group > .btn-group {\n  float: right;\n}\n.btn-group.btn-group-justified > .btn,\n.btn-group.btn-group-justified > .btn-group {\n  float: none;\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: 4px;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-top-left-radius: 4px;\n  border-bottom-left-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.btn .caret {\n  margin-right: 0;\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-right: 0;\n}\n.input-group .form-control {\n  float: right;\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-bottom-right-radius: 4px;\n  border-top-right-radius: 4px;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.input-group-addon:first-child {\n  border-right-width: 1px;\n  border-right-style: solid;\n  border-left: 0px;\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-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.input-group-addon:last-child {\n  border-left-width: 1px;\n  border-left-style: solid;\n  border-right: 0px;\n}\n.input-group-btn > .btn + .btn {\n  margin-right: -1px;\n  margin-left: auto;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n  margin-left: -1px;\n  margin-right: auto;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n  margin-right: -1px;\n  margin-left: auto;\n}\n.nav {\n  padding-right: 0;\n  padding-left: initial;\n}\n.nav-tabs > li {\n  float: right;\n}\n.nav-tabs > li > a {\n  margin-left: auto;\n  margin-right: -2px;\n  border-radius: 4px 4px 0 0;\n}\n.nav-pills > li {\n  float: right;\n}\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n.nav-pills > li + li {\n  margin-right: 2px;\n  margin-left: auto;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-right: 0;\n  margin-left: auto;\n}\n.nav-justified > .dropdown .dropdown-menu {\n  right: auto;\n}\n.nav-tabs-justified > li > a {\n  margin-left: 0;\n  margin-right: auto;\n}\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-radius: 4px 4px 0 0;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-header {\n    float: right;\n  }\n}\n.navbar-collapse {\n  padding-right: 15px;\n  padding-left: 15px;\n}\n.navbar-brand {\n  float: right;\n}\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand,\n  .navbar > .container-fluid .navbar-brand {\n    margin-right: -15px;\n    margin-left: auto;\n  }\n}\n.navbar-toggle {\n  float: left;\n  margin-left: 15px;\n  margin-right: auto;\n}\n@media (max-width: 767px) {\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 25px 5px 15px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: right;\n  }\n  .navbar-nav > li {\n    float: right;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-left.flip {\n    float: right !important;\n  }\n  .navbar-right:last-child {\n    margin-left: -15px;\n    margin-right: auto;\n  }\n  .navbar-right.flip {\n    float: left !important;\n    margin-left: -15px;\n    margin-right: auto;\n  }\n  .navbar-right .dropdown-menu {\n    left: 0;\n    right: auto;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-text {\n    float: right;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-left: 0;\n    margin-right: auto;\n  }\n}\n.pagination {\n  padding-right: 0;\n}\n.pagination > li > a,\n.pagination > li > span {\n  float: right;\n  margin-right: -1px;\n  margin-left: 0px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-right-radius: 4px;\n  border-top-right-radius: 4px;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  margin-right: -1px;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.pager {\n  padding-right: 0;\n  padding-left: initial;\n}\n.pager .next > a,\n.pager .next > span {\n  float: left;\n}\n.pager .previous > a,\n.pager .previous > span {\n  float: right;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 0px;\n  margin-right: 3px;\n}\n.list-group-item > .badge {\n  float: left;\n}\n.list-group-item > .badge + .badge {\n  margin-left: 5px;\n  margin-right: auto;\n}\n.alert-dismissable,\n.alert-dismissible {\n  padding-left: 35px;\n  padding-right: 15px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n  right: auto;\n  left: -21px;\n}\n.progress-bar {\n  float: right;\n}\n.media > .pull-left {\n  margin-right: 10px;\n}\n.media > .pull-left.flip {\n  margin-right: 0;\n  margin-left: 10px;\n}\n.media > .pull-right {\n  margin-left: 10px;\n}\n.media > .pull-right.flip {\n  margin-left: 0;\n  margin-right: 10px;\n}\n.media-right,\n.media > .pull-right {\n  padding-right: 10px;\n  padding-left: initial;\n}\n.media-left,\n.media > .pull-left {\n  padding-left: 10px;\n  padding-right: initial;\n}\n.media-list {\n  padding-right: 0;\n  padding-left: initial;\n  list-style: none;\n}\n.list-group {\n  padding-right: 0;\n  padding-left: initial;\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-right-radius: 3px;\n  border-top-left-radius: 0;\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-left-radius: 3px;\n  border-top-right-radius: 0;\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  border-top-right-radius: 0;\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  border-top-left-radius: 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-right: 0;\n  border-left: none;\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: none;\n  border-left: 0;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object {\n  right: 0;\n  left: auto;\n}\n.close {\n  float: left;\n}\n.modal-footer {\n  text-align: left;\n}\n.modal-footer .btn + .btn {\n  margin-left: auto;\n  margin-right: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-right: -1px;\n  margin-left: auto;\n}\n.modal-footer .btn-block + .btn-block {\n  margin-right: 0;\n  margin-left: auto;\n}\n.popover {\n  left: auto;\n  text-align: right;\n}\n.popover.top > .arrow {\n  right: 50%;\n  left: auto;\n  margin-right: -11px;\n  margin-left: auto;\n}\n.popover.top > .arrow:after {\n  margin-right: -10px;\n  margin-left: auto;\n}\n.popover.bottom > .arrow {\n  right: 50%;\n  left: auto;\n  margin-right: -11px;\n  margin-left: auto;\n}\n.popover.bottom > .arrow:after {\n  margin-right: -10px;\n  margin-left: auto;\n}\n.carousel-control {\n  right: 0;\n  bottom: 0;\n}\n.carousel-control.left {\n  right: auto;\n  left: 0;\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: -o-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.carousel-control.right {\n  left: auto;\n  right: 0;\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: -o-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.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n  right: auto;\n  margin-right: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\n  left: auto;\n  margin-left: -10px;\n}\n.carousel-indicators {\n  right: 50%;\n  left: 0;\n  margin-right: -30%;\n  margin-left: 0;\n  padding-left: 0;\n}\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon-chevron-left,\n  .carousel-control .icon-prev {\n    margin-left: 0;\n    margin-right: -15px;\n  }\n  .carousel-control .glyphicon-chevron-right,\n  .carousel-control .icon-next {\n    margin-left: 0;\n    margin-right: -15px;\n  }\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n}\n.pull-right.flip {\n  float: left !important;\n}\n.pull-left.flip {\n  float: right !important;\n}\n/*# sourceMappingURL=bootstrap-rtl.css.map */\n"
  },
  {
    "path": "src/main/resources/static/css/demo/webuploader-demo.css",
    "content": "#container {\n    color: #838383;\n    font-size: 12px;\n}\n\n#uploader .queueList {\n    margin: 20px;\n    border: 3px dashed #e6e6e6;\n}\n#uploader .queueList.filled {\n    padding: 17px;\n    margin: 0;\n    border: 3px dashed transparent;\n}\n#uploader .queueList.webuploader-dnd-over {\n    border: 3px dashed #999999;\n}\n\n#uploader p {margin: 0;}\n\n.element-invisible {\n    position: absolute !important;\n    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n    clip: rect(1px,1px,1px,1px);\n}\n\n#uploader .placeholder {\n    min-height: 350px;\n    padding-top: 178px;\n    text-align: center;\n    background: url(../../../img/webuploader.png) center 93px no-repeat;\n    color: #cccccc;\n    font-size: 18px;\n    position: relative;\n}\n\n#uploader .placeholder .webuploader-pick {\n    font-size: 18px;\n    background: #00b7ee;\n    border-radius: 3px;\n    line-height: 44px;\n    padding: 0 30px;\n    *width: 120px;\n    color: #fff;\n    display: inline-block;\n    margin: 0 auto 20px auto;\n    cursor: pointer;\n    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n}\n\n#uploader .placeholder .webuploader-pick-hover {\n    background: #00a2d4;\n}\n\n#uploader .placeholder .flashTip {\n    color: #666666;\n    font-size: 12px;\n    position: absolute;\n    width: 100%;\n    text-align: center;\n    bottom: 20px;\n}\n#uploader .placeholder .flashTip a {\n    color: #0785d1;\n    text-decoration: none;\n}\n#uploader .placeholder .flashTip a:hover {\n    text-decoration: underline;\n}\n\n#uploader .filelist {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n}\n\n#uploader .filelist:after {\n    content: '';\n    display: block;\n    width: 0;\n    height: 0;\n    overflow: hidden;\n    clear: both;\n}\n\n#uploader .filelist li {\n    width: 110px;\n    height: 110px;\n    background: url(../../img/bg.png) no-repeat;\n    text-align: center;\n    margin: 0 8px 20px 0;\n    position: relative;\n    display: inline;\n    float: left;\n    overflow: hidden;\n    font-size: 12px;\n}\n\n#uploader .filelist li p.log {\n    position: relative;\n    top: -45px;\n}\n\n#uploader .filelist li p.title {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    overflow: hidden;\n    white-space: nowrap;\n    text-overflow : ellipsis;\n    top: 5px;\n    text-indent: 5px;\n    text-align: left;\n}\n\n#uploader .filelist li p.progress {\n    position: absolute;\n    width: 100%;\n    bottom: 0;\n    left: 0;\n    height: 8px;\n    overflow: hidden;\n    z-index: 50;\n    margin: 0;\n    border-radius: 0;\n    background: none;\n    -webkit-box-shadow: 0 0 0;\n}\n#uploader .filelist li p.progress span {\n    display: none;\n    overflow: hidden;\n    width: 0;\n    height: 100%;\n    background: #1483d8 url(../../img/progress.png) repeat-x;\n\n    -webit-transition: width 200ms linear;\n    -moz-transition: width 200ms linear;\n    -o-transition: width 200ms linear;\n    -ms-transition: width 200ms linear;\n    transition: width 200ms linear;\n\n    -webkit-animation: progressmove 2s linear infinite;\n    -moz-animation: progressmove 2s linear infinite;\n    -o-animation: progressmove 2s linear infinite;\n    -ms-animation: progressmove 2s linear infinite;\n    animation: progressmove 2s linear infinite;\n\n    -webkit-transform: translateZ(0);\n}\n\n@-webkit-keyframes progressmove {\n    0% {\n       background-position: 0 0;\n    }\n    100% {\n       background-position: 17px 0;\n    }\n}\n@-moz-keyframes progressmove {\n    0% {\n       background-position: 0 0;\n    }\n    100% {\n       background-position: 17px 0;\n    }\n}\n@keyframes progressmove {\n    0% {\n       background-position: 0 0;\n    }\n    100% {\n       background-position: 17px 0;\n    }\n}\n\n#uploader .filelist li p.imgWrap {\n    position: relative;\n    z-index: 2;\n    line-height: 110px;\n    vertical-align: middle;\n    overflow: hidden;\n    width: 110px;\n    height: 110px;\n\n    -webkit-transform-origin: 50% 50%;\n    -moz-transform-origin: 50% 50%;\n    -o-transform-origin: 50% 50%;\n    -ms-transform-origin: 50% 50%;\n    transform-origin: 50% 50%;\n\n    -webit-transition: 200ms ease-out;\n    -moz-transition: 200ms ease-out;\n    -o-transition: 200ms ease-out;\n    -ms-transition: 200ms ease-out;\n    transition: 200ms ease-out;\n}\n\n#uploader .filelist li img {\n    width: 100%;\n}\n\n#uploader .filelist li p.error {\n    background: #f43838;\n    color: #fff;\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    height: 28px;\n    line-height: 28px;\n    width: 100%;\n    z-index: 100;\n}\n\n#uploader .filelist li .success {\n    display: block;\n    position: absolute;\n    left: 0;\n    bottom: 0;\n    height: 40px;\n    width: 100%;\n    z-index: 200;\n    background: url(../../img/success.png) no-repeat right bottom;\n}\n\n#uploader .filelist div.file-panel {\n    position: absolute;\n    height: 0;\n    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#80000000', endColorstr='#80000000')\\0;\n    background: rgba( 0, 0, 0, 0.5 );\n    width: 100%;\n    top: 0;\n    left: 0;\n    overflow: hidden;\n    z-index: 300;\n}\n\n#uploader .filelist div.file-panel span {\n    width: 24px;\n    height: 24px;\n    display: inline;\n    float: right;\n    text-indent: -9999px;\n    overflow: hidden;\n    background: url(../../img/icons.png) no-repeat;\n    margin: 5px 1px 1px;\n    cursor: pointer;\n}\n\n#uploader .filelist div.file-panel span.rotateLeft {\n    background-position: 0 -24px;\n}\n#uploader .filelist div.file-panel span.rotateLeft:hover {\n    background-position: 0 0;\n}\n\n#uploader .filelist div.file-panel span.rotateRight {\n    background-position: -24px -24px;\n}\n#uploader .filelist div.file-panel span.rotateRight:hover {\n    background-position: -24px 0;\n}\n\n#uploader .filelist div.file-panel span.cancel {\n    background-position: -48px -24px;\n}\n#uploader .filelist div.file-panel span.cancel:hover {\n    background-position: -48px 0;\n}\n\n#uploader .statusBar {\n    height: 63px;\n    border-top: 1px solid #dadada;\n    padding: 0 20px;\n    line-height: 63px;\n    vertical-align: middle;\n    position: relative;\n}\n\n#uploader .statusBar .progress {\n    border: 1px solid #1483d8;\n    width: 198px;\n    background: #fff;\n    height: 18px;\n    position: relative;\n    display: inline-block;\n    text-align: center;\n    line-height: 20px;\n    color: #6dbfff;\n    position: relative;\n    margin: 0 10px 0 0;\n}\n#uploader .statusBar .progress span.percentage {\n    width: 0;\n    height: 100%;\n    left: 0;\n    top: 0;\n    background: #1483d8;\n    position: absolute;\n}\n#uploader .statusBar .progress span.text {\n    position: relative;\n    z-index: 10;\n}\n\n#uploader .statusBar .info {\n    display: inline-block;\n    font-size: 14px;\n    color: #666666;\n}\n\n#uploader .statusBar .btns {\n    position: absolute;\n    top: 10px;\n    right: 20px;\n    line-height: 40px;\n}\n\n#filePicker2 {\n    display: inline-block;\n    float: left;\n}\n\n#uploader .statusBar .btns .webuploader-pick,\n#uploader .statusBar .btns .uploadBtn,\n#uploader .statusBar .btns .uploadBtn.state-uploading,\n#uploader .statusBar .btns .uploadBtn.state-paused {\n    background: #ffffff;\n    border: 1px solid #cfcfcf;\n    color: #565656;\n    padding: 0 18px;\n    display: inline-block;\n    border-radius: 3px;\n    margin-left: 10px;\n    cursor: pointer;\n    font-size: 14px;\n    float: left;\n}\n#uploader .statusBar .btns .webuploader-pick-hover,\n#uploader .statusBar .btns .uploadBtn:hover,\n#uploader .statusBar .btns .uploadBtn.state-uploading:hover,\n#uploader .statusBar .btns .uploadBtn.state-paused:hover {\n    background: #f0f0f0;\n}\n\n#uploader .statusBar .btns .uploadBtn {\n    background: #00b7ee;\n    color: #fff;\n    border-color: transparent;\n}\n#uploader .statusBar .btns .uploadBtn:hover {\n    background: #00a2d4;\n}\n\n#uploader .statusBar .btns .uploadBtn.disabled {\n    pointer-events: none;\n    opacity: 0.6;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.4.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.4.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.4.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  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  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  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  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  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: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-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-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"
  },
  {
    "path": "src/main/resources/static/css/gg-bootdo.css",
    "content": "/*this file is used for the bootdo project, it is a unique css file*/\n@charset \"utf-8\";\n*{\n\tfont-size: 14px;\n\tfont-family: \"microsoft yahei\";\n\tpadding:0;\n\tmargin: 0;\n\t\n}\na{\n\ttext-decoration: none !important;\n}\nul{\n\tlist-style: none !important;\n}\n.gg-font0{\n\tfont-size: 0;\n}\n/*表单通用的样式*/\n.gg-star{\n\tcolor: red;\n\tfont-style: normal;\n}\n.gg-form{\n\tmargin-top: 15px;\n\tpadding: 20px;\n    position: relative;\n}\n.gg-formGroup{\n\twidth: 100%;\n    margin-bottom: 15px;\n    font-size: 0;\n}\n.gg-formGroup .gg-formTitle{\n\twidth:30%;\n\tdisplay: inline-block;\n\ttext-align: right;\n\tpadding-right: 2%;\n\twhite-space: nowrap;\n}\n.gg-formGroup .gg-formTitle span{\n\tfont-size: 14px;\n    color: #666666;\n    font-family: \"microsoft yahei\";\n    line-height: 28px;\n    white-space: nowrap;\n}\n.gg-formGroup .gg-formDetail{\n\twidth:60%;\n\tdisplay: inline-block;\n}\n.gg-area{\n\twidth: 33.33%;\n\tdisplay: inline-block;\n\tpadding-right: 2%;\n}\n.gg-area:last-child{\n\tpadding-right: 0;\n}\n.gg-btnGroup{\n\ttext-align: center;\n}\n.gg-border0{\n\tborder: 0;\n}\n.gg-dashed{\n\tborder-bottom: 1px dashed #b3afaf;\n\twidth: 40% !important;\n\tposition: relative;\n}\n.error-mes{\n\tposition: relative;\n    margin-left: 30%;\n}\n.gg-faeye{\n\tposition: absolute;\n    top: 24%;\n    right: 10%;\n    padding: 10px;\n    color: #666;\n\n}\n/*头像裁剪上传部分*/\n.avatar-view {\n  display: block;\n  margin: 12% auto 5%;\n  height: 220px;\n  width: 220px;\n  border: 3px solid #fff;\n  border-radius: 5px;\n  box-shadow: 0 0 5px rgba(0,0,0,.15);\n  cursor: pointer;\n  overflow: hidden;\n}\n\n.avatar-view img {\n  width: 100%;\n}\n.avatar-body {\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.avatar-upload {\n  overflow: hidden;\n}\n\n.avatar-upload label {\n  display: block;\n  float: left;\n  clear: left;\n  width: 100px;\n}\n\n.avatar-upload input {\n  display: block;\n  margin-left: 110px;\n}\n\n.avater-alert {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\n.avatar-wrapper {\n  height: 364px;\n  width: 100%;\n  margin-top: 15px;\n  box-shadow: inset 0 0 5px rgba(0,0,0,.25);\n  background-color: #fcfcfc;\n  overflow: hidden;\n}\n\n.avatar-wrapper img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n}\n\n.avatar-preview {\n  float: left;\n  margin-top: 15px;\n  margin-right: 15px;\n  border: 1px solid #eee;\n  border-radius: 4px;\n  background-color: #fff;\n  overflow: hidden;\n}\n\n.avatar-preview:hover {\n  border-color: #ccf;\n  box-shadow: 0 0 5px rgba(0,0,0,.15);\n}\n\n.avatar-preview img {\n  width: 100%;\n}\n\n.preview-lg {\n  height: 184px;\n  width: 184px;\n  margin-top: 15px;\n}\n\n.preview-md {\n  height: 100px;\n  width: 100px;\n}\n\n.preview-sm {\n  height: 50px;\n  width: 50px;\n}\n\n@media (min-width: 992px) {\n  .avatar-preview {\n    float: none;\n  }\n}\n\n.avatar-btns {\n  margin-top: 30px;\n  margin-bottom: 15px;\n}\n\n.avatar-btns .btn-group {\n  margin-right: 5px;\n}\n\n.loading {\n  display: none;\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  background: #fff url(\"/img/loading.gif\") no-repeat center center;\n  opacity: .75;\n  filter: alpha(opacity=75);\n  z-index: 20140628;\n}\n.avatar-title{\n\tcolor:#999;\n\tfont-size: 12px;\n\ttext-align: center;\n}\n.modal-backdrop{\n}\n.gg-avatarShow{\n\tposition: relative;\n\tmargin-top: -10%;\n\tmargin-bottom: 12%;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/layui.css",
    "content": "/**\n \n @Name: layui\n @author 郑保乐\n @Site: www.layui.com\n \n */\n\n\n/** 初始化 **/\nbody,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,input,button,textarea,p,blockquote,th,td,form,pre{margin: 0; padding: 0; -webkit-tap-highlight-color:rgba(0,0,0,0);}\na:active,a:hover{outline:0}\nimg{display: inline-block; border: none; vertical-align: middle;}\nli{list-style:none;}\ntable{border-collapse: collapse; border-spacing: 0;}\nh1,h2,h3{font-size: 14px; font-weight: 400;}\nh4, h5, h6{font-size: 100%; font-weight: 400;}\nbutton,input,select,textarea{font-size: 100%; }\ninput,button,textarea,select,optgroup,option{font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; outline: 0;}\npre{white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;}\n\n\n/** 图标字体 **/\n@font-face {font-family: 'layui-icon';\n  src: url('../font/iconfont.eot?v=213');\n  src: url('../font/iconfont.eot?v=213#iefix') format('embedded-opentype'),\n  url('../font/iconfont.svg?v=213#iconfont') format('svg'),\n  url('../font/iconfont.woff?v=213') format('woff'),\n  url('../font/iconfont.ttf?v=213') format('truetype');\n}\n                    \n.layui-icon{\n  font-family:\"layui-icon\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n/** 初始化全局标签 **/\nbody{line-height: 24px; font: 14px Helvetica Neue,Helvetica,PingFang SC,\\5FAE\\8F6F\\96C5\\9ED1,Tahoma,Arial,sans-serif;}\nhr{height: 1px; margin: 10px 0; border: 0; background-color: #e2e2e2; clear: both;}\na{color: #333; text-decoration:none; }\na:hover{color: #777;}\na cite{font-style: normal; *cursor:pointer;}\n\n/** 基础通用 **/\n.layui-border-box, .layui-border-box *{box-sizing: border-box;}\n/* 消除第三方ui可能造成的冲突 */.layui-box, .layui-box *{box-sizing: content-box;}\n.layui-clear{clear: both; *zoom: 1;}\n.layui-clear:after{content:'\\20'; clear:both; *zoom:1; display:block; height:0;}\n.layui-inline{position: relative; display: inline-block; *display:inline; *zoom:1; vertical-align: middle;}\n/* 三角形 */.layui-edge{position: absolute; width: 0; height: 0; border-style: dashed; border-color: transparent; overflow: hidden;}\n/* 单行溢出省略 */.layui-elip{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}\n/* 屏蔽选中 */.layui-unselect,.layui-icon, .layui-disabled{-moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;}\n/* 禁用 */.layui-disabled,.layui-disabled:hover{color: #d2d2d2 !important; cursor: not-allowed !important;}\n/* 纯圆角 */.layui-circle{border-radius: 100%;}\n.layui-show{display: block !important;}\n.layui-hide{display: none !important;}\n\n\n/* 基本布局 */\n.layui-main{position: relative; width: 1140px; margin: 0 auto;}\n.layui-header{position: relative; z-index: 1000; height: 60px;}\n.layui-header a:hover{transition: all .5s; -webkit-transition: all .5s;}\n.layui-side{position: fixed; top: 0; bottom: 0; z-index: 999; width: 200px; overflow-x: hidden;}\n.layui-side-scroll{width: 220px; height: 100%; overflow-x: hidden;}\n.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;}\n\n/* 后台框架大布局 */.layui-layout-body{overflow: hidden;}\n.layui-layout-admin .layui-header{background-color: #23262E;}\n.layui-layout-admin .layui-side{top: 60px; width: 200px; overflow-x: hidden;}\n.layui-layout-admin .layui-body{top: 60px; bottom: 44px;}\n.layui-layout-admin .layui-main{width: auto; margin: 0 15px;}\n.layui-layout-admin .layui-footer{position: fixed; left: 200px; right: 0; bottom: 0; height: 44px; line-height: 44px; padding: 0 15px; background-color: #eee;}\n.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;}\n.layui-layout-admin .layui-header .layui-nav{background: none;}\n.layui-layout-left{position: absolute !important; left: 200px; top: 0;}\n.layui-layout-right{position: absolute !important; right: 0; top: 0;}\n\n/* 响应式类 */\n\n\n/* 栅格布局 */\n.layui-container{position: relative; margin: 0 auto; padding: 0 15px; box-sizing: border-box;}\n.layui-fluid{position: relative; margin: 0 auto; padding: 0 15px;}\n\n.layui-row:before, .layui-row:after{content: ''; display: block; clear: both;}\n.layui-col-xs1, .layui-col-xs2, .layui-col-xs3, .layui-col-xs4, .layui-col-xs5, .layui-col-xs6, .layui-col-xs7, .layui-col-xs8, .layui-col-xs9, .layui-col-xs10, .layui-col-xs11, .layui-col-xs12\n,.layui-col-sm1, .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-sm10, .layui-col-sm11, .layui-col-sm12\n,.layui-col-md1, .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-md10, .layui-col-md11, .layui-col-md12\n,.layui-col-lg1, .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-lg10, .layui-col-lg11, .layui-col-lg12\n{position: relative; display: block; box-sizing: border-box;}\n\n.layui-col-xs1, .layui-col-xs2, .layui-col-xs3, .layui-col-xs4, .layui-col-xs5, .layui-col-xs6, .layui-col-xs7, .layui-col-xs8, .layui-col-xs9, .layui-col-xs10, .layui-col-xs11, .layui-col-xs12{float: left;}\n.layui-col-xs1{width: 8.33333333%;}\n.layui-col-xs2{width: 16.66666667%;}\n.layui-col-xs3{width: 25%;}\n.layui-col-xs4{width: 33.33333333%;}\n.layui-col-xs5{width: 41.66666667%;}\n.layui-col-xs6{width: 50%;}\n.layui-col-xs7{width: 58.33333333%;}\n.layui-col-xs8{width: 66.66666667%;}\n.layui-col-xs9{width: 75%;}\n.layui-col-xs10{width: 83.33333333%;}\n.layui-col-xs11{width: 91.66666667%;}\n.layui-col-xs12{width: 100%;}\n\n.layui-col-xs-offset1{margin-left: 8.33333333%;}\n.layui-col-xs-offset2{margin-left: 16.66666667%;}\n.layui-col-xs-offset3{margin-left: 25%;}\n.layui-col-xs-offset4{margin-left: 33.33333333%;}\n.layui-col-xs-offset5{margin-left: 41.66666667%;}\n.layui-col-xs-offset6{margin-left: 50%;}\n.layui-col-xs-offset7{margin-left: 58.33333333%;}\n.layui-col-xs-offset8{margin-left: 66.66666667%;}\n.layui-col-xs-offset9{margin-left: 75%;}\n.layui-col-xs-offset10{margin-left: 83.33333333%;}\n.layui-col-xs-offset11{margin-left: 91.66666667%;}\n.layui-col-xs-offset12{margin-left: 100%;}\n\n/* 超小屏幕(手机) */@media screen and (max-width: 768px) {\n  .layui-hide-xs{display: none!important;}\n  .layui-show-xs-block{display: block!important;}\n  .layui-show-xs-inline{display: inline!important;}\n  .layui-show-xs-inline-block{display: inline-block!important;}\n}\n\n/* 小型屏幕(平板) */@media screen and (min-width: 768px) {\n  .layui-container{width: 750px;}\n  .layui-hide-sm{display: none!important;}\n  .layui-show-sm-block{display: block!important;}\n  .layui-show-sm-inline{display: inline!important;}\n  .layui-show-sm-inline-block{display: inline-block!important;}\n\n  .layui-col-sm1, .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-sm10, .layui-col-sm11, .layui-col-sm12{float: left;}\n  .layui-col-sm1{width: 8.33333333%;}\n  .layui-col-sm2{width: 16.66666667%;}\n  .layui-col-sm3{width: 25%;}\n  .layui-col-sm4{width: 33.33333333%;}\n  .layui-col-sm5{width: 41.66666667%;}\n  .layui-col-sm6{width: 50%;}\n  .layui-col-sm7{width: 58.33333333%;}\n  .layui-col-sm8{width: 66.66666667%;}\n  .layui-col-sm9{width: 75%;}\n  .layui-col-sm10{width: 83.33333333%;}\n  .layui-col-sm11{width: 91.66666667%;}\n  .layui-col-sm12{width: 100%;}\n  /* 列偏移 */\n  .layui-col-sm-offset1{margin-left: 8.33333333%;}\n  .layui-col-sm-offset2{margin-left: 16.66666667%;}\n  .layui-col-sm-offset3{margin-left: 25%;}\n  .layui-col-sm-offset4{margin-left: 33.33333333%;}\n  .layui-col-sm-offset5{margin-left: 41.66666667%;}\n  .layui-col-sm-offset6{margin-left: 50%;}\n  .layui-col-sm-offset7{margin-left: 58.33333333%;}\n  .layui-col-sm-offset8{margin-left: 66.66666667%;}\n  .layui-col-sm-offset9{margin-left: 75%;}\n  .layui-col-sm-offset10{margin-left: 83.33333333%;}\n  .layui-col-sm-offset11{margin-left: 91.66666667%;}\n  .layui-col-sm-offset12{margin-left: 100%;}\n}\n/* 中型屏幕(桌面) */@media screen and (min-width: 992px) {\n  .layui-container{width: 970px;}\n  .layui-hide-md{display: none!important;}\n  .layui-show-md-block{display: block!important;}\n  .layui-show-md-inline{display: inline!important;}\n  .layui-show-md-inline-block{display: inline-block!important;}\n  \n  .layui-col-md1, .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-md10, .layui-col-md11, .layui-col-md12{float: left;}\n  .layui-col-md1{width: 8.33333333%;}\n  .layui-col-md2{width: 16.66666667%;}\n  .layui-col-md3{width: 25%;}\n  .layui-col-md4{width: 33.33333333%;}\n  .layui-col-md5{width: 41.66666667%;}\n  .layui-col-md6{width: 50%;}\n  .layui-col-md7{width: 58.33333333%;}\n  .layui-col-md8{width: 66.66666667%;}\n  .layui-col-md9{width: 75%;}\n  .layui-col-md10{width: 83.33333333%;}\n  .layui-col-md11{width: 91.66666667%;}\n  .layui-col-md12{width: 100%;}\n  /* 列偏移 */\n  .layui-col-md-offset1{margin-left: 8.33333333%;}\n  .layui-col-md-offset2{margin-left: 16.66666667%;}\n  .layui-col-md-offset3{margin-left: 25%;}\n  .layui-col-md-offset4{margin-left: 33.33333333%;}\n  .layui-col-md-offset5{margin-left: 41.66666667%;}\n  .layui-col-md-offset6{margin-left: 50%;}\n  .layui-col-md-offset7{margin-left: 58.33333333%;}\n  .layui-col-md-offset8{margin-left: 66.66666667%;}\n  .layui-col-md-offset9{margin-left: 75%;}\n  .layui-col-md-offset10{margin-left: 83.33333333%;}\n  .layui-col-md-offset11{margin-left: 91.66666667%;}\n  .layui-col-md-offset12{margin-left: 100%;}\n}\n/* 大型屏幕(桌面) */@media screen and (min-width: 1200px) {\n  .layui-container{width: 1170px;}\n  .layui-hide-lg{display: none!important;}\n  .layui-show-lg-block{display: block!important;}\n  .layui-show-lg-inline{display: inline!important;}\n  .layui-show-lg-inline-block{display: inline-block!important;}\n  \n  .layui-col-lg1, .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-lg10, .layui-col-lg11, .layui-col-lg12{float: left;}\n  .layui-col-lg1{width: 8.33333333%;}\n  .layui-col-lg2{width: 16.66666667%;}\n  .layui-col-lg3{width: 25%;}\n  .layui-col-lg4{width: 33.33333333%;}\n  .layui-col-lg5{width: 41.66666667%;}\n  .layui-col-lg6{width: 50%;}\n  .layui-col-lg7{width: 58.33333333%;}\n  .layui-col-lg8{width: 66.66666667%;}\n  .layui-col-lg9{width: 75%;}\n  .layui-col-lg10{width: 83.33333333%;}\n  .layui-col-lg11{width: 91.66666667%;}\n  .layui-col-lg12{width: 100%;}\n  /* 列偏移 */\n  .layui-col-lg-offset1{margin-left: 8.33333333%;}\n  .layui-col-lg-offset2{margin-left: 16.66666667%;}\n  .layui-col-lg-offset3{margin-left: 25%;}\n  .layui-col-lg-offset4{margin-left: 33.33333333%;}\n  .layui-col-lg-offset5{margin-left: 41.66666667%;}\n  .layui-col-lg-offset6{margin-left: 50%;}\n  .layui-col-lg-offset7{margin-left: 58.33333333%;}\n  .layui-col-lg-offset8{margin-left: 66.66666667%;}\n  .layui-col-lg-offset9{margin-left: 75%;}\n  .layui-col-lg-offset10{margin-left: 83.33333333%;}\n  .layui-col-lg-offset11{margin-left: 91.66666667%;}\n  .layui-col-lg-offset12{margin-left: 100%;}\n}\n\n/* 列间隔 */.layui-col-space1{margin: -0.5px;}\n.layui-col-space1>*{padding: 0.5px;}\n.layui-col-space3{margin: -1.5px;}\n.layui-col-space3>*{padding: 1.5px;}\n.layui-col-space5{margin: -2.5px;}\n.layui-col-space5>*{padding: 2.5px;}\n.layui-col-space8{margin: -3.5px;}\n.layui-col-space8>*{padding: 3.5px;}\n.layui-col-space10{margin: -5px;}\n.layui-col-space10>*{padding: 5px;}\n.layui-col-space12{margin: -6px;}\n.layui-col-space12>*{padding: 6px;}\n.layui-col-space15{margin: -7.5px;}\n.layui-col-space15>*{padding: 7.5px;}\n.layui-col-space18{margin: -9px;}\n.layui-col-space18>*{padding: 9px;}\n.layui-col-space20{margin: -10px;}\n.layui-col-space20>*{padding: 10px;}\n.layui-col-space22{margin: -11px;}\n.layui-col-space22>*{padding: 11px;}\n.layui-col-space25{margin: -12.5px;}\n.layui-col-space25>*{padding: 12.5px;}\n.layui-col-space30{margin: -15px;}\n.layui-col-space30>*{padding: 15px;}\n\n\n/** 页面元素 **/\n.layui-btn, .layui-input, .layui-textarea, .layui-upload-button, .layui-select{outline: none; -webkit-appearance: none; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box;}\n\n/* 引用 */.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;}\n.layui-quote-nm{border-color: #e2e2e2; border-style: solid; border-width: 1px; border-left-width: 5px; background: none;}\n/* 字段集合 */.layui-elem-field{margin-bottom: 10px; padding: 0; border: 1px solid #e2e2e2;}\n.layui-elem-field legend{margin-left: 20px; padding: 0 10px; font-size: 20px; font-weight: 300;}\n.layui-field-title{margin: 10px 0 20px; border: none; border-top: 1px solid #e2e2e2;}\n.layui-field-box{padding: 10px 15px;}\n.layui-field-title .layui-field-box{padding: 10px 0;}\n\n/* 进度条 */\n.layui-progress{position: relative; height: 6px; border-radius: 20px; background-color: #e2e2e2;}\n.layui-progress-bar{position: absolute; width: 0; max-width: 100%; height: 6px; border-radius: 20px; text-align: right; background-color: #5FB878; transition: all .3s; -webkit-transition: all .3s;}\n.layui-progress-big,\n.layui-progress-big .layui-progress-bar{height: 18px; line-height: 18px;}\n.layui-progress-text{position: relative; top: -18px; line-height: 18px; font-size: 12px; color: #666}\n.layui-progress-big .layui-progress-text{position: static; padding: 0 10px; color: #fff;}\n\n/* 折叠面板 */\n.layui-collapse{border: 1px solid #e2e2e2; border-radius: 2px;}\n.layui-colla-item{border-top: 1px solid #e2e2e2}\n.layui-colla-item:first-child{border-top: none;}\n.layui-colla-title{position: relative; height: 42px; line-height: 42px; padding: 0 15px 0 35px; color: #333; background-color: #f2f2f2; cursor: pointer;}\n.layui-colla-content{display: none; padding: 10px 15px; line-height: 22px; border-top: 1px solid #e2e2e2; color: #666;}\n.layui-colla-icon{position: absolute; left: 15px; top: 0; font-size: 14px;}\n\n\n/* 背景颜色 */\n.layui-bg-red{background-color: #FF5722 !important; color: #fff!important;} /*赤*/\n.layui-bg-orange{background-color: #FFB800!important; color: #fff!important;} /*橙*/\n.layui-bg-green{background-color: #009688!important; color: #fff!important;} /*绿*/\n.layui-bg-cyan{background-color: #2F4056!important; color: #fff!important;} /*青*/\n.layui-bg-blue{background-color: #1E9FFF!important; color: #fff!important;} /*蓝*/\n.layui-bg-black{background-color: #393D49!important; color: #fff!important;} /*黑*/\n.layui-bg-gray{background-color: #eee!important; color: #666!important;} /*灰*/\n\n\n/* 文本区域 */\n.layui-text{line-height: 22px; font-size: 14px; color: #666;}\n.layui-text h1,\n.layui-text h2,\n.layui-text h3{font-weight: 500; color: #333;}\n.layui-text h1{font-size: 30px;}\n.layui-text h2{font-size: 24px;}\n.layui-text h3{font-size: 18px;}\n.layui-text a{color: #01AAED;}\n.layui-text a:hover{text-decoration: underline;}\n.layui-text ul{padding: 5px 0 5px 15px;}\n.layui-text ul li{margin-top: 5px; list-style-type: disc;}\n.layui-text em,\n.layui-word-aux{color: #999 !important; padding: 0 5px !important;}\n\n/* 按钮 */\n.layui-btn{display: inline-block; vertical-align: middle; 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; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;}\n.layui-btn:hover{opacity: 0.8; filter:alpha(opacity=80); color: #fff;}\n.layui-btn:active{opacity: 1; filter:alpha(opacity=100);}\n.layui-btn+.layui-btn{margin-left: 10px;}\n/* 圆角 */.layui-btn-radius{border-radius: 100px;}\n.layui-btn .layui-icon{margin-right: 3px; font-size: 18px; vertical-align: bottom; vertical-align: middle\\0;}\n\n/* 原始 */.layui-btn-primary{border: 1px solid #C9C9C9; background-color: #fff; color: #555;}\n.layui-btn-primary:hover{border-color: #009688; color: #333}\n/* 百搭 */.layui-btn-normal{background-color: #1E9FFF;}\n/* 暖色 */.layui-btn-warm{background-color: #FFB800;}\n/* 警告 */.layui-btn-danger{background-color: #FF5722;}\n/* 禁用 */.layui-btn-disabled,.layui-btn-disabled:hover,.layui-btn-disabled:active{border: 1px solid #e6e6e6; background-color: #FBFBFB; color: #C9C9C9; cursor: not-allowed; opacity: 1;}\n\n/* 大型 */.layui-btn-big{height: 44px; line-height: 44px; padding: 0 25px; font-size: 16px;}\n/* 小型 */.layui-btn-small{height: 30px; line-height: 30px; padding: 0 10px; font-size: 12px;}\n.layui-btn-small i{font-size: 16px !important;}\n/* 迷你 */.layui-btn-mini{height: 22px; line-height: 22px; padding: 0 5px; font-size: 12px;}\n.layui-btn-mini i{font-size: 14px !important;}\n/* 按钮组 */.layui-btn-group{display: inline-block; vertical-align: middle; font-size: 0;}\n.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;}\n.layui-btn-group .layui-btn-primary{border-left: none;}\n.layui-btn-group .layui-btn-primary:hover{border-color: #C9C9C9; color: #009688;}\n.layui-btn-group .layui-btn:first-child{border-left: none; border-radius: 2px 0 0 2px;}\n.layui-btn-group .layui-btn-primary:first-child{border-left: 1px solid #c9c9c9;}\n.layui-btn-group .layui-btn:last-child{border-radius: 0 2px 2px 0;}\n.layui-btn-group .layui-btn+.layui-btn{margin-left: 0;}\n.layui-btn-group+.layui-btn-group{margin-left: 10px;}\n\n/** 表单 **/\n.layui-input, .layui-textarea, .layui-select{height: 38px; line-height: 1.3; line-height: 38px\\9; border: 1px solid #e6e6e6; background-color: #fff; border-radius: 2px;}\n.layui-input::-webkit-input-placeholder,\n.layui-textarea::-webkit-input-placeholder,\n.layui-select::-webkit-input-placeholder{line-height: 1.3;}\n.layui-input, .layui-textarea{display: block; width: 100%; padding-left: 10px;}\n.layui-input:hover, .layui-textarea:hover{border-color: #D2D2D2 !important;}\n.layui-input:focus, .layui-textarea:focus{border-color: #C9C9C9 !important;}\n.layui-textarea{position: relative; min-height: 100px; height: auto; line-height: 20px; padding: 6px 10px; resize: vertical;}\n.layui-select{padding: 0 10px;}\n.layui-form select, \n.layui-form input[type=checkbox],\n.layui-form input[type=radio]{display: none;}\n\n.layui-form-item{margin-bottom: 15px; clear: both; *zoom: 1;}\n.layui-form-item:after{content:'\\20'; clear: both; *zoom: 1; display: block; height:0;}\n.layui-form-label{position: relative; float: left; display: block; padding: 9px 15px;  width: 80px; font-weight:normal;line-height: 20px; text-align: right;}\n.layui-form-item .layui-inline{margin-bottom: 5px; margin-right: 10px;}\n.layui-input-block, .layui-input-inline{position: relative;}\n.layui-input-block{margin-left: 110px; min-height: 36px;}\n.layui-input-inline{display: inline-block; vertical-align: middle;}\n.layui-form-item .layui-input-inline{float: left; width: 190px; margin-right: 10px;}\n.layui-form-text .layui-input-inline{width: auto;}\n\n/* 分割块 */.layui-form-mid{position: relative; float: left; display: block; padding: 8px 0 !important; line-height: 20px; margin-right: 10px;}\n/* 警告域 */.layui-form-danger:focus\n,.layui-form-danger+.layui-form-select .layui-input{border: 1px solid #FF5722 !important;}\n\n\n/* 下拉选择 */.layui-form-select{position: relative;}\n.layui-form-select .layui-input{padding-right: 30px; cursor: pointer;}\n.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;}\n.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;}\n.layui-form-select dl dt,\n.layui-form-select dl dd{padding: 0 10px; line-height: 36px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}\n.layui-form-select dl dt{font-size: 12px; color: #999;}\n.layui-form-select dl dd{cursor: pointer;}\n.layui-form-select dl dd:hover{background-color: #f2f2f2;}\n.layui-form-select .layui-select-group dd{padding-left: 20px;}\n.layui-form-select dl dd.layui-select-tips{padding-left: 10px !important; color: #999;}\n.layui-form-select dl dd.layui-this{background-color: #5FB878; color: #fff;}\n.layui-form-select dl dd.layui-disabled{background-color: #fff;}\n.layui-form-selected dl{display: block;}\n.layui-form-selected .layui-edge{margin-top: -9px; -webkit-transform:rotate(180deg); transform: rotate(180deg);}\n.layui-form-selected .layui-edge{margin-top: -3px\\0; }\n:root .layui-form-selected .layui-edge{margin-top: -9px\\0/IE9;}\n.layui-form-selectup dl{top: auto; bottom: 42px;}\n.layui-select-none{margin: 5px 0; text-align: center; color: #999;}\n\n.layui-select-disabled .layui-disabled{border-color: #eee !important;}\n.layui-select-disabled .layui-edge{border-top-color: #d2d2d2}\n\n/* 复选框 */.layui-form-checkbox{position: relative; display: inline-block; vertical-align: middle; height: 30px; line-height: 28px; margin-right: 10px; padding-right: 30px; border: 1px solid #d2d2d2; background-color: #fff; cursor: pointer; font-size: 0; border-radius: 2px;  -webkit-transition: .1s linear; transition: .1s linear; box-sizing: border-box;}\n.layui-form-checkbox:hover{border: 1px solid #c2c2c2;}\n.layui-form-checkbox *{display: inline-block; vertical-align: middle;}\n.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;}\n.layui-form-checkbox:hover span{background-color: #c2c2c2;}\n.layui-form-checkbox i{position: absolute; right: 0; width: 30px; color: #fff; font-size: 20px; text-align: center;}\n.layui-form-checkbox:hover i{color: #c2c2c2;}\n.layui-form-checked, .layui-form-checked:hover{border-color: #5FB878;}\n.layui-form-checked span, .layui-form-checked:hover span{background-color: #5FB878;}\n.layui-form-checked i, .layui-form-checked:hover i{color: #5FB878;}\n.layui-form-item .layui-form-checkbox{margin-top: 4px;}\n\n/* 复选框-原始风格 */.layui-form-checkbox[lay-skin=\"primary\"]{height: auto!important; line-height: normal!important; border: none!important; margin-right: 0; padding-right: 0; background: none;}\n.layui-form-checkbox[lay-skin=\"primary\"] span{float: right; padding-right: 15px; line-height: 18px; background: none; color: #666;}\n.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;}\n.layui-form-checkbox[lay-skin=\"primary\"]:hover i{border-color: #5FB878; color: #fff;}\n.layui-form-checked[lay-skin=\"primary\"] i{border-color: #5FB878; background-color: #5FB878; color: #fff;}\n.layui-checkbox-disbaled[lay-skin=\"primary\"] span{background: none!important;}\n.layui-checkbox-disbaled[lay-skin=\"primary\"]:hover i{border-color: #d2d2d2;}\n.layui-form-item .layui-form-checkbox[lay-skin=\"primary\"]{margin-top: 10px;}\n\n/* 复选框-开关风格 */.layui-form-switch{position: relative; display: inline-block; vertical-align: middle; 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;}\n.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;}\n.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;}\n.layui-form-onswitch{border-color: #5FB878; background-color: #5FB878;}\n.layui-form-onswitch i{left: 32px; background-color: #fff;}\n.layui-form-onswitch em{left: 5px; right: auto; color: #fff!important;}\n\n.layui-checkbox-disbaled{border-color: #e2e2e2 !important;}\n.layui-checkbox-disbaled span{background-color: #e2e2e2 !important;}\n.layui-checkbox-disbaled:hover i{color: #fff !important;}\n\n/* 单选框 */\n.layui-form-radio{display: inline-block; vertical-align: middle; line-height: 28px; margin: 6px 10px 0 0; padding-right: 10px; cursor: pointer; font-size: 0;}\n.layui-form-radio *{display: inline-block; vertical-align: middle;}\n.layui-form-radio i{margin-right: 8px; font-size: 22px; color: #c2c2c2;}\n.layui-form-radio  span{font-size: 14px;}\n.layui-form-radioed i,.layui-form-radio i:hover{color: #5FB878;}\n.layui-radio-disbaled i{color: #e2e2e2 !important;}\n\n/* 表单方框风格 */.layui-form-pane .layui-form-label{width: 110px; padding: 8px 15px; height: 38px; 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; box-sizing: border-box;}\n.layui-form-pane .layui-input-inline{margin-left: -1px;}\n.layui-form-pane .layui-input-block{margin-left: 110px; left: -1px;}\n.layui-form-pane .layui-input{border-radius: 0 2px 2px 0;}\n.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; text-align: left;}\n.layui-form-pane .layui-form-text .layui-input-inline{display: block; margin: 0; top: -1px; clear: both;}\n.layui-form-pane .layui-form-text .layui-input-block{margin: 0; left: 0; top: -1px;}\n.layui-form-pane .layui-form-text .layui-textarea{min-height: 100px; border-radius: 0 0 2px 2px;}\n.layui-form-pane .layui-form-checkbox{margin: 4px 0 4px 10px;}\n.layui-form-pane .layui-form-switch, \n.layui-form-pane .layui-form-radio{margin-top: 6px; margin-left: 10px; }\n.layui-form-pane .layui-form-item[pane]{position: relative; border: 1px solid #e6e6e6;}\n.layui-form-pane .layui-form-item[pane] .layui-form-label{position: absolute; left: 0; top: 0; height: 100%; border-width: 0px; border-right-width: 1px;}\n.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left: 110px;}\n\n/** 表单响应式 **/\n@media screen and (max-width: 450px) {\n  .layui-form-item .layui-form-label{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}\n  .layui-form-item .layui-inline{display: block; margin-right: 0; margin-bottom: 20px; clear: both;}\n  .layui-form-item .layui-inline:after{content:'\\20'; clear:both; display:block; height:0;}\n  .layui-form-item .layui-input-inline{display: block; float: none; left: -3px; width: auto; margin: 0 0 10px 112px; }\n  .layui-form-item .layui-input-inline+.layui-form-mid{margin-left: 110px; top: -5px; padding: 0;}\n  .layui-form-item .layui-form-checkbox{margin-right: 5px; margin-bottom: 5px;}\n}\n\n/** 富文本编辑器 **/\n.layui-layedit{border: 1px solid #d2d2d2; border-radius: 2px;}\n.layui-layedit-tool{padding: 3px 5px; border-bottom: 1px solid #e2e2e2; font-size: 0;}\n.layedit-tool-fixed{position: fixed; top: 0; border-top: 1px solid #e2e2e2;}\n.layui-layedit-tool .layedit-tool-mid,\n.layui-layedit-tool .layui-icon{display: inline-block; vertical-align: middle; text-align: center; font-size: 14px;}\n.layui-layedit-tool .layui-icon{position: relative; width: 32px; height: 30px; line-height: 30px; margin: 3px 5px; border-radius: 2px; color: #777; cursor: pointer; border-radius: 2px;}\n.layui-layedit-tool .layui-icon:hover{color: #393D49;}\n.layui-layedit-tool .layui-icon:active{color: #000;}\n.layui-layedit-tool .layedit-tool-active{background-color: #e2e2e2; color: #000;}\n.layui-layedit-tool .layui-disabled,\n.layui-layedit-tool .layui-disabled:hover{color: #d2d2d2; cursor: not-allowed;}\n.layui-layedit-tool .layedit-tool-mid{width: 1px; height: 18px; margin: 0 10px; background-color: #d2d2d2;}\n\n.layedit-tool-html{width: 50px !important; font-size: 30px !important;}\n.layedit-tool-b,\n.layedit-tool-code,\n.layedit-tool-help{font-size: 16px !important;}\n.layedit-tool-d,\n.layedit-tool-unlink,\n.layedit-tool-face,\n.layedit-tool-image{font-size: 18px !important;}\n.layedit-tool-image input{position: absolute; font-size: 0; left: 0; top: 0; width: 100%; height: 100%; opacity: 0.01; filter: Alpha(opacity=1); cursor: pointer;}\n\n.layui-layedit-iframe iframe{display: block; width: 100%;}\n#LAY_layedit_code{overflow: hidden;}\n\n/** 分页 **/\n.layui-laypage{display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; margin: 10px 0; font-size: 0;}\n.layui-laypage>a:first-child,\n.layui-laypage>a:first-child em{border-radius: 2px 0 0 2px;}\n.layui-laypage>a:last-child,\n.layui-laypage>a:last-child em{border-radius: 0 2px 2px 0;}\n.layui-laypage>*:first-child{margin-left: 0!important;}\n.layui-laypage>*:last-child{margin-right: 0!important;}\n.layui-laypage a,\n.layui-laypage span,\n.layui-laypage input, \n.layui-laypage button,\n.layui-laypage select{border: 1px solid #e2e2e2;}\n.layui-laypage a,\n.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;}\n.layui-laypage a:hover{color: #009688;}\n.layui-laypage em{font-style: normal;}\n.layui-laypage .layui-laypage-spr{color:#999; font-weight: 700;}\n.layui-laypage a{ text-decoration: none;}\n.layui-laypage .layui-laypage-curr{position: relative;}\n.layui-laypage .layui-laypage-curr em{position: relative; color: #fff;}\n.layui-laypage .layui-laypage-curr .layui-laypage-em{position: absolute; left: -1px; top: -1px; padding: 1px; width: 100%; height: 100%; background-color: #009688; }\n.layui-laypage-em{border-radius: 2px;}\n.layui-laypage-prev em,\n.layui-laypage-next em{font-family: Sim sun; font-size: 16px;}\n\n.layui-laypage .layui-laypage-count,\n.layui-laypage .layui-laypage-limits,\n.layui-laypage .layui-laypage-skip{margin-left: 10px; margin-right: 10px; padding: 0; border: none;}\n.layui-laypage .layui-laypage-limits{vertical-align: top;}\n.layui-laypage select{height: 22px; padding: 3px; border-radius: 2px; cursor: pointer;}\n.layui-laypage .layui-laypage-skip{height: 30px; line-height: 30px; color: #999;}\n.layui-laypage input, .layui-laypage button{height: 30px; line-height: 30px; border:1px solid #e2e2e2; border-radius: 2px; vertical-align: top;  background-color: #fff; box-sizing: border-box;}\n.layui-laypage input{display: inline-block; width: 40px; margin: 0 10px; padding: 0 3px; text-align: center;}\n.layui-laypage input:focus,\n.layui-laypage select:focus{border-color: #009688!important;}\n.layui-laypage button{margin-left: 10px; padding: 0 10px; cursor: pointer;}\n\n/** 流加载 **/\n.layui-flow-more{margin: 10px 0; text-align: center; color: #999; font-size: 14px;}\n.layui-flow-more a{ height: 32px; line-height: 32px;  }\n.layui-flow-more a *{display: inline-block; vertical-align: top;}\n.layui-flow-more a cite{padding: 0 20px; border-radius: 3px; background-color: #eee; color: #333; font-style: normal;}\n.layui-flow-more a cite:hover{opacity: 0.8;}\n.layui-flow-more a i{font-size: 30px; color: #737383;}\n\n/** 表格 **/\n.layui-table{width: 100%; margin: 10px 0; background-color: #fff;}\n.layui-table tr{transition: all .3s; -webkit-transition: all .3s;}\n.layui-table thead tr,\n.layui-table-header,\n.layui-table-fixed-l tr,\n.layui-table-tool,\n.layui-table-patch,\n.layui-table-mend{background-color: #f2f2f2;}\n.layui-table th{text-align: left; font-weight: 400;}\n\n.layui-table th,\n.layui-table td,\n.layui-table[lay-skin=\"line\"],\n.layui-table[lay-skin=\"row\"],\n.layui-table-view,\n.layui-table-header,\n.layui-table-tool{border: 1px solid #e2e2e2}\n\n.layui-table th, .layui-table td{position: relative; padding: 9px 15px; min-height: 20px; line-height: 20px;  font-size: 14px;}\n.layui-table[lay-even] tr:nth-child(even){background-color: #f8f8f8;}\n.layui-table tbody tr:hover,\n.layui-table-hover{background-color: #f2f2f2!important;}\n.layui-table-click{background-color: #FFEEE8!important;}\n\n.layui-table[lay-skin=\"line\"] th, .layui-table[lay-skin=\"line\"] td{border-width: 0; border-bottom-width: 1px;}\n.layui-table[lay-skin=\"row\"] th, .layui-table[lay-skin=\"row\"] td{border-width: 0;border-right-width: 1px;}\n.layui-table[lay-skin=\"nob\"] th, .layui-table[lay-skin=\"nob\"] td{border: none;}\n\n.layui-table img{max-width:100px;}\n\n/* 大表格 */.layui-table[lay-size=\"lg\"] th,\n.layui-table[lay-size=\"lg\"] td{padding-top: 15px; padding-right: 30px; padding-bottom: 15px; padding-left: 30px;}\n.layui-table-view .layui-table[lay-size=\"lg\"] .layui-table-cell{height: 40px; line-height: 40px;}  \n/* 小表格 */.layui-table[lay-size=\"sm\"] th,\n.layui-table[lay-size=\"sm\"] td{padding-top: 5px; padding-right: 10px; padding-bottom: 5px; padding-left: 10px; font-size: 12px;}\n.layui-table-view .layui-table[lay-size=\"sm\"] .layui-table-cell{height: 20px; line-height: 20px;} \n\n/* 数据表格 */\n.layui-table[lay-data]{display: none;}\n.layui-table-view{position: relative; margin: 10px 0; overflow: hidden;}\n.layui-table-view .layui-table{position: relative; width: auto; margin: 0;}\n.layui-table-view .layui-table[lay-skin=\"line\"]{border-width: 0; border-right-width: 1px;}\n.layui-table-view .layui-table[lay-skin=\"row\"]{border-width: 0; border-bottom-width: 1px;}\n.layui-table-view .layui-table th,\n.layui-table-view .layui-table td{padding: 5px 0; border-top: none; border-left: none;}\n.layui-table-view .layui-table td{cursor: default;}\n.layui-table-view .layui-form-checkbox[lay-skin=\"primary\"] i{width: 18px; height: 18px;}\n.layui-table-header{border-width: 0; border-bottom-width: 1px; overflow: hidden;}\n.layui-table-header .layui-table{margin-bottom: -1px;}\n.layui-table-sort{width: 20px; height: 20px; margin-left: 5px; cursor: pointer!important;}\n.layui-table-sort .layui-edge{left: 5px; border-width: 5px;}\n.layui-table-sort .layui-table-sort-asc{top: 4px; border-top: none; border-bottom-style: solid; border-bottom-color: #b2b2b2;}\n.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color: #666;}\n.layui-table-sort .layui-table-sort-desc{bottom: 4px; border-bottom: none; border-top-style: solid; border-top-color: #b2b2b2;}\n.layui-table-sort .layui-table-sort-desc:hover{border-top-color: #666;}\n.layui-table-sort[lay-sort=\"asc\"] .layui-table-sort-asc{border-bottom-color: #000;}\n.layui-table-sort[lay-sort=\"desc\"] .layui-table-sort-desc{border-top-color: #000;}\n.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;}\n.layui-table-cell .layui-form-checkbox{top: -1px;}\n.layui-table-cell .layui-table-link{color: #01AAED;}\n.laytable-cell-space{width: 15px; padding: 0; text-align: center;}\n\n.layui-table-body{position: relative; overflow: auto; margin-right: -1px; margin-bottom: -1px;}\n.layui-table-body .layui-none{line-height: 40px; text-align: center; color: #999;}\n.layui-table-fixed{position: absolute; left: 0; top: 0;}\n.layui-table-fixed .layui-table-body{overflow: hidden;}\n.layui-table-fixed-r{left: auto; right: -1px; border-left: 1px solid #e2e2e2; box-shadow: -1px 0 8px rgba(0,0,0,.1);}\n.layui-table-fixed-r .layui-table-header{position: relative; overflow: visible;}\n.layui-table-mend{position: absolute; right: -49px; top: 0; height: 100%; width: 50px;}\n.layui-table-tool{position: relative; width: 100%; padding: 7px 10px 0 0; border-width: 0; border-top-width: 1px; height: 41px; margin-bottom: -1px; font-size: 12px;  white-space: nowrap;}\n.layui-table-tool:hover{overflow-x: auto;}\n\n.layui-table-page{height: 26px;}\n.layui-table-tool .layui-laypage{margin: 0;}\n.layui-table-tool .layui-laypage span,\n.layui-table-tool .layui-laypage a{height: 26px; line-height: 26px; border: none; background: none; padding: 0 12px}\n.layui-table-tool .layui-laypage .layui-laypage-count,\n.layui-table-tool .layui-laypage .layui-laypage-limits,\n.layui-table-tool .layui-laypage .layui-laypage-skip{margin-left: 0; padding: 0;}\n.layui-table-tool .layui-laypage .layui-laypage-total{padding: 0 10px;}\n.layui-table-tool .layui-laypage .layui-laypage-spr{padding: 0;}\n.layui-table-tool .layui-laypage input,\n.layui-table-tool .layui-laypage button{height: 26px; line-height: 26px; }\n.layui-table-tool .layui-laypage input{width: 40px;}\n.layui-table-tool .layui-laypage button{padding: 0 10px;}\n.layui-table-view select[lay-ignore]{display: inline-block;}\n.layui-table-tool select{height: 18px;}\n.layui-table-patch .layui-table-cell{padding: 0; width: 30px;}\n.layui-table-edit{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding: 0 15px 1px; border: none;}\n.layui-table-edit:focus{background-color: #F0F9F2;}\n\nbody .layui-table-tips .layui-layer-content{background: none; padding: 0; box-shadow: 0 1px 6px rgba(0,0,0,.1);}\n.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; border: 1px solid #e2e2e2}\n.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;}\n.layui-table-tips-c:hover{background-color: #999;}\n\n\n/** 文件上传 **/\n.layui-upload-file{display: none!important; opacity: .01; filter: Alpha(opacity=1);}\n.layui-upload-list{margin: 10px 0;}\n.layui-upload-choose{padding: 0 10px; color: #999;}\n.layui-upload-drag{position: relative; display: inline-block; padding: 30px; border: 1px dashed #e2e2e2; background-color: #fff; text-align: center; cursor: pointer; color: #999;}\n.layui-upload-drag .layui-icon{font-size: 50px; color: #009688;}\n.layui-upload-drag[lay-over]{border-color: #009688}\n.layui-upload-form{display: inline-block;}\n.layui-upload-iframe{position: absolute; width: 0; height: 0; border: 0; visibility: hidden}\n.layui-upload-wrap{position: relative; display: inline-block; vertical-align: middle;}\n.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;}\n\n\n\n/** 代码修饰器 **/\n.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;}\n\n\n/** 树组件 **/\n.layui-tree{line-height: 26px;}\n.layui-tree li{text-overflow: ellipsis; overflow:hidden; white-space: nowrap;}\n.layui-tree li a, \n.layui-tree li .layui-tree-spread{display: inline-block; vertical-align: top; height: 26px; *display: inline; *zoom:1; cursor: pointer;}\n.layui-tree li a{font-size: 0;}\n.layui-tree li a i{font-size: 16px;}\n.layui-tree li a cite{padding: 0 6px; font-size: 14px; font-style: normal;}\n.layui-tree li i{padding-left: 6px; color: #333; -moz-user-select: none;}\n.layui-tree li .layui-tree-check{font-size: 13px;}\n.layui-tree li .layui-tree-check:hover{color: #009E94;}\n.layui-tree li ul{display: none; margin-left: 20px;}\n.layui-tree li .layui-tree-enter{line-height: 24px; border: 1px dotted #000;}\n.layui-tree-drag{display: none; position: absolute; left: -666px; top: -666px; background-color: #f2f2f2; padding: 5px 10px; border: 1px dotted #000; white-space: nowrap}\n.layui-tree-drag i{padding-right: 5px;}\n\n/** 导航菜单 **/\n.layui-nav{position: relative; padding: 0 20px; background-color: #393D49; color: #fff; border-radius: 2px; font-size: 0; box-sizing: border-box;}\n.layui-nav *{font-size: 14px;}\n.layui-nav .layui-nav-item{position: relative; display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; line-height: 60px;}\n.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;}\n.layui-nav-bar,\n.layui-nav .layui-this:after,\n.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;}\n.layui-nav-bar{z-index: 1000;}\n.layui-nav .layui-this a\n,.layui-nav .layui-nav-item a:hover{color: #fff;}\n.layui-nav .layui-this:after{content: ''; top: auto; bottom: 0; width: 100%;}\n.layui-nav-img{width: 30px; height: 30px; margin-right: 10px; border-radius: 50%;}\n\n.layui-nav .layui-nav-more{content:''; width: 0; height: 0; border-style: dashed; border-color: transparent; overflow: hidden; cursor: pointer; transition: all .2s; -webkit-transition: all .2s;}\n.layui-nav .layui-nav-more{position: absolute; top: 28px; right: 3px; border-width: 6px; border-top-style: solid; border-top-color: #fff; border-top-color: rgba(255,255,255,.7);}\n.layui-nav .layui-nav-mored,\n.layui-nav-itemed .layui-nav-more{top: 22px; border-style: dashed; border-color: transparent; border-bottom-style: solid; border-bottom-color: #fff;}\n\n.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;}\n.layui-nav .layui-nav-child a{color: #333;}\n.layui-nav .layui-nav-child a:hover{background-color: #f2f2f2; color: #000;}\n.layui-nav-child dd{position: relative;}\n.layui-nav-child dd.layui-this{background-color: #5FB878; color: #fff;}\n.layui-nav .layui-nav-child dd.layui-this a{background-color: #5FB878; color: #fff;}\n.layui-nav-child dd.layui-this:after{display: none;}\n\n/* 垂直导航菜单 */.layui-nav-tree{width: 200px; padding: 0;}\n.layui-nav-tree .layui-nav-item{display: block; width: 100%; line-height: 45px;}\n.layui-nav-tree .layui-nav-item a{height: 45px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}\n.layui-nav-tree .layui-nav-item a:hover{background-color: #4E5465;}\n.layui-nav-tree .layui-nav-bar{width: 5px; height: 0;}\n.layui-nav-tree .layui-this,\n.layui-nav-tree .layui-this>a,\n.layui-nav-tree .layui-this>a:hover,\n.layui-nav-tree .layui-nav-child dd.layui-this,\n.layui-nav-tree .layui-nav-child dd.layui-this a{background-color: #009688; color: #fff;}\n.layui-nav-tree .layui-this:after{display: none;}\n.layui-nav-tree .layui-nav-title a,\n.layui-nav-tree .layui-nav-title a:hover,\n.layui-nav-itemed>a{color: #fff !important;}\n.layui-nav-tree .layui-nav-bar{background-color: #009688;}\n\n.layui-nav-tree .layui-nav-child{position: relative; z-index: 0; top: 0; border: none; box-shadow: none;}\n.layui-nav-tree .layui-nav-child a{height: 40px; line-height: 40px;}\n.layui-nav-tree .layui-nav-child a{color: #fff; color: rgba(255,255,255,.7);}\n.layui-nav-tree .layui-nav-child a:hover,\n.layui-nav-tree .layui-nav-child{background: none; color: #fff;}\n.layui-nav-tree .layui-nav-more{top: 20px; right: 10px;}\n.layui-nav-itemed .layui-nav-more{top: 14px;}\n.layui-nav-itemed .layui-nav-child{display: block; padding: 0; background-color: rgba(0,0,0,.3) !important;} \n\n/* 侧边 */.layui-nav-side{position: fixed; top: 0; bottom: 0; left: 0; overflow-x: hidden; z-index: 999;}\n\n/* 导航主题色 */.layui-bg-blue .layui-nav-bar,\n.layui-bg-blue .layui-this:after,\n.layui-bg-blue .layui-nav-itemed:after{background-color: #93D1FF;}\n.layui-bg-blue .layui-nav-child dd.layui-this{background-color: #1E9FFF;}\n.layui-nav-tree.layui-bg-blue .layui-nav-title a,\n.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover, \n.layui-bg-blue .layui-nav-itemed>a{background-color: #007DDB !important;}\n\n\n/** 面包屑 **/\n.layui-breadcrumb{visibility: hidden; font-size: 0;}\n.layui-breadcrumb a{padding-right: 8px; line-height: 22px; font-size: 14px; color: #333 !important;}\n.layui-breadcrumb a:hover{color: #01AAED !important;}\n.layui-breadcrumb a span,\n.layui-breadcrumb a cite{ color: #666; cursor: text; font-style: normal;}\n.layui-breadcrumb a span{padding-left: 8px; font-family: Sim sun;}\n\n/** Tab选项卡 **/\n.layui-tab{margin: 10px 0; text-align: left !important;}\n.layui-tab[overflow]>.layui-tab-title{overflow: hidden;}\n.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;}\n.layui-tab-title li{display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; font-size: 14px; transition: all .2s; -webkit-transition: all .2s;}\n.layui-tab-title li{position: relative; line-height: 40px; min-width: 65px; padding: 0 15px; text-align: center; cursor: pointer;}\n.layui-tab-title li a{display: block;}\n.layui-tab-title .layui-this{color: #000;}\n\n.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; box-sizing: border-box; pointer-events: none;}\n.layui-tab-bar{position: absolute; right: 0; top: 0; z-index: 10; width: 30px; height: 39px; line-height: 39px; border: 1px solid #e2e2e2; border-radius: 2px; text-align: center; background-color: #fff; cursor: pointer;}\n.layui-tab-bar .layui-icon{position: relative; display: inline-block; top: 3px; transition: all .3s; -webkit-transition: all .3s;}\n.layui-tab-item{display: none;}\n.layui-tab-more{padding-right: 30px; height: auto !important; white-space: normal !important;}\n.layui-tab-more li.layui-this:after{border-bottom-color: #e2e2e2; border-radius: 2px;}\n.layui-tab-more .layui-tab-bar .layui-icon{top: -2px; top: 3px\\0; -webkit-transform: rotate(180deg); transform: rotate(180deg);}\n:root .layui-tab-more .layui-tab-bar .layui-icon{top: -2px\\0/IE9;}\n\n.layui-tab-content{padding: 10px;}\n\n/* Tab关闭 */.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;}\n.layui-tab-title li .layui-tab-close:hover{border-radius: 2px; background-color: #FF5722; color: #fff;}\n\n/* Tab简洁风格 */.layui-tab-brief > .layui-tab-title .layui-this{color: #009688;}\n.layui-tab-brief > .layui-tab-title .layui-this:after\n,.layui-tab-brief > .layui-tab-more li.layui-this:after{border: none; border-radius: 0; border-bottom: 2px solid #5FB878;}\n.layui-tab-brief[overflow] > .layui-tab-title .layui-this:after{top: -1px;}\n\n/* Tab卡片风格 */.layui-tab-card{border: 1px solid #e2e2e2; border-radius: 2px; box-shadow: 0 2px 5px 0 rgba(0,0,0,.1);}\n.layui-tab-card > .layui-tab-title{ background-color: #f2f2f2;}\n.layui-tab-card > .layui-tab-title li{margin-right: -1px; margin-left: -1px;}\n.layui-tab-card > .layui-tab-title .layui-this{background-color: #fff;     }\n.layui-tab-card > .layui-tab-title .layui-this:after{border-top: none; border-width: 1px; border-bottom-color: #fff;}\n.layui-tab-card > .layui-tab-title .layui-tab-bar{height: 40px; line-height: 40px; border-radius: 0; border-top: none; border-right: none;}\n.layui-tab-card > .layui-tab-more .layui-this{background: none; color: #5FB878;}\n.layui-tab-card > .layui-tab-more .layui-this:after{border: none;}\n\n/* 时间线 */\n.layui-timeline{padding-left: 5px;}\n.layui-timeline-item{position: relative; padding-bottom: 20px;}\n.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;}\n.layui-timeline-axis:hover{color: #FF5722;}\n.layui-timeline-item:before{content: ''; position: absolute; left: 5px; top: 0; z-index: 0; width: 1px; height: 100%; background-color: #e2e2e2;}\n.layui-timeline-item:last-child:before{display: none;}\n.layui-timeline-item:first-child:before{display: block;}\n.layui-timeline-content{padding-left: 25px;;}\n.layui-timeline-title{position: relative; margin-bottom: 10px;}\n\n/* 小徽章 */\n.layui-badge,\n.layui-badge-dot,\n.layui-badge-rim{position:relative; display: inline-block; font-size: 12px; background-color: #FF5722; color: #fff;}\n.layui-badge{min-width: 8px; height: 18px; line-height: 18px; padding: 0 5px; text-align: center; border-radius: 9px;}\n.layui-badge-dot{width: 8px; height: 8px; border-radius: 50%;}\n.layui-badge-rim{height: 18px; line-height: 18px; padding: 0 5px; border: 1px solid #e2e2e2; border-radius: 3px; background-color: #fff; color: #666;}\n\n.layui-btn .layui-badge,\n.layui-btn .layui-badge-dot{margin-left: 5px;}\n.layui-nav .layui-badge,\n.layui-nav .layui-badge-dot{position: absolute; top: 50%; margin: -10px 6px 0;}\n.layui-tab-title .layui-badge,\n.layui-tab-title .layui-badge-dot{left: 5px; top: -2px;}\n\n/* carousel 轮播 */\n.layui-carousel{position: relative; left: 0; top: 0; background-color: #f2f2f2;}\n.layui-carousel>*[carousel-item]{position: relative; width: 100%; height: 100%; overflow: hidden;}\n.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: #999; font-family:\"layui-icon\" !important; font-size: 20px; font-style:normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}\n.layui-carousel>*[carousel-item] > *{display: none; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #f2f2f2; transition-duration: .3s; -webkit-transition-duration: .3s;}\n.layui-carousel-updown > *{-webkit-transition: .3s ease-in-out up; transition: .3s ease-in-out up;}\n.layui-carousel-arrow{display: none\\0; 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: none 0; border-radius: 50%; background-color: rgba(0,0,0,.2); color: #fff; -webkit-transition-duration: .3s; transition-duration: .3s; cursor: pointer;}\n.layui-carousel-arrow[lay-type=\"add\"]{left: auto!important; right: 10px;}\n.layui-carousel[lay-arrow=\"always\"] .layui-carousel-arrow{opacity: 1; left: 20px;}\n.layui-carousel[lay-arrow=\"always\"] .layui-carousel-arrow[lay-type=\"add\"]{right: 20px;}\n.layui-carousel[lay-arrow=\"none\"] .layui-carousel-arrow{display: none;}\n.layui-carousel-arrow:hover,\n.layui-carousel-ind ul:hover{background-color: rgba(0,0,0,.35);}\n.layui-carousel:hover .layui-carousel-arrow{display: block\\0; opacity: 1; left: 20px;}\n.layui-carousel:hover .layui-carousel-arrow[lay-type=\"add\"]{right: 20px;}\n.layui-carousel-ind{position: relative; top: -35px; width: 100%; line-height: 0!important; text-align: center; font-size: 0;}\n.layui-carousel[lay-indicator=\"outside\"]{margin-bottom: 30px;}\n.layui-carousel[lay-indicator=\"outside\"] .layui-carousel-ind{top: 10px;}\n.layui-carousel[lay-indicator=\"outside\"] .layui-carousel-ind ul{background-color: rgba(0,0,0,.5);}\n.layui-carousel[lay-indicator=\"none\"] .layui-carousel-ind{display: none;}\n.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;}\n.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;}\n.layui-carousel-ind li:hover{background-color: rgba(255,255,255,.7);}\n.layui-carousel-ind li.layui-this{background-color: #fff;}\n.layui-carousel>*[carousel-item]>.layui-this,\n.layui-carousel>*[carousel-item]>.layui-carousel-prev,\n.layui-carousel>*[carousel-item]>.layui-carousel-next{display: block}\n.layui-carousel>*[carousel-item]>.layui-this{left: 0;}\n.layui-carousel>*[carousel-item]>.layui-carousel-prev{left: -100%;}\n.layui-carousel>*[carousel-item]>.layui-carousel-next{left: 100%;}\n.layui-carousel>*[carousel-item]>.layui-carousel-prev.layui-carousel-right,\n.layui-carousel>*[carousel-item]>.layui-carousel-next.layui-carousel-left{left: 0;}\n.layui-carousel>*[carousel-item]>.layui-this.layui-carousel-left{left: -100%;}\n.layui-carousel>*[carousel-item]>.layui-this.layui-carousel-right{left: 100%;}\n\n/* 上下切换 */.layui-carousel[lay-anim=\"updown\"] .layui-carousel-arrow{left: 50%!important; top: 20px; margin: 0 0 0 -18px;}\n.layui-carousel[lay-anim=\"updown\"] .layui-carousel-arrow[lay-type=\"add\"]{top: auto!important; bottom: 20px;}\n.layui-carousel[lay-anim=\"updown\"] .layui-carousel-ind{position: absolute; top: 50%; right: 20px; width: auto; height: auto;}\n.layui-carousel[lay-anim=\"updown\"] .layui-carousel-ind ul{padding: 3px 5px;}\n.layui-carousel[lay-anim=\"updown\"] .layui-carousel-ind li{display: block; margin: 6px 0;}\n\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>*{left: 0!important;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-this{top: 0;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-carousel-prev{top: -100%;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-carousel-next{top: 100%;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-carousel-prev.layui-carousel-right,\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-carousel-next.layui-carousel-left{top: 0;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-this.layui-carousel-left{top: -100%;}\n.layui-carousel[lay-anim=\"updown\"]>*[carousel-item]>.layui-this.layui-carousel-right{top: 100%;}\n\n/* 渐显切换 */.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>*{left: 0!important;}\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-carousel-prev,\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-carousel-next{opacity: 0;}\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-carousel-prev.layui-carousel-right,\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-carousel-next.layui-carousel-left{opacity: 1;}\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-this.layui-carousel-left,\n.layui-carousel[lay-anim=\"fade\"]>*[carousel-item]>.layui-this.layui-carousel-right{opacity: 0}\n\n\n/** fixbar **/\n.layui-fixbar{position: fixed; right: 15px; bottom: 15px; z-index: 9999;}\n.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: 0.95;}\n.layui-fixbar li:hover{opacity: 0.85;}\n.layui-fixbar li:active{opacity: 1;}\n.layui-fixbar .layui-fixbar-top{display: none; font-size: 40px;}\n\n/** 表情面板 **/\nbody .layui-util-face{border: none; background: none;}\nbody .layui-util-face  .layui-layer-content{padding:0; background-color:#fff; color:#666; box-shadow:none}\n.layui-util-face .layui-layer-TipsG{display:none;}\n.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);}\n.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;}\n.layui-util-face ul li:hover{position: relative; z-index: 2; border: 1px solid #eb7350; background: #fff9ec;}\n\n/** 动画 **/\n.layui-anim{-webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both;}\n.layui-anim.layui-icon{display: inline-block;}\n.layui-anim-loop{-webkit-animation-iteration-count: infinite; animation-iteration-count: infinite;}\n\n@-webkit-keyframes layui-rotate{ /* 循环旋转 */\n  from {-webkit-transform: rotate(0deg);}\n  to {-webkit-transform: rotate(360deg);}\n}\n@keyframes layui-rotate{\n  from {transform: rotate(0deg);}\n  to {transform: rotate(360deg);}\n}\n.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;}\n\n@-webkit-keyframes layui-up{ /* 从最底部往上滑入 */\n  from {-webkit-transform: translate3d(0, 100%, 0); opacity: 0.3;}\n  to {-webkit-transform: translate3d(0, 0, 0);  opacity: 1;}\n}\n@keyframes layui-up{\n  from {transform: translate3d(0, 100%, 0);  opacity: 0.3;}\n  to {transform: translate3d(0, 0, 0);  opacity: 1;}\n}\n.layui-anim-up{-webkit-animation-name: layui-up; animation-name: layui-up;}\n\n@-webkit-keyframes layui-upbit{ /* 微微往上滑入 */\n  from {-webkit-transform: translate3d(0, 30px, 0); opacity: 0.3;}\n  to {-webkit-transform: translate3d(0, 0, 0);  opacity: 1;}\n}\n@keyframes layui-upbit{\n  from {transform: translate3d(0, 30px, 0);  opacity: 0.3;}\n  to {transform: translate3d(0, 0, 0);  opacity: 1;}\n}\n.layui-anim-upbit{-webkit-animation-name: layui-upbit; animation-name: layui-upbit;}\n\n@-webkit-keyframes layui-scale { /* 放大 */\n  0% {opacity: 0.3; -webkit-transform: scale(.5);}\n  100% {opacity: 1; -webkit-transform: scale(1);}\n}\n@keyframes layui-scale {\n  0% {opacity: 0.3; -ms-transform: scale(.5); transform: scale(.5);}\n  100% {opacity: 1; -ms-transform: scale(1); transform: scale(1);}\n}\n.layui-anim-scale{-webkit-animation-name: layui-scale; animation-name: layui-scale}\n\n@-webkit-keyframes layui-scale-spring { /* 弹簧式放大 */\n  0% {opacity: 0.5; -webkit-transform: scale(.5);}\n  80% {opacity: 0.8; -webkit-transform: scale(1.1);}\n  100% {opacity: 1; -webkit-transform: scale(1);}\n}\n@keyframes layui-scale-spring {\n  0% {opacity: 0.5; transform: scale(.5);}\n  80% {opacity: 0.8; transform: scale(1.1);}\n  100% {opacity: 1; transform: scale(1);}\n}\n.layui-anim-scaleSpring{-webkit-animation-name: layui-scale-spring; animation-name: layui-scale-spring}\n\n@-webkit-keyframes layui-fadein { /* 渐现 */\n  0% {opacity: 0;}\n  100% {opacity: 1;}\n}\n@keyframes layui-fadein {\n  0% {opacity: 0;}\n  100% {opacity: 1;}\n}\n.layui-anim-fadein{-webkit-animation-name: layui-fadein; animation-name: layui-fadein}\n\n@-webkit-keyframes layui-fadeout { /* 渐隐 */\n  0% {opacity: 1;}\n  100% {opacity: 0;}\n}\n@keyframes layui-fadeout {\n  0% {opacity: 1;}\n  100% {opacity: 0;}\n}\n.layui-anim-fadeout{-webkit-animation-name: layui-fadeout; animation-name: layui-fadeout}\n\n\n\n"
  },
  {
    "path": "src/main/resources/static/css/layui.mobile.css",
    "content": "/**\n \n @Name: layui mobile\n @author 郑保乐\n @Site: http://www.layui.com/mobile/\n \n */\n \n/* reset */\nbody,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,input,button,textarea,p,blockquote,th,td,form,legend{margin:0; padding:0; -webkit-tap-highlight-color:rgba(0,0,0,0)}\nhtml{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif; -ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}\na,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0);}\na{text-decoration: none; background:transparent}\na:active,a:hover{outline:0}\ntable{border-collapse:collapse;border-spacing:0}\nli{list-style:none;}\nb,strong{font-weight:700;}\nh1, h2, h3, h4, h5, h6{font-weight:500;}\naddress,cite,dfn,em,var{font-style:normal;}\ndfn{font-style:italic}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nimg{border:0; vertical-align: bottom}\nbutton,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0; outline: 0;}\nbutton,select{text-transform:none}\nselect{-webkit-appearance: none; border:none;}\ninput{line-height:normal; }\ninput[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}\ninput[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}\ninput[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}\ninput[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}\nlabel,input{vertical-align: middle;}\n\n\n/** 图标字体 **/\n@font-face {font-family: 'layui-icon';\n  src: url('../font/iconfont.eot?v=1.0.7');\n  src: url('../font/iconfont.eot?v=1.0.7#iefix') format('embedded-opentype'),\n  url('../font/iconfont.woff?v=1.0.7') format('woff'),\n  url('../font/iconfont.ttf?v=1.0.7') format('truetype'),\n  url('../font/iconfont.svg?v=1.0.7#iconfont') format('svg');\n}\n                    \n.layui-icon{\n  font-family:\"layui-icon\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n\n/** 基础通用 **/\n/* 消除第三方ui可能造成的冲突 */.layui-box, .layui-box *{-webkit-box-sizing: content-box !important; -moz-box-sizing: content-box !important; box-sizing: content-box !important;}\n.layui-border-box, .layui-border-box *{-webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\n.layui-inline{position: relative; display: inline-block; *display:inline; *zoom:1; vertical-align: middle;}\n/* 三角形 */.layui-edge{position: absolute; width: 0; height: 0; border-style: dashed; border-color: transparent; overflow: hidden;}\n/* 单行溢出省略 */.layui-elip{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}\n/* 屏蔽选中 */.layui-unselect{-moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;}\n.layui-disabled,.layui-disabled:active{background-color: #d2d2d2 !important; color: #fff !important; cursor: not-allowed !important;}\n/* 纯圆角 */.layui-circle{border-radius: 100%;}\n.layui-show{display: block !important;}\n.layui-hide{display: none !important;}\n\n\n.layui-upload-iframe{position: absolute; width: 0px; height: 0px; border: 0px; visibility: hidden;}\n.layui-upload-enter{border: 1px solid #009E94; background-color: #009E94; color: #fff; -webkit-transform: scale(1.1); transform: scale(1.1);}\n\n\n/* 弹出动画 */\n@-webkit-keyframes layui-m-anim-scale { /* 默认 */\n\t0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}\n\t100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}\n}\n@keyframes layui-m-anim-scale { /* 由小到大 */\n\t0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}\n\t100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}\n}\n.layui-m-anim-scale{animation-name:  layui-m-anim-scale; -webkit-animation-name:  layui-m-anim-scale;}\n\n@-webkit-keyframes layui-m-anim-up{ /* 从下往上 */\n  0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}\n  100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}\n}\n@keyframes layui-m-anim-up{\n  0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}\n  100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}\n}\n.layui-m-anim-up{-webkit-animation-name: layui-m-anim-up; animation-name: layui-m-anim-up}\n\n@-webkit-keyframes layui-m-anim-left{ /* 从右往左 */\n  0%{-webkit-transform: translateX(100%); transform: translateX(100%)}\n  100%{-webkit-transform: translateX(0); transform: translateX(0)}\n}\n@keyframes layui-m-anim-left{\n  0%{-webkit-transform: translateX(100%); transform: translateX(100%)}\n  100%{-webkit-transform: translateX(0); transform: translateX(0)}\n}\n.layui-m-anim-left{-webkit-animation-name: layui-m-anim-left; animation-name: layui-m-anim-left}\n\n@-webkit-keyframes layui-m-anim-right{ /* 从左往右 */\n  0%{-webkit-transform: translateX(-100%); transform: translateX(-100%)}\n  100%{-webkit-transform: translateX(0); transform: translateX(0)}\n}\n@keyframes layui-m-anim-right{\n  0%{-webkit-transform: translateX(-100%); transform: translateX(-100%)}\n  100%{-webkit-transform: translateX(0); transform: translateX(0)}\n}\n.layui-m-anim-right{-webkit-animation-name: layui-m-anim-right; animation-name: layui-m-anim-right}\n\n@-webkit-keyframes layui-m-anim-lout{ /* 往左收缩 */\n  0%{-webkit-transform: translateX(0); transform: translateX(0)}\n  100%{-webkit-transform: translateX(-100%); transform: translateX(-100%)}\n}\n@keyframes layui-m-anim-lout{\n  0%{-webkit-transform: translateX(0); transform: translateX(0)}\n  100%{-webkit-transform: translateX(-100%); transform: translateX(-100%)}\n}\n.layui-m-anim-lout{-webkit-animation-name: layui-m-anim-lout; animation-name: layui-m-anim-lout}\n\n@-webkit-keyframes layui-m-anim-rout{ /* 往右收缩 */\n  0%{-webkit-transform: translateX(0); transform: translateX(0)}\n  100%{-webkit-transform: translateX(100%); transform: translateX(100%)}\n}\n@keyframes layui-m-anim-rout{\n  0%{-webkit-transform: translateX(0); transform: translateX(0)}\n  100%{-webkit-transform: translateX(100%); transform: translateX(100%)}\n}\n.layui-m-anim-rout{-webkit-animation-name: layui-m-anim-rout; animation-name: layui-m-anim-rout}\n\n\n/** layer mobile */\n.layui-m-layer{position:relative; z-index: 19891014;}\n.layui-m-layer *{-webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box;}\n.layui-m-layershade,\n.layui-m-layermain{position:fixed; left:0; top:0; width:100%; height:100%;}\n.layui-m-layershade{background-color:rgba(0,0,0, .7); pointer-events:auto;}\n.layui-m-layermain{display:table; font-family: Helvetica, arial, sans-serif; pointer-events: none;}\n.layui-m-layermain .layui-m-layersection{display:table-cell; vertical-align:middle; text-align:center;}\n.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, 0.1);  pointer-events:auto;  -webkit-overflow-scrolling: touch;}\n.layui-m-layerchild{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration: .2s; animation-duration: .2s;}\n\n.layui-m-layer0 .layui-m-layerchild{width: 90%; max-width: 640px;}\n.layui-m-layer1 .layui-m-layerchild{border:none; border-radius:0;}\n.layui-m-layer2 .layui-m-layerchild{width:auto; max-width:260px; min-width:40px; border:none; background: none; box-shadow: none; color:#fff;}\n.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;}\n.layui-m-layerchild h3,\n.layui-m-layerbtn span{ text-overflow:ellipsis; overflow:hidden; white-space:nowrap;}\n.layui-m-layercont{padding: 50px 30px; line-height: 22px; text-align:center;}\n.layui-m-layer1 .layui-m-layercont{padding:0; text-align:left;}\n.layui-m-layer2 .layui-m-layercont{text-align:center; padding: 0; line-height: 0;}\n.layui-m-layer2 .layui-m-layercont i{width:25px; height:25px; margin-left:8px; display:inline-block; background-color:#fff; border-radius:100%;}\n.layui-m-layer2 .layui-m-layercont p{margin-top: 20px;}\n\n/* loading */\n@-webkit-keyframes layui-m-anim-loading{\n    0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}\n    40%{transform:scale(1); -webkit-transform:scale(1)}\n}\n@keyframes layui-m-anim-loading{\n    0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}\n    40%{transform:scale(1); -webkit-transform:scale(1)}\n}\n.layui-m-layer2 .layui-m-layercont i{-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;}\n\n.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0; -webkit-animation-delay: -.32s; animation-delay: -.32s;}\n.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay: -.16s; animation-delay: -.16s;}\n.layui-m-layer2 .layui-m-layercont>div{line-height:22px; padding-top:7px; margin-bottom:20px; font-size: 14px;}\n.layui-m-layerbtn{display: box; display: -moz-box; display: -webkit-box; width: 100%; position:relative; height: 50px; line-height: 50px; font-size: 0; text-align:center;  border-top:1px solid #D0D0D0; background-color: #F2F2F2; border-radius: 0 0 5px 5px;}\n.layui-m-layerbtn span{position:relative; display: block; -moz-box-flex: 1; box-flex: 1; -webkit-box-flex: 1;  text-align:center; font-size:14px; border-radius: 0 0 5px 5px; cursor:pointer;}\n.layui-m-layerbtn span[yes]{color: #40AFFE;}\n.layui-m-layerbtn span[no]{border-right: 1px solid #D0D0D0; border-radius: 0 0 0 5px;}\n.layui-m-layerbtn span:active{background-color: #F6F6F6;}\n.layui-m-layerend{position:absolute; right:7px; top:10px; width:30px; height:30px; border: 0; font-weight:400; background: transparent; cursor: pointer; -webkit-appearance: none; font-size:30px;}\n.layui-m-layerend::before, .layui-m-layerend::after{position:absolute; left:5px; top:15px; content:''; width:18px; height:1px; background-color:#999; transform:rotate(45deg); -webkit-transform:rotate(45deg); border-radius: 3px;}\n.layui-m-layerend::after{transform:rotate(-45deg);  -webkit-transform:rotate(-45deg);}\n\n/* 底部对话框风格 */\nbody .layui-m-layer .layui-m-layer-footer{position: fixed; width: 95%; max-width: 100%; margin: 0 auto; left:0; right: 0; bottom: 10px; background: none;}\n.layui-m-layer-footer .layui-m-layercont{padding: 20px; border-radius: 5px 5px 0 0; background-color: rgba(255,255,255,.8);}\n.layui-m-layer-footer .layui-m-layerbtn{display: block; height: auto; background: none; border-top: none;}\n.layui-m-layer-footer .layui-m-layerbtn span{background-color: rgba(255,255,255,.8);}\n.layui-m-layer-footer .layui-m-layerbtn span[no]{color: #FD482C; border-top: 1px solid #c2c2c2; border-radius: 0 0 5px 5px;}\n.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top: 10px; border-radius: 5px;}\n\n/* 通用提示 */\nbody .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;}\n.layui-m-layer-msg .layui-m-layercont{padding: 10px 20px;}\n\n\n\n\n"
  },
  {
    "path": "src/main/resources/static/css/login.css",
    "content": "html{\n\theight: 100%;\n    font-family: PingFangSC-Light,'helvetica neue','hiragino sans gb',arial,'microsoft yahei ui','microsoft yahei',simsun,sans-serif;\n    font-size: 14px;\n}\nbody.signin {\n    background: #18c8f6;\n    height: auto;\n    background:url(\"../img/backg02.jpg\") no-repeat center fixed;\n    -webkit-background-size: cover;\n    -moz-background-size: cover;\n    -o-background-size: cover;\n    background-size: cover;\n    color: rgba(255,255,255,.95);\n}\n.logopanel h1{\n\tfont-size: 40px;\n}\n.signin-info h3{\n\tfont-size: 24px;\n}\n\n.signinpanel {\n    width: 912px;\n    margin: 7% auto 0 auto;\n}\n.btn-login{\n\tborder: 1px solid #00a3ff;\n\tbackground-color: #00A3FF;\n\tcolor: #fff;\n\tborder-radius: 2px;\n}\n.btn-login:hover{\n\tcolor: #fff;\n    background-color: #0097ee;\n    border: 1px solid #0097ee;\n}\n.signinpanel .logopanel {\n    float: none;\n    width: auto;\n    padding: 0;\n    background: none;\n}\n\n.signinpanel .signin-info ul {\n    list-style: none;\n    padding: 0;\n    margin: 20px 0;\n    font-size: 20px;\n    \n}\n\n.signinpanel .form-control {\n    display: block;\n    margin-top: 15px;\n}\n\n.signinpanel .uname {\n    background: #fff url(../img/user.png) no-repeat 95% center;color:#333;\n}\n\n.signinpanel .pword {\n    background: #fff url(../img/locked.png) no-repeat 95% center;color:#333;\n}\n\n.signinpanel .btn {\n    margin-top: 15px;\n}\n\n.signinpanel form {\n    background: #fff;\n    border: 1px solid rgba(255,255,255,.3);\n    -moz-box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03);\n    -webkit-box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03);\n    box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03);\n    -moz-border-radius: 3px;\n    -webkit-border-radius: 3px;\n    border-radius: 3px;\n    padding: 30px;\n    color:#666;\n}\n.signinpanel form >h3{\n\tcolor: #333333;\n\tfont-size: 24px;\n\tfont-family: \"microsoft yahei\";\n\tfont-weight: 400;\n}\n.signup-footer{border-top: solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top: 15px;}\n.outside-login{\n    border-top: #dcdee3 1px solid;\n    padding: 7% 0 0;\n    text-align: center;\n    position: relative;\n    margin: 9% 0% 0;\n    border-radius: 0 0 1% 1%;\n}\n.outside-login-tit{\n\tposition: absolute;\n    top: -8px;\n    left: 50%;\n    margin: 0 0 0 -50px;\n    text-align: center;\n    width: 100px;\n    height: 14px;\n    line-height: 1;\n    color: #999;\n}\n.outside-login-tit span{\n\tposition: relative;\n\tz-index: 2;\n}\n.outside-login-tit:before {\n    top: 0;\n    left: 0;\n    background-color: #fff;\n}\n.outside-login-tit:after {\n    top: 7px;\n    left: 0;\n    background-color: #fff;\n}\n.outside-login-tit:after, .outside-login-tit:before {\n    content: '';\n    display: block;\n    width: 100%;\n    height: 7px;\n    position: absolute;\n    z-index: 1;\n}\n.outside-login-con {\n    font-size: 0;\n    padding-top: 10px;\n}\n.outside-login-list {\n    width: 116%;\n    margin-left: -8%;\n}\n.outside-login-btn {\n    display: inline-block;\n    vertical-align: middle;\n    text-align: center;\n    width: 33.3333%;\n}\n.outside-login-list .actived {\n    display: inline-block;\n}\n.outside-login-btn em {\n    display: block;\n    width: 50px;\n    height: 50px;\n    line-height: 50px;\n    border-radius: 50%;\n    margin: 0 auto 5px;\n    white-space: normal;\n    font-size: 20px;\n    color: #fff;\n}\n.outside-login-btn:first-child, .outside-login-btn:last-child {\n    width: 30.3333%;\n}\n.outside-login-btn span {\n    font-size: 14px;\n    color: #333;\n}\n.oschina em{\n\tbackground-color: #4ec34d;\n}\n.git em{\n\tbackground-color: #211b1b;\n}\n.my em{\n\tbackground-color: #ff4700\n}\n@media screen and (max-width: 768px) {\n    .signinpanel,\n    .signuppanel {\n        margin: 0 auto;\n        width: 413px!important;\n        padding: 20px;\n    }\n    .signinpanel form {\n        margin-top: 20px;\n    }\n    .signup-footer {\n        margin-bottom: 10px;\n    }\n    .signuppanel .form-control {\n        margin-bottom: 10px;\n    }\n    .signup-footer .pull-left,\n    .signup-footer .pull-right {\n        float: none !important;\n        text-align: center;\n    }\n    .signinpanel .signin-info ul {\n        display: none;\n    }\n}\n@media screen and (max-width: 320px) {\n    .signinpanel,\n    .signuppanel {\n        margin:0 20px;\n        width:auto;\n    }\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css",
    "content": ".checkbox {\n  padding-left: 20px;\n}\n.checkbox label {\n  display: inline-block;\n  vertical-align: middle;\n  position: relative;\n  padding-left: 5px;\n}\n.checkbox label::before {\n  content: \"\";\n  display: inline-block;\n  position: absolute;\n  width: 17px;\n  height: 17px;\n  left: 0;\n  margin-left: -20px;\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.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: -20px;\n  padding-left: 3px;\n  padding-top: 1px;\n  font-size: 11px;\n  color: #555555;\n}\n.checkbox input[type=\"checkbox\"],\n.checkbox input[type=\"radio\"] {\n  opacity: 0;\n  z-index: 1;\n}\n.checkbox input[type=\"checkbox\"]:focus + label::before,\n.checkbox input[type=\"radio\"]:focus + label::before {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.checkbox input[type=\"checkbox\"]:checked + label::after,\n.checkbox input[type=\"radio\"]:checked + label::after {\n  font-family: \"FontAwesome\";\n  content: \"\\f00c\";\n}\n.checkbox input[type=\"checkbox\"]:disabled + label,\n.checkbox input[type=\"radio\"]:disabled + label {\n  opacity: 0.65;\n}\n.checkbox input[type=\"checkbox\"]:disabled + label::before,\n.checkbox input[type=\"radio\"]:disabled + label::before {\n  background-color: #eeeeee;\n  cursor: not-allowed;\n}\n.checkbox.checkbox-circle label::before {\n  border-radius: 50%;\n}\n.checkbox.checkbox-inline {\n  margin-top: 0;\n}\n\n.checkbox-primary input[type=\"checkbox\"]:checked + label::before,\n.checkbox-primary input[type=\"radio\"]:checked + label::before {\n  background-color: #337ab7;\n  border-color: #337ab7;\n}\n.checkbox-primary input[type=\"checkbox\"]:checked + label::after,\n.checkbox-primary input[type=\"radio\"]:checked + label::after {\n  color: #fff;\n}\n\n.checkbox-danger input[type=\"checkbox\"]:checked + label::before,\n.checkbox-danger input[type=\"radio\"]:checked + label::before {\n  background-color: #d9534f;\n  border-color: #d9534f;\n}\n.checkbox-danger input[type=\"checkbox\"]:checked + label::after,\n.checkbox-danger input[type=\"radio\"]:checked + label::after {\n  color: #fff;\n}\n\n.checkbox-info input[type=\"checkbox\"]:checked + label::before,\n.checkbox-info input[type=\"radio\"]:checked + label::before {\n  background-color: #5bc0de;\n  border-color: #5bc0de;\n}\n.checkbox-info input[type=\"checkbox\"]:checked + label::after,\n.checkbox-info input[type=\"radio\"]:checked + label::after {\n  color: #fff;\n}\n\n.checkbox-warning input[type=\"checkbox\"]:checked + label::before,\n.checkbox-warning input[type=\"radio\"]:checked + label::before {\n  background-color: #f0ad4e;\n  border-color: #f0ad4e;\n}\n.checkbox-warning input[type=\"checkbox\"]:checked + label::after,\n.checkbox-warning input[type=\"radio\"]:checked + label::after {\n  color: #fff;\n}\n\n.checkbox-success input[type=\"checkbox\"]:checked + label::before,\n.checkbox-success input[type=\"radio\"]:checked + label::before {\n  background-color: #5cb85c;\n  border-color: #5cb85c;\n}\n.checkbox-success input[type=\"checkbox\"]:checked + label::after,\n.checkbox-success input[type=\"radio\"]:checked + label::after {\n  color: #fff;\n}\n\n.radio {\n  padding-left: 20px;\n}\n.radio label {\n  display: inline-block;\n  vertical-align: middle;\n  position: relative;\n  padding-left: 5px;\n}\n.radio label::before {\n  content: \"\";\n  display: inline-block;\n  position: absolute;\n  width: 17px;\n  height: 17px;\n  left: 0;\n  margin-left: -20px;\n  border: 1px solid #cccccc;\n  border-radius: 50%;\n  background-color: #fff;\n  -webkit-transition: border 0.15s ease-in-out;\n  -o-transition: border 0.15s ease-in-out;\n  transition: border 0.15s ease-in-out;\n}\n.radio label::after {\n  display: inline-block;\n  position: absolute;\n  content: \" \";\n  width: 11px;\n  height: 11px;\n  left: 3px;\n  top: 3px;\n  margin-left: -20px;\n  border-radius: 50%;\n  background-color: #555555;\n  -webkit-transform: scale(0, 0);\n  -ms-transform: scale(0, 0);\n  -o-transform: scale(0, 0);\n  transform: scale(0, 0);\n  -webkit-transition: -webkit-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);\n  -moz-transition: -moz-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);\n  -o-transition: -o-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);\n  transition: transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);\n}\n.radio input[type=\"radio\"] {\n  opacity: 0;\n  z-index: 1;\n}\n.radio input[type=\"radio\"]:focus + label::before {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.radio input[type=\"radio\"]:checked + label::after {\n  -webkit-transform: scale(1, 1);\n  -ms-transform: scale(1, 1);\n  -o-transform: scale(1, 1);\n  transform: scale(1, 1);\n}\n.radio input[type=\"radio\"]:disabled + label {\n  opacity: 0.65;\n}\n.radio input[type=\"radio\"]:disabled + label::before {\n  cursor: not-allowed;\n}\n.radio.radio-inline {\n  margin-top: 0;\n}\n\n.radio-primary input[type=\"radio\"] + label::after {\n  background-color: #337ab7;\n}\n.radio-primary input[type=\"radio\"]:checked + label::before {\n  border-color: #337ab7;\n}\n.radio-primary input[type=\"radio\"]:checked + label::after {\n  background-color: #337ab7;\n}\n\n.radio-danger input[type=\"radio\"] + label::after {\n  background-color: #d9534f;\n}\n.radio-danger input[type=\"radio\"]:checked + label::before {\n  border-color: #d9534f;\n}\n.radio-danger input[type=\"radio\"]:checked + label::after {\n  background-color: #d9534f;\n}\n\n.radio-info input[type=\"radio\"] + label::after {\n  background-color: #5bc0de;\n}\n.radio-info input[type=\"radio\"]:checked + label::before {\n  border-color: #5bc0de;\n}\n.radio-info input[type=\"radio\"]:checked + label::after {\n  background-color: #5bc0de;\n}\n\n.radio-warning input[type=\"radio\"] + label::after {\n  background-color: #f0ad4e;\n}\n.radio-warning input[type=\"radio\"]:checked + label::before {\n  border-color: #f0ad4e;\n}\n.radio-warning input[type=\"radio\"]:checked + label::after {\n  background-color: #f0ad4e;\n}\n\n.radio-success input[type=\"radio\"] + label::after {\n  background-color: #5cb85c;\n}\n.radio-success input[type=\"radio\"]:checked + label::before {\n  border-color: #5cb85c;\n}\n.radio-success input[type=\"radio\"]:checked + label::after {\n  background-color: #5cb85c;\n}\n\ninput[type=\"checkbox\"].styled:checked + label:after,\ninput[type=\"radio\"].styled:checked + label:after {\n  font-family: 'FontAwesome';\n  content: \"\\f00c\";\n}\ninput[type=\"checkbox\"] .styled:checked + label::before,\ninput[type=\"radio\"] .styled:checked + label::before {\n  color: #fff;\n}\ninput[type=\"checkbox\"] .styled:checked + label::after,\ninput[type=\"radio\"] .styled:checked + label::after {\n  color: #fff;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/blueimp/css/blueimp-gallery-indicator.css",
    "content": "@charset \"UTF-8\";\n/*\n * blueimp Gallery Indicator CSS 1.1.0\n * https://github.com/blueimp/Gallery\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n.blueimp-gallery > .indicator {\n  position: absolute;\n  top: auto;\n  right: 15px;\n  bottom: 15px;\n  left: 15px;\n  margin: 0 40px;\n  padding: 0;\n  list-style: none;\n  text-align: center;\n  line-height: 10px;\n  display: none;\n}\n.blueimp-gallery > .indicator > li {\n  display: inline-block;\n  width: 9px;\n  height: 9px;\n  margin: 6px 3px 0 3px;\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  border: 1px solid transparent;\n  background: #ccc;\n  background: rgba(255, 255, 255, 0.25) center no-repeat;\n  border-radius: 5px;\n  box-shadow: 0 0 2px #000;\n  opacity: 0.5;\n  cursor: pointer;\n}\n.blueimp-gallery > .indicator > li:hover,\n.blueimp-gallery > .indicator > .active {\n  background-color: #fff;\n  border-color: #fff;\n  opacity: 1;\n}\n.blueimp-gallery-controls > .indicator {\n  display: block;\n  /* Fix z-index issues (controls behind slide element) on Android: */\n  -webkit-transform: translateZ(0);\n     -moz-transform: translateZ(0);\n      -ms-transform: translateZ(0);\n       -o-transform: translateZ(0);\n          transform: translateZ(0);\n}\n.blueimp-gallery-single > .indicator {\n  display: none;\n}\n.blueimp-gallery > .indicator {\n  -webkit-user-select: none;\n   -khtml-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n}\n\n/* IE7 fixes */\n*+html .blueimp-gallery > .indicator > li {\n  display: inline;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/blueimp/css/blueimp-gallery-video.css",
    "content": "@charset \"UTF-8\";\n/*\n * blueimp Gallery Video Factory CSS 1.3.0\n * https://github.com/blueimp/Gallery\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n.blueimp-gallery > .slides > .slide > .video-content > img {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  margin: auto;\n  width: auto;\n  height: auto;\n  max-width: 100%;\n  max-height: 100%;\n  /* Prevent artifacts in Mozilla Firefox: */\n  -moz-backface-visibility: hidden;\n}\n.blueimp-gallery > .slides > .slide > .video-content > video {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n.blueimp-gallery > .slides > .slide > .video-content > iframe {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: none;\n}\n.blueimp-gallery > .slides > .slide > .video-playing > iframe {\n  top: 0;\n}\n.blueimp-gallery > .slides > .slide > .video-content > a {\n  position: absolute;\n  top: 50%;\n  right: 0;\n  left: 0;\n  margin: -64px auto 0;\n  width: 128px;\n  height: 128px;\n  background: url(../img/video-play.png) center no-repeat;\n  opacity: 0.8;\n  cursor: pointer;\n}\n.blueimp-gallery > .slides > .slide > .video-content > a:hover {\n  opacity: 1;\n}\n.blueimp-gallery > .slides > .slide > .video-playing > a,\n.blueimp-gallery > .slides > .slide > .video-playing > img {\n  display: none;\n}\n.blueimp-gallery > .slides > .slide > .video-content > video {\n  display: none;\n}\n.blueimp-gallery > .slides > .slide > .video-playing > video {\n  display: block;\n}\n.blueimp-gallery > .slides > .slide > .video-loading > a {\n  background: url(../img/loading.gif) center no-repeat;\n  background-size: 64px 64px;\n}\n\n/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */\nbody:last-child .blueimp-gallery > .slides > .slide > .video-content:not(.video-loading) > a {\n  background-image: url(../img/video-play.svg);\n}\n\n/* IE7 fixes */\n*+html .blueimp-gallery > .slides > .slide > .video-content {\n  height: 100%;\n}\n*+html .blueimp-gallery > .slides > .slide > .video-content > a {\n  left: 50%;\n  margin-left: -64px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/blueimp/css/blueimp-gallery.css",
    "content": "@charset \"UTF-8\";\n/*\n * blueimp Gallery CSS 2.11.1\n * https://github.com/blueimp/Gallery\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n.blueimp-gallery,\n.blueimp-gallery > .slides > .slide > .slide-content {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  /* Prevent artifacts in Mozilla Firefox: */\n  -moz-backface-visibility: hidden;\n}\n.blueimp-gallery > .slides > .slide > .slide-content {\n  margin: auto;\n  width: auto;\n  height: auto;\n  max-width: 100%;\n  max-height: 100%;\n  opacity: 1;\n}\n.blueimp-gallery {\n  position: fixed;\n  z-index: 999999;\n  overflow: hidden;\n  background: #000;\n  background: rgba(0, 0, 0, 0.9);\n  opacity: 0;\n  display: none;\n  direction: ltr;\n  -ms-touch-action: none;\n  touch-action: none;\n}\n.blueimp-gallery-carousel {\n  position: relative;\n  z-index: auto;\n  margin: 1em auto;\n  /* Set the carousel width/height ratio to 16/9: */\n  padding-bottom: 56.25%;\n  box-shadow: 0 0 10px #000;\n  -ms-touch-action: pan-y;\n  touch-action: pan-y;\n}\n.blueimp-gallery-display {\n  display: block;\n  opacity: 1;\n}\n.blueimp-gallery > .slides {\n  position: relative;\n  height: 100%;\n  overflow: hidden;\n}\n.blueimp-gallery-carousel > .slides {\n  position: absolute;\n}\n.blueimp-gallery > .slides > .slide {\n  position: relative;\n  float: left;\n  height: 100%;\n  text-align: center;\n  -webkit-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);\n     -moz-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);\n      -ms-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);\n       -o-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);\n          transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);\n}\n.blueimp-gallery,\n.blueimp-gallery > .slides > .slide > .slide-content {\n  -webkit-transition: opacity 0.5s linear;\n     -moz-transition: opacity 0.5s linear;\n      -ms-transition: opacity 0.5s linear;\n       -o-transition: opacity 0.5s linear;\n          transition: opacity 0.5s linear;\n}\n.blueimp-gallery > .slides > .slide-loading {\n  background: url(../img/loading.gif) center no-repeat;\n  background-size: 64px 64px;\n}\n.blueimp-gallery > .slides > .slide-loading > .slide-content {\n  opacity: 0;\n}\n.blueimp-gallery > .slides > .slide-error {\n  background: url(../img/error.png) center no-repeat;\n}\n.blueimp-gallery > .slides > .slide-error > .slide-content {\n  display: none;\n}\n.blueimp-gallery > .prev,\n.blueimp-gallery > .next {\n  position: absolute;\n  top: 50%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -23px;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #fff;\n  text-decoration: none;\n  text-shadow: 0 0 2px #000;\n  text-align: center;\n  background: #222;\n  background: rgba(0, 0, 0, 0.5);\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  border: 3px solid #fff;\n  -webkit-border-radius: 23px;\n     -moz-border-radius: 23px;\n          border-radius: 23px;\n  opacity: 0.5;\n  cursor: pointer;\n  display: none;\n}\n.blueimp-gallery > .next {\n  left: auto;\n  right: 15px;\n}\n.blueimp-gallery > .close,\n.blueimp-gallery > .title {\n  position: absolute;\n  top: 15px;\n  left: 15px;\n  margin: 0 40px 0 0;\n  font-size: 20px;\n  line-height: 30px;\n  color: #fff;\n  text-shadow: 0 0 2px #000;\n  opacity: 0.8;\n  display: none;\n}\n.blueimp-gallery > .close {\n  padding: 15px;\n  right: 15px;\n  left: auto;\n  margin: -15px;\n  font-size: 30px;\n  text-decoration: none;\n  cursor: pointer;\n}\n.blueimp-gallery > .play-pause {\n  position: absolute;\n  right: 15px;\n  bottom: 15px;\n  width: 15px;\n  height: 15px;\n  background: url(../img/play-pause.png) 0 0 no-repeat;\n  cursor: pointer;\n  opacity: 0.5;\n  display: none;\n}\n.blueimp-gallery-playing > .play-pause {\n  background-position: -15px 0;\n}\n.blueimp-gallery > .prev:hover,\n.blueimp-gallery > .next:hover,\n.blueimp-gallery > .close:hover,\n.blueimp-gallery > .title:hover,\n.blueimp-gallery > .play-pause:hover {\n  color: #fff;\n  opacity: 1;\n}\n.blueimp-gallery-controls > .prev,\n.blueimp-gallery-controls > .next,\n.blueimp-gallery-controls > .close,\n.blueimp-gallery-controls > .title,\n.blueimp-gallery-controls > .play-pause {\n  display: block;\n  /* Fix z-index issues (controls behind slide element) on Android: */\n  -webkit-transform: translateZ(0);\n     -moz-transform: translateZ(0);\n      -ms-transform: translateZ(0);\n       -o-transform: translateZ(0);\n          transform: translateZ(0);\n}\n.blueimp-gallery-single > .prev,\n.blueimp-gallery-left > .prev,\n.blueimp-gallery-single > .next,\n.blueimp-gallery-right > .next,\n.blueimp-gallery-single > .play-pause {\n  display: none;\n}\n.blueimp-gallery > .slides > .slide > .slide-content,\n.blueimp-gallery > .prev,\n.blueimp-gallery > .next,\n.blueimp-gallery > .close,\n.blueimp-gallery > .play-pause {\n  -webkit-user-select: none;\n   -khtml-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n}\n\n/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */\nbody:last-child .blueimp-gallery > .slides > .slide-error {\n  background-image: url(../img/error.svg);\n}\nbody:last-child .blueimp-gallery > .play-pause {\n  width: 20px;\n  height: 20px;\n  background-size: 40px 20px;\n  background-image: url(../img/play-pause.svg);\n}\nbody:last-child .blueimp-gallery-playing > .play-pause {\n  background-position: -20px 0;\n}\n\n/* IE7 fixes */\n*+html .blueimp-gallery > .slides > .slide {\n  min-height: 300px;\n}\n*+html .blueimp-gallery > .slides > .slide > .slide-content {\n  position: relative;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/blueimp/css/demo.css",
    "content": "/*\n * blueimp Gallery Demo CSS 2.0.0\n * https://github.com/blueimp/Gallery\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\nbody {\n  max-width: 750px;\n  margin: 0 auto;\n  padding: 1em;\n  font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, sans-serif;\n  font-size: 1em;\n  line-height: 1.4em;\n  background: #222;\n  color: #fff;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\na {\n  color: orange;\n  text-decoration: none;\n}\nimg {\n  border: 0;\n  vertical-align: middle;\n}\nh1 {\n  line-height: 1em;\n}\nh2,\n.links {\n  text-align: center;\n}\n\n@media (min-width: 481px) {\n  .navigation {\n    list-style: none;\n    padding: 0;\n  }\n  .navigation li {\n    display: inline-block;\n  }\n  .navigation li:not(:first-child):before {\n    content: '| ';\n  }\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/chosen/chosen.css",
    "content": "/*!\nChosen, a Select Box Enhancer for jQuery and Prototype\nby Patrick Filler for Harvest, http://getharvest.com\n\nVersion 1.1.0\nFull source at https://github.com/harvesthq/chosen\nCopyright (c) 2011 Harvest http://getharvest.com\n\nMIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md\nThis file is generated by `grunt build`, do not edit it by hand.\n*/\n\n/* @group Base */\n.chosen-container {\n    position: relative;\n    display: inline-block;\n    vertical-align: middle;\n    font-size: 13px;\n    zoom: 1;\n    *display: inline;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n}\n.chosen-container .chosen-drop {\n    position: absolute;\n    top: 100%;\n    left: -9999px;\n    z-index: 1010;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    width: 100%;\n    border: 1px solid #aaa;\n    border-top: 0;\n    background: #fff;\n    box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);\n}\n.chosen-container.chosen-with-drop .chosen-drop {\n    left: 0;\n}\n.chosen-container a {\n    cursor: pointer;\n}\n\n/* @end */\n/* @group Single Chosen */\n.chosen-container-single .chosen-single {\n    position: relative;\n    display: block;\n    overflow: hidden;\n    padding: 0 0 0 8px;\n    height: 23px;\n    border: 1px solid #aaa;\n    border-radius: 5px;\n    background-color: #fff;\n    background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));\n    background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);\n    background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);\n    background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);\n    background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);\n    background-clip: padding-box;\n    box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);\n    color: #444;\n    text-decoration: none;\n    white-space: nowrap;\n    line-height: 24px;\n}\n.chosen-container-single .chosen-default {\n    color: #999;\n}\n.chosen-container-single .chosen-single span {\n    display: block;\n    overflow: hidden;\n    margin-right: 26px;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n.chosen-container-single .chosen-single-with-deselect span {\n    margin-right: 38px;\n}\n.chosen-container-single .chosen-single abbr {\n    position: absolute;\n    top: 6px;\n    right: 26px;\n    display: block;\n    width: 12px;\n    height: 12px;\n    background: url('chosen-sprite.png') -42px 1px no-repeat;\n    font-size: 1px;\n}\n.chosen-container-single .chosen-single abbr:hover {\n    background-position: -42px -10px;\n}\n.chosen-container-single.chosen-disabled .chosen-single abbr:hover {\n    background-position: -42px -10px;\n}\n.chosen-container-single .chosen-single div {\n    position: absolute;\n    top: 0;\n    right: 0;\n    display: block;\n    width: 18px;\n    height: 100%;\n}\n.chosen-container-single .chosen-single div b {\n    display: block;\n    width: 100%;\n    height: 100%;\n    background: url('chosen-sprite.png') no-repeat 0px 7px;\n}\n.chosen-container-single .chosen-search {\n    position: relative;\n    z-index: 1010;\n    margin: 0;\n    padding: 3px 4px;\n    white-space: nowrap;\n}\n.chosen-container-single .chosen-search input[type=\"text\"] {\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    margin: 1px 0;\n    padding: 4px 20px 4px 5px;\n    width: 100%;\n    height: auto;\n    outline: 0;\n    border: 1px solid #aaa;\n    background: white url('chosen-sprite.png') no-repeat 100% -20px;\n    background: url('chosen-sprite.png') no-repeat 100% -20px;\n    font-size: 1em;\n    font-family: sans-serif;\n    line-height: normal;\n    border-radius: 0;\n}\n.chosen-container-single .chosen-drop {\n    margin-top: -1px;\n    border-radius: 0 0 4px 4px;\n    background-clip: padding-box;\n}\n.chosen-container-single.chosen-container-single-nosearch .chosen-search {\n    position: absolute;\n    left: -9999px;\n}\n\n/* @end */\n/* @group Results */\n.chosen-container .chosen-results {\n    position: relative;\n    overflow-x: hidden;\n    overflow-y: auto;\n    margin: 0 4px 4px 0;\n    padding: 0 0 0 4px;\n    max-height: 240px;\n    -webkit-overflow-scrolling: touch;\n}\n.chosen-container .chosen-results li {\n    display: none;\n    margin: 0;\n    padding: 5px 6px;\n    list-style: none;\n    line-height: 15px;\n    -webkit-touch-callout: none;\n}\n.chosen-container .chosen-results li.active-result {\n    display: list-item;\n    cursor: pointer;\n}\n.chosen-container .chosen-results li.disabled-result {\n    display: list-item;\n    color: #ccc;\n    cursor: default;\n}\n.chosen-container .chosen-results li.highlighted {\n    background-color: #3875d7;\n    background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));\n    background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);\n    background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);\n    background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);\n    background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);\n    color: #fff;\n}\n.chosen-container .chosen-results li.no-results {\n    display: list-item;\n    background: #f4f4f4;\n}\n.chosen-container .chosen-results li.group-result {\n    display: list-item;\n    font-weight: bold;\n    cursor: default;\n}\n.chosen-container .chosen-results li.group-option {\n    padding-left: 15px;\n}\n.chosen-container .chosen-results li em {\n    font-style: normal;\n    text-decoration: underline;\n}\n\n/* @end */\n/* @group Multi Chosen */\n.chosen-container-multi .chosen-choices {\n    -moz-box-sizing: border-box;\n    background-color: #FFFFFF;\n    border: 1px solid #CBD5DD;\n    border-radius: 2px;\n    cursor: text;\n    height: auto !important;\n    margin: 0;\n    min-height: 30px;\n    overflow: hidden;\n    padding: 2px;\n    position: relative;\n    width: 100%;\n}\n.chosen-container-multi .chosen-choices li {\n    float: left;\n    list-style: none;\n}\n.chosen-container-multi .chosen-choices li.search-field {\n    margin: 0;\n    padding: 0;\n    white-space: nowrap;\n}\n.chosen-container-multi .chosen-choices li.search-field input[type=\"text\"] {\n    margin: 1px 0;\n    padding: 5px;\n    height: 25px;\n    outline: 0;\n    border: 0 !important;\n    background: transparent !important;\n    box-shadow: none;\n    color: #666;\n    font-size: 100%;\n    font-family: sans-serif;\n    line-height: normal;\n    border-radius: 0;\n}\n.chosen-container-multi .chosen-choices li.search-field .default {\n    color: #999;\n}\n.chosen-container-multi .chosen-choices li.search-choice {\n    position: relative;\n    margin: 3px 0 3px 5px;\n    padding: 3px 20px 3px 5px;\n    border: 1px solid #aaa;\n    border-radius: 3px;\n    background-color: #e4e4e4;\n    background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));\n    background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-clip: padding-box;\n    box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);\n    color: #333;\n    line-height: 13px;\n    cursor: default;\n}\n.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {\n    position: absolute;\n    top: 4px;\n    right: 3px;\n    display: block;\n    width: 12px;\n    height: 12px;\n    background: url('chosen-sprite.png') -42px 1px no-repeat;\n    font-size: 1px;\n}\n.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {\n    background-position: -42px -10px;\n}\n.chosen-container-multi .chosen-choices li.search-choice-disabled {\n    padding-right: 5px;\n    border: 1px solid #ccc;\n    background-color: #e4e4e4;\n    background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));\n    background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);\n    color: #666;\n}\n.chosen-container-multi .chosen-choices li.search-choice-focus {\n    background: #d4d4d4;\n}\n.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {\n    background-position: -42px -10px;\n}\n.chosen-container-multi .chosen-results {\n    margin: 0;\n    padding: 0;\n}\n.chosen-container-multi .chosen-drop .result-selected {\n    display: list-item;\n    color: #ccc;\n    cursor: default;\n}\n\n/* @end */\n/* @group Active  */\n.chosen-container-active .chosen-single {\n    border: 1px solid #5897fb;\n    box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);\n}\n.chosen-container-active.chosen-with-drop .chosen-single {\n    border: 1px solid #aaa;\n    -moz-border-radius-bottomright: 0;\n    border-bottom-right-radius: 0;\n    -moz-border-radius-bottomleft: 0;\n    border-bottom-left-radius: 0;\n}\n.chosen-container-active.chosen-with-drop .chosen-single div {\n    border-left: none;\n    background: transparent;\n}\n.chosen-container-active.chosen-with-drop .chosen-single div b {\n    background-position: -18px 7px;\n}\n.chosen-container-active .chosen-choices {\n    border: 1px solid #5897fb;\n    box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);\n}\n.chosen-container-active .chosen-choices li.search-field input[type=\"text\"] {\n    color: #111 !important;\n}\n\n/* @end */\n/* @group Disabled Support */\n.chosen-disabled {\n    opacity: 0.5 !important;\n    cursor: default;\n}\n.chosen-disabled .chosen-single {\n    cursor: default;\n}\n.chosen-disabled .chosen-choices .search-choice .search-choice-close {\n    cursor: default;\n}\n\n/* @end */\n/* @group Right to Left */\n.chosen-rtl {\n    text-align: right;\n}\n.chosen-rtl .chosen-single {\n    overflow: visible;\n    padding: 0 8px 0 0;\n}\n.chosen-rtl .chosen-single span {\n    margin-right: 0;\n    margin-left: 26px;\n    direction: rtl;\n}\n.chosen-rtl .chosen-single-with-deselect span {\n    margin-left: 38px;\n}\n.chosen-rtl .chosen-single div {\n    right: auto;\n    left: 3px;\n}\n.chosen-rtl .chosen-single abbr {\n    right: auto;\n    left: 26px;\n}\n.chosen-rtl .chosen-choices li {\n    float: right;\n}\n.chosen-rtl .chosen-choices li.search-field input[type=\"text\"] {\n    direction: rtl;\n}\n.chosen-rtl .chosen-choices li.search-choice {\n    margin: 3px 5px 3px 0;\n    padding: 3px 5px 3px 19px;\n}\n.chosen-rtl .chosen-choices li.search-choice .search-choice-close {\n    right: auto;\n    left: 4px;\n}\n.chosen-rtl.chosen-container-single-nosearch .chosen-search,\n.chosen-rtl .chosen-drop {\n    left: 9999px;\n}\n.chosen-rtl.chosen-container-single .chosen-results {\n    margin: 0 0 4px 4px;\n    padding: 0 4px 0 0;\n}\n.chosen-rtl .chosen-results li.group-option {\n    padding-right: 15px;\n    padding-left: 0;\n}\n.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {\n    border-right: none;\n}\n.chosen-rtl .chosen-search input[type=\"text\"] {\n    padding: 4px 5px 4px 20px;\n    background: white url('chosen-sprite.png') no-repeat -30px -20px;\n    background: url('chosen-sprite.png') no-repeat -30px -20px;\n    direction: rtl;\n}\n.chosen-rtl.chosen-container-single .chosen-single div b {\n    background-position: 6px 2px;\n}\n.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {\n    background-position: -12px 2px;\n}\n\n/* @end */\n/* @group Retina compatibility */\n@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {\n    .chosen-rtl .chosen-search input[type=\"text\"],\n    .chosen-container-single .chosen-single abbr,\n    .chosen-container-single .chosen-single div b,\n    .chosen-container-single .chosen-search input[type=\"text\"],\n    .chosen-container-multi .chosen-choices .search-choice .search-choice-close,\n    .chosen-container .chosen-results-scroll-down span,\n    .chosen-container .chosen-results-scroll-up span {\n        background-image: url('chosen-sprite@2x.png') !important;\n        background-size: 52px 37px !important;\n        background-repeat: no-repeat !important;\n    }\n}\n/* @end */\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/clockpicker/clockpicker.css",
    "content": "/*!\n * ClockPicker v{package.version} for Bootstrap (http://weareoutman.github.io/clockpicker/)\n * Copyright 2014 Wang Shenwei.\n * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE)\n */\n\n.clockpicker .input-group-addon {\n\tcursor: pointer;\n}\n.clockpicker-moving {\n\tcursor: move;\n}\n.clockpicker-align-left.popover > .arrow {\n\tleft: 25px;\n}\n.clockpicker-align-top.popover > .arrow {\n\ttop: 17px;\n}\n.clockpicker-align-right.popover > .arrow {\n\tleft: auto;\n\tright: 25px;\n}\n.clockpicker-align-bottom.popover > .arrow {\n\ttop: auto;\n\tbottom: 6px;\n}\n.clockpicker-popover .popover-title {\n\tbackground-color: #fff;\n\tcolor: #999;\n\tfont-size: 24px;\n\tfont-weight: bold;\n\tline-height: 30px;\n\ttext-align: center;\n}\n.clockpicker-popover .popover-title span {\n\tcursor: pointer;\n}\n.clockpicker-popover .popover-content {\n\tbackground-color: #f8f8f8;\n\tpadding: 12px;\n}\n.popover-content:last-child {\n\tborder-bottom-left-radius: 5px;\n\tborder-bottom-right-radius: 5px;\n}\n.clockpicker-plate {\n\tbackground-color: #fff;\n\tborder: 1px solid #ccc;\n\tborder-radius: 50%;\n\twidth: 200px;\n\theight: 200px;\n\toverflow: visible;\n\tposition: relative;\n\t/* Disable text selection highlighting. Thanks to Hermanya */\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-khtml-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.clockpicker-canvas,\n.clockpicker-dial {\n\twidth: 200px;\n\theight: 200px;\n\tposition: absolute;\n\tleft: -1px;\n\ttop: -1px;\n}\n.clockpicker-minutes {\n\tvisibility: hidden;\n}\n.clockpicker-tick {\n\tborder-radius: 50%;\n\tcolor: #666;\n\tline-height: 26px;\n\ttext-align: center;\n\twidth: 26px;\n\theight: 26px;\n\tposition: absolute;\n\tcursor: pointer;\n}\n.clockpicker-tick.active,\n.clockpicker-tick:hover {\n\tbackground-color: rgb(192, 229, 247);\n\tbackground-color: rgba(0, 149, 221, .25);\n}\n.clockpicker-button {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\tborder-width: 1px 0 0;\n\tborder-top-left-radius: 0;\n\tborder-top-right-radius: 0;\n\tmargin: 0;\n\tpadding: 10px 0;\n}\n.clockpicker-button:hover {\n\tbackground-image: none;\n\tbackground-color: #ebebeb;\n}\n.clockpicker-button:focus {\n\toutline: none!important;\n}\n.clockpicker-dial {\n\t-webkit-transition: -webkit-transform 350ms, opacity 350ms;\n\t-moz-transition: -moz-transform 350ms, opacity 350ms;\n\t-ms-transition: -ms-transform 350ms, opacity 350ms;\n\t-o-transition: -o-transform 350ms, opacity 350ms;\n\ttransition: transform 350ms, opacity 350ms;\n}\n.clockpicker-dial-out {\n\topacity: 0;\n}\n.clockpicker-hours.clockpicker-dial-out {\n\t-webkit-transform: scale(1.2, 1.2);\n\t-moz-transform: scale(1.2, 1.2);\n\t-ms-transform: scale(1.2, 1.2);\n\t-o-transform: scale(1.2, 1.2);\n\ttransform: scale(1.2, 1.2);\n}\n.clockpicker-minutes.clockpicker-dial-out {\n\t-webkit-transform: scale(.8, .8);\n\t-moz-transform: scale(.8, .8);\n\t-ms-transform: scale(.8, .8);\n\t-o-transform: scale(.8, .8);\n\ttransform: scale(.8, .8);\n}\n.clockpicker-canvas {\n\t-webkit-transition: opacity 175ms;\n\t-moz-transition: opacity 175ms;\n\t-ms-transition: opacity 175ms;\n\t-o-transition: opacity 175ms;\n\ttransition: opacity 175ms;\n}\n.clockpicker-canvas-out {\n\topacity: 0.25;\n}\n.clockpicker-canvas-bearing,\n.clockpicker-canvas-fg {\n\tstroke: none;\n\tfill: rgb(0, 149, 221);\n}\n.clockpicker-canvas-bg {\n\tstroke: none;\n\tfill: rgb(192, 229, 247);\n}\n.clockpicker-canvas-bg-trans {\n\tfill: rgba(0, 149, 221, .25);\n}\n.clockpicker-canvas line {\n\tstroke: rgb(0, 149, 221);\n\tstroke-width: 1;\n\tstroke-linecap: round;\n\t/*shape-rendering: crispEdges;*/\n}\n.clockpicker-button.am-button {\n\tmargin: 1px;\n\tpadding: 5px;\n\tborder: 1px solid rgba(0, 0, 0, .2);\n\tborder-radius: 4px;\n\n}\n.clockpicker-button.pm-button {\n\tmargin: 1px 1px 1px 136px;\n\tpadding: 5px;\n\tborder: 1px solid rgba(0, 0, 0, .2);\n\tborder-radius: 4px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/codemirror/ambiance.css",
    "content": "/* ambiance theme for codemirror */\n\n/* Color scheme */\n\n.cm-s-ambiance .cm-keyword { color: #cda869; }\n.cm-s-ambiance .cm-atom { color: #CF7EA9; }\n.cm-s-ambiance .cm-number { color: #78CF8A; }\n.cm-s-ambiance .cm-def { color: #aac6e3; }\n.cm-s-ambiance .cm-variable { color: #ffb795; }\n.cm-s-ambiance .cm-variable-2 { color: #eed1b3; }\n.cm-s-ambiance .cm-variable-3 { color: #faded3; }\n.cm-s-ambiance .cm-property { color: #eed1b3; }\n.cm-s-ambiance .cm-operator {color: #fa8d6a;}\n.cm-s-ambiance .cm-comment { color: #555; font-style:italic; }\n.cm-s-ambiance .cm-string { color: #8f9d6a; }\n.cm-s-ambiance .cm-string-2 { color: #9d937c; }\n.cm-s-ambiance .cm-meta { color: #D2A8A1; }\n.cm-s-ambiance .cm-qualifier { color: yellow; }\n.cm-s-ambiance .cm-builtin { color: #9999cc; }\n.cm-s-ambiance .cm-bracket { color: #24C2C7; }\n.cm-s-ambiance .cm-tag { color: #fee4ff }\n.cm-s-ambiance .cm-attribute {  color: #9B859D; }\n.cm-s-ambiance .cm-header {color: blue;}\n.cm-s-ambiance .cm-quote { color: #24C2C7; }\n.cm-s-ambiance .cm-hr { color: pink; }\n.cm-s-ambiance .cm-link { color: #F4C20B; }\n.cm-s-ambiance .cm-special { color: #FF9D00; }\n.cm-s-ambiance .cm-error { color: #AF2018; }\n\n.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }\n.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }\n\n.cm-s-ambiance .CodeMirror-selected {\n  background: rgba(255, 255, 255, 0.15);\n}\n.cm-s-ambiance.CodeMirror-focused .CodeMirror-selected {\n  background: rgba(255, 255, 255, 0.10);\n}\n\n/* Editor styling */\n\n.cm-s-ambiance.CodeMirror {\n  line-height: 1.40em;\n  color: #E6E1DC;\n  background-color: #202020;\n  -webkit-box-shadow: inset 0 0 10px black;\n  -moz-box-shadow: inset 0 0 10px black;\n  box-shadow: inset 0 0 10px black;\n}\n\n.cm-s-ambiance .CodeMirror-gutters {\n  background: #3D3D3D;\n  border-right: 1px solid #4D4D4D;\n  box-shadow: 0 10px 20px black;\n}\n\n.cm-s-ambiance .CodeMirror-linenumber {\n  text-shadow: 0px 1px 1px #4d4d4d;\n  color: #111;\n  padding: 0 5px;\n}\n\n.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }\n.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }\n\n.cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {\n  border-left: 1px solid #7991E8;\n}\n\n.cm-s-ambiance .CodeMirror-activeline-background {\n  background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);\n}\n\n.cm-s-ambiance.CodeMirror,\n.cm-s-ambiance .CodeMirror-gutters {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC\");\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/codemirror/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}\n.CodeMirror-scroll {\n  /* Set scrolling behaviour here */\n  overflow: auto;\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  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror div.CodeMirror-cursor {\n  border-left: 1px solid black;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n  border-left: 1px solid silver;\n}\n.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: #7e7;\n}\n.CodeMirror.cm-keymap-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}\n@-moz-keyframes blink {\n  0% { background: #7e7; }\n  50% { background: none; }\n  100% { background: #7e7; }\n}\n@-webkit-keyframes blink {\n  0% { background: #7e7; }\n  50% { background: none; }\n  100% { background: #7e7; }\n}\n@keyframes blink {\n  0% { background: #7e7; }\n  50% { background: none; }\n  100% { background: #7e7; }\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\ndiv.CodeMirror-overwrite div.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-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-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\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\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\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  line-height: 1;\n  position: relative;\n  overflow: hidden;\n  background: white;\n  color: black;\n}\n\n.CodeMirror-scroll {\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  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n.CodeMirror-sizer {\n  position: relative;\n  border-right: 30px solid transparent;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n   before actuall 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  padding-bottom: 30px;\n  z-index: 3;\n}\n.CodeMirror-gutter {\n  white-space: normal;\n  height: 100%;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  padding-bottom: 30px;\n  margin-bottom: -32px;\n  display: inline-block;\n  /* Hack to make IE7 behave */\n  *zoom:1;\n  *display:inline;\n}\n.CodeMirror-gutter-elt {\n  position: absolute;\n  cursor: default;\n  z-index: 4;\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}\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-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror-measure {\n  position: absolute;\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  visibility: hidden;\n}\n.CodeMirror-measure pre { position: static; }\n\n.CodeMirror div.CodeMirror-cursor {\n  position: absolute;\n  border-right: none;\n  width: 0;\n}\n\ndiv.CodeMirror-cursors {\n  visibility: hidden;\n  position: relative;\n  z-index: 3;\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\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/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/cropper/cropper.css",
    "content": "/*!\n * Cropper v0.9.2\n * https://github.com/fengyuanchen/cropper\n *\n * Copyright (c) 2014-2015 Fengyuan Chen and contributors\n * Released under the MIT license\n *\n * Date: 2015-04-18T04:35:01.500Z\n */\n.cropper-container {\n  position: relative;\n  overflow: hidden;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n\n  -webkit-tap-highlight-color: transparent;\n  -webkit-touch-callout: none;\n}\n.cropper-container img {\n  display: block;\n  width: 100%;\n  min-width: 0 !important;\n  max-width: none !important;\n  height: 100%;\n  min-height: 0 !important;\n  max-height: none !important;\n\n  image-orientation: 0deg !important;\n}\n.cropper-canvas,\n.cropper-drag-box,\n.cropper-crop-box,\n.cropper-modal {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n}\n.cropper-drag-box {\n  background-color: #fff;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.cropper-modal {\n  background-color: #000;\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\n.cropper-view-box {\n  display: block;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  outline: 1px solid #69f;\n  outline-color: rgba(102, 153, 255, .75);\n}\n.cropper-dashed {\n  position: absolute;\n  display: block;\n  filter: alpha(opacity=50);\n  border: 0 dashed #fff;\n  opacity: .5;\n}\n.cropper-dashed.dashed-h {\n  top: 33.33333333%;\n  left: 0;\n  width: 100%;\n  height: 33.33333333%;\n  border-top-width: 1px;\n  border-bottom-width: 1px;\n}\n.cropper-dashed.dashed-v {\n  top: 0;\n  left: 33.33333333%;\n  width: 33.33333333%;\n  height: 100%;\n  border-right-width: 1px;\n  border-left-width: 1px;\n}\n.cropper-face,\n.cropper-line,\n.cropper-point {\n  position: absolute;\n  display: block;\n  width: 100%;\n  height: 100%;\n  filter: alpha(opacity=10);\n  opacity: .1;\n}\n.cropper-face {\n  top: 0;\n  left: 0;\n  cursor: move;\n  background-color: #fff;\n}\n.cropper-line {\n  background-color: #69f;\n}\n.cropper-line.line-e {\n  top: 0;\n  right: -3px;\n  width: 5px;\n  cursor: e-resize;\n}\n.cropper-line.line-n {\n  top: -3px;\n  left: 0;\n  height: 5px;\n  cursor: n-resize;\n}\n.cropper-line.line-w {\n  top: 0;\n  left: -3px;\n  width: 5px;\n  cursor: w-resize;\n}\n.cropper-line.line-s {\n  bottom: -3px;\n  left: 0;\n  height: 5px;\n  cursor: s-resize;\n}\n.cropper-point {\n  width: 5px;\n  height: 5px;\n  background-color: #69f;\n  filter: alpha(opacity=75);\n  opacity: .75;\n}\n.cropper-point.point-e {\n  top: 50%;\n  right: -3px;\n  margin-top: -3px;\n  cursor: e-resize;\n}\n.cropper-point.point-n {\n  top: -3px;\n  left: 50%;\n  margin-left: -3px;\n  cursor: n-resize;\n}\n.cropper-point.point-w {\n  top: 50%;\n  left: -3px;\n  margin-top: -3px;\n  cursor: w-resize;\n}\n.cropper-point.point-s {\n  bottom: -3px;\n  left: 50%;\n  margin-left: -3px;\n  cursor: s-resize;\n}\n.cropper-point.point-ne {\n  top: -3px;\n  right: -3px;\n  cursor: ne-resize;\n}\n.cropper-point.point-nw {\n  top: -3px;\n  left: -3px;\n  cursor: nw-resize;\n}\n.cropper-point.point-sw {\n  bottom: -3px;\n  left: -3px;\n  cursor: sw-resize;\n}\n.cropper-point.point-se {\n  right: -3px;\n  bottom: -3px;\n  width: 20px;\n  height: 20px;\n  cursor: se-resize;\n  filter: alpha(opacity=100);\n  opacity: 1;\n}\n.cropper-point.point-se:before {\n  position: absolute;\n  right: -50%;\n  bottom: -50%;\n  display: block;\n  width: 200%;\n  height: 200%;\n  content: \" \";\n  background-color: #69f;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n@media (min-width: 768px) {\n  .cropper-point.point-se {\n    width: 15px;\n    height: 15px;\n  }\n}\n@media (min-width: 992px) {\n  .cropper-point.point-se {\n    width: 10px;\n    height: 10px;\n  }\n}\n@media (min-width: 1200px) {\n  .cropper-point.point-se {\n    width: 5px;\n    height: 5px;\n    filter: alpha(opacity=75);\n    opacity: .75;\n  }\n}\n.cropper-bg {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC\");\n}\n.cropper-invisible {\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.cropper-hide {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: -1;\n  width: auto!important;\n  min-width: 0!important;\n  max-width: none!important;\n  height: auto!important;\n  min-height: 0!important;\n  max-height: none!important;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.cropper-hidden {\n  display: none !important;\n}\n.cropper-move {\n  cursor: move;\n}\n.cropper-crop {\n  cursor: crosshair;\n}\n.cropper-disabled .cropper-drag-box,\n.cropper-disabled .cropper-face,\n.cropper-disabled .cropper-line,\n.cropper-disabled .cropper-point {\n  cursor: not-allowed;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/dataTables/dataTables.bootstrap.css",
    "content": "div.dataTables_length label {\n    float: left;\n    text-align: left;\n    font-weight: normal;\n}\n\ndiv.dataTables_length select {\n    width: 75px;\n}\n\ndiv.dataTables_filter label {\n    float: right;\n    font-weight: normal;\n}\n\ndiv.dataTables_filter input {\n    width: 16em;\n}\n\ndiv.dataTables_info {\n    padding-top: 8px;\n}\n\ndiv.dataTables_paginate {\n    float: right;\n    margin: 0;\n}\n\ndiv.dataTables_paginate ul.pagination {\n    margin: 2px 0;\n    white-space: nowrap;\n}\n\ntable.dataTable,\ntable.dataTable td,\ntable.dataTable th {\n    -webkit-box-sizing: content-box;\n    -moz-box-sizing: content-box;\n    box-sizing: content-box;\n}\n\ntable.dataTable {\n    clear: both;\n    margin-top: 6px !important;\n    margin-bottom: 6px !important;\n    max-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    cursor: pointer;\n}\n\ntable.dataTable thead .sorting {\n\n}\n\ntable.dataTable thead .sorting_asc {\n    background: url('../images/sort_asc.png') no-repeat center right;\n}\n\ntable.dataTable thead .sorting_desc {\n    background: url('../images/sort_desc.png') no-repeat center right;\n}\n\ntable.dataTable thead .sorting_asc_disabled {\n}\n\ntable.dataTable thead .sorting_desc_disabled {\n}\n\ntable.dataTable th:active {\n    outline: none;\n}\n\n/* Scrolling */\n\ndiv.dataTables_scrollHead table {\n    margin-bottom: 0 !important;\n    border-bottom-left-radius: 0;\n    border-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    border-bottom-left-radius: 0 !important;\n    border-bottom-right-radius: 0 !important;\n}\n\ndiv.dataTables_scrollBody table {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n    border-top: none;\n}\n\ndiv.dataTables_scrollBody tbody tr:first-child th,\ndiv.dataTables_scrollBody tbody tr:first-child td {\n    border-top: none;\n}\n\ndiv.dataTables_scrollFoot table {\n    margin-top: 0 !important;\n    border-top: none;\n}\n\n/*\n * TableTools styles\n */\n\n.table tbody tr.active td,\n.table tbody tr.active th {\n    color: white;\n    background-color: #08C;\n}\n\n.table tbody tr.active:hover td,\n.table tbody tr.active:hover th {\n    background-color: #0075b0 !important;\n}\n\n.table tbody tr.active a {\n    color: white;\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\ntable.DTTT_selectable tbody tr {\n    cursor: pointer;\n}\n\ndiv.DTTT .btn {\n    font-size: 12px;\n    color: #333 !important;\n}\n\ndiv.DTTT .btn:hover {\n    text-decoration: none !important;\n}\n\nul.DTTT_dropdown.dropdown-menu {\n    z-index: 2003;\n}\n\nul.DTTT_dropdown.dropdown-menu a {\n    color: #333 !important; /* needed only when demo_page.css is included */\n}\n\nul.DTTT_dropdown.dropdown-menu li {\n    position: relative;\n}\n\nul.DTTT_dropdown.dropdown-menu li:hover a {\n    color: white !important;\n    background-color: #0088cc;\n}\n\ndiv.DTTT_collection_background {\n    z-index: 2002;\n}\n\n/* TableTools information display */\n\ndiv.DTTT_print_info.modal {\n    height: 150px;\n    margin-top: -75px;\n    text-align: center;\n}\n\ndiv.DTTT_print_info h6 {\n    margin: 1em;\n    font-size: 28px;\n    font-weight: normal;\n    line-height: 28px;\n}\n\ndiv.DTTT_print_info p {\n    font-size: 14px;\n    line-height: 20px;\n}\n\n/*\n * FixedColumns styles\n */\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}\n\ndiv.DTFC_RightHeadWrapper table,\ndiv.DTFC_LeftHeadWrapper table {\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    margin-bottom: 0 !important;\n    border-top: none;\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}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/datapicker/datepicker3.css",
    "content": "/*!\n * Datepicker for Bootstrap\n *\n * Copyright 2012 Stefan Petre\n * Improvements by Andrew Rowls\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n */\n.datepicker {\n  padding: 4px;\n  border-radius: 4px;\n  direction: ltr;\n  /*.dow {\n\t\tborder-top: 1px solid #ddd !important;\n\t}*/\n}\n.datepicker-inline {\n  width: 220px;\n}\n.datepicker.datepicker-rtl {\n  direction: rtl;\n}\n.datepicker.datepicker-rtl table tr td span {\n  float: right;\n}\n.datepicker-dropdown {\n  top: 0;\n  left: 0;\n}\n.datepicker-dropdown:before {\n  content: '';\n  display: inline-block;\n  border-left: 7px solid transparent;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-top: 0;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  position: absolute;\n}\n.datepicker-dropdown:after {\n  content: '';\n  display: inline-block;\n  border-left: 6px solid transparent;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #fff;\n  border-top: 0;\n  position: absolute;\n}\n.datepicker-dropdown.datepicker-orient-left:before {\n  left: 6px;\n}\n.datepicker-dropdown.datepicker-orient-left:after {\n  left: 7px;\n}\n.datepicker-dropdown.datepicker-orient-right:before {\n  right: 6px;\n}\n.datepicker-dropdown.datepicker-orient-right:after {\n  right: 7px;\n}\n.datepicker-dropdown.datepicker-orient-top:before {\n  top: -7px;\n}\n.datepicker-dropdown.datepicker-orient-top:after {\n  top: -6px;\n}\n.datepicker-dropdown.datepicker-orient-bottom:before {\n  bottom: -7px;\n  border-bottom: 0;\n  border-top: 7px solid #999;\n}\n.datepicker-dropdown.datepicker-orient-bottom:after {\n  bottom: -6px;\n  border-bottom: 0;\n  border-top: 6px solid #fff;\n}\n.datepicker > div {\n  display: none;\n}\n.datepicker.days div.datepicker-days {\n  display: block;\n}\n.datepicker.months div.datepicker-months {\n  display: block;\n}\n.datepicker.years div.datepicker-years {\n  display: block;\n}\n.datepicker table {\n  margin: 0;\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.datepicker table tr td,\n.datepicker table tr th {\n  text-align: center;\n  width: 30px;\n  height: 30px;\n  border-radius: 4px;\n  border: none;\n}\n.table-striped .datepicker table tr td,\n.table-striped .datepicker table tr th {\n  background-color: transparent;\n}\n.datepicker table tr td.day:hover,\n.datepicker table tr td.day.focused {\n  background: #eeeeee;\n  cursor: pointer;\n}\n.datepicker table tr td.old,\n.datepicker table tr td.new {\n  color: #999999;\n}\n.datepicker table tr td.disabled,\n.datepicker table tr td.disabled:hover {\n  background: none;\n  color: #999999;\n  cursor: default;\n}\n.datepicker table tr td.today,\n.datepicker table tr td.today:hover,\n.datepicker table tr td.today.disabled,\n.datepicker table tr td.today.disabled:hover {\n  color: #000000;\n  background-color: #ffdb99;\n  border-color: #ffb733;\n}\n.datepicker table tr td.today:hover,\n.datepicker table tr td.today:hover:hover,\n.datepicker table tr td.today.disabled:hover,\n.datepicker table tr td.today.disabled:hover:hover,\n.datepicker table tr td.today:focus,\n.datepicker table tr td.today:hover:focus,\n.datepicker table tr td.today.disabled:focus,\n.datepicker table tr td.today.disabled:hover:focus,\n.datepicker table tr td.today:active,\n.datepicker table tr td.today:hover:active,\n.datepicker table tr td.today.disabled:active,\n.datepicker table tr td.today.disabled:hover:active,\n.datepicker table tr td.today.active,\n.datepicker table tr td.today:hover.active,\n.datepicker table tr td.today.disabled.active,\n.datepicker table tr td.today.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.today,\n.open .dropdown-toggle.datepicker table tr td.today:hover,\n.open .dropdown-toggle.datepicker table tr td.today.disabled,\n.open .dropdown-toggle.datepicker table tr td.today.disabled:hover {\n  color: #000000;\n  background-color: #ffcd70;\n  border-color: #f59e00;\n}\n.datepicker table tr td.today:active,\n.datepicker table tr td.today:hover:active,\n.datepicker table tr td.today.disabled:active,\n.datepicker table tr td.today.disabled:hover:active,\n.datepicker table tr td.today.active,\n.datepicker table tr td.today:hover.active,\n.datepicker table tr td.today.disabled.active,\n.datepicker table tr td.today.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.today,\n.open .dropdown-toggle.datepicker table tr td.today:hover,\n.open .dropdown-toggle.datepicker table tr td.today.disabled,\n.open .dropdown-toggle.datepicker table tr td.today.disabled:hover {\n  background-image: none;\n}\n.datepicker table tr td.today.disabled,\n.datepicker table tr td.today:hover.disabled,\n.datepicker table tr td.today.disabled.disabled,\n.datepicker table tr td.today.disabled:hover.disabled,\n.datepicker table tr td.today[disabled],\n.datepicker table tr td.today:hover[disabled],\n.datepicker table tr td.today.disabled[disabled],\n.datepicker table tr td.today.disabled:hover[disabled],\nfieldset[disabled] .datepicker table tr td.today,\nfieldset[disabled] .datepicker table tr td.today:hover,\nfieldset[disabled] .datepicker table tr td.today.disabled,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover,\n.datepicker table tr td.today.disabled:hover,\n.datepicker table tr td.today:hover.disabled:hover,\n.datepicker table tr td.today.disabled.disabled:hover,\n.datepicker table tr td.today.disabled:hover.disabled:hover,\n.datepicker table tr td.today[disabled]:hover,\n.datepicker table tr td.today:hover[disabled]:hover,\n.datepicker table tr td.today.disabled[disabled]:hover,\n.datepicker table tr td.today.disabled:hover[disabled]:hover,\nfieldset[disabled] .datepicker table tr td.today:hover,\nfieldset[disabled] .datepicker table tr td.today:hover:hover,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover:hover,\n.datepicker table tr td.today.disabled:focus,\n.datepicker table tr td.today:hover.disabled:focus,\n.datepicker table tr td.today.disabled.disabled:focus,\n.datepicker table tr td.today.disabled:hover.disabled:focus,\n.datepicker table tr td.today[disabled]:focus,\n.datepicker table tr td.today:hover[disabled]:focus,\n.datepicker table tr td.today.disabled[disabled]:focus,\n.datepicker table tr td.today.disabled:hover[disabled]:focus,\nfieldset[disabled] .datepicker table tr td.today:focus,\nfieldset[disabled] .datepicker table tr td.today:hover:focus,\nfieldset[disabled] .datepicker table tr td.today.disabled:focus,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover:focus,\n.datepicker table tr td.today.disabled:active,\n.datepicker table tr td.today:hover.disabled:active,\n.datepicker table tr td.today.disabled.disabled:active,\n.datepicker table tr td.today.disabled:hover.disabled:active,\n.datepicker table tr td.today[disabled]:active,\n.datepicker table tr td.today:hover[disabled]:active,\n.datepicker table tr td.today.disabled[disabled]:active,\n.datepicker table tr td.today.disabled:hover[disabled]:active,\nfieldset[disabled] .datepicker table tr td.today:active,\nfieldset[disabled] .datepicker table tr td.today:hover:active,\nfieldset[disabled] .datepicker table tr td.today.disabled:active,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover:active,\n.datepicker table tr td.today.disabled.active,\n.datepicker table tr td.today:hover.disabled.active,\n.datepicker table tr td.today.disabled.disabled.active,\n.datepicker table tr td.today.disabled:hover.disabled.active,\n.datepicker table tr td.today[disabled].active,\n.datepicker table tr td.today:hover[disabled].active,\n.datepicker table tr td.today.disabled[disabled].active,\n.datepicker table tr td.today.disabled:hover[disabled].active,\nfieldset[disabled] .datepicker table tr td.today.active,\nfieldset[disabled] .datepicker table tr td.today:hover.active,\nfieldset[disabled] .datepicker table tr td.today.disabled.active,\nfieldset[disabled] .datepicker table tr td.today.disabled:hover.active {\n  background-color: #ffdb99;\n  border-color: #ffb733;\n}\n.datepicker table tr td.today:hover:hover {\n  color: #000;\n}\n.datepicker table tr td.today.active:hover {\n  color: #fff;\n}\n.datepicker table tr td.range,\n.datepicker table tr td.range:hover,\n.datepicker table tr td.range.disabled,\n.datepicker table tr td.range.disabled:hover {\n  background: #eeeeee;\n  border-radius: 0;\n}\n.datepicker table tr td.range.today,\n.datepicker table tr td.range.today:hover,\n.datepicker table tr td.range.today.disabled,\n.datepicker table tr td.range.today.disabled:hover {\n  color: #000000;\n  background-color: #f7ca77;\n  border-color: #f1a417;\n  border-radius: 0;\n}\n.datepicker table tr td.range.today:hover,\n.datepicker table tr td.range.today:hover:hover,\n.datepicker table tr td.range.today.disabled:hover,\n.datepicker table tr td.range.today.disabled:hover:hover,\n.datepicker table tr td.range.today:focus,\n.datepicker table tr td.range.today:hover:focus,\n.datepicker table tr td.range.today.disabled:focus,\n.datepicker table tr td.range.today.disabled:hover:focus,\n.datepicker table tr td.range.today:active,\n.datepicker table tr td.range.today:hover:active,\n.datepicker table tr td.range.today.disabled:active,\n.datepicker table tr td.range.today.disabled:hover:active,\n.datepicker table tr td.range.today.active,\n.datepicker table tr td.range.today:hover.active,\n.datepicker table tr td.range.today.disabled.active,\n.datepicker table tr td.range.today.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.range.today,\n.open .dropdown-toggle.datepicker table tr td.range.today:hover,\n.open .dropdown-toggle.datepicker table tr td.range.today.disabled,\n.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover {\n  color: #000000;\n  background-color: #f4bb51;\n  border-color: #bf800c;\n}\n.datepicker table tr td.range.today:active,\n.datepicker table tr td.range.today:hover:active,\n.datepicker table tr td.range.today.disabled:active,\n.datepicker table tr td.range.today.disabled:hover:active,\n.datepicker table tr td.range.today.active,\n.datepicker table tr td.range.today:hover.active,\n.datepicker table tr td.range.today.disabled.active,\n.datepicker table tr td.range.today.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.range.today,\n.open .dropdown-toggle.datepicker table tr td.range.today:hover,\n.open .dropdown-toggle.datepicker table tr td.range.today.disabled,\n.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover {\n  background-image: none;\n}\n.datepicker table tr td.range.today.disabled,\n.datepicker table tr td.range.today:hover.disabled,\n.datepicker table tr td.range.today.disabled.disabled,\n.datepicker table tr td.range.today.disabled:hover.disabled,\n.datepicker table tr td.range.today[disabled],\n.datepicker table tr td.range.today:hover[disabled],\n.datepicker table tr td.range.today.disabled[disabled],\n.datepicker table tr td.range.today.disabled:hover[disabled],\nfieldset[disabled] .datepicker table tr td.range.today,\nfieldset[disabled] .datepicker table tr td.range.today:hover,\nfieldset[disabled] .datepicker table tr td.range.today.disabled,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover,\n.datepicker table tr td.range.today.disabled:hover,\n.datepicker table tr td.range.today:hover.disabled:hover,\n.datepicker table tr td.range.today.disabled.disabled:hover,\n.datepicker table tr td.range.today.disabled:hover.disabled:hover,\n.datepicker table tr td.range.today[disabled]:hover,\n.datepicker table tr td.range.today:hover[disabled]:hover,\n.datepicker table tr td.range.today.disabled[disabled]:hover,\n.datepicker table tr td.range.today.disabled:hover[disabled]:hover,\nfieldset[disabled] .datepicker table tr td.range.today:hover,\nfieldset[disabled] .datepicker table tr td.range.today:hover:hover,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover:hover,\n.datepicker table tr td.range.today.disabled:focus,\n.datepicker table tr td.range.today:hover.disabled:focus,\n.datepicker table tr td.range.today.disabled.disabled:focus,\n.datepicker table tr td.range.today.disabled:hover.disabled:focus,\n.datepicker table tr td.range.today[disabled]:focus,\n.datepicker table tr td.range.today:hover[disabled]:focus,\n.datepicker table tr td.range.today.disabled[disabled]:focus,\n.datepicker table tr td.range.today.disabled:hover[disabled]:focus,\nfieldset[disabled] .datepicker table tr td.range.today:focus,\nfieldset[disabled] .datepicker table tr td.range.today:hover:focus,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:focus,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover:focus,\n.datepicker table tr td.range.today.disabled:active,\n.datepicker table tr td.range.today:hover.disabled:active,\n.datepicker table tr td.range.today.disabled.disabled:active,\n.datepicker table tr td.range.today.disabled:hover.disabled:active,\n.datepicker table tr td.range.today[disabled]:active,\n.datepicker table tr td.range.today:hover[disabled]:active,\n.datepicker table tr td.range.today.disabled[disabled]:active,\n.datepicker table tr td.range.today.disabled:hover[disabled]:active,\nfieldset[disabled] .datepicker table tr td.range.today:active,\nfieldset[disabled] .datepicker table tr td.range.today:hover:active,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:active,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover:active,\n.datepicker table tr td.range.today.disabled.active,\n.datepicker table tr td.range.today:hover.disabled.active,\n.datepicker table tr td.range.today.disabled.disabled.active,\n.datepicker table tr td.range.today.disabled:hover.disabled.active,\n.datepicker table tr td.range.today[disabled].active,\n.datepicker table tr td.range.today:hover[disabled].active,\n.datepicker table tr td.range.today.disabled[disabled].active,\n.datepicker table tr td.range.today.disabled:hover[disabled].active,\nfieldset[disabled] .datepicker table tr td.range.today.active,\nfieldset[disabled] .datepicker table tr td.range.today:hover.active,\nfieldset[disabled] .datepicker table tr td.range.today.disabled.active,\nfieldset[disabled] .datepicker table tr td.range.today.disabled:hover.active {\n  background-color: #f7ca77;\n  border-color: #f1a417;\n}\n.datepicker table tr td.selected,\n.datepicker table tr td.selected:hover,\n.datepicker table tr td.selected.disabled,\n.datepicker table tr td.selected.disabled:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #555555;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td.selected:hover,\n.datepicker table tr td.selected:hover:hover,\n.datepicker table tr td.selected.disabled:hover,\n.datepicker table tr td.selected.disabled:hover:hover,\n.datepicker table tr td.selected:focus,\n.datepicker table tr td.selected:hover:focus,\n.datepicker table tr td.selected.disabled:focus,\n.datepicker table tr td.selected.disabled:hover:focus,\n.datepicker table tr td.selected:active,\n.datepicker table tr td.selected:hover:active,\n.datepicker table tr td.selected.disabled:active,\n.datepicker table tr td.selected.disabled:hover:active,\n.datepicker table tr td.selected.active,\n.datepicker table tr td.selected:hover.active,\n.datepicker table tr td.selected.disabled.active,\n.datepicker table tr td.selected.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.selected,\n.open .dropdown-toggle.datepicker table tr td.selected:hover,\n.open .dropdown-toggle.datepicker table tr td.selected.disabled,\n.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover {\n  color: #ffffff;\n  background-color: #858585;\n  border-color: #373737;\n}\n.datepicker table tr td.selected:active,\n.datepicker table tr td.selected:hover:active,\n.datepicker table tr td.selected.disabled:active,\n.datepicker table tr td.selected.disabled:hover:active,\n.datepicker table tr td.selected.active,\n.datepicker table tr td.selected:hover.active,\n.datepicker table tr td.selected.disabled.active,\n.datepicker table tr td.selected.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.selected,\n.open .dropdown-toggle.datepicker table tr td.selected:hover,\n.open .dropdown-toggle.datepicker table tr td.selected.disabled,\n.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover {\n  background-image: none;\n}\n.datepicker table tr td.selected.disabled,\n.datepicker table tr td.selected:hover.disabled,\n.datepicker table tr td.selected.disabled.disabled,\n.datepicker table tr td.selected.disabled:hover.disabled,\n.datepicker table tr td.selected[disabled],\n.datepicker table tr td.selected:hover[disabled],\n.datepicker table tr td.selected.disabled[disabled],\n.datepicker table tr td.selected.disabled:hover[disabled],\nfieldset[disabled] .datepicker table tr td.selected,\nfieldset[disabled] .datepicker table tr td.selected:hover,\nfieldset[disabled] .datepicker table tr td.selected.disabled,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover,\n.datepicker table tr td.selected.disabled:hover,\n.datepicker table tr td.selected:hover.disabled:hover,\n.datepicker table tr td.selected.disabled.disabled:hover,\n.datepicker table tr td.selected.disabled:hover.disabled:hover,\n.datepicker table tr td.selected[disabled]:hover,\n.datepicker table tr td.selected:hover[disabled]:hover,\n.datepicker table tr td.selected.disabled[disabled]:hover,\n.datepicker table tr td.selected.disabled:hover[disabled]:hover,\nfieldset[disabled] .datepicker table tr td.selected:hover,\nfieldset[disabled] .datepicker table tr td.selected:hover:hover,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover:hover,\n.datepicker table tr td.selected.disabled:focus,\n.datepicker table tr td.selected:hover.disabled:focus,\n.datepicker table tr td.selected.disabled.disabled:focus,\n.datepicker table tr td.selected.disabled:hover.disabled:focus,\n.datepicker table tr td.selected[disabled]:focus,\n.datepicker table tr td.selected:hover[disabled]:focus,\n.datepicker table tr td.selected.disabled[disabled]:focus,\n.datepicker table tr td.selected.disabled:hover[disabled]:focus,\nfieldset[disabled] .datepicker table tr td.selected:focus,\nfieldset[disabled] .datepicker table tr td.selected:hover:focus,\nfieldset[disabled] .datepicker table tr td.selected.disabled:focus,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover:focus,\n.datepicker table tr td.selected.disabled:active,\n.datepicker table tr td.selected:hover.disabled:active,\n.datepicker table tr td.selected.disabled.disabled:active,\n.datepicker table tr td.selected.disabled:hover.disabled:active,\n.datepicker table tr td.selected[disabled]:active,\n.datepicker table tr td.selected:hover[disabled]:active,\n.datepicker table tr td.selected.disabled[disabled]:active,\n.datepicker table tr td.selected.disabled:hover[disabled]:active,\nfieldset[disabled] .datepicker table tr td.selected:active,\nfieldset[disabled] .datepicker table tr td.selected:hover:active,\nfieldset[disabled] .datepicker table tr td.selected.disabled:active,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover:active,\n.datepicker table tr td.selected.disabled.active,\n.datepicker table tr td.selected:hover.disabled.active,\n.datepicker table tr td.selected.disabled.disabled.active,\n.datepicker table tr td.selected.disabled:hover.disabled.active,\n.datepicker table tr td.selected[disabled].active,\n.datepicker table tr td.selected:hover[disabled].active,\n.datepicker table tr td.selected.disabled[disabled].active,\n.datepicker table tr td.selected.disabled:hover[disabled].active,\nfieldset[disabled] .datepicker table tr td.selected.active,\nfieldset[disabled] .datepicker table tr td.selected:hover.active,\nfieldset[disabled] .datepicker table tr td.selected.disabled.active,\nfieldset[disabled] .datepicker table tr td.selected.disabled:hover.active {\n  background-color: #999999;\n  border-color: #555555;\n}\n.datepicker table tr td.active,\n.datepicker table tr td.active:hover,\n.datepicker table tr td.active.disabled,\n.datepicker table tr td.active.disabled:hover {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td.active:hover,\n.datepicker table tr td.active:hover:hover,\n.datepicker table tr td.active.disabled:hover,\n.datepicker table tr td.active.disabled:hover:hover,\n.datepicker table tr td.active:focus,\n.datepicker table tr td.active:hover:focus,\n.datepicker table tr td.active.disabled:focus,\n.datepicker table tr td.active.disabled:hover:focus,\n.datepicker table tr td.active:active,\n.datepicker table tr td.active:hover:active,\n.datepicker table tr td.active.disabled:active,\n.datepicker table tr td.active.disabled:hover:active,\n.datepicker table tr td.active.active,\n.datepicker table tr td.active:hover.active,\n.datepicker table tr td.active.disabled.active,\n.datepicker table tr td.active.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.active,\n.open .dropdown-toggle.datepicker table tr td.active:hover,\n.open .dropdown-toggle.datepicker table tr td.active.disabled,\n.open .dropdown-toggle.datepicker table tr td.active.disabled:hover {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.datepicker table tr td.active:active,\n.datepicker table tr td.active:hover:active,\n.datepicker table tr td.active.disabled:active,\n.datepicker table tr td.active.disabled:hover:active,\n.datepicker table tr td.active.active,\n.datepicker table tr td.active:hover.active,\n.datepicker table tr td.active.disabled.active,\n.datepicker table tr td.active.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td.active,\n.open .dropdown-toggle.datepicker table tr td.active:hover,\n.open .dropdown-toggle.datepicker table tr td.active.disabled,\n.open .dropdown-toggle.datepicker table tr td.active.disabled:hover {\n  background-image: none;\n}\n.datepicker table tr td.active.disabled,\n.datepicker table tr td.active:hover.disabled,\n.datepicker table tr td.active.disabled.disabled,\n.datepicker table tr td.active.disabled:hover.disabled,\n.datepicker table tr td.active[disabled],\n.datepicker table tr td.active:hover[disabled],\n.datepicker table tr td.active.disabled[disabled],\n.datepicker table tr td.active.disabled:hover[disabled],\nfieldset[disabled] .datepicker table tr td.active,\nfieldset[disabled] .datepicker table tr td.active:hover,\nfieldset[disabled] .datepicker table tr td.active.disabled,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover,\n.datepicker table tr td.active.disabled:hover,\n.datepicker table tr td.active:hover.disabled:hover,\n.datepicker table tr td.active.disabled.disabled:hover,\n.datepicker table tr td.active.disabled:hover.disabled:hover,\n.datepicker table tr td.active[disabled]:hover,\n.datepicker table tr td.active:hover[disabled]:hover,\n.datepicker table tr td.active.disabled[disabled]:hover,\n.datepicker table tr td.active.disabled:hover[disabled]:hover,\nfieldset[disabled] .datepicker table tr td.active:hover,\nfieldset[disabled] .datepicker table tr td.active:hover:hover,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover:hover,\n.datepicker table tr td.active.disabled:focus,\n.datepicker table tr td.active:hover.disabled:focus,\n.datepicker table tr td.active.disabled.disabled:focus,\n.datepicker table tr td.active.disabled:hover.disabled:focus,\n.datepicker table tr td.active[disabled]:focus,\n.datepicker table tr td.active:hover[disabled]:focus,\n.datepicker table tr td.active.disabled[disabled]:focus,\n.datepicker table tr td.active.disabled:hover[disabled]:focus,\nfieldset[disabled] .datepicker table tr td.active:focus,\nfieldset[disabled] .datepicker table tr td.active:hover:focus,\nfieldset[disabled] .datepicker table tr td.active.disabled:focus,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover:focus,\n.datepicker table tr td.active.disabled:active,\n.datepicker table tr td.active:hover.disabled:active,\n.datepicker table tr td.active.disabled.disabled:active,\n.datepicker table tr td.active.disabled:hover.disabled:active,\n.datepicker table tr td.active[disabled]:active,\n.datepicker table tr td.active:hover[disabled]:active,\n.datepicker table tr td.active.disabled[disabled]:active,\n.datepicker table tr td.active.disabled:hover[disabled]:active,\nfieldset[disabled] .datepicker table tr td.active:active,\nfieldset[disabled] .datepicker table tr td.active:hover:active,\nfieldset[disabled] .datepicker table tr td.active.disabled:active,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover:active,\n.datepicker table tr td.active.disabled.active,\n.datepicker table tr td.active:hover.disabled.active,\n.datepicker table tr td.active.disabled.disabled.active,\n.datepicker table tr td.active.disabled:hover.disabled.active,\n.datepicker table tr td.active[disabled].active,\n.datepicker table tr td.active:hover[disabled].active,\n.datepicker table tr td.active.disabled[disabled].active,\n.datepicker table tr td.active.disabled:hover[disabled].active,\nfieldset[disabled] .datepicker table tr td.active.active,\nfieldset[disabled] .datepicker table tr td.active:hover.active,\nfieldset[disabled] .datepicker table tr td.active.disabled.active,\nfieldset[disabled] .datepicker table tr td.active.disabled:hover.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.datepicker table tr td span {\n  display: block;\n  width: 23%;\n  height: 54px;\n  line-height: 54px;\n  float: left;\n  margin: 1%;\n  cursor: pointer;\n  border-radius: 4px;\n}\n.datepicker table tr td span:hover {\n  background: #eeeeee;\n}\n.datepicker table tr td span.disabled,\n.datepicker table tr td span.disabled:hover {\n  background: none;\n  color: #999999;\n  cursor: default;\n}\n.datepicker table tr td span.active,\n.datepicker table tr td span.active:hover,\n.datepicker table tr td span.active.disabled,\n.datepicker table tr td span.active.disabled:hover {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td span.active:hover,\n.datepicker table tr td span.active:hover:hover,\n.datepicker table tr td span.active.disabled:hover,\n.datepicker table tr td span.active.disabled:hover:hover,\n.datepicker table tr td span.active:focus,\n.datepicker table tr td span.active:hover:focus,\n.datepicker table tr td span.active.disabled:focus,\n.datepicker table tr td span.active.disabled:hover:focus,\n.datepicker table tr td span.active:active,\n.datepicker table tr td span.active:hover:active,\n.datepicker table tr td span.active.disabled:active,\n.datepicker table tr td span.active.disabled:hover:active,\n.datepicker table tr td span.active.active,\n.datepicker table tr td span.active:hover.active,\n.datepicker table tr td span.active.disabled.active,\n.datepicker table tr td span.active.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td span.active,\n.open .dropdown-toggle.datepicker table tr td span.active:hover,\n.open .dropdown-toggle.datepicker table tr td span.active.disabled,\n.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.datepicker table tr td span.active:active,\n.datepicker table tr td span.active:hover:active,\n.datepicker table tr td span.active.disabled:active,\n.datepicker table tr td span.active.disabled:hover:active,\n.datepicker table tr td span.active.active,\n.datepicker table tr td span.active:hover.active,\n.datepicker table tr td span.active.disabled.active,\n.datepicker table tr td span.active.disabled:hover.active,\n.open .dropdown-toggle.datepicker table tr td span.active,\n.open .dropdown-toggle.datepicker table tr td span.active:hover,\n.open .dropdown-toggle.datepicker table tr td span.active.disabled,\n.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover {\n  background-image: none;\n}\n.datepicker table tr td span.active.disabled,\n.datepicker table tr td span.active:hover.disabled,\n.datepicker table tr td span.active.disabled.disabled,\n.datepicker table tr td span.active.disabled:hover.disabled,\n.datepicker table tr td span.active[disabled],\n.datepicker table tr td span.active:hover[disabled],\n.datepicker table tr td span.active.disabled[disabled],\n.datepicker table tr td span.active.disabled:hover[disabled],\nfieldset[disabled] .datepicker table tr td span.active,\nfieldset[disabled] .datepicker table tr td span.active:hover,\nfieldset[disabled] .datepicker table tr td span.active.disabled,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover,\n.datepicker table tr td span.active.disabled:hover,\n.datepicker table tr td span.active:hover.disabled:hover,\n.datepicker table tr td span.active.disabled.disabled:hover,\n.datepicker table tr td span.active.disabled:hover.disabled:hover,\n.datepicker table tr td span.active[disabled]:hover,\n.datepicker table tr td span.active:hover[disabled]:hover,\n.datepicker table tr td span.active.disabled[disabled]:hover,\n.datepicker table tr td span.active.disabled:hover[disabled]:hover,\nfieldset[disabled] .datepicker table tr td span.active:hover,\nfieldset[disabled] .datepicker table tr td span.active:hover:hover,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,\n.datepicker table tr td span.active.disabled:focus,\n.datepicker table tr td span.active:hover.disabled:focus,\n.datepicker table tr td span.active.disabled.disabled:focus,\n.datepicker table tr td span.active.disabled:hover.disabled:focus,\n.datepicker table tr td span.active[disabled]:focus,\n.datepicker table tr td span.active:hover[disabled]:focus,\n.datepicker table tr td span.active.disabled[disabled]:focus,\n.datepicker table tr td span.active.disabled:hover[disabled]:focus,\nfieldset[disabled] .datepicker table tr td span.active:focus,\nfieldset[disabled] .datepicker table tr td span.active:hover:focus,\nfieldset[disabled] .datepicker table tr td span.active.disabled:focus,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus,\n.datepicker table tr td span.active.disabled:active,\n.datepicker table tr td span.active:hover.disabled:active,\n.datepicker table tr td span.active.disabled.disabled:active,\n.datepicker table tr td span.active.disabled:hover.disabled:active,\n.datepicker table tr td span.active[disabled]:active,\n.datepicker table tr td span.active:hover[disabled]:active,\n.datepicker table tr td span.active.disabled[disabled]:active,\n.datepicker table tr td span.active.disabled:hover[disabled]:active,\nfieldset[disabled] .datepicker table tr td span.active:active,\nfieldset[disabled] .datepicker table tr td span.active:hover:active,\nfieldset[disabled] .datepicker table tr td span.active.disabled:active,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover:active,\n.datepicker table tr td span.active.disabled.active,\n.datepicker table tr td span.active:hover.disabled.active,\n.datepicker table tr td span.active.disabled.disabled.active,\n.datepicker table tr td span.active.disabled:hover.disabled.active,\n.datepicker table tr td span.active[disabled].active,\n.datepicker table tr td span.active:hover[disabled].active,\n.datepicker table tr td span.active.disabled[disabled].active,\n.datepicker table tr td span.active.disabled:hover[disabled].active,\nfieldset[disabled] .datepicker table tr td span.active.active,\nfieldset[disabled] .datepicker table tr td span.active:hover.active,\nfieldset[disabled] .datepicker table tr td span.active.disabled.active,\nfieldset[disabled] .datepicker table tr td span.active.disabled:hover.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.datepicker table tr td span.old,\n.datepicker table tr td span.new {\n  color: #999999;\n}\n.datepicker th.datepicker-switch {\n  width: 145px;\n}\n.datepicker thead tr:first-child th,\n.datepicker tfoot tr th {\n  cursor: pointer;\n}\n.datepicker thead tr:first-child th:hover,\n.datepicker tfoot tr th:hover {\n  background: #eeeeee;\n}\n.datepicker .cw {\n  font-size: 10px;\n  width: 12px;\n  padding: 0 2px 0 5px;\n  vertical-align: middle;\n}\n.datepicker thead tr:first-child th.cw {\n  cursor: default;\n  background-color: transparent;\n}\n.input-group.date .input-group-addon i {\n  cursor: pointer;\n  width: 16px;\n  height: 16px;\n}\n.input-daterange input {\n  text-align: center;\n}\n.input-daterange input:first-child {\n  border-radius: 3px 0 0 3px;\n}\n.input-daterange input:last-child {\n  border-radius: 0 3px 3px 0;\n}\n.input-daterange .input-group-addon {\n  width: auto;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  text-shadow: 0 1px 0 #fff;\n  vertical-align: middle;\n  background-color: #eeeeee;\n  border-width: 1px 0;\n  margin-left: -5px;\n  margin-right: -5px;\n}\n.datepicker.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  float: left;\n  display: none;\n  min-width: 160px;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 5px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding;\n  background-clip: padding-box;\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  color: #333333;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  line-height: 1.428571429;\n}\n.datepicker.dropdown-menu th,\n.datepicker.dropdown-menu td {\n  padding: 4px 5px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/dropzone/basic.css",
    "content": "/* The MIT License */\n.dropzone,\n.dropzone *,\n.dropzone-previews,\n.dropzone-previews * {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.dropzone {\n  position: relative;\n  border: 1px solid rgba(0,0,0,0.08);\n  background: rgba(0,0,0,0.02);\n  padding: 1em;\n}\n.dropzone.dz-clickable {\n  cursor: pointer;\n}\n.dropzone.dz-clickable .dz-message,\n.dropzone.dz-clickable .dz-message span {\n  cursor: pointer;\n}\n.dropzone.dz-clickable * {\n  cursor: default;\n}\n.dropzone .dz-message {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n}\n.dropzone.dz-drag-hover {\n  border-color: rgba(0,0,0,0.15);\n  background: rgba(0,0,0,0.04);\n}\n.dropzone.dz-started .dz-message {\n  display: none;\n}\n.dropzone .dz-preview,\n.dropzone-previews .dz-preview {\n  background: rgba(255,255,255,0.8);\n  position: relative;\n  display: inline-block;\n  margin: 17px;\n  vertical-align: top;\n  border: 1px solid #acacac;\n  padding: 6px 6px 6px 6px;\n}\n.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail],\n.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] {\n  display: none;\n}\n.dropzone .dz-preview .dz-details,\n.dropzone-previews .dz-preview .dz-details {\n  width: 100px;\n  height: 100px;\n  position: relative;\n  background: #ebebeb;\n  padding: 5px;\n  margin-bottom: 22px;\n}\n.dropzone .dz-preview .dz-details .dz-filename,\n.dropzone-previews .dz-preview .dz-details .dz-filename {\n  overflow: hidden;\n  height: 100%;\n}\n.dropzone .dz-preview .dz-details img,\n.dropzone-previews .dz-preview .dz-details img {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100px;\n  height: 100px;\n}\n.dropzone .dz-preview .dz-details .dz-size,\n.dropzone-previews .dz-preview .dz-details .dz-size {\n  position: absolute;\n  bottom: -28px;\n  left: 3px;\n  height: 28px;\n  line-height: 28px;\n}\n.dropzone .dz-preview.dz-error .dz-error-mark,\n.dropzone-previews .dz-preview.dz-error .dz-error-mark {\n  display: block;\n}\n.dropzone .dz-preview.dz-success .dz-success-mark,\n.dropzone-previews .dz-preview.dz-success .dz-success-mark {\n  display: block;\n}\n.dropzone .dz-preview:hover .dz-details img,\n.dropzone-previews .dz-preview:hover .dz-details img {\n  display: none;\n}\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark,\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark {\n  display: none;\n  position: absolute;\n  width: 40px;\n  height: 40px;\n  font-size: 30px;\n  text-align: center;\n  right: -10px;\n  top: -10px;\n}\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark {\n  color: #8cc657;\n}\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark {\n  color: #ee162d;\n}\n.dropzone .dz-preview .dz-progress,\n.dropzone-previews .dz-preview .dz-progress {\n  position: absolute;\n  top: 100px;\n  left: 6px;\n  right: 6px;\n  height: 6px;\n  background: #d7d7d7;\n  display: none;\n}\n.dropzone .dz-preview .dz-progress .dz-upload,\n.dropzone-previews .dz-preview .dz-progress .dz-upload {\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 0%;\n  background-color: #8cc657;\n}\n.dropzone .dz-preview.dz-processing .dz-progress,\n.dropzone-previews .dz-preview.dz-processing .dz-progress {\n  display: block;\n}\n.dropzone .dz-preview .dz-error-message,\n.dropzone-previews .dz-preview .dz-error-message {\n  display: none;\n  position: absolute;\n  top: -5px;\n  left: -20px;\n  background: rgba(245,245,245,0.8);\n  padding: 8px 10px;\n  color: #800;\n  min-width: 140px;\n  max-width: 500px;\n  z-index: 500;\n}\n.dropzone .dz-preview:hover.dz-error .dz-error-message,\n.dropzone-previews .dz-preview:hover.dz-error .dz-error-message {\n  display: block;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/dropzone/dropzone.css",
    "content": "/* The MIT License */\n.dropzone,\n.dropzone *,\n.dropzone-previews,\n.dropzone-previews * {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.dropzone {\n  position: relative;\n  border: 1px solid rgba(0,0,0,0.08);\n  background: rgba(0,0,0,0.02);\n  padding: 1em;\n}\n.dropzone.dz-clickable {\n  cursor: pointer;\n}\n.dropzone.dz-clickable .dz-message,\n.dropzone.dz-clickable .dz-message span {\n  cursor: pointer;\n}\n.dropzone.dz-clickable * {\n  cursor: default;\n}\n.dropzone .dz-message {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n}\n.dropzone.dz-drag-hover {\n  border-color: rgba(0,0,0,0.15);\n  background: rgba(0,0,0,0.04);\n}\n.dropzone.dz-started .dz-message {\n  display: none;\n}\n.dropzone .dz-preview,\n.dropzone-previews .dz-preview {\n  background: rgba(255,255,255,0.8);\n  position: relative;\n  display: inline-block;\n  margin: 17px;\n  vertical-align: top;\n  border: 1px solid #acacac;\n  padding: 6px 6px 6px 6px;\n}\n.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail],\n.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] {\n  display: none;\n}\n.dropzone .dz-preview .dz-details,\n.dropzone-previews .dz-preview .dz-details {\n  width: 100px;\n  height: 100px;\n  position: relative;\n  background: #ebebeb;\n  padding: 5px;\n  margin-bottom: 22px;\n}\n.dropzone .dz-preview .dz-details .dz-filename,\n.dropzone-previews .dz-preview .dz-details .dz-filename {\n  overflow: hidden;\n  height: 100%;\n}\n.dropzone .dz-preview .dz-details img,\n.dropzone-previews .dz-preview .dz-details img {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100px;\n  height: 100px;\n}\n.dropzone .dz-preview .dz-details .dz-size,\n.dropzone-previews .dz-preview .dz-details .dz-size {\n  position: absolute;\n  bottom: -28px;\n  left: 3px;\n  height: 28px;\n  line-height: 28px;\n}\n.dropzone .dz-preview.dz-error .dz-error-mark,\n.dropzone-previews .dz-preview.dz-error .dz-error-mark {\n  display: block;\n}\n.dropzone .dz-preview.dz-success .dz-success-mark,\n.dropzone-previews .dz-preview.dz-success .dz-success-mark {\n  display: block;\n}\n.dropzone .dz-preview:hover .dz-details img,\n.dropzone-previews .dz-preview:hover .dz-details img {\n  display: none;\n}\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark,\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark {\n  display: none;\n  position: absolute;\n  width: 40px;\n  height: 40px;\n  font-size: 30px;\n  text-align: center;\n  right: -10px;\n  top: -10px;\n}\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark {\n  color: #8cc657;\n}\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark {\n  color: #ee162d;\n}\n.dropzone .dz-preview .dz-progress,\n.dropzone-previews .dz-preview .dz-progress {\n  position: absolute;\n  top: 100px;\n  left: 6px;\n  right: 6px;\n  height: 6px;\n  background: #d7d7d7;\n  display: none;\n}\n.dropzone .dz-preview .dz-progress .dz-upload,\n.dropzone-previews .dz-preview .dz-progress .dz-upload {\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 0%;\n  background-color: #8cc657;\n}\n.dropzone .dz-preview.dz-processing .dz-progress,\n.dropzone-previews .dz-preview.dz-processing .dz-progress {\n  display: block;\n}\n.dropzone .dz-preview .dz-error-message,\n.dropzone-previews .dz-preview .dz-error-message {\n  display: none;\n  position: absolute;\n  top: -5px;\n  left: -20px;\n  background: rgba(245,245,245,0.8);\n  padding: 8px 10px;\n  color: #800;\n  min-width: 140px;\n  max-width: 500px;\n  z-index: 500;\n}\n.dropzone .dz-preview:hover.dz-error .dz-error-message,\n.dropzone-previews .dz-preview:hover.dz-error .dz-error-message {\n  display: block;\n}\n.dropzone {\n  border: 1px solid rgba(0,0,0,0.03);\n  min-height: 360px;\n  -webkit-border-radius: 3px;\n  border-radius: 3px;\n  background: rgba(0,0,0,0.03);\n  padding: 23px;\n}\n.dropzone .dz-default.dz-message {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n  -webkit-transition: opacity 0.3s ease-in-out;\n  -moz-transition: opacity 0.3s ease-in-out;\n  -o-transition: opacity 0.3s ease-in-out;\n  -ms-transition: opacity 0.3s ease-in-out;\n  transition: opacity 0.3s ease-in-out;\n  background-image: url(\"../images/spritemap.png\");\n  background-repeat: no-repeat;\n  background-position: 0 0;\n  position: absolute;\n  width: 428px;\n  height: 123px;\n  margin-left: -214px;\n  margin-top: -61.5px;\n  top: 50%;\n  left: 50%;\n}\n@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {\n  .dropzone .dz-default.dz-message {\n    background-image: url(\"../images/spritemap@2x.png\");\n    -webkit-background-size: 428px 406px;\n    -moz-background-size: 428px 406px;\n    background-size: 428px 406px;\n  }\n}\n.dropzone .dz-default.dz-message span {\n  display: none;\n}\n.dropzone.dz-square .dz-default.dz-message {\n  background-position: 0 -123px;\n  width: 268px;\n  margin-left: -134px;\n  height: 174px;\n  margin-top: -87px;\n}\n.dropzone.dz-drag-hover .dz-message {\n  opacity: 0.15;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=15)\";\n  filter: alpha(opacity=15);\n}\n.dropzone.dz-started .dz-message {\n  display: block;\n  opacity: 0;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";\n  filter: alpha(opacity=0);\n}\n.dropzone .dz-preview,\n.dropzone-previews .dz-preview {\n  -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16);\n  box-shadow: 1px 1px 4px rgba(0,0,0,0.16);\n  font-size: 14px;\n}\n.dropzone .dz-preview.dz-image-preview:hover .dz-details img,\n.dropzone-previews .dz-preview.dz-image-preview:hover .dz-details img {\n  display: block;\n  opacity: 0.1;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=10)\";\n  filter: alpha(opacity=10);\n}\n.dropzone .dz-preview.dz-success .dz-success-mark,\n.dropzone-previews .dz-preview.dz-success .dz-success-mark {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n}\n.dropzone .dz-preview.dz-error .dz-error-mark,\n.dropzone-previews .dz-preview.dz-error .dz-error-mark {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n}\n.dropzone .dz-preview.dz-error .dz-progress .dz-upload,\n.dropzone-previews .dz-preview.dz-error .dz-progress .dz-upload {\n  background: #ee1e2d;\n}\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark,\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark {\n  display: block;\n  opacity: 0;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";\n  filter: alpha(opacity=0);\n  -webkit-transition: opacity 0.4s ease-in-out;\n  -moz-transition: opacity 0.4s ease-in-out;\n  -o-transition: opacity 0.4s ease-in-out;\n  -ms-transition: opacity 0.4s ease-in-out;\n  transition: opacity 0.4s ease-in-out;\n  background-image: url(\"../images/spritemap.png\");\n  background-repeat: no-repeat;\n}\n@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {\n  .dropzone .dz-preview .dz-error-mark,\n  .dropzone-previews .dz-preview .dz-error-mark,\n  .dropzone .dz-preview .dz-success-mark,\n  .dropzone-previews .dz-preview .dz-success-mark {\n    background-image: url(\"../images/spritemap@2x.png\");\n    -webkit-background-size: 428px 406px;\n    -moz-background-size: 428px 406px;\n    background-size: 428px 406px;\n  }\n}\n.dropzone .dz-preview .dz-error-mark span,\n.dropzone-previews .dz-preview .dz-error-mark span,\n.dropzone .dz-preview .dz-success-mark span,\n.dropzone-previews .dz-preview .dz-success-mark span {\n  display: none;\n}\n.dropzone .dz-preview .dz-error-mark,\n.dropzone-previews .dz-preview .dz-error-mark {\n  background-position: -268px -123px;\n}\n.dropzone .dz-preview .dz-success-mark,\n.dropzone-previews .dz-preview .dz-success-mark {\n  background-position: -268px -163px;\n}\n.dropzone .dz-preview .dz-progress .dz-upload,\n.dropzone-previews .dz-preview .dz-progress .dz-upload {\n  -webkit-animation: loading 0.4s linear infinite;\n  -moz-animation: loading 0.4s linear infinite;\n  -o-animation: loading 0.4s linear infinite;\n  -ms-animation: loading 0.4s linear infinite;\n  animation: loading 0.4s linear infinite;\n  -webkit-transition: width 0.3s ease-in-out;\n  -moz-transition: width 0.3s ease-in-out;\n  -o-transition: width 0.3s ease-in-out;\n  -ms-transition: width 0.3s ease-in-out;\n  transition: width 0.3s ease-in-out;\n  -webkit-border-radius: 2px;\n  border-radius: 2px;\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 0%;\n  height: 100%;\n  background-image: url(\"../images/spritemap.png\");\n  background-repeat: repeat-x;\n  background-position: 0px -400px;\n}\n@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {\n  .dropzone .dz-preview .dz-progress .dz-upload,\n  .dropzone-previews .dz-preview .dz-progress .dz-upload {\n    background-image: url(\"../images/spritemap@2x.png\");\n    -webkit-background-size: 428px 406px;\n    -moz-background-size: 428px 406px;\n    background-size: 428px 406px;\n  }\n}\n.dropzone .dz-preview.dz-success .dz-progress,\n.dropzone-previews .dz-preview.dz-success .dz-progress {\n  display: block;\n  opacity: 0;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";\n  filter: alpha(opacity=0);\n  -webkit-transition: opacity 0.4s ease-in-out;\n  -moz-transition: opacity 0.4s ease-in-out;\n  -o-transition: opacity 0.4s ease-in-out;\n  -ms-transition: opacity 0.4s ease-in-out;\n  transition: opacity 0.4s ease-in-out;\n}\n.dropzone .dz-preview .dz-error-message,\n.dropzone-previews .dz-preview .dz-error-message {\n  display: block;\n  opacity: 0;\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";\n  filter: alpha(opacity=0);\n  -webkit-transition: opacity 0.3s ease-in-out;\n  -moz-transition: opacity 0.3s ease-in-out;\n  -o-transition: opacity 0.3s ease-in-out;\n  -ms-transition: opacity 0.3s ease-in-out;\n  transition: opacity 0.3s ease-in-out;\n}\n.dropzone .dz-preview:hover.dz-error .dz-error-message,\n.dropzone-previews .dz-preview:hover.dz-error .dz-error-message {\n  opacity: 1;\n  -ms-filter: none;\n  filter: none;\n}\n.dropzone a.dz-remove,\n.dropzone-previews a.dz-remove {\n  background-image: -webkit-linear-gradient(top, #fafafa, #eee);\n  background-image: -moz-linear-gradient(top, #fafafa, #eee);\n  background-image: -o-linear-gradient(top, #fafafa, #eee);\n  background-image: -ms-linear-gradient(top, #fafafa, #eee);\n  background-image: linear-gradient(to bottom, #fafafa, #eee);\n  -webkit-border-radius: 2px;\n  border-radius: 2px;\n  border: 1px solid #eee;\n  text-decoration: none;\n  display: block;\n  padding: 4px 5px;\n  text-align: center;\n  color: #aaa;\n  margin-top: 26px;\n}\n.dropzone a.dz-remove:hover,\n.dropzone-previews a.dz-remove:hover {\n  color: #666;\n}\n@-moz-keyframes loading {\n  0% {\n    background-position: 0 -400px;\n  }\n\n  100% {\n    background-position: -7px -400px;\n  }\n}\n@-webkit-keyframes loading {\n  0% {\n    background-position: 0 -400px;\n  }\n\n  100% {\n    background-position: -7px -400px;\n  }\n}\n@-o-keyframes loading {\n  0% {\n    background-position: 0 -400px;\n  }\n\n  100% {\n    background-position: -7px -400px;\n  }\n}\n@-ms-keyframes loading {\n  0% {\n    background-position: 0 -400px;\n  }\n\n  100% {\n    background-position: -7px -400px;\n  }\n}\n@keyframes loading {\n  0% {\n    background-position: 0 -400px;\n  }\n\n  100% {\n    background-position: -7px -400px;\n  }\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/duallistbox/bootstrap-duallistbox.css",
    "content": ".bootstrap-duallistbox-container .buttons {\n  width:calc(100% + 1px);\n  margin-bottom: -6px;\n    box-sizing: border-box;\n}\n\n.bootstrap-duallistbox-container label {\n  display: block;\n}\n\n.bootstrap-duallistbox-container .info {\n  display: inline-block;\n  margin-bottom: 5px;\n}\n\n.bootstrap-duallistbox-container .clear1,\n.bootstrap-duallistbox-container .clear2 {\n  display: none;\n  font-size: 10px;\n}\n\n.bootstrap-duallistbox-container .box1.filtered .clear1,\n.bootstrap-duallistbox-container .box2.filtered .clear2 {\n  display: inline-block;\n}\n\n.bootstrap-duallistbox-container .move,\n.bootstrap-duallistbox-container .remove {\n  width: 50%;box-sizing: border-box;\n}\n\n.bootstrap-duallistbox-container .btn-group .btn {\n  border-bottom-left-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.bootstrap-duallistbox-container select {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.bootstrap-duallistbox-container .moveall,\n.bootstrap-duallistbox-container .removeall {\n  width: 50%;box-sizing: border-box;\n}\n\n.bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn {\n  margin-left: 0;\n}\n\n.bootstrap-duallistbox-container select {\n  height: 300px;\n  box-sizing: border-box;\n}\n.bootstrap-duallistbox-container select:focus{\n    border-color: #e5e6e7!important;\n}\n\n.bootstrap-duallistbox-container .filter {\n  display: inline-block;\n  width: 100%;\n  height: 31px;margin-bottom:-1px;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n}\n\n.bootstrap-duallistbox-container .filter.placeholder {\n  color: #aaa;\n}\n\n.bootstrap-duallistbox-container.moveonselect .move,\n.bootstrap-duallistbox-container.moveonselect .remove {\n  display:none;\n}\n\n.bootstrap-duallistbox-container.moveonselect .moveall,\n.bootstrap-duallistbox-container.moveonselect .removeall {\n  width: 100%;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/footable/footable.core.css",
    "content": "@font-face {\n  font-family: 'footable';\n  src: url('fonts/footable.eot');\n  src: url('fonts/footable.eot?#iefix') format('embedded-opentype'), url('fonts/footable.woff') format('woff'), url('fonts/footable.ttf') format('truetype'), url('fonts/footable.svg#footable') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n  @font-face {\n    font-family: 'footable';\n    src: url('fonts/footable.svg#footable') format('svg');\n    font-weight: normal;\n    font-style: normal;\n  }\n}\n.footable {\n  width: 100%;\n  /** SORTING **/\n\n  /** PAGINATION **/\n\n}\n.footable.breakpoint > tbody > tr.footable-detail-show > td {\n  border-bottom: none;\n}\n.footable.breakpoint > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e001\";\n}\n.footable.breakpoint > tbody > tr:hover:not(.footable-row-detail) {\n  cursor: pointer;\n}\n.footable.breakpoint > tbody > tr > td.footable-cell-detail {\n  background: #eee;\n  border-top: none;\n}\n.footable.breakpoint > tbody > tr > td > span.footable-toggle {\n  display: inline-block;\n  font-family: 'footable';\n  speak: none;\n  font-style: normal;\n  font-weight: normal;\n  font-variant: normal;\n  text-transform: none;\n  -webkit-font-smoothing: antialiased;\n  padding-right: 5px;\n  font-size: 14px;\n  color: #888888;\n}\n.footable.breakpoint > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e000\";\n}\n.footable.breakpoint.toggle-circle > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e005\";\n}\n.footable.breakpoint.toggle-circle > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e004\";\n}\n.footable.breakpoint.toggle-circle-filled > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e003\";\n}\n.footable.breakpoint.toggle-circle-filled > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e002\";\n}\n.footable.breakpoint.toggle-square > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e007\";\n}\n.footable.breakpoint.toggle-square > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e006\";\n}\n.footable.breakpoint.toggle-square-filled > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e009\";\n}\n.footable.breakpoint.toggle-square-filled > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e008\";\n}\n.footable.breakpoint.toggle-arrow > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e00f\";\n}\n.footable.breakpoint.toggle-arrow > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e011\";\n}\n.footable.breakpoint.toggle-arrow-small > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e013\";\n}\n.footable.breakpoint.toggle-arrow-small > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e015\";\n}\n.footable.breakpoint.toggle-arrow-circle > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e01b\";\n}\n.footable.breakpoint.toggle-arrow-circle > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e01d\";\n}\n.footable.breakpoint.toggle-arrow-circle-filled > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e00b\";\n}\n.footable.breakpoint.toggle-arrow-circle-filled > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e00d\";\n}\n.footable.breakpoint.toggle-arrow-tiny > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e01f\";\n}\n.footable.breakpoint.toggle-arrow-tiny > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e021\";\n}\n.footable.breakpoint.toggle-arrow-alt > tbody > tr.footable-detail-show > td > span.footable-toggle:before {\n  content: \"\\e017\";\n}\n.footable.breakpoint.toggle-arrow-alt > tbody > tr > td > span.footable-toggle:before {\n  content: \"\\e019\";\n}\n.footable.breakpoint.toggle-medium > tbody > tr > td > span.footable-toggle {\n  font-size: 18px;\n}\n.footable.breakpoint.toggle-large > tbody > tr > td > span.footable-toggle {\n  font-size: 24px;\n}\n.footable > thead > tr > th {\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: -moz-none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.footable > thead > tr > th.footable-sortable:hover {\n  cursor: pointer;\n}\n.footable > thead > tr > th.footable-sorted > span.footable-sort-indicator:before {\n  content: \"\\e013\";\n}\n.footable > thead > tr > th.footable-sorted-desc > span.footable-sort-indicator:before {\n  content: \"\\e012\";\n}\n.footable > thead > tr > th > span.footable-sort-indicator {\n  display: inline-block;\n  font-family: 'footable';\n  speak: none;\n  font-style: normal;\n  font-weight: normal;\n  font-variant: normal;\n  text-transform: none;\n  -webkit-font-smoothing: antialiased;\n  padding-left: 5px;\n}\n.footable > thead > tr > th > span.footable-sort-indicator:before {\n  content: \"\\e022\";\n}\n.footable > tfoot .pagination {\n  margin: 0;\n}\n.footable.no-paging .hide-if-no-paging {\n  display: none;\n}\n.footable-row-detail-inner {\n  display: table;\n}\n.footable-row-detail-row {\n  display: table-row;\n  line-height: 1.5em;\n}\n.footable-row-detail-group {\n  display: block;\n  line-height: 2em;\n  font-size: 1.2em;\n  font-weight: bold;\n}\n.footable-row-detail-name {\n  display: table-cell;\n  font-weight: bold;\n  padding-right: 0.5em;\n}\n.footable-row-detail-value {\n  display: table-cell;\n}\n.footable-odd {\n  background-color: #f7f7f7;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/fullcalendar/fullcalendar.css",
    "content": "/*!\n * FullCalendar v1.6.4 Stylesheet\n * Docs & License: http://arshaw.com/fullcalendar/\n * (c) 2013 Adam Shaw\n */\n\n\n.fc {\n\tdirection: ltr;\n\ttext-align: left;\n\t}\n\n.fc table {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n\t}\n\nhtml .fc,\n.fc table {\n\tfont-size: 1em;\n\t}\n\n.fc td,\n.fc th {\n\tpadding: 0;\n\tvertical-align: top;\n\t}\n\n\n\n/* Header\n------------------------------------------------------------------------*/\n\n.fc-header td {\n\twhite-space: nowrap;\n\t}\n\n.fc-header-left {\n\twidth: 25%;\n\ttext-align: left;\n\t}\n\n.fc-header-center {\n\ttext-align: center;\n\t}\n\n.fc-header-right {\n\twidth: 25%;\n\ttext-align: right;\n\t}\n\n.fc-header-title {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\t}\n\n.fc-header-title h2 {\n\tmargin-top: 0;\n\twhite-space: nowrap;\n\t}\n\n.fc .fc-header-space {\n\tpadding-left: 10px;\n\t}\n\n.fc-header .fc-button {\n\tmargin-bottom: 1em;\n\tvertical-align: top;\n\t}\n\n/* buttons edges butting together */\n\n.fc-header .fc-button {\n\tmargin-right: -1px;\n\t}\n\n.fc-header .fc-corner-right,  /* non-theme */\n.fc-header .ui-corner-right { /* theme */\n\tmargin-right: 0; /* back to normal */\n\t}\n\n/* button layering (for border precedence) */\n\n.fc-header .fc-state-hover,\n.fc-header .ui-state-hover {\n\tz-index: 2;\n\t}\n\n.fc-header .fc-state-down {\n\tz-index: 3;\n\t}\n\n.fc-header .fc-state-active,\n.fc-header .ui-state-active {\n\tz-index: 4;\n\t}\n\n\n\n/* Content\n------------------------------------------------------------------------*/\n\n.fc-content {\n\tclear: both;\n\tzoom: 1; /* for IE7, gives accurate coordinates for [un]freezeContentHeight */\n\t}\n\n.fc-view {\n\twidth: 100%;\n\toverflow: hidden;\n\t}\n\n\n\n/* Cell Styles\n------------------------------------------------------------------------*/\n\n.fc-widget-header,    /* <th>, usually */\n.fc-widget-content {  /* <td>, usually */\n\tborder: 1px solid #ddd;\n\t}\n\n.fc-state-highlight { /* <td> today cell */ /* TODO: add .fc-today to <th> */\n\tbackground: #fcf8e3;\n\t}\n\n.fc-cell-overlay { /* semi-transparent rectangle while dragging */\n\tbackground: #bce8f1;\n\topacity: .3;\n\tfilter: alpha(opacity=30); /* for IE */\n\t}\n\n\n\n/* Buttons\n------------------------------------------------------------------------*/\n\n.fc-button {\n\tposition: relative;\n\tdisplay: inline-block;\n\tpadding: 0 .6em;\n\toverflow: hidden;\n\theight: 1.9em;\n\tline-height: 1.9em;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t}\n\n.fc-state-default { /* non-theme */\n\tborder: 1px solid;\n\t}\n\n.fc-state-default.fc-corner-left { /* non-theme */\n\tborder-top-left-radius: 4px;\n\tborder-bottom-left-radius: 4px;\n\t}\n\n.fc-state-default.fc-corner-right { /* non-theme */\n\tborder-top-right-radius: 4px;\n\tborder-bottom-right-radius: 4px;\n\t}\n\n/*\n\tOur default prev/next buttons use HTML entities like &lsaquo; &rsaquo; &laquo; &raquo;\n\tand we'll try to make them look good cross-browser.\n*/\n\n.fc-text-arrow {\n\tmargin: 0 .1em;\n\tfont-size: 2em;\n\tfont-family: \"Courier New\", Courier, monospace;\n\tvertical-align: baseline; /* for IE7 */\n\t}\n\n.fc-button-prev .fc-text-arrow,\n.fc-button-next .fc-text-arrow { /* for &lsaquo; &rsaquo; */\n\tfont-weight: bold;\n\t}\n\n/* icon (for jquery ui) */\n\n.fc-button .fc-icon-wrap {\n\tposition: relative;\n\tfloat: left;\n\ttop: 50%;\n\t}\n\n.fc-button .ui-icon {\n\tposition: relative;\n\tfloat: left;\n\tmargin-top: -50%;\n\t*margin-top: 0;\n\t*top: -50%;\n\t}\n\n/*\n  button states\n  borrowed from twitter bootstrap (http://twitter.github.com/bootstrap/)\n*/\n\n.fc-state-default {\n\tbackground-color: #f5f5f5;\n\tbackground-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n\tbackground-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n\tbackground-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n\tbackground-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n\tbackground-repeat: repeat-x;\n\tborder-color: #e6e6e6 #e6e6e6 #bfbfbf;\n\tborder-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n\tcolor: #333;\n\ttext-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n\tbox-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n\t}\n\n.fc-state-hover,\n.fc-state-down,\n.fc-state-active,\n.fc-state-disabled {\n\tcolor: #333333;\n\tbackground-color: #e6e6e6;\n\t}\n\n.fc-state-hover {\n\tcolor: #333333;\n\ttext-decoration: none;\n\tbackground-position: 0 -15px;\n\t-webkit-transition: background-position 0.1s linear;\n\t   -moz-transition: background-position 0.1s linear;\n\t     -o-transition: background-position 0.1s linear;\n\t        transition: background-position 0.1s linear;\n\t}\n\n.fc-state-down,\n.fc-state-active {\n\tbackground-color: #cccccc;\n\tbackground-image: none;\n\toutline: 0;\n\tbox-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n\t}\n\n.fc-state-disabled {\n\tcursor: default;\n\tbackground-image: none;\n\topacity: 0.65;\n\tfilter: alpha(opacity=65);\n\tbox-shadow: none;\n\t}\n\n\n\n/* Global Event Styles\n------------------------------------------------------------------------*/\n\n.fc-event-container > * {\n\tz-index: 8;\n\t}\n\n.fc-event-container > .ui-draggable-dragging,\n.fc-event-container > .ui-resizable-resizing {\n\tz-index: 9;\n\t}\n\n.fc-event {\n\tborder: 1px solid #3a87ad; /* default BORDER color */\n\tbackground-color: #3a87ad; /* default BACKGROUND color */\n\tcolor: #fff;               /* default TEXT color */\n\tfont-size: .85em;\n\tcursor: default;\n\t}\n\na.fc-event {\n\ttext-decoration: none;\n\t}\n\na.fc-event,\n.fc-event-draggable {\n\tcursor: pointer;\n\t}\n\n.fc-rtl .fc-event {\n\ttext-align: right;\n\t}\n\n.fc-event-inner {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t}\n\n.fc-event-time,\n.fc-event-title {\n\tpadding: 0 1px;\n\t}\n\n.fc .ui-resizable-handle {\n\tdisplay: block;\n\tposition: absolute;\n\tz-index: 99999;\n\toverflow: hidden; /* hacky spaces (IE6/7) */\n\tfont-size: 300%;  /* */\n\tline-height: 50%; /* */\n\t}\n\n\n\n/* Horizontal Events\n------------------------------------------------------------------------*/\n\n.fc-event-hori {\n\tborder-width: 1px 0;\n\tmargin-bottom: 1px;\n\t}\n\n.fc-ltr .fc-event-hori.fc-event-start,\n.fc-rtl .fc-event-hori.fc-event-end {\n\tborder-left-width: 1px;\n\tborder-top-left-radius: 3px;\n\tborder-bottom-left-radius: 3px;\n\t}\n\n.fc-ltr .fc-event-hori.fc-event-end,\n.fc-rtl .fc-event-hori.fc-event-start {\n\tborder-right-width: 1px;\n\tborder-top-right-radius: 3px;\n\tborder-bottom-right-radius: 3px;\n\t}\n\n/* resizable */\n\n.fc-event-hori .ui-resizable-e {\n\ttop: 0           !important; /* importants override pre jquery ui 1.7 styles */\n\tright: -3px      !important;\n\twidth: 7px       !important;\n\theight: 100%     !important;\n\tcursor: e-resize;\n\t}\n\n.fc-event-hori .ui-resizable-w {\n\ttop: 0           !important;\n\tleft: -3px       !important;\n\twidth: 7px       !important;\n\theight: 100%     !important;\n\tcursor: w-resize;\n\t}\n\n.fc-event-hori .ui-resizable-handle {\n\t_padding-bottom: 14px; /* IE6 had 0 height */\n\t}\n\n\n\n/* Reusable Separate-border Table\n------------------------------------------------------------*/\n\ntable.fc-border-separate {\n\tborder-collapse: separate;\n\t}\n\n.fc-border-separate th,\n.fc-border-separate td {\n\tborder-width: 1px 0 0 1px;\n\t}\n\n.fc-border-separate th.fc-last,\n.fc-border-separate td.fc-last {\n\tborder-right-width: 1px;\n\t}\n\n.fc-border-separate tr.fc-last th,\n.fc-border-separate tr.fc-last td {\n\tborder-bottom-width: 1px;\n\t}\n\n.fc-border-separate tbody tr.fc-first td,\n.fc-border-separate tbody tr.fc-first th {\n\tborder-top-width: 0;\n\t}\n\n\n\n/* Month View, Basic Week View, Basic Day View\n------------------------------------------------------------------------*/\n\n.fc-grid th {\n\ttext-align: center;\n\t}\n\n.fc .fc-week-number {\n\twidth: 22px;\n\ttext-align: center;\n\t}\n\n.fc .fc-week-number div {\n\tpadding: 0 2px;\n\t}\n\n.fc-grid .fc-day-number {\n\tfloat: right;\n\tpadding: 0 2px;\n\t}\n\n.fc-grid .fc-other-month .fc-day-number {\n\topacity: 0.3;\n\tfilter: alpha(opacity=30); /* for IE */\n\t/* opacity with small font can sometimes look too faded\n\t   might want to set the 'color' property instead\n\t   making day-numbers bold also fixes the problem */\n\t}\n\n.fc-grid .fc-day-content {\n\tclear: both;\n\tpadding: 2px 2px 1px; /* distance between events and day edges */\n\t}\n\n/* event styles */\n\n.fc-grid .fc-event-time {\n\tfont-weight: bold;\n\t}\n\n/* right-to-left */\n\n.fc-rtl .fc-grid .fc-day-number {\n\tfloat: left;\n\t}\n\n.fc-rtl .fc-grid .fc-event-time {\n\tfloat: right;\n\t}\n\n\n\n/* Agenda Week View, Agenda Day View\n------------------------------------------------------------------------*/\n\n.fc-agenda table {\n\tborder-collapse: separate;\n\t}\n\n.fc-agenda-days th {\n\ttext-align: center;\n\t}\n\n.fc-agenda .fc-agenda-axis {\n\twidth: 50px;\n\tpadding: 0 4px;\n\tvertical-align: middle;\n\ttext-align: right;\n\twhite-space: nowrap;\n\tfont-weight: normal;\n\t}\n\n.fc-agenda .fc-week-number {\n\tfont-weight: bold;\n\t}\n\n.fc-agenda .fc-day-content {\n\tpadding: 2px 2px 1px;\n\t}\n\n/* make axis border take precedence */\n\n.fc-agenda-days .fc-agenda-axis {\n\tborder-right-width: 1px;\n\t}\n\n.fc-agenda-days .fc-col0 {\n\tborder-left-width: 0;\n\t}\n\n/* all-day area */\n\n.fc-agenda-allday th {\n\tborder-width: 0 1px;\n\t}\n\n.fc-agenda-allday .fc-day-content {\n\tmin-height: 34px; /* TODO: doesnt work well in quirksmode */\n\t_height: 34px;\n\t}\n\n/* divider (between all-day and slots) */\n\n.fc-agenda-divider-inner {\n\theight: 2px;\n\toverflow: hidden;\n\t}\n\n.fc-widget-header .fc-agenda-divider-inner {\n\tbackground: #eee;\n\t}\n\n/* slot rows */\n\n.fc-agenda-slots th {\n\tborder-width: 1px 1px 0;\n\t}\n\n.fc-agenda-slots td {\n\tborder-width: 1px 0 0;\n\tbackground: none;\n\t}\n\n.fc-agenda-slots td div {\n\theight: 20px;\n\t}\n\n.fc-agenda-slots tr.fc-slot0 th,\n.fc-agenda-slots tr.fc-slot0 td {\n\tborder-top-width: 0;\n\t}\n\n.fc-agenda-slots tr.fc-minor th,\n.fc-agenda-slots tr.fc-minor td {\n\tborder-top-style: dotted;\n\t}\n\n.fc-agenda-slots tr.fc-minor th.ui-widget-header {\n\t*border-top-style: solid; /* doesn't work with background in IE6/7 */\n\t}\n\n\n\n/* Vertical Events\n------------------------------------------------------------------------*/\n\n.fc-event-vert {\n\tborder-width: 0 1px;\n\t}\n\n.fc-event-vert.fc-event-start {\n\tborder-top-width: 1px;\n\tborder-top-left-radius: 3px;\n\tborder-top-right-radius: 3px;\n\t}\n\n.fc-event-vert.fc-event-end {\n\tborder-bottom-width: 1px;\n\tborder-bottom-left-radius: 3px;\n\tborder-bottom-right-radius: 3px;\n\t}\n\n.fc-event-vert .fc-event-time {\n\twhite-space: nowrap;\n\tfont-size: 10px;\n\t}\n\n.fc-event-vert .fc-event-inner {\n\tposition: relative;\n\tz-index: 2;\n\t}\n\n.fc-event-vert .fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay  */\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: #fff;\n\topacity: .25;\n\tfilter: alpha(opacity=25);\n\t}\n\n.fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */\n.fc-select-helper .fc-event-bg {\n\tdisplay: none\\9; /* for IE6/7/8. nested opacity filters while dragging don't work */\n\t}\n\n/* resizable */\n\n.fc-event-vert .ui-resizable-s {\n\tbottom: 0        !important; /* importants override pre jquery ui 1.7 styles */\n\twidth: 100%      !important;\n\theight: 8px      !important;\n\toverflow: hidden !important;\n\tline-height: 8px !important;\n\tfont-size: 11px  !important;\n\tfont-family: monospace;\n\ttext-align: center;\n\tcursor: s-resize;\n\t}\n\n.fc-agenda .ui-resizable-resizing { /* TODO: better selector */\n\t_overflow: hidden;\n\t}\n\n\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/fullcalendar/fullcalendar.print.css",
    "content": "/*!\n * FullCalendar v1.6.4 Print Stylesheet\n * Docs & License: http://arshaw.com/fullcalendar/\n * (c) 2013 Adam Shaw\n */\n\n/*\n * Include this stylesheet on your page to get a more printer-friendly calendar.\n * When including this stylesheet, use the media='print' attribute of the <link> tag.\n * Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css.\n */\n\n\n /* Events\n-----------------------------------------------------*/\n\n.fc-event {\n\tbackground: #fff !important;\n\tcolor: #000 !important;\n\t}\n\n/* for vertical events */\n\n.fc-event-bg {\n\tdisplay: none !important;\n\t}\n\n.fc-event .ui-resizable-handle {\n\tdisplay: none !important;\n\t}\n\n\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/iCheck/custom.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}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/ionRangeSlider/ion.rangeSlider.css",
    "content": "/* Ion.RangeSlider\n// css version 1.8.5\n// by Denis Ineshin | ionden.com\n// ===================================================================================================================*/\n\n/* =====================================================================================================================\n// RangeSlider */\n\n.irs {\n    position: relative; display: block;\n}\n    .irs-line {\n        position: relative; display: block;\n        overflow: hidden;\n    }\n        .irs-line-left, .irs-line-mid, .irs-line-right {\n            position: absolute; display: block;\n            top: 0;\n        }\n        .irs-line-left {\n            left: 0; width: 10%;\n        }\n        .irs-line-mid {\n            left: 10%; width: 80%;\n        }\n        .irs-line-right {\n            right: 0; width: 10%;\n        }\n\n    .irs-diapason {\n        position: absolute; display: block;\n        left: 0; width: 100%;\n    }\n    .irs-slider {\n        position: absolute; display: block;\n        cursor: default;\n        z-index: 1;\n    }\n        .irs-slider.single {\n            left: 10px;\n        }\n            .irs-slider.single:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: -30%;\n                width: 160%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.from {\n            left: 100px;\n        }\n            .irs-slider.from:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: -30%;\n                width: 130%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.to {\n            left: 300px;\n        }\n            .irs-slider.to:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: 0;\n                width: 130%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.last {\n            z-index: 2;\n        }\n\n    .irs-min {\n        position: absolute; display: block;\n        left: 0;\n        cursor: default;\n    }\n    .irs-max {\n        position: absolute; display: block;\n        right: 0;\n        cursor: default;\n    }\n\n    .irs-from, .irs-to, .irs-single {\n        position: absolute; display: block;\n        top: 0; left: 0;\n        cursor: default;\n        white-space: nowrap;\n    }\n\n\n.irs-grid {\n    position: absolute; display: none;\n    bottom: 0; left: 0;\n    width: 100%; height: 20px;\n}\n.irs-with-grid .irs-grid {\n    display: block;\n}\n    .irs-grid-pol {\n        position: absolute;\n        top: 0; left: 0;\n        width: 1px; height: 8px;\n        background: #000;\n    }\n    .irs-grid-pol.small {\n        height: 4px;\n    }\n    .irs-grid-text {\n        position: absolute;\n        bottom: 0; left: 0;\n        width: 100px;\n        white-space: nowrap;\n        text-align: center;\n        font-size: 9px; line-height: 9px;\n        color: #000;\n    }\n\n.irs-disable-mask {\n    position: absolute; display: block;\n    top: 0; left: 0;\n    width: 100%; height: 100%;\n    cursor: default;\n    background: rgba(0,0,0,0.0);\n    z-index: 2;\n}\n.irs-disabled {\n    opacity: 0.4;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/ionRangeSlider/ion.rangeSlider.skinFlat.css",
    "content": "/* Ion.RangeSlider, Flat UI Skin\n// css version 1.8.5\n// by Denis Ineshin | ionden.com\n// ===================================================================================================================*/\n\n/* =====================================================================================================================\n// Skin details */\n\n.irs-line-mid,\n.irs-line-left,\n.irs-line-right,\n.irs-diapason,\n.irs-slider {\n    background: url(../images/sprite-skin-flat.png) repeat-x;\n}\n\n.irs {\n    height: 40px;\n}\n.irs-with-grid {\n    height: 60px;\n}\n.irs-line {\n    height: 12px; top: 25px;\n}\n    .irs-line-left {\n        height: 12px;\n        background-position: 0 -30px;\n    }\n    .irs-line-mid {\n        height: 12px;\n        background-position: 0 0;\n    }\n    .irs-line-right {\n        height: 12px;\n        background-position: 100% -30px;\n    }\n\n.irs-diapason {\n    height: 12px; top: 25px;\n    background-position: 0 -60px;\n}\n\n.irs-slider {\n    width: 16px; height: 18px;\n    top: 22px;\n    background-position: 0 -90px;\n}\n#irs-active-slider, .irs-slider:hover {\n    background-position: 0 -120px;\n}\n\n.irs-min, .irs-max {\n    color: #999;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    top: 0; padding: 1px 3px;\n    background: #e1e4e9;\n    border-radius: 4px;\n}\n\n.irs-from, .irs-to, .irs-single {\n    color: #fff;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    padding: 1px 5px;\n    background: #ed5565;\n    border-radius: 4px;\n}\n.irs-from:after, .irs-to:after, .irs-single:after {\n    position: absolute; display: block; content: \"\";\n    bottom: -6px; left: 50%;\n    width: 0; height: 0;\n    margin-left: -3px;\n    overflow: hidden;\n    border: 3px solid transparent;\n    border-top-color: #ed5565;\n}\n\n\n.irs-grid-pol {\n    background: #e1e4e9;\n}\n.irs-grid-text {\n    color: #999;\n}\n\n.irs-disabled {\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/jqTreeGrid/jquery.treegrid.css",
    "content": ".treegrid-indent {width:16px; height: 16px; display: inline-block; position: relative;}\n\n.treegrid-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}\n\n.treegrid-expander-expanded{background-image: url(../img/collapse.png); }\n.treegrid-expander-collapsed{background-image: url(../img/expand.png);}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/jqgrid/ui.jqgrid.css",
    "content": "/*Grid*/\n.ui-jqgrid {\n\tposition: relative;\n\tborder: 1px solid #ddd;\n    overflow: hidden;\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: 3px;\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-x:hidden;\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 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.ui-jqgrid tr.jqfoot td {}\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\tpadding : 4px 0px;\n\tposition: relative;\n\theight: 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\theight: 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\tpadding:0px 6px;\n}\n.ui-jqgrid .ui-pg-button  {\n\theight:auto;\n}\n.ui-jqgrid .ui-pg-button span {\n\tdisplay: block;\n\tmargin: 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;\n\theight:auto;\n\twidth: auto;\n\tfont-size:.9em;\n\tmargin:0;\n\tline-height: inherit;\n\tpadding: 0px 5px\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}\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\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;\n}\n.ui-jqgrid .ui-userdata-bottom {\n\tborder-left-width: 0px;    //default\n\tborder-top: 1px solid #ddd;\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;\n\theight: 18px;\n\twidth: 18px;\n\toverflow: hidden;\n}\n.ui-jqgrid .tree-leaf {\n\tposition: absolute;\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\tpadding-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\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\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%;\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"
  },
  {
    "path": "src/main/resources/static/css/plugins/multiselect/bootstrap-multiselect.css",
    "content": ".multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/nouslider/jquery.nouislider.css",
    "content": "\n/* Functional styling;\n * These styles are required for noUiSlider to function.\n * You don't need to change these rules to apply your design.\n */\n.noUi-target,\n.noUi-target * {\n-webkit-touch-callout: none;\n-webkit-user-select: none;\n-ms-touch-action: none;\n-ms-user-select: none;\n-moz-user-select: none;\n-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.noUi-base {\n\twidth: 100%;\n\theight: 100%;\n\tposition: relative;\n}\n.noUi-origin {\n\tposition: absolute;\n\tright: 0;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n}\n.noUi-handle {\n\tposition: relative;\n\tz-index: 1;\n}\n.noUi-stacking .noUi-handle {\n/* This class is applied to the lower origin when\n   its values is > 50%. */\n\tz-index: 10;\n}\n.noUi-stacking + .noUi-origin {\n/* Fix stacking order in IE7, which incorrectly\n   creates a new context for the origins. */\n\t*z-index: -1;\n}\n.noUi-state-tap .noUi-origin {\n-webkit-transition: left 0.3s, top 0.3s;\n\ttransition: left 0.3s, top 0.3s;\n}\n.noUi-state-drag * {\n\tcursor: inherit !important;\n}\n\n/* Slider size and handle placement;\n */\n.noUi-horizontal {\n\theight: 18px;\n}\n.noUi-horizontal .noUi-handle {\n\twidth: 34px;\n\theight: 28px;\n\tleft: -17px;\n\ttop: -6px;\n}\n.noUi-horizontal.noUi-extended {\n\tpadding: 0 15px;\n}\n.noUi-horizontal.noUi-extended .noUi-origin  {\n\tright: -15px;\n}\n.noUi-vertical {\n\twidth: 18px;\n}\n.noUi-vertical .noUi-handle {\n\twidth: 28px;\n\theight: 34px;\n\tleft: -6px;\n\ttop: -17px;\n}\n.noUi-vertical.noUi-extended {\n\tpadding: 15px 0;\n}\n.noUi-vertical.noUi-extended .noUi-origin  {\n\tbottom: -15px;\n}\n\n/* Styling;\n */\n.noUi-background {\n\tbackground: #FAFAFA;\n\tbox-shadow: inset 0 1px 1px #f0f0f0;\n}\n.noUi-connect {\n\tbackground: #3FB8AF;\n\tbox-shadow: inset 0 0 3px rgba(51,51,51,0.45);\n-webkit-transition: background 450ms;\n\ttransition: background 450ms;\n}\n.noUi-origin {\n\tborder-radius: 2px;\n}\n.noUi-target {\n\tborder-radius: 4px;\n\tborder: 1px solid #D3D3D3;\n\tbox-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;\n}\n.noUi-target.noUi-connect {\n\tbox-shadow: inset 0 0 3px rgba(51,51,51,0.45), 0 3px 6px -5px #BBB;\n}\n\n/* Handles and cursors;\n */\n.noUi-dragable {\n\tcursor: w-resize;\n}\n.noUi-vertical .noUi-dragable {\n\tcursor: n-resize;\n}\n.noUi-handle {\n\tborder: 1px solid #D9D9D9;\n\tborder-radius: 3px;\n\tbackground: #FFF;\n\tcursor: default;\n\tbox-shadow: inset 0 0 1px #FFF,\n\t\t\t\tinset 0 1px 7px #EBEBEB,\n\t\t\t\t0 3px 6px -3px #BBB;\n}\n.noUi-active {\n\tbox-shadow: inset 0 0 1px #FFF,\n\t\t\t\tinset 0 1px 7px #DDD,\n\t\t\t\t0 3px 6px -3px #BBB;\n}\n\n/* Handle stripes;\n */\n.noUi-handle:before,\n.noUi-handle:after {\n\tcontent: \"\";\n\tdisplay: block;\n\tposition: absolute;\n\theight: 14px;\n\twidth: 1px;\n\tbackground: #E8E7E6;\n\tleft: 14px;\n\ttop: 6px;\n}\n.noUi-handle:after {\n\tleft: 17px;\n}\n.noUi-vertical .noUi-handle:before,\n.noUi-vertical .noUi-handle:after {\n\twidth: 14px;\n\theight: 1px;\n\tleft: 6px;\n\ttop: 14px;\n}\n.noUi-vertical .noUi-handle:after {\n\ttop: 17px;\n}\n\n/* Disabled state;\n */\n[disabled].noUi-connect,\n[disabled] .noUi-connect {\n\tbackground: #B8B8B8;\n}\n[disabled] .noUi-handle {\n\tcursor: not-allowed;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/plyr/plyr.css",
    "content": "@-webkit-keyframes progress{to{background-position:40px 0}}@keyframes progress{to{background-position:40px 0}}.sr-only{position:absolute!important;clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.player{position:relative;max-width:100%;min-width:290px}.player,.player *,.player ::after,.player ::before{box-sizing:border-box}.player-video-wrapper{position:relative}.player audio,.player video{width:100%;height:auto;vertical-align:middle}.player-video-embed{padding-bottom:56.25%;height:0}.player-video-embed iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:0}.player-captions{display:none;position:absolute;bottom:0;left:0;width:100%;padding:20px 20px 30px;color:#fff;font-size:20px;text-align:center;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.player-captions span{border-radius:2px;padding:3px 10px;background:rgba(0,0,0,.9)}.player-captions span:empty{display:none}@media (min-width:768px){.player-captions{font-size:24px}}.player.captions-active .player-captions{display:block}.player.fullscreen-active .player-captions{font-size:32px}.player-controls{zoom:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;position:relative;padding:10px;background:#fff;line-height:1;text-align:center;box-shadow:0 1px 1px rgba(52,63,74,.2)}.player-controls:after,.player-controls:before{content:\"\";display:table}.player-controls:after{clear:both}.player-controls-right{display:block;margin:10px auto 0}@media (min-width:560px){.player-controls-left{float:left}.player-controls-right{float:right;margin-top:0}}.player-controls button{display:inline-block;vertical-align:middle;margin:0 2px;padding:5px 10px;overflow:hidden;border:0;background:0 0;border-radius:3px;cursor:pointer;color:#6b7d86;transition:background .3s ease,color .3s ease,opacity .3s ease}.player-controls button svg{width:18px;height:18px;display:block;fill:currentColor;transition:fill .3s ease}.player-controls button.tab-focus,.player-controls button:hover{background:#3498db;color:#fff}.player-controls button:focus{outline:0}.player-controls .icon-captions-on,.player-controls .icon-exit-fullscreen,.player-controls .icon-muted{display:none}.player-controls .player-time{display:inline-block;vertical-align:middle;margin-left:10px;color:#6b7d86;font-weight:600;font-size:14px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.player-controls .player-time+.player-time{display:none}@media (min-width:560px){.player-controls .player-time+.player-time{display:inline-block}}.player-controls .player-time+.player-time::before{content:'\\2044';margin-right:10px}.player-tooltip{position:absolute;z-index:2;bottom:100%;margin-bottom:10px;padding:10px 15px;opacity:0;background:#fff;border:1px solid #d6dadd;border-radius:3px;color:#6b7d86;font-size:14px;line-height:1.5;font-weight:600;-webkit-transform:translate(-50%,30px) scale(0);transform:translate(-50%,30px) scale(0);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;transition:-webkit-transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease}.player-tooltip::after{content:'';position:absolute;z-index:1;top:100%;left:50%;display:block;width:10px;height:10px;background:#fff;-webkit-transform:translate(-50%,-50%) rotate(45deg) translateY(1px);transform:translate(-50%,-50%) rotate(45deg) translateY(1px);border:1px solid #d6dadd;border-width:0 1px 1px 0}.player button.tab-focus:focus .player-tooltip,.player button:hover .player-tooltip{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.player button:hover .player-tooltip{z-index:3}.player-progress{position:absolute;bottom:100%;left:0;right:0;width:100%;height:10px;background:rgba(86,93,100,.2)}.player-progress-buffer[value],.player-progress-played[value],.player-progress-seek[type=range]{position:absolute;left:0;top:0;width:100%;height:10px;margin:0;padding:0;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;border:none;background:0 0}.player-progress-buffer[value]::-webkit-progress-bar,.player-progress-played[value]::-webkit-progress-bar{background:0 0}.player-progress-buffer[value]::-webkit-progress-value,.player-progress-played[value]::-webkit-progress-value{background:currentColor}.player-progress-buffer[value]::-moz-progress-bar,.player-progress-played[value]::-moz-progress-bar{background:currentColor}.player-progress-played[value]{z-index:2;color:#3498db}.player-progress-buffer[value]{color:rgba(86,93,100,.25)}.player-progress-seek[type=range]{z-index:4;cursor:pointer;outline:0}.player-progress-seek[type=range]::-webkit-slider-runnable-track{background:0 0;border:0}.player-progress-seek[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]::-moz-range-track{background:0 0;border:0}.player-progress-seek[type=range]::-moz-range-thumb{-moz-appearance:none;background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]::-ms-track{color:transparent;background:0 0;border:0}.player-progress-seek[type=range]::-ms-fill-lower,.player-progress-seek[type=range]::-ms-fill-upper{background:0 0;border:0}.player-progress-seek[type=range]::-ms-thumb{background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]:focus{outline:0}.player-progress-seek[type=range]::-moz-focus-outer{border:0}.player.loading .player-progress-buffer{-webkit-animation:progress 1s linear infinite;animation:progress 1s linear infinite;background-size:40px 40px;background-repeat:repeat-x;background-color:rgba(86,93,100,.25);background-image:linear-gradient(-45deg,rgba(0,0,0,.15) 25%,transparent 25%,transparent 50%,rgba(0,0,0,.15) 50%,rgba(0,0,0,.15) 75%,transparent 75%,transparent);color:transparent}.player-controls [data-player=pause],.player.playing .player-controls [data-player=play]{display:none}.player.playing .player-controls [data-player=pause]{display:inline-block}.player-volume[type=range]{display:inline-block;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;width:100px;margin:0 10px 0 0;padding:0;cursor:pointer;background:0 0;border:none}.player-volume[type=range]::-webkit-slider-runnable-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-webkit-slider-thumb{-webkit-appearance:none;margin-top:-3px;height:12px;width:12px;background:#6b7d86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]::-moz-range-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-moz-range-thumb{height:12px;width:12px;background:#6b7d86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]::-ms-track{height:6px;background:0 0;border-color:transparent;border-width:3px 0;color:transparent}.player-volume[type=range]::-ms-fill-lower,.player-volume[type=range]::-ms-fill-upper{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-ms-thumb{height:12px;width:12px;background:#6b7d86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]:focus{outline:0}.player-volume[type=range]:focus::-webkit-slider-thumb{background:#3498db}.player-volume[type=range]:focus::-moz-range-thumb{background:#3498db}.player-volume[type=range]:focus::-ms-thumb{background:#3498db}.player-audio.ios .player-controls-right,.player.ios .player-volume,.player.ios [data-player=mute]{display:none}.player-audio.ios .player-controls-left{float:none}.player-audio .player-controls{padding-top:20px}.player-audio .player-progress{bottom:auto;top:0;background:#d6dadd}.player-fullscreen,.player.fullscreen-active{position:fixed;top:0;left:0;right:0;bottom:0;height:100%;width:100%;z-index:10000000;background:#000}.player-fullscreen video,.player.fullscreen-active video{height:100%}.player-fullscreen .player-video-wrapper,.player.fullscreen-active .player-video-wrapper{height:100%;width:100%}.player-fullscreen .player-controls,.player.fullscreen-active .player-controls{position:absolute;bottom:0;left:0;right:0}.player-fullscreen.fullscreen-hide-controls.playing .player-controls,.player.fullscreen-active.fullscreen-hide-controls.playing .player-controls{-webkit-transform:translateY(100%) translateY(5px);transform:translateY(100%) translateY(5px);transition:-webkit-transform .3s .2s ease;transition:transform .3s .2s ease}.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-controls,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-controls{-webkit-transform:translateY(0);transform:translateY(0)}.player-fullscreen.fullscreen-hide-controls.playing .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing .player-captions{bottom:5px;transition:bottom .3s .2s ease}.player-fullscreen .player-captions,.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-captions,.player.fullscreen-active .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-captions{top:auto;bottom:90px}@media (min-width:560px){.player-fullscreen .player-captions,.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-captions,.player.fullscreen-active .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-captions{bottom:60px}}.player.captions-active .player-controls .icon-captions-on,.player.fullscreen-active .icon-exit-fullscreen,.player.muted .player-controls .icon-muted{display:block}.player [data-player=captions],.player [data-player=fullscreen],.player.captions-active .player-controls .icon-captions-on+svg,.player.fullscreen-active .icon-exit-fullscreen+svg,.player.muted .player-controls .icon-muted+svg{display:none}.player.captions-enabled [data-player=captions],.player.fullscreen-enabled [data-player=fullscreen]{display:inline-block}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/simditor/simditor.css",
    "content": ".simditor {\n  position: relative;\n  border: 1px solid #c9d8db;\n}\n.simditor .simditor-wrapper {\n  position: relative;\n  background: #ffffff;\n  overflow: hidden;\n}\n.simditor .simditor-wrapper .simditor-placeholder {\n  display: none;\n  position: absolute;\n  left: 0;\n  z-index: 0;\n  padding: 22px 15px;\n  font-size: 16px;\n  font-family: arial, sans-serif;\n  line-height: 1.5;\n  color: #999999;\n  background: transparent;\n}\n.simditor .simditor-wrapper.toolbar-floating .simditor-toolbar {\n  position: fixed;\n  top: 0;\n  z-index: 10;\n  box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);\n}\n.simditor .simditor-wrapper .simditor-image-loading {\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.4);\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 2;\n}\n.simditor .simditor-wrapper .simditor-image-loading span {\n  width: 30px;\n  height: 30px;\n  background: #ffffff url(../../../img/loading-upload.gif) no-repeat center center;\n  border-radius: 30px;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin: -15px 0 0 -15px;\n  box-shadow: 0 0 8px rgba(0, 0, 0, 0.4);\n}\n.simditor .simditor-wrapper .simditor-image-loading.uploading span {\n  background: #ffffff;\n  color: #333333;\n  font-size: 14px;\n  line-height: 30px;\n  text-align: center;\n}\n.simditor .simditor-body {\n  padding: 22px 15px 40px;\n  min-height: 300px;\n  outline: none;\n  cursor: text;\n  position: relative;\n  z-index: 1;\n  background: transparent;\n}\n.simditor .simditor-body a.selected {\n  background: #b3d4fd;\n}\n.simditor .simditor-body a.simditor-mention {\n  cursor: pointer;\n}\n.simditor .simditor-body .simditor-table {\n  position: relative;\n}\n.simditor .simditor-body .simditor-table.resizing {\n  cursor: col-resize;\n}\n.simditor .simditor-body .simditor-table .simditor-resize-handle {\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 10px;\n  height: 100%;\n  cursor: col-resize;\n}\n.simditor .simditor-body pre {\n  /*min-height: 28px;*/\n  box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  word-wrap: break-word !important;\n  white-space: pre-wrap !important;\n}\n.simditor .simditor-body img {\n  cursor: pointer;\n}\n.simditor .simditor-body img.selected {\n  box-shadow: 0 0 0 4px #cccccc;\n}\n.simditor .simditor-paste-area,\n.simditor .simditor-clean-paste-area {\n  background: transparent;\n  border: none;\n  outline: none;\n  resize: none;\n  padding: 0;\n  margin: 0;\n}\n.simditor .simditor-toolbar {\n  border-bottom: 1px solid #eeeeee;\n  background: #ffffff;\n  width: 100%;\n}\n.simditor .simditor-toolbar > ul {\n  margin: 0;\n  padding: 0 0 0 6px;\n  list-style: none;\n}\n.simditor .simditor-toolbar > ul:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n.simditor .simditor-toolbar > ul > li {\n  position: relative;\n  float: left;\n}\n.simditor .simditor-toolbar > ul > li > span.separator {\n  display: block;\n  float: left;\n  background: #cfcfcf;\n  width: 1px;\n  height: 18px;\n  margin: 11px 15px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item {\n  display: block;\n  float: left;\n  width: 50px;\n  height: 40px;\n  outline: none;\n  color: #333333;\n  font-size: 15px;\n  line-height: 40px;\n  text-align: center;\n  text-decoration: none;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item span {\n  opacity: 0.6;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item span.fa {\n  display: inline;\n  line-height: normal;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item:hover span {\n  opacity: 1;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.active {\n  background: #eeeeee;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.active span {\n  opacity: 1;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled {\n  cursor: default;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled span {\n  opacity: 0.3;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title span:before {\n  content: \"T\";\n  font-size: 19px;\n  font-weight: bold;\n  font-family: 'Times New Roman';\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h1 span:before {\n  content: 'H1';\n  font-size: 18px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h2 span:before {\n  content: 'H2';\n  font-size: 18px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h3 span:before {\n  content: 'H3';\n  font-size: 18px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-color {\n  font-size: 14px;\n  position: relative;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-color span:before {\n  position: relative;\n  top: -2px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-color:after {\n  content: '';\n  display: block;\n  width: 14px;\n  height: 4px;\n  background: #cccccc;\n  position: absolute;\n  top: 26px;\n  left: 50%;\n  margin: 0 0 0 -7px;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-color:hover:after {\n  background: #999999;\n}\n.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-color.disabled:after {\n  background: #dfdfdf;\n}\n.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item {\n  position: relative;\n  z-index: 21;\n  background: #ffffff;\n  box-shadow: 0 -3px 3px rgba(0, 0, 0, 0.2);\n}\n.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item span {\n  opacity: 1;\n}\n.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item.toolbar-item-color:after {\n  background: #999999;\n}\n.simditor .simditor-toolbar > ul > li.menu-on .toolbar-menu {\n  display: block;\n}\n.simditor .simditor-toolbar .toolbar-menu {\n  display: none;\n  position: absolute;\n  top: 40px;\n  left: 0;\n  z-index: 20;\n  background: #ffffff;\n  text-align: left;\n  box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\n}\n.simditor .simditor-toolbar .toolbar-menu ul {\n  min-width: 160px;\n  list-style: none;\n  margin: 0;\n  padding: 10px 1px;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item {\n  display: block;\n  font-size: 16px;\n  line-height: 2em;\n  padding: 0 10px;\n  text-decoration: none;\n  color: #666666;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item:hover {\n  background: #f6f6f6;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h1 {\n  font-size: 24px;\n  color: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h2 {\n  font-size: 22px;\n  color: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h3 {\n  font-size: 20px;\n  color: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h4 {\n  font-size: 18px;\n  color: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h5 {\n  font-size: 16px;\n  color: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu ul > li .separator {\n  display: block;\n  border-top: 1px solid #cccccc;\n  height: 0;\n  line-height: 0;\n  font-size: 0;\n  margin: 6px 0;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color {\n  width: 96px;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list {\n  height: 40px;\n  margin: 10px 6px 6px 10px;\n  padding: 0;\n  min-width: 0;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li {\n  float: left;\n  margin: 0 4px 4px 0;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color {\n  display: block;\n  width: 16px;\n  height: 16px;\n  background: #dfdfdf;\n  border-radius: 2px;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color:hover {\n  opacity: 0.8;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color.font-color-default {\n  background: #333333;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-1 {\n  background: #E33737;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-2 {\n  background: #e28b41;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-3 {\n  background: #c8a732;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-4 {\n  background: #209361;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-5 {\n  background: #418caf;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-6 {\n  background: #aa8773;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-7 {\n  background: #999999;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table {\n  background: #ffffff;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table {\n  border: none;\n  border-collapse: collapse;\n  border-spacing: 0;\n  table-layout: fixed;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td {\n  height: 16px;\n  padding: 0;\n  border: 2px solid #ffffff;\n  background: #f3f3f3;\n  cursor: pointer;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td:before {\n  width: 16px;\n  display: block;\n  content: \"\";\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td.selected {\n  background: #cfcfcf;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table {\n  display: none;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table ul {\n  min-width: 240px;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image {\n  position: relative;\n  overflow: hidden;\n}\n.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image input[type=file] {\n  position: absolute;\n  right: 0px;\n  top: 0px;\n  opacity: 0;\n  font-size: 100px;\n  cursor: pointer;\n}\n.simditor .simditor-popover {\n  display: none;\n  padding: 5px 8px 0;\n  background: #ffffff;\n  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);\n  border-radius: 2px;\n  position: absolute;\n  z-index: 2;\n}\n.simditor .simditor-popover .settings-field {\n  margin: 0 0 5px 0;\n  font-size: 12px;\n  height: 25px;\n  line-height: 25px;\n}\n.simditor .simditor-popover .settings-field label {\n  margin: 0 8px 0 0;\n  float: left;\n}\n.simditor .simditor-popover .settings-field input[type=text] {\n  float: left;\n  width: 200px;\n  box-sizing: border-box;\n  font-size: 12px;\n}\n.simditor .simditor-popover .settings-field input[type=text].image-size {\n  width: 87px;\n}\n.simditor .simditor-popover .settings-field .times {\n  float: left;\n  width: 26px;\n  font-size: 12px;\n  text-align: center;\n}\n.simditor .simditor-popover.link-popover .btn-unlink, .simditor .simditor-popover.image-popover .btn-upload, .simditor .simditor-popover.image-popover .btn-restore {\n  float: left;\n  margin: 0 0 0 8px;\n  color: #333333;\n  font-size: 14px;\n  outline: 0;\n}\n.simditor .simditor-popover.link-popover .btn-unlink span, .simditor .simditor-popover.image-popover .btn-upload span, .simditor .simditor-popover.image-popover .btn-restore span {\n  opacity: 0.6;\n}\n.simditor .simditor-popover.link-popover .btn-unlink:hover span, .simditor .simditor-popover.image-popover .btn-upload:hover span, .simditor .simditor-popover.image-popover .btn-restore:hover span {\n  opacity: 1;\n}\n.simditor .simditor-popover.image-popover .btn-upload {\n  position: relative;\n  display: inline-block;\n  overflow: hidden;\n}\n.simditor .simditor-popover.image-popover .btn-upload input[type=file] {\n  position: absolute;\n  right: 0px;\n  top: 0px;\n  opacity: 0;\n  height: 100%;\n  width: 28px;\n}\n.simditor.simditor-mobile .simditor-toolbar > ul > li > .toolbar-item {\n  width: 46px;\n}\n.simditor.simditor-mobile .simditor-wrapper.toolbar-floating .simditor-toolbar {\n  position: absolute;\n  top: 0;\n  z-index: 10;\n  box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);\n}\n\n.simditor .simditor-body, .editor-style {\n  font-size: 16px;\n  font-family: arial, sans-serif;\n  line-height: 1.6;\n  color: #333;\n  outline: none;\n  word-wrap: break-word;\n}\n.simditor .simditor-body > :first-child, .editor-style > :first-child {\n  margin-top: 0 !important;\n}\n.simditor .simditor-body a, .editor-style a {\n  color: #4298BA;\n  text-decoration: none;\n  word-break: break-all;\n}\n.simditor .simditor-body a:visited, .editor-style a:visited {\n  color: #4298BA;\n}\n.simditor .simditor-body a:hover, .editor-style a:hover {\n  color: #0F769F;\n}\n.simditor .simditor-body a:active, .editor-style a:active {\n  color: #9E792E;\n}\n.simditor .simditor-body a:hover, .simditor .simditor-body a:active, .editor-style a:hover, .editor-style a:active {\n  outline: 0;\n}\n.simditor .simditor-body h1, .simditor .simditor-body h2, .simditor .simditor-body h3, .simditor .simditor-body h4, .simditor .simditor-body h5, .simditor .simditor-body h6, .editor-style h1, .editor-style h2, .editor-style h3, .editor-style h4, .editor-style h5, .editor-style h6 {\n  font-weight: normal;\n  margin: 40px 0 20px;\n  color: #000000;\n}\n.simditor .simditor-body h1, .editor-style h1 {\n  font-size: 24px;\n}\n.simditor .simditor-body h2, .editor-style h2 {\n  font-size: 22px;\n}\n.simditor .simditor-body h3, .editor-style h3 {\n  font-size: 20px;\n}\n.simditor .simditor-body h4, .editor-style h4 {\n  font-size: 18px;\n}\n.simditor .simditor-body h5, .editor-style h5 {\n  font-size: 16px;\n}\n.simditor .simditor-body h6, .editor-style h6 {\n  font-size: 16px;\n}\n.simditor .simditor-body p, .simditor .simditor-body div, .editor-style p, .editor-style div {\n  word-wrap: break-word;\n  margin: 0 0 15px 0;\n  color: #333;\n  word-wrap: break-word;\n}\n.simditor .simditor-body b, .simditor .simditor-body strong, .editor-style b, .editor-style strong {\n  font-weight: bold;\n}\n.simditor .simditor-body i, .simditor .simditor-body em, .editor-style i, .editor-style em {\n  font-style: italic;\n}\n.simditor .simditor-body u, .editor-style u {\n  text-decoration: underline;\n}\n.simditor .simditor-body strike, .simditor .simditor-body del, .editor-style strike, .editor-style del {\n  text-decoration: line-through;\n}\n.simditor .simditor-body ul, .simditor .simditor-body ol, .editor-style ul, .editor-style ol {\n  list-style: disc outside none;\n  margin: 15px 0;\n  padding: 0 0 0 40px;\n  line-height: 1.6;\n}\n.simditor .simditor-body ul ul, .simditor .simditor-body ul ol, .simditor .simditor-body ol ul, .simditor .simditor-body ol ol, .editor-style ul ul, .editor-style ul ol, .editor-style ol ul, .editor-style ol ol {\n  padding-left: 30px;\n}\n.simditor .simditor-body ul ul, .simditor .simditor-body ol ul, .editor-style ul ul, .editor-style ol ul {\n  list-style: circle outside none;\n}\n.simditor .simditor-body ul ul ul, .simditor .simditor-body ol ul ul, .editor-style ul ul ul, .editor-style ol ul ul {\n  list-style: square outside none;\n}\n.simditor .simditor-body ol, .editor-style ol {\n  list-style: decimal;\n}\n.simditor .simditor-body blockquote, .editor-style blockquote {\n  border-left: 6px solid #ddd;\n  padding: 5px 0 5px 10px;\n  margin: 15px 0 15px 15px;\n}\n.simditor .simditor-body blockquote > :first-child, .editor-style blockquote > :first-child {\n  margin-top: 0;\n}\n.simditor .simditor-body pre, .editor-style pre {\n  padding: 10px 5px 10px 10px;\n  margin: 15px 0;\n  display: block;\n  line-height: 18px;\n  background: #F0F0F0;\n  border-radius: 3px;\n  font-size: 13px;\n  font-family: 'monaco', 'Consolas', \"Liberation Mono\", Courier, monospace;\n  overflow-x: auto;\n  white-space: nowrap;\n}\n.simditor .simditor-body code, .editor-style code {\n  display: inline-block;\n  padding: 0 4px;\n  margin: 0 5px;\n  background: #eeeeee;\n  border-radius: 3px;\n  font-size: 13px;\n  font-family: 'monaco', 'Consolas', \"Liberation Mono\", Courier, monospace;\n}\n.simditor .simditor-body hr, .editor-style hr {\n  display: block;\n  height: 0px;\n  border: 0;\n  border-top: 1px solid #ccc;\n  margin: 15px 0;\n  padding: 0;\n}\n.simditor .simditor-body table, .editor-style table {\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: collapse;\n  border-spacing: 0;\n  margin: 15px 0;\n}\n.simditor .simditor-body table thead, .editor-style table thead {\n  background-color: #f9f9f9;\n}\n.simditor .simditor-body table td, .editor-style table td {\n  min-width: 40px;\n  height: 30px;\n  border: 1px solid #ccc;\n  vertical-align: top;\n  padding: 2px 4px;\n  box-sizing: border-box;\n}\n.simditor .simditor-body table td.active, .editor-style table td.active {\n  background-color: #ffffee;\n}\n.simditor .simditor-body img, .editor-style img {\n  margin: 0 5px;\n  vertical-align: middle;\n}\n.simditor .simditor-body *[data-indent=\"0\"], .editor-style *[data-indent=\"0\"] {\n  margin-left: 0px;\n}\n.simditor .simditor-body *[data-indent=\"1\"], .editor-style *[data-indent=\"1\"] {\n  margin-left: 40px;\n}\n.simditor .simditor-body *[data-indent=\"2\"], .editor-style *[data-indent=\"2\"] {\n  margin-left: 80px;\n}\n.simditor .simditor-body *[data-indent=\"3\"], .editor-style *[data-indent=\"3\"] {\n  margin-left: 120px;\n}\n.simditor .simditor-body *[data-indent=\"4\"], .editor-style *[data-indent=\"4\"] {\n  margin-left: 160px;\n}\n.simditor .simditor-body *[data-indent=\"5\"], .editor-style *[data-indent=\"5\"] {\n  margin-left: 200px;\n}\n.simditor .simditor-body *[data-indent=\"6\"], .editor-style *[data-indent=\"6\"] {\n  margin-left: 240px;\n}\n.simditor .simditor-body *[data-indent=\"7\"], .editor-style *[data-indent=\"7\"] {\n  margin-left: 280px;\n}\n.simditor .simditor-body *[data-indent=\"8\"], .editor-style *[data-indent=\"8\"] {\n  margin-left: 320px;\n}\n.simditor .simditor-body *[data-indent=\"9\"], .editor-style *[data-indent=\"9\"] {\n  margin-left: 360px;\n}\n.simditor .simditor-body *[data-indent=\"10\"], .editor-style *[data-indent=\"10\"] {\n  margin-left: 400px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/steps/jquery.steps.css",
    "content": "/*\n    Common\n*/\n\n.wizard,\n.tabcontrol\n{\n    display: block;\n    width: 100%;\n    overflow: hidden;\n}\n\n.wizard a,\n.tabcontrol a\n{\n    outline: 0;\n}\n\n.wizard ul,\n.tabcontrol ul\n{\n    list-style: none !important;\n    padding: 0;\n    margin: 0;\n}\n\n.wizard ul > li,\n.tabcontrol ul > li\n{\n    display: block;\n    padding: 0;\n}\n\n/* Accessibility */\n.wizard > .steps .current-info,\n.tabcontrol > .steps .current-info\n{\n    position: absolute;\n    left: -999em;\n}\n\n.wizard > .content > .title,\n.tabcontrol > .content > .title\n{\n    position: absolute;\n    left: -999em;\n}\n\n\n\n/*\n    Wizard\n*/\n\n.wizard > .steps\n{\n    position: relative;\n    display: block;\n    width: 100%;\n}\n\n.wizard.vertical > .steps\n{\n    display: inline;\n    float: left;\n    width: 30%;\n}\n\n.wizard > .steps > ul > li\n{\n    width: 25%;\n}\n\n.wizard > .steps > ul > li,\n.wizard > .actions > ul > li\n{\n    float: left;\n}\n\n.wizard.vertical > .steps > ul > li\n{\n    float: none;\n    width: 100%;\n}\n\n.wizard > .steps a,\n.wizard > .steps a:hover,\n.wizard > .steps a:active\n{\n    display: block;\n    width: auto;\n    margin: 0 0.5em 0.5em;\n    padding: 8px;\n    text-decoration: none;\n\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n}\n\n.wizard > .steps .disabled a,\n.wizard > .steps .disabled a:hover,\n.wizard > .steps .disabled a:active\n{\n    background: #eee;\n    color: #aaa;\n    cursor: default;\n}\n\n.wizard > .steps .current a,\n.wizard > .steps .current a:hover,\n.wizard > .steps .current a:active\n{\n    background: #1AB394;\n    color: #fff;\n    cursor: default;\n}\n\n.wizard > .steps .done a,\n.wizard > .steps .done a:hover,\n.wizard > .steps .done a:active\n{\n    background: #6fd1bd;\n    color: #fff;\n}\n\n.wizard > .steps .error a,\n.wizard > .steps .error a:hover,\n.wizard > .steps .error a:active\n{\n    background: #ED5565 ;\n    color: #fff;\n}\n\n.wizard > .content\n{\n    background: #eee;\n    display: block;\n    margin: 5px 5px 10px 5px;\n    min-height: 120px;\n    overflow: hidden;\n    position: relative;\n    width: auto;\n\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n}\n\n.wizard-big.wizard > .content {\n    min-height: 320px;\n}\n.wizard.vertical > .content\n{\n    display: inline;\n    float: left;\n    margin: 0 2.5% 0.5em 2.5%;\n    width: 65%;\n}\n\n.wizard > .content > .body\n{\n    float: left;\n    position: absolute;\n    width: 95%;\n    height: 95%;\n    padding: 2.5%;\n}\n\n.wizard > .content > .body ul\n{\n    list-style: disc !important;\n}\n\n.wizard > .content > .body ul > li\n{\n    display: list-item;\n}\n\n.wizard > .content > .body > iframe\n{\n    border: 0 none;\n    width: 100%;\n    height: 100%;\n}\n\n.wizard > .content > .body input\n{\n    display: block;\n    border: 1px solid #ccc;\n}\n\n.wizard > .content > .body input[type=\"checkbox\"]\n{\n    display: inline-block;\n}\n\n.wizard > .content > .body input.error\n{\n    background: rgb(251, 227, 228);\n    border: 1px solid #fbc2c4;\n    color: #8a1f11;\n}\n\n.wizard > .content > .body label\n{\n    display: inline-block;\n    margin-bottom: 0.5em;\n}\n\n.wizard > .content > .body label.error\n{\n    color: #8a1f11;\n    display: inline-block;\n    margin-left: 1.5em;\n}\n\n.wizard > .actions\n{\n    position: relative;\n    display: block;\n    text-align: right;\n    width: 100%;\n}\n\n.wizard.vertical > .actions\n{\n    display: inline;\n    float: right;\n    margin: 0 2.5%;\n    width: 95%;\n}\n\n.wizard > .actions > ul\n{\n    display: inline-block;\n    text-align: right;\n}\n\n.wizard > .actions > ul > li\n{\n    margin: 0 0.5em;\n}\n\n.wizard.vertical > .actions > ul > li\n{\n    margin: 0 0 0 1em;\n}\n\n.wizard > .actions a,\n.wizard > .actions a:hover,\n.wizard > .actions a:active\n{\n    background: #1AB394;\n    color: #fff;\n    display: block;\n    padding: 0.5em 1em;\n    text-decoration: none;\n\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n}\n\n.wizard > .actions .disabled a,\n.wizard > .actions .disabled a:hover,\n.wizard > .actions .disabled a:active\n{\n    background: #eee;\n    color: #aaa;\n}\n\n.wizard > .loading\n{\n}\n\n.wizard > .loading .spinner\n{\n}\n\n\n\n/*\n    Tabcontrol\n*/\n\n.tabcontrol > .steps\n{\n    position: relative;\n    display: block;\n    width: 100%;\n}\n\n.tabcontrol > .steps > ul\n{\n    position: relative;\n    margin: 6px 0 0 0;\n    top: 1px;\n    z-index: 1;\n}\n\n.tabcontrol > .steps > ul > li\n{\n    float: left;\n    margin: 5px 2px 0 0;\n    padding: 1px;\n\n    -webkit-border-top-left-radius: 5px;\n    -webkit-border-top-right-radius: 5px;\n    -moz-border-radius-topleft: 5px;\n    -moz-border-radius-topright: 5px;\n    border-top-left-radius: 5px;\n    border-top-right-radius: 5px;\n}\n\n.tabcontrol > .steps > ul > li:hover\n{\n    background: #edecec;\n    border: 1px solid #bbb;\n    padding: 0;\n}\n\n.tabcontrol > .steps > ul > li.current\n{\n    background: #fff;\n    border: 1px solid #bbb;\n    border-bottom: 0 none;\n    padding: 0 0 1px 0;\n    margin-top: 0;\n}\n\n.tabcontrol > .steps > ul > li > a\n{\n    color: #5f5f5f;\n    display: inline-block;\n    border: 0 none;\n    margin: 0;\n    padding: 10px 30px;\n    text-decoration: none;\n}\n\n.tabcontrol > .steps > ul > li > a:hover\n{\n    text-decoration: none;\n}\n\n.tabcontrol > .steps > ul > li.current > a\n{\n    padding: 15px 30px 10px 30px;\n}\n\n.tabcontrol > .content\n{\n    position: relative;\n    display: inline-block;\n    width: 100%;\n    height: 35em;\n    overflow: hidden;\n    border-top: 1px solid #bbb;\n    padding-top: 20px;\n}\n\n.tabcontrol > .content > .body\n{\n    float: left;\n    position: absolute;\n    width: 95%;\n    height: 95%;\n    padding: 2.5%;\n}\n\n.tabcontrol > .content > .body ul\n{\n    list-style: disc !important;\n}\n\n.tabcontrol > .content > .body ul > li\n{\n    display: list-item;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/summernote/summernote-0.8.8.css",
    "content": "@font-face{font-family:\"summernote\";font-style:normal;font-weight:normal;src:url(\"./font/summernote.eot?0d0d5fac99cc8774d89eb08b1a8323c4\");src:url(\"./font/summernote.eot?#iefix\") format(\"embedded-opentype\"),url(\"./font/summernote.woff?0d0d5fac99cc8774d89eb08b1a8323c4\") format(\"woff\"),url(\"./font/summernote.ttf?0d0d5fac99cc8774d89eb08b1a8323c4\") format(\"truetype\")}[class^=\"note-icon-\"]:before,[class*=\" note-icon-\"]:before{display:inline-block;font:normal normal normal 14px summernote;font-size:inherit;-webkit-font-smoothing:antialiased;text-decoration:inherit;text-rendering:auto;text-transform:none;vertical-align:middle;speak:none;-moz-osx-font-smoothing:grayscale}.note-icon-align-center:before,.note-icon-align-indent:before,.note-icon-align-justify:before,.note-icon-align-left:before,.note-icon-align-outdent:before,.note-icon-align-right:before,.note-icon-align:before,.note-icon-arrow-circle-down:before,.note-icon-arrow-circle-left:before,.note-icon-arrow-circle-right:before,.note-icon-arrow-circle-up:before,.note-icon-arrows-alt:before,.note-icon-arrows-h:before,.note-icon-arrows-v:before,.note-icon-bold:before,.note-icon-caret:before,.note-icon-chain-broken:before,.note-icon-circle:before,.note-icon-close:before,.note-icon-code:before,.note-icon-col-after:before,.note-icon-col-before:before,.note-icon-col-remove:before,.note-icon-eraser:before,.note-icon-font:before,.note-icon-frame:before,.note-icon-italic:before,.note-icon-link:before,.note-icon-magic:before,.note-icon-menu-check:before,.note-icon-minus:before,.note-icon-orderedlist:before,.note-icon-pencil:before,.note-icon-picture:before,.note-icon-question:before,.note-icon-redo:before,.note-icon-row-above:before,.note-icon-row-below:before,.note-icon-row-remove:before,.note-icon-special-character:before,.note-icon-square:before,.note-icon-strikethrough:before,.note-icon-subscript:before,.note-icon-summernote:before,.note-icon-superscript:before,.note-icon-table:before,.note-icon-text-height:before,.note-icon-trash:before,.note-icon-underline:before,.note-icon-undo:before,.note-icon-unorderedlist:before,.note-icon-video:before{display:inline-block;font-family:\"summernote\";font-style:normal;font-weight:normal;text-decoration:inherit}.note-icon-align-center:before{content:\"\\f101\"}.note-icon-align-indent:before{content:\"\\f102\"}.note-icon-align-justify:before{content:\"\\f103\"}.note-icon-align-left:before{content:\"\\f104\"}.note-icon-align-outdent:before{content:\"\\f105\"}.note-icon-align-right:before{content:\"\\f106\"}.note-icon-align:before{content:\"\\f107\"}.note-icon-arrow-circle-down:before{content:\"\\f108\"}.note-icon-arrow-circle-left:before{content:\"\\f109\"}.note-icon-arrow-circle-right:before{content:\"\\f10a\"}.note-icon-arrow-circle-up:before{content:\"\\f10b\"}.note-icon-arrows-alt:before{content:\"\\f10c\"}.note-icon-arrows-h:before{content:\"\\f10d\"}.note-icon-arrows-v:before{content:\"\\f10e\"}.note-icon-bold:before{content:\"\\f10f\"}.note-icon-caret:before{content:\"\\f110\"}.note-icon-chain-broken:before{content:\"\\f111\"}.note-icon-circle:before{content:\"\\f112\"}.note-icon-close:before{content:\"\\f113\"}.note-icon-code:before{content:\"\\f114\"}.note-icon-col-after:before{content:\"\\f115\"}.note-icon-col-before:before{content:\"\\f116\"}.note-icon-col-remove:before{content:\"\\f117\"}.note-icon-eraser:before{content:\"\\f118\"}.note-icon-font:before{content:\"\\f119\"}.note-icon-frame:before{content:\"\\f11a\"}.note-icon-italic:before{content:\"\\f11b\"}.note-icon-link:before{content:\"\\f11c\"}.note-icon-magic:before{content:\"\\f11d\"}.note-icon-menu-check:before{content:\"\\f11e\"}.note-icon-minus:before{content:\"\\f11f\"}.note-icon-orderedlist:before{content:\"\\f120\"}.note-icon-pencil:before{content:\"\\f121\"}.note-icon-picture:before{content:\"\\f122\"}.note-icon-question:before{content:\"\\f123\"}.note-icon-redo:before{content:\"\\f124\"}.note-icon-row-above:before{content:\"\\f125\"}.note-icon-row-below:before{content:\"\\f126\"}.note-icon-row-remove:before{content:\"\\f127\"}.note-icon-special-character:before{content:\"\\f128\"}.note-icon-square:before{content:\"\\f129\"}.note-icon-strikethrough:before{content:\"\\f12a\"}.note-icon-subscript:before{content:\"\\f12b\"}.note-icon-summernote:before{content:\"\\f12c\"}.note-icon-superscript:before{content:\"\\f12d\"}.note-icon-table:before{content:\"\\f12e\"}.note-icon-text-height:before{content:\"\\f12f\"}.note-icon-trash:before{content:\"\\f130\"}.note-icon-underline:before{content:\"\\f131\"}.note-icon-undo:before{content:\"\\f132\"}.note-icon-unorderedlist:before{content:\"\\f133\"}.note-icon-video:before{content:\"\\f134\"}.note-editor{position:relative}.note-editor .note-dropzone{position:absolute;z-index:100;display:none;color:#87cefa;background-color:white;opacity:.95}.note-editor .note-dropzone .note-dropzone-message{display:table-cell;font-size:28px;font-weight:bold;text-align:center;vertical-align:middle}.note-editor .note-dropzone.hover{color:#098ddf}.note-editor.dragover .note-dropzone{display:table}.note-editor .note-editing-area{position:relative}.note-editor .note-editing-area .note-editable{outline:0}.note-editor .note-editing-area .note-editable sup{vertical-align:super}.note-editor .note-editing-area .note-editable sub{vertical-align:sub}.note-editor .note-editing-area img.note-float-left{margin-right:10px}.note-editor .note-editing-area img.note-float-right{margin-left:10px}.note-editor.note-frame{border:1px solid #a9a9a9}.note-editor.note-frame.codeview .note-editing-area .note-editable{display:none}.note-editor.note-frame.codeview .note-editing-area .note-codable{display:block}.note-editor.note-frame .note-editing-area{overflow:hidden}.note-editor.note-frame .note-editing-area .note-editable{padding:10px;overflow:auto;color:#000;background-color:#fff}.note-editor.note-frame .note-editing-area .note-editable[contenteditable=\"false\"]{background-color:#e5e5e5}.note-editor.note-frame .note-editing-area .note-codable{display:none;width:100%;padding:10px;margin-bottom:0;font-family:Menlo,Monaco,monospace,sans-serif;font-size:14px;color:#ccc;background-color:#222;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;box-shadow:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;resize:none}.note-editor.note-frame.fullscreen{position:fixed;top:0;left:0;z-index:1050;width:100%!important}.note-editor.note-frame.fullscreen .note-editable{background-color:white}.note-editor.note-frame.fullscreen .note-resizebar{display:none}.note-editor.note-frame .note-statusbar{background-color:#f5f5f5;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.note-editor.note-frame .note-statusbar .note-resizebar{width:100%;height:8px;padding-top:1px;cursor:ns-resize}.note-editor.note-frame .note-statusbar .note-resizebar .note-icon-bar{width:20px;margin:1px auto;border-top:1px solid #a9a9a9}.note-editor.note-frame .note-placeholder{padding:10px}.note-popover.popover{max-width:none}.note-popover.popover .popover-content a{display:inline-block;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.note-popover.popover .arrow{left:20px!important}.note-popover .popover-content,.panel-heading.note-toolbar{padding:0 0 5px 5px;margin:0}.note-popover .popover-content>.btn-group,.panel-heading.note-toolbar>.btn-group{margin-top:5px;margin-right:5px;margin-left:0}.note-popover .popover-content .btn-group .note-table,.panel-heading.note-toolbar .btn-group .note-table{min-width:0;padding:5px}.note-popover .popover-content .btn-group .note-table .note-dimension-picker,.panel-heading.note-toolbar .btn-group .note-table .note-dimension-picker{font-size:18px}.note-popover .popover-content .btn-group .note-table .note-dimension-picker .note-dimension-picker-mousecatcher,.panel-heading.note-toolbar .btn-group .note-table .note-dimension-picker .note-dimension-picker-mousecatcher{position:absolute!important;z-index:3;width:10em;height:10em;cursor:pointer}.note-popover .popover-content .btn-group .note-table .note-dimension-picker .note-dimension-picker-unhighlighted,.panel-heading.note-toolbar .btn-group .note-table .note-dimension-picker .note-dimension-picker-unhighlighted{position:relative!important;z-index:1;width:5em;height:5em;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat}.note-popover .popover-content .btn-group .note-table .note-dimension-picker .note-dimension-picker-highlighted,.panel-heading.note-toolbar .btn-group .note-table .note-dimension-picker .note-dimension-picker-highlighted{position:absolute!important;z-index:2;width:1em;height:1em;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIjd6vvD2f9LKLW+AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKwNDEVT0AAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat}.note-popover .popover-content .note-style h1,.panel-heading.note-toolbar .note-style h1,.note-popover .popover-content .note-style h2,.panel-heading.note-toolbar .note-style h2,.note-popover .popover-content .note-style h3,.panel-heading.note-toolbar .note-style h3,.note-popover .popover-content .note-style h4,.panel-heading.note-toolbar .note-style h4,.note-popover .popover-content .note-style h5,.panel-heading.note-toolbar .note-style h5,.note-popover .popover-content .note-style h6,.panel-heading.note-toolbar .note-style h6,.note-popover .popover-content .note-style blockquote,.panel-heading.note-toolbar .note-style blockquote{margin:0}.note-popover .popover-content .note-color .dropdown-toggle,.panel-heading.note-toolbar .note-color .dropdown-toggle{width:20px;padding-left:5px}.note-popover .popover-content .note-color .dropdown-menu,.panel-heading.note-toolbar .note-color .dropdown-menu{min-width:337px}.note-popover .popover-content .note-color .dropdown-menu .note-palette,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette{display:inline-block;width:160px;margin:0}.note-popover .popover-content .note-color .dropdown-menu .note-palette:first-child,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette:first-child{margin:0 5px}.note-popover .popover-content .note-color .dropdown-menu .note-palette .note-palette-title,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette .note-palette-title{margin:2px 7px;font-size:12px;text-align:center;border-bottom:1px solid #eee}.note-popover .popover-content .note-color .dropdown-menu .note-palette .note-color-reset,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette .note-color-reset{width:100%;padding:0 3px;margin:3px;font-size:11px;cursor:pointer;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.note-popover .popover-content .note-color .dropdown-menu .note-palette .note-color-row,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette .note-color-row{height:20px}.note-popover .popover-content .note-color .dropdown-menu .note-palette .note-color-reset:hover,.panel-heading.note-toolbar .note-color .dropdown-menu .note-palette .note-color-reset:hover{background:#eee}.note-popover .popover-content .note-para .dropdown-menu,.panel-heading.note-toolbar .note-para .dropdown-menu{min-width:216px;padding:5px}.note-popover .popover-content .note-para .dropdown-menu>div:first-child,.panel-heading.note-toolbar .note-para .dropdown-menu>div:first-child{margin-right:5px}.note-popover .popover-content .dropdown-menu,.panel-heading.note-toolbar .dropdown-menu{min-width:90px}.note-popover .popover-content .dropdown-menu.right,.panel-heading.note-toolbar .dropdown-menu.right{right:0;left:auto}.note-popover .popover-content .dropdown-menu.right::before,.panel-heading.note-toolbar .dropdown-menu.right::before{right:9px;left:auto!important}.note-popover .popover-content .dropdown-menu.right::after,.panel-heading.note-toolbar .dropdown-menu.right::after{right:10px;left:auto!important}.note-popover .popover-content .dropdown-menu.note-check li a i,.panel-heading.note-toolbar .dropdown-menu.note-check li a i{color:deepskyblue;visibility:hidden}.note-popover .popover-content .dropdown-menu.note-check li a.checked i,.panel-heading.note-toolbar .dropdown-menu.note-check li a.checked i{visibility:visible}.note-popover .popover-content .note-fontsize-10,.panel-heading.note-toolbar .note-fontsize-10{font-size:10px}.note-popover .popover-content .note-color-palette,.panel-heading.note-toolbar .note-color-palette{line-height:1}.note-popover .popover-content .note-color-palette div .note-color-btn,.panel-heading.note-toolbar .note-color-palette div .note-color-btn{width:20px;height:20px;padding:0;margin:0;border:1px solid #fff}.note-popover .popover-content .note-color-palette div .note-color-btn:hover,.panel-heading.note-toolbar .note-color-palette div .note-color-btn:hover{border:1px solid #000}.note-dialog>div{display:none}.note-dialog .form-group{margin-right:0;margin-left:0}.note-dialog .note-modal-form{margin:0}.note-dialog .note-image-dialog .note-dropzone{min-height:100px;margin-bottom:10px;font-size:30px;line-height:4;color:lightgray;text-align:center;border:4px dashed lightgray}@-moz-document url-prefix(){.note-image-input{height:auto}}.note-placeholder{position:absolute;display:none;color:gray}.note-handle .note-control-selection{position:absolute;display:none;border:1px solid black}.note-handle .note-control-selection>div{position:absolute}.note-handle .note-control-selection .note-control-selection-bg{width:100%;height:100%;background-color:black;-webkit-opacity:.3;-khtml-opacity:.3;-moz-opacity:.3;opacity:.3;-ms-filter:alpha(opacity=30);filter:alpha(opacity=30)}.note-handle .note-control-selection .note-control-handle{width:7px;height:7px;border:1px solid black}.note-handle .note-control-selection .note-control-holder{width:7px;height:7px;border:1px solid black}.note-handle .note-control-selection .note-control-sizing{width:7px;height:7px;background-color:white;border:1px solid black}.note-handle .note-control-selection .note-control-nw{top:-5px;left:-5px;border-right:0;border-bottom:0}.note-handle .note-control-selection .note-control-ne{top:-5px;right:-5px;border-bottom:0;border-left:none}.note-handle .note-control-selection .note-control-sw{bottom:-5px;left:-5px;border-top:0;border-right:0}.note-handle .note-control-selection .note-control-se{right:-5px;bottom:-5px;cursor:se-resize}.note-handle .note-control-selection .note-control-se.note-control-holder{cursor:default;border-top:0;border-left:none}.note-handle .note-control-selection .note-control-selection-info{right:0;bottom:0;padding:5px;margin:5px;font-size:12px;color:white;background-color:black;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-opacity:.7;-khtml-opacity:.7;-moz-opacity:.7;opacity:.7;-ms-filter:alpha(opacity=70);filter:alpha(opacity=70)}.note-hint-popover{min-width:100px;padding:2px}.note-hint-popover .popover-content{max-height:150px;padding:3px;overflow:auto}.note-hint-popover .popover-content .note-hint-group .note-hint-item{display:block!important;padding:3px}.note-hint-popover .popover-content .note-hint-group .note-hint-item.active,.note-hint-popover .popover-content .note-hint-group .note-hint-item:hover{display:block;clear:both;font-weight:400;line-height:1.4;color:white;text-decoration:none;white-space:nowrap;cursor:pointer;background-color:#428bca;outline:0}"
  },
  {
    "path": "src/main/resources/static/css/plugins/summernote/summernote-bs3.css",
    "content": ".note-editor {\n  /*! normalize.css v2.1.3 | MIT License | git.io/normalize */\n\n}\n.note-editor article,\n.note-editor aside,\n.note-editor details,\n.note-editor figcaption,\n.note-editor figure,\n.note-editor footer,\n.note-editor header,\n.note-editor hgroup,\n.note-editor main,\n.note-editor nav,\n.note-editor section,\n.note-editor summary {\n  display: block;\n}\n.note-editor audio,\n.note-editor canvas,\n.note-editor video {\n  display: inline-block;\n}\n.note-editor audio:not([controls]) {\n  display: none;\n  height: 0;\n}\n.note-editor [hidden],\n.note-editor template {\n  display: none;\n}\n.note-editor html {\n  font-family: sans-serif;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n}\n.note-editor body {\n  margin: 0;\n}\n.note-editor a {\n  background: transparent;\n}\n.note-editor a:focus {\n  outline: thin dotted;\n}\n.note-editor a:active,\n.note-editor a:hover {\n  outline: 0;\n}\n.note-editor h1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n.note-editor abbr[title] {\n  border-bottom: 1px dotted;\n}\n.note-editor b,\n.note-editor strong {\n  font-weight: bold;\n}\n.note-editor dfn {\n  font-style: italic;\n}\n.note-editor hr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n.note-editor mark {\n  background: #ff0;\n  color: #000;\n}\n.note-editor code,\n.note-editor kbd,\n.note-editor pre,\n.note-editor samp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n.note-editor pre {\n  white-space: pre-wrap;\n}\n.note-editor q {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n.note-editor small {\n  font-size: 80%;\n}\n.note-editor sub,\n.note-editor sup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n.note-editor sup {\n  top: -0.5em;\n}\n.note-editor sub {\n  bottom: -0.25em;\n}\n.note-editor img {\n  border: 0;\n}\n.note-editor svg:not(:root) {\n  overflow: hidden;\n}\n.note-editor figure {\n  margin: 0;\n}\n.note-editor fieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n.note-editor legend {\n  border: 0;\n  padding: 0;\n}\n.note-editor button,\n.note-editor input,\n.note-editor select,\n.note-editor textarea {\n  font-family: inherit;\n  font-size: 100%;\n  margin: 0;\n}\n.note-editor button,\n.note-editor input {\n  line-height: normal;\n}\n.note-editor button,\n.note-editor select {\n  text-transform: none;\n}\n.note-editor button,\n.note-editor html input[type=\"button\"],\n.note-editor input[type=\"reset\"],\n.note-editor input[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\n.note-editor button[disabled],\n.note-editor html input[disabled] {\n  cursor: default;\n}\n.note-editor input[type=\"checkbox\"],\n.note-editor input[type=\"radio\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n.note-editor input[type=\"search\"] {\n  -webkit-appearance: textfield;\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box;\n  box-sizing: content-box;\n}\n.note-editor input[type=\"search\"]::-webkit-search-cancel-button,\n.note-editor input[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n.note-editor button::-moz-focus-inner,\n.note-editor input::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n.note-editor textarea {\n  overflow: auto;\n  vertical-align: top;\n}\n.note-editor table {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n@media print {\n  .note-editor * {\n    text-shadow: none !important;\n    color: #000 !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  .note-editor a,\n  .note-editor a:visited {\n    text-decoration: underline;\n  }\n  .note-editor a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  .note-editor abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  .note-editor .ir a:after,\n  .note-editor a[href^=\"javascript:\"]:after,\n  .note-editor a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  .note-editor pre,\n  .note-editor blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  .note-editor thead {\n    display: table-header-group;\n  }\n  .note-editor tr,\n  .note-editor img {\n    page-break-inside: avoid;\n  }\n  .note-editor img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 2cm .5cm;\n  }\n  .note-editor p,\n  .note-editor h2,\n  .note-editor h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  .note-editor h2,\n  .note-editor h3 {\n    page-break-after: avoid;\n  }\n  .note-editor .navbar {\n    display: none;\n  }\n  .note-editor .table td,\n  .note-editor .table th {\n    background-color: #fff !important;\n  }\n  .note-editor .btn > .caret,\n  .note-editor .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n  .note-editor .label {\n    border: 1px solid #000;\n  }\n  .note-editor .table {\n    border-collapse: collapse !important;\n  }\n  .note-editor .table-bordered th,\n  .note-editor .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n.note-editor *,\n.note-editor *:before,\n.note-editor *:after {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.note-editor html {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.note-editor body {\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.note-editor input,\n.note-editor button,\n.note-editor select,\n.note-editor textarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n.note-editor a {\n  color: #428bca;\n  text-decoration: none;\n}\n.note-editor a:hover,\n.note-editor a:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n.note-editor a:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.note-editor img {\n  vertical-align: middle;\n}\n.note-editor .img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.note-editor .img-rounded {\n  border-radius: 6px;\n}\n.note-editor .img-thumbnail {\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  display: inline-block;\n  max-width: 100%;\n  height: auto;\n}\n.note-editor .img-circle {\n  border-radius: 50%;\n}\n.note-editor hr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n.note-editor .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.note-editor p {\n  margin: 0 0 10px;\n}\n.note-editor .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  .note-editor .lead {\n    font-size: 21px;\n  }\n}\n.note-editor small,\n.note-editor .small {\n  font-size: 85%;\n}\n.note-editor cite {\n  font-style: normal;\n}\n.note-editor .text-muted {\n  color: #999999;\n}\n.note-editor .text-primary {\n  color: #428bca;\n}\n.note-editor .text-primary:hover {\n  color: #3071a9;\n}\n.note-editor .text-warning {\n  color: #c09853;\n}\n.note-editor .text-warning:hover {\n  color: #a47e3c;\n}\n.note-editor .text-danger {\n  color: #b94a48;\n}\n.note-editor .text-danger:hover {\n  color: #953b39;\n}\n.note-editor .text-success {\n  color: #468847;\n}\n.note-editor .text-success:hover {\n  color: #356635;\n}\n.note-editor .text-info {\n  color: #3a87ad;\n}\n.note-editor .text-info:hover {\n  color: #2d6987;\n}\n.note-editor .text-left {\n  text-align: left;\n}\n.note-editor .text-right {\n  text-align: right;\n}\n.note-editor .text-center {\n  text-align: center;\n}\n.note-editor h1,\n.note-editor h2,\n.note-editor h3,\n.note-editor h4,\n.note-editor h5,\n.note-editor h6,\n.note-editor .h1,\n.note-editor .h2,\n.note-editor .h3,\n.note-editor .h4,\n.note-editor .h5,\n.note-editor .h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\n.note-editor h1 small,\n.note-editor h2 small,\n.note-editor h3 small,\n.note-editor h4 small,\n.note-editor h5 small,\n.note-editor h6 small,\n.note-editor .h1 small,\n.note-editor .h2 small,\n.note-editor .h3 small,\n.note-editor .h4 small,\n.note-editor .h5 small,\n.note-editor .h6 small,\n.note-editor h1 .small,\n.note-editor h2 .small,\n.note-editor h3 .small,\n.note-editor h4 .small,\n.note-editor h5 .small,\n.note-editor h6 .small,\n.note-editor .h1 .small,\n.note-editor .h2 .small,\n.note-editor .h3 .small,\n.note-editor .h4 .small,\n.note-editor .h5 .small,\n.note-editor .h6 .small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n.note-editor h1,\n.note-editor h2,\n.note-editor h3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n.note-editor h1 small,\n.note-editor h2 small,\n.note-editor h3 small,\n.note-editor h1 .small,\n.note-editor h2 .small,\n.note-editor h3 .small {\n  font-size: 65%;\n}\n.note-editor h4,\n.note-editor h5,\n.note-editor h6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.note-editor h4 small,\n.note-editor h5 small,\n.note-editor h6 small,\n.note-editor h4 .small,\n.note-editor h5 .small,\n.note-editor h6 .small {\n  font-size: 75%;\n}\n.note-editor h1,\n.note-editor .h1 {\n  font-size: 36px;\n}\n.note-editor h2,\n.note-editor .h2 {\n  font-size: 30px;\n}\n.note-editor h3,\n.note-editor .h3 {\n  font-size: 24px;\n}\n.note-editor h4,\n.note-editor .h4 {\n  font-size: 18px;\n}\n.note-editor h5,\n.note-editor .h5 {\n  font-size: 14px;\n}\n.note-editor h6,\n.note-editor .h6 {\n  font-size: 12px;\n}\n.note-editor .page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n.note-editor ul,\n.note-editor ol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n.note-editor ul ul,\n.note-editor ol ul,\n.note-editor ul ol,\n.note-editor ol ol {\n  margin-bottom: 0;\n}\n.note-editor .list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.note-editor .list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n.note-editor .list-inline > li {\n  display: inline-block;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n.note-editor dl {\n  margin-bottom: 20px;\n}\n.note-editor dt,\n.note-editor dd {\n  line-height: 1.428571429;\n}\n.note-editor dt {\n  font-weight: bold;\n}\n.note-editor dd {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .note-editor .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    clear: left;\n    text-align: right;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .note-editor .dl-horizontal dd {\n    margin-left: 180px;\n  }\n  .note-editor .dl-horizontal dd:before,\n  .note-editor .dl-horizontal dd:after {\n    content: \" \";\n    /* 1 */\n\n    display: table;\n    /* 2 */\n\n  }\n  .note-editor .dl-horizontal dd:after {\n    clear: both;\n  }\n  .note-editor .dl-horizontal dd:before,\n  .note-editor .dl-horizontal dd:after {\n    content: \" \";\n    /* 1 */\n\n    display: table;\n    /* 2 */\n\n  }\n  .note-editor .dl-horizontal dd:after {\n    clear: both;\n  }\n}\n.note-editor abbr[title],\n.note-editor abbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n.note-editor abbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n.note-editor blockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n.note-editor blockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n.note-editor blockquote p:last-child {\n  margin-bottom: 0;\n}\n.note-editor blockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n.note-editor blockquote small:before {\n  content: '\\2014 \\00A0';\n}\n.note-editor blockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n.note-editor blockquote.pull-right p,\n.note-editor blockquote.pull-right small,\n.note-editor blockquote.pull-right .small {\n  text-align: right;\n}\n.note-editor blockquote.pull-right small:before,\n.note-editor blockquote.pull-right .small:before {\n  content: '';\n}\n.note-editor blockquote.pull-right small:after,\n.note-editor blockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\n.note-editor blockquote:before,\n.note-editor blockquote:after {\n  content: \"\";\n}\n.note-editor address {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n.note-editor code,\n.note-editor kdb,\n.note-editor pre,\n.note-editor samp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\n.note-editor code {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  background-color: #f9f2f4;\n  white-space: nowrap;\n  border-radius: 4px;\n}\n.note-editor pre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #333333;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n.note-editor pre 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.note-editor .pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.note-editor .container {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left: 15px;\n  padding-right: 15px;\n}\n.note-editor .container:before,\n.note-editor .container:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .container:after {\n  clear: both;\n}\n.note-editor .container:before,\n.note-editor .container:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .container:after {\n  clear: both;\n}\n.note-editor .row {\n  margin-left: -15px;\n  margin-right: -15px;\n}\n.note-editor .row:before,\n.note-editor .row:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .row:after {\n  clear: both;\n}\n.note-editor .row:before,\n.note-editor .row:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .row:after {\n  clear: both;\n}\n.note-editor .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-left: 15px;\n  padding-right: 15px;\n}\n.note-editor .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 {\n  float: left;\n}\n.note-editor .col-xs-12 {\n  width: 100%;\n}\n.note-editor .col-xs-11 {\n  width: 91.66666666666666%;\n}\n.note-editor .col-xs-10 {\n  width: 83.33333333333334%;\n}\n.note-editor .col-xs-9 {\n  width: 75%;\n}\n.note-editor .col-xs-8 {\n  width: 66.66666666666666%;\n}\n.note-editor .col-xs-7 {\n  width: 58.333333333333336%;\n}\n.note-editor .col-xs-6 {\n  width: 50%;\n}\n.note-editor .col-xs-5 {\n  width: 41.66666666666667%;\n}\n.note-editor .col-xs-4 {\n  width: 33.33333333333333%;\n}\n.note-editor .col-xs-3 {\n  width: 25%;\n}\n.note-editor .col-xs-2 {\n  width: 16.666666666666664%;\n}\n.note-editor .col-xs-1 {\n  width: 8.333333333333332%;\n}\n.note-editor .col-xs-pull-12 {\n  right: 100%;\n}\n.note-editor .col-xs-pull-11 {\n  right: 91.66666666666666%;\n}\n.note-editor .col-xs-pull-10 {\n  right: 83.33333333333334%;\n}\n.note-editor .col-xs-pull-9 {\n  right: 75%;\n}\n.note-editor .col-xs-pull-8 {\n  right: 66.66666666666666%;\n}\n.note-editor .col-xs-pull-7 {\n  right: 58.333333333333336%;\n}\n.note-editor .col-xs-pull-6 {\n  right: 50%;\n}\n.note-editor .col-xs-pull-5 {\n  right: 41.66666666666667%;\n}\n.note-editor .col-xs-pull-4 {\n  right: 33.33333333333333%;\n}\n.note-editor .col-xs-pull-3 {\n  right: 25%;\n}\n.note-editor .col-xs-pull-2 {\n  right: 16.666666666666664%;\n}\n.note-editor .col-xs-pull-1 {\n  right: 8.333333333333332%;\n}\n.note-editor .col-xs-push-12 {\n  left: 100%;\n}\n.note-editor .col-xs-push-11 {\n  left: 91.66666666666666%;\n}\n.note-editor .col-xs-push-10 {\n  left: 83.33333333333334%;\n}\n.note-editor .col-xs-push-9 {\n  left: 75%;\n}\n.note-editor .col-xs-push-8 {\n  left: 66.66666666666666%;\n}\n.note-editor .col-xs-push-7 {\n  left: 58.333333333333336%;\n}\n.note-editor .col-xs-push-6 {\n  left: 50%;\n}\n.note-editor .col-xs-push-5 {\n  left: 41.66666666666667%;\n}\n.note-editor .col-xs-push-4 {\n  left: 33.33333333333333%;\n}\n.note-editor .col-xs-push-3 {\n  left: 25%;\n}\n.note-editor .col-xs-push-2 {\n  left: 16.666666666666664%;\n}\n.note-editor .col-xs-push-1 {\n  left: 8.333333333333332%;\n}\n.note-editor .col-xs-offset-12 {\n  margin-left: 100%;\n}\n.note-editor .col-xs-offset-11 {\n  margin-left: 91.66666666666666%;\n}\n.note-editor .col-xs-offset-10 {\n  margin-left: 83.33333333333334%;\n}\n.note-editor .col-xs-offset-9 {\n  margin-left: 75%;\n}\n.note-editor .col-xs-offset-8 {\n  margin-left: 66.66666666666666%;\n}\n.note-editor .col-xs-offset-7 {\n  margin-left: 58.333333333333336%;\n}\n.note-editor .col-xs-offset-6 {\n  margin-left: 50%;\n}\n.note-editor .col-xs-offset-5 {\n  margin-left: 41.66666666666667%;\n}\n.note-editor .col-xs-offset-4 {\n  margin-left: 33.33333333333333%;\n}\n.note-editor .col-xs-offset-3 {\n  margin-left: 25%;\n}\n.note-editor .col-xs-offset-2 {\n  margin-left: 16.666666666666664%;\n}\n.note-editor .col-xs-offset-1 {\n  margin-left: 8.333333333333332%;\n}\n@media (min-width: 768px) {\n  .note-editor .container {\n    width: 750px;\n  }\n  .note-editor .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 {\n    float: left;\n  }\n  .note-editor .col-sm-12 {\n    width: 100%;\n  }\n  .note-editor .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .note-editor .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .note-editor .col-sm-9 {\n    width: 75%;\n  }\n  .note-editor .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .note-editor .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .note-editor .col-sm-6 {\n    width: 50%;\n  }\n  .note-editor .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .note-editor .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .note-editor .col-sm-3 {\n    width: 25%;\n  }\n  .note-editor .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .note-editor .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .note-editor .col-sm-pull-12 {\n    right: 100%;\n  }\n  .note-editor .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .note-editor .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .note-editor .col-sm-pull-9 {\n    right: 75%;\n  }\n  .note-editor .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .note-editor .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .note-editor .col-sm-pull-6 {\n    right: 50%;\n  }\n  .note-editor .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .note-editor .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .note-editor .col-sm-pull-3 {\n    right: 25%;\n  }\n  .note-editor .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .note-editor .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .note-editor .col-sm-push-12 {\n    left: 100%;\n  }\n  .note-editor .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n  .note-editor .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n  .note-editor .col-sm-push-9 {\n    left: 75%;\n  }\n  .note-editor .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n  .note-editor .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n  .note-editor .col-sm-push-6 {\n    left: 50%;\n  }\n  .note-editor .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n  .note-editor .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n  .note-editor .col-sm-push-3 {\n    left: 25%;\n  }\n  .note-editor .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n  .note-editor .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n  .note-editor .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .note-editor .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .note-editor .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .note-editor .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .note-editor .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .note-editor .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .note-editor .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .note-editor .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .note-editor .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .note-editor .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .note-editor .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .note-editor .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n}\n@media (min-width: 992px) {\n  .note-editor .container {\n    width: 970px;\n  }\n  .note-editor .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 {\n    float: left;\n  }\n  .note-editor .col-md-12 {\n    width: 100%;\n  }\n  .note-editor .col-md-11 {\n    width: 91.66666666666666%;\n  }\n  .note-editor .col-md-10 {\n    width: 83.33333333333334%;\n  }\n  .note-editor .col-md-9 {\n    width: 75%;\n  }\n  .note-editor .col-md-8 {\n    width: 66.66666666666666%;\n  }\n  .note-editor .col-md-7 {\n    width: 58.333333333333336%;\n  }\n  .note-editor .col-md-6 {\n    width: 50%;\n  }\n  .note-editor .col-md-5 {\n    width: 41.66666666666667%;\n  }\n  .note-editor .col-md-4 {\n    width: 33.33333333333333%;\n  }\n  .note-editor .col-md-3 {\n    width: 25%;\n  }\n  .note-editor .col-md-2 {\n    width: 16.666666666666664%;\n  }\n  .note-editor .col-md-1 {\n    width: 8.333333333333332%;\n  }\n  .note-editor .col-md-pull-12 {\n    right: 100%;\n  }\n  .note-editor .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .note-editor .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .note-editor .col-md-pull-9 {\n    right: 75%;\n  }\n  .note-editor .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .note-editor .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .note-editor .col-md-pull-6 {\n    right: 50%;\n  }\n  .note-editor .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .note-editor .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .note-editor .col-md-pull-3 {\n    right: 25%;\n  }\n  .note-editor .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .note-editor .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .note-editor .col-md-push-12 {\n    left: 100%;\n  }\n  .note-editor .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n  .note-editor .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n  .note-editor .col-md-push-9 {\n    left: 75%;\n  }\n  .note-editor .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n  .note-editor .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n  .note-editor .col-md-push-6 {\n    left: 50%;\n  }\n  .note-editor .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n  .note-editor .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n  .note-editor .col-md-push-3 {\n    left: 25%;\n  }\n  .note-editor .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n  .note-editor .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n  .note-editor .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .note-editor .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .note-editor .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .note-editor .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .note-editor .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .note-editor .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .note-editor .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .note-editor .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .note-editor .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .note-editor .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .note-editor .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .note-editor .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n}\n@media (min-width: 1200px) {\n  .note-editor .container {\n    width: 1170px;\n  }\n  .note-editor .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 {\n    float: left;\n  }\n  .note-editor .col-lg-12 {\n    width: 100%;\n  }\n  .note-editor .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .note-editor .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .note-editor .col-lg-9 {\n    width: 75%;\n  }\n  .note-editor .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .note-editor .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .note-editor .col-lg-6 {\n    width: 50%;\n  }\n  .note-editor .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .note-editor .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .note-editor .col-lg-3 {\n    width: 25%;\n  }\n  .note-editor .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .note-editor .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .note-editor .col-lg-pull-12 {\n    right: 100%;\n  }\n  .note-editor .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .note-editor .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .note-editor .col-lg-pull-9 {\n    right: 75%;\n  }\n  .note-editor .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .note-editor .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .note-editor .col-lg-pull-6 {\n    right: 50%;\n  }\n  .note-editor .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .note-editor .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .note-editor .col-lg-pull-3 {\n    right: 25%;\n  }\n  .note-editor .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .note-editor .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .note-editor .col-lg-push-12 {\n    left: 100%;\n  }\n  .note-editor .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n  .note-editor .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n  .note-editor .col-lg-push-9 {\n    left: 75%;\n  }\n  .note-editor .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n  .note-editor .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n  .note-editor .col-lg-push-6 {\n    left: 50%;\n  }\n  .note-editor .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n  .note-editor .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n  .note-editor .col-lg-push-3 {\n    left: 25%;\n  }\n  .note-editor .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n  .note-editor .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n  .note-editor .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .note-editor .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .note-editor .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .note-editor .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .note-editor .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .note-editor .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .note-editor .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .note-editor .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .note-editor .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .note-editor .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .note-editor .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .note-editor .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n}\n.note-editor table {\n  max-width: 100%;\n  background-color: transparent;\n}\n.note-editor th {\n  text-align: left;\n}\n.note-editor .table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n.note-editor .table > thead > tr > th,\n.note-editor .table > tbody > tr > th,\n.note-editor .table > tfoot > tr > th,\n.note-editor .table > thead > tr > td,\n.note-editor .table > tbody > tr > td,\n.note-editor .table > tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n.note-editor .table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #dddddd;\n}\n.note-editor .table > caption + thead > tr:first-child > th,\n.note-editor .table > colgroup + thead > tr:first-child > th,\n.note-editor .table > thead:first-child > tr:first-child > th,\n.note-editor .table > caption + thead > tr:first-child > td,\n.note-editor .table > colgroup + thead > tr:first-child > td,\n.note-editor .table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.note-editor .table > tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n.note-editor .table .table {\n  background-color: #ffffff;\n}\n.note-editor .table-condensed > thead > tr > th,\n.note-editor .table-condensed > tbody > tr > th,\n.note-editor .table-condensed > tfoot > tr > th,\n.note-editor .table-condensed > thead > tr > td,\n.note-editor .table-condensed > tbody > tr > td,\n.note-editor .table-condensed > tfoot > tr > td {\n  padding: 5px;\n}\n.note-editor .table-bordered {\n  border: 1px solid #dddddd;\n}\n.note-editor .table-bordered > thead > tr > th,\n.note-editor .table-bordered > tbody > tr > th,\n.note-editor .table-bordered > tfoot > tr > th,\n.note-editor .table-bordered > thead > tr > td,\n.note-editor .table-bordered > tbody > tr > td,\n.note-editor .table-bordered > tfoot > tr > td {\n  border: 1px solid #dddddd;\n}\n.note-editor .table-bordered > thead > tr > th,\n.note-editor .table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n.note-editor .table-striped > tbody > tr:nth-child(odd) > td,\n.note-editor .table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n.note-editor .table-hover > tbody > tr:hover > td,\n.note-editor .table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n.note-editor table col[class*=\"col-\"] {\n  float: none;\n  display: table-column;\n}\n.note-editor table td[class*=\"col-\"],\n.note-editor table th[class*=\"col-\"] {\n  float: none;\n  display: table-cell;\n}\n.note-editor .table > thead > tr > td.active,\n.note-editor .table > tbody > tr > td.active,\n.note-editor .table > tfoot > tr > td.active,\n.note-editor .table > thead > tr > th.active,\n.note-editor .table > tbody > tr > th.active,\n.note-editor .table > tfoot > tr > th.active,\n.note-editor .table > thead > tr.active > td,\n.note-editor .table > tbody > tr.active > td,\n.note-editor .table > tfoot > tr.active > td,\n.note-editor .table > thead > tr.active > th,\n.note-editor .table > tbody > tr.active > th,\n.note-editor .table > tfoot > tr.active > th {\n  background-color: #f5f5f5;\n}\n.note-editor .table > thead > tr > td.success,\n.note-editor .table > tbody > tr > td.success,\n.note-editor .table > tfoot > tr > td.success,\n.note-editor .table > thead > tr > th.success,\n.note-editor .table > tbody > tr > th.success,\n.note-editor .table > tfoot > tr > th.success,\n.note-editor .table > thead > tr.success > td,\n.note-editor .table > tbody > tr.success > td,\n.note-editor .table > tfoot > tr.success > td,\n.note-editor .table > thead > tr.success > th,\n.note-editor .table > tbody > tr.success > th,\n.note-editor .table > tfoot > tr.success > th {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.note-editor .table-hover > tbody > tr > td.success:hover,\n.note-editor .table-hover > tbody > tr > th.success:hover,\n.note-editor .table-hover > tbody > tr.success:hover > td,\n.note-editor .table-hover > tbody > tr.success:hover > th {\n  background-color: #d0e9c6;\n  border-color: #c9e2b3;\n}\n.note-editor .table > thead > tr > td.danger,\n.note-editor .table > tbody > tr > td.danger,\n.note-editor .table > tfoot > tr > td.danger,\n.note-editor .table > thead > tr > th.danger,\n.note-editor .table > tbody > tr > th.danger,\n.note-editor .table > tfoot > tr > th.danger,\n.note-editor .table > thead > tr.danger > td,\n.note-editor .table > tbody > tr.danger > td,\n.note-editor .table > tfoot > tr.danger > td,\n.note-editor .table > thead > tr.danger > th,\n.note-editor .table > tbody > tr.danger > th,\n.note-editor .table > tfoot > tr.danger > th {\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.note-editor .table-hover > tbody > tr > td.danger:hover,\n.note-editor .table-hover > tbody > tr > th.danger:hover,\n.note-editor .table-hover > tbody > tr.danger:hover > td,\n.note-editor .table-hover > tbody > tr.danger:hover > th {\n  background-color: #ebcccc;\n  border-color: #e4b9c0;\n}\n.note-editor .table > thead > tr > td.warning,\n.note-editor .table > tbody > tr > td.warning,\n.note-editor .table > tfoot > tr > td.warning,\n.note-editor .table > thead > tr > th.warning,\n.note-editor .table > tbody > tr > th.warning,\n.note-editor .table > tfoot > tr > th.warning,\n.note-editor .table > thead > tr.warning > td,\n.note-editor .table > tbody > tr.warning > td,\n.note-editor .table > tfoot > tr.warning > td,\n.note-editor .table > thead > tr.warning > th,\n.note-editor .table > tbody > tr.warning > th,\n.note-editor .table > tfoot > tr.warning > th {\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.note-editor .table-hover > tbody > tr > td.warning:hover,\n.note-editor .table-hover > tbody > tr > th.warning:hover,\n.note-editor .table-hover > tbody > tr.warning:hover > td,\n.note-editor .table-hover > tbody > tr.warning:hover > th {\n  background-color: #faf2cc;\n  border-color: #f7e1b5;\n}\n@media (max-width: 767px) {\n  .note-editor .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-y: hidden;\n    overflow-x: scroll;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid #dddddd;\n    -webkit-overflow-scrolling: touch;\n  }\n  .note-editor .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  .note-editor .table-responsive > .table > thead > tr > th,\n  .note-editor .table-responsive > .table > tbody > tr > th,\n  .note-editor .table-responsive > .table > tfoot > tr > th,\n  .note-editor .table-responsive > .table > thead > tr > td,\n  .note-editor .table-responsive > .table > tbody > tr > td,\n  .note-editor .table-responsive > .table > tfoot > tr > td {\n    white-space: nowrap;\n  }\n  .note-editor .table-responsive > .table-bordered {\n    border: 0;\n  }\n  .note-editor .table-responsive > .table-bordered > thead > tr > th:first-child,\n  .note-editor .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n  .note-editor .table-responsive > .table-bordered > thead > tr > td:first-child,\n  .note-editor .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n    border-left: 0;\n  }\n  .note-editor .table-responsive > .table-bordered > thead > tr > th:last-child,\n  .note-editor .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .note-editor .table-responsive > .table-bordered > thead > tr > td:last-child,\n  .note-editor .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .note-editor .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .note-editor .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .note-editor .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\n.note-editor fieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n.note-editor legend {\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.note-editor label {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n.note-editor input[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.note-editor input[type=\"radio\"],\n.note-editor input[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n.note-editor input[type=\"file\"] {\n  display: block;\n}\n.note-editor select[multiple],\n.note-editor select[size] {\n  height: auto;\n}\n.note-editor select optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\n.note-editor input[type=\"file\"]:focus,\n.note-editor input[type=\"radio\"]:focus,\n.note-editor input[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.note-editor input[type=\"number\"]::-webkit-outer-spin-button,\n.note-editor input[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n.note-editor output {\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.note-editor .form-control:-moz-placeholder {\n  color: #999999;\n}\n.note-editor .form-control::-moz-placeholder {\n  color: #999999;\n}\n.note-editor .form-control:-ms-input-placeholder {\n  color: #999999;\n}\n.note-editor .form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n.note-editor .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 .15s, box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.note-editor .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, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.note-editor .form-control[disabled],\n.note-editor .form-control[readonly],\nfieldset[disabled] .note-editor .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\ntextarea.note-editor .form-control {\n  height: auto;\n}\n.note-editor .form-group {\n  margin-bottom: 15px;\n}\n.note-editor .radio,\n.note-editor .checkbox {\n  display: block;\n  min-height: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.note-editor .radio label,\n.note-editor .checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.note-editor .radio input[type=\"radio\"],\n.note-editor .radio-inline input[type=\"radio\"],\n.note-editor .checkbox input[type=\"checkbox\"],\n.note-editor .checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n.note-editor .radio + .radio,\n.note-editor .checkbox + .checkbox {\n  margin-top: -5px;\n}\n.note-editor .radio-inline,\n.note-editor .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.note-editor .radio-inline + .radio-inline,\n.note-editor .checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n.note-editor input[type=\"radio\"][disabled],\n.note-editor input[type=\"checkbox\"][disabled],\n.note-editor .radio[disabled],\n.note-editor .radio-inline[disabled],\n.note-editor .checkbox[disabled],\n.note-editor .checkbox-inline[disabled],\nfieldset[disabled] .note-editor input[type=\"radio\"],\nfieldset[disabled] .note-editor input[type=\"checkbox\"],\nfieldset[disabled] .note-editor .radio,\nfieldset[disabled] .note-editor .radio-inline,\nfieldset[disabled] .note-editor .checkbox,\nfieldset[disabled] .note-editor .checkbox-inline {\n  cursor: not-allowed;\n}\n.note-editor .input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.note-editor .input-sm {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.note-editor .input-sm {\n  height: auto;\n}\n.note-editor .input-lg {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.note-editor .input-lg {\n  height: 45px;\n  line-height: 45px;\n}\ntextarea.note-editor .input-lg {\n  height: auto;\n}\n.note-editor .has-warning .help-block,\n.note-editor .has-warning .control-label {\n  color: #c09853;\n}\n.note-editor .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.note-editor .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.note-editor .has-warning .input-group-addon {\n  color: #c09853;\n  border-color: #c09853;\n  background-color: #fcf8e3;\n}\n.note-editor .has-error .help-block,\n.note-editor .has-error .control-label {\n  color: #b94a48;\n}\n.note-editor .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.note-editor .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.note-editor .has-error .input-group-addon {\n  color: #b94a48;\n  border-color: #b94a48;\n  background-color: #f2dede;\n}\n.note-editor .has-success .help-block,\n.note-editor .has-success .control-label {\n  color: #468847;\n}\n.note-editor .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.note-editor .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.note-editor .has-success .input-group-addon {\n  color: #468847;\n  border-color: #468847;\n  background-color: #dff0d8;\n}\n.note-editor .form-control-static {\n  margin-bottom: 0;\n}\n.note-editor .help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n@media (min-width: 768px) {\n  .note-editor .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .note-editor .form-inline .form-control {\n    display: inline-block;\n  }\n  .note-editor .form-inline .radio,\n  .note-editor .form-inline .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n  }\n  .note-editor .form-inline .radio input[type=\"radio\"],\n  .note-editor .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n.note-editor .form-horizontal .control-label,\n.note-editor .form-horizontal .radio,\n.note-editor .form-horizontal .checkbox,\n.note-editor .form-horizontal .radio-inline,\n.note-editor .form-horizontal .checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 7px;\n}\n.note-editor .form-horizontal .form-group {\n  margin-left: -15px;\n  margin-right: -15px;\n}\n.note-editor .form-horizontal .form-group:before,\n.note-editor .form-horizontal .form-group:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .form-horizontal .form-group:after {\n  clear: both;\n}\n.note-editor .form-horizontal .form-group:before,\n.note-editor .form-horizontal .form-group:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .form-horizontal .form-group:after {\n  clear: both;\n}\n.note-editor .form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n@media (min-width: 768px) {\n  .note-editor .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n.note-editor .btn {\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  white-space: nowrap;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\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.note-editor .btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.note-editor .btn:hover,\n.note-editor .btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\n.note-editor .btn:active,\n.note-editor .btn.active {\n  outline: 0;\n  background-image: none;\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.note-editor .btn.disabled,\n.note-editor .btn[disabled],\nfieldset[disabled] .note-editor .btn {\n  cursor: not-allowed;\n  pointer-events: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.note-editor .btn-default {\n  color: #333333;\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n.note-editor .btn-default:hover,\n.note-editor .btn-default:focus,\n.note-editor .btn-default:active,\n.note-editor .btn-default.active,\n.open .dropdown-toggle.note-editor .btn-default {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.note-editor .btn-default:active,\n.note-editor .btn-default.active,\n.open .dropdown-toggle.note-editor .btn-default {\n  background-image: none;\n}\n.note-editor .btn-default.disabled,\n.note-editor .btn-default[disabled],\nfieldset[disabled] .note-editor .btn-default,\n.note-editor .btn-default.disabled:hover,\n.note-editor .btn-default[disabled]:hover,\nfieldset[disabled] .note-editor .btn-default:hover,\n.note-editor .btn-default.disabled:focus,\n.note-editor .btn-default[disabled]:focus,\nfieldset[disabled] .note-editor .btn-default:focus,\n.note-editor .btn-default.disabled:active,\n.note-editor .btn-default[disabled]:active,\nfieldset[disabled] .note-editor .btn-default:active,\n.note-editor .btn-default.disabled.active,\n.note-editor .btn-default[disabled].active,\nfieldset[disabled] .note-editor .btn-default.active {\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n.note-editor .btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.note-editor .btn-primary:hover,\n.note-editor .btn-primary:focus,\n.note-editor .btn-primary:active,\n.note-editor .btn-primary.active,\n.open .dropdown-toggle.note-editor .btn-primary {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.note-editor .btn-primary:active,\n.note-editor .btn-primary.active,\n.open .dropdown-toggle.note-editor .btn-primary {\n  background-image: none;\n}\n.note-editor .btn-primary.disabled,\n.note-editor .btn-primary[disabled],\nfieldset[disabled] .note-editor .btn-primary,\n.note-editor .btn-primary.disabled:hover,\n.note-editor .btn-primary[disabled]:hover,\nfieldset[disabled] .note-editor .btn-primary:hover,\n.note-editor .btn-primary.disabled:focus,\n.note-editor .btn-primary[disabled]:focus,\nfieldset[disabled] .note-editor .btn-primary:focus,\n.note-editor .btn-primary.disabled:active,\n.note-editor .btn-primary[disabled]:active,\nfieldset[disabled] .note-editor .btn-primary:active,\n.note-editor .btn-primary.disabled.active,\n.note-editor .btn-primary[disabled].active,\nfieldset[disabled] .note-editor .btn-primary.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.note-editor .btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.note-editor .btn-warning:hover,\n.note-editor .btn-warning:focus,\n.note-editor .btn-warning:active,\n.note-editor .btn-warning.active,\n.open .dropdown-toggle.note-editor .btn-warning {\n  color: #ffffff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.note-editor .btn-warning:active,\n.note-editor .btn-warning.active,\n.open .dropdown-toggle.note-editor .btn-warning {\n  background-image: none;\n}\n.note-editor .btn-warning.disabled,\n.note-editor .btn-warning[disabled],\nfieldset[disabled] .note-editor .btn-warning,\n.note-editor .btn-warning.disabled:hover,\n.note-editor .btn-warning[disabled]:hover,\nfieldset[disabled] .note-editor .btn-warning:hover,\n.note-editor .btn-warning.disabled:focus,\n.note-editor .btn-warning[disabled]:focus,\nfieldset[disabled] .note-editor .btn-warning:focus,\n.note-editor .btn-warning.disabled:active,\n.note-editor .btn-warning[disabled]:active,\nfieldset[disabled] .note-editor .btn-warning:active,\n.note-editor .btn-warning.disabled.active,\n.note-editor .btn-warning[disabled].active,\nfieldset[disabled] .note-editor .btn-warning.active {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.note-editor .btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.note-editor .btn-danger:hover,\n.note-editor .btn-danger:focus,\n.note-editor .btn-danger:active,\n.note-editor .btn-danger.active,\n.open .dropdown-toggle.note-editor .btn-danger {\n  color: #ffffff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.note-editor .btn-danger:active,\n.note-editor .btn-danger.active,\n.open .dropdown-toggle.note-editor .btn-danger {\n  background-image: none;\n}\n.note-editor .btn-danger.disabled,\n.note-editor .btn-danger[disabled],\nfieldset[disabled] .note-editor .btn-danger,\n.note-editor .btn-danger.disabled:hover,\n.note-editor .btn-danger[disabled]:hover,\nfieldset[disabled] .note-editor .btn-danger:hover,\n.note-editor .btn-danger.disabled:focus,\n.note-editor .btn-danger[disabled]:focus,\nfieldset[disabled] .note-editor .btn-danger:focus,\n.note-editor .btn-danger.disabled:active,\n.note-editor .btn-danger[disabled]:active,\nfieldset[disabled] .note-editor .btn-danger:active,\n.note-editor .btn-danger.disabled.active,\n.note-editor .btn-danger[disabled].active,\nfieldset[disabled] .note-editor .btn-danger.active {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.note-editor .btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.note-editor .btn-success:hover,\n.note-editor .btn-success:focus,\n.note-editor .btn-success:active,\n.note-editor .btn-success.active,\n.open .dropdown-toggle.note-editor .btn-success {\n  color: #ffffff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.note-editor .btn-success:active,\n.note-editor .btn-success.active,\n.open .dropdown-toggle.note-editor .btn-success {\n  background-image: none;\n}\n.note-editor .btn-success.disabled,\n.note-editor .btn-success[disabled],\nfieldset[disabled] .note-editor .btn-success,\n.note-editor .btn-success.disabled:hover,\n.note-editor .btn-success[disabled]:hover,\nfieldset[disabled] .note-editor .btn-success:hover,\n.note-editor .btn-success.disabled:focus,\n.note-editor .btn-success[disabled]:focus,\nfieldset[disabled] .note-editor .btn-success:focus,\n.note-editor .btn-success.disabled:active,\n.note-editor .btn-success[disabled]:active,\nfieldset[disabled] .note-editor .btn-success:active,\n.note-editor .btn-success.disabled.active,\n.note-editor .btn-success[disabled].active,\nfieldset[disabled] .note-editor .btn-success.active {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.note-editor .btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.note-editor .btn-info:hover,\n.note-editor .btn-info:focus,\n.note-editor .btn-info:active,\n.note-editor .btn-info.active,\n.open .dropdown-toggle.note-editor .btn-info {\n  color: #ffffff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.note-editor .btn-info:active,\n.note-editor .btn-info.active,\n.open .dropdown-toggle.note-editor .btn-info {\n  background-image: none;\n}\n.note-editor .btn-info.disabled,\n.note-editor .btn-info[disabled],\nfieldset[disabled] .note-editor .btn-info,\n.note-editor .btn-info.disabled:hover,\n.note-editor .btn-info[disabled]:hover,\nfieldset[disabled] .note-editor .btn-info:hover,\n.note-editor .btn-info.disabled:focus,\n.note-editor .btn-info[disabled]:focus,\nfieldset[disabled] .note-editor .btn-info:focus,\n.note-editor .btn-info.disabled:active,\n.note-editor .btn-info[disabled]:active,\nfieldset[disabled] .note-editor .btn-info:active,\n.note-editor .btn-info.disabled.active,\n.note-editor .btn-info[disabled].active,\nfieldset[disabled] .note-editor .btn-info.active {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.note-editor .btn-link {\n  color: #428bca;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.note-editor .btn-link,\n.note-editor .btn-link:active,\n.note-editor .btn-link[disabled],\nfieldset[disabled] .note-editor .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.note-editor .btn-link,\n.note-editor .btn-link:hover,\n.note-editor .btn-link:focus,\n.note-editor .btn-link:active {\n  border-color: transparent;\n}\n.note-editor .btn-link:hover,\n.note-editor .btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.note-editor .btn-link[disabled]:hover,\nfieldset[disabled] .note-editor .btn-link:hover,\n.note-editor .btn-link[disabled]:focus,\nfieldset[disabled] .note-editor .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n.note-editor .btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.note-editor .btn-sm,\n.note-editor .btn-xs {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.note-editor .btn-xs {\n  padding: 1px 5px;\n}\n.note-editor .btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n.note-editor .btn-block + .btn-block {\n  margin-top: 5px;\n}\n.note-editor input[type=\"submit\"].btn-block,\n.note-editor input[type=\"reset\"].btn-block,\n.note-editor input[type=\"button\"].btn-block {\n  width: 100%;\n}\n.note-editor .fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n.note-editor .fade.in {\n  opacity: 1;\n}\n.note-editor .collapse {\n  display: none;\n}\n.note-editor .collapse.in {\n  display: block;\n}\n.note-editor .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@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('../../../fonts/glyphicons-halflings-regular.eot');\n  src: url('../../../fonts/glyphicons-halflings-regular.eot?') 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') format('svg');\n}\n.note-editor .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  -webkit-font-smoothing: antialiased;\n}\n.note-editor .glyphicon:empty {\n  width: 1em;\n}\n.note-editor .glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n.note-editor .glyphicon-plus:before {\n  content: \"\\2b\";\n}\n.note-editor .glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n.note-editor .glyphicon-minus:before {\n  content: \"\\2212\";\n}\n.note-editor .glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n.note-editor .glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n.note-editor .glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n.note-editor .glyphicon-glass:before {\n  content: \"\\e001\";\n}\n.note-editor .glyphicon-music:before {\n  content: \"\\e002\";\n}\n.note-editor .glyphicon-search:before {\n  content: \"\\e003\";\n}\n.note-editor .glyphicon-heart:before {\n  content: \"\\e005\";\n}\n.note-editor .glyphicon-star:before {\n  content: \"\\e006\";\n}\n.note-editor .glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n.note-editor .glyphicon-user:before {\n  content: \"\\e008\";\n}\n.note-editor .glyphicon-film:before {\n  content: \"\\e009\";\n}\n.note-editor .glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n.note-editor .glyphicon-th:before {\n  content: \"\\e011\";\n}\n.note-editor .glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n.note-editor .glyphicon-ok:before {\n  content: \"\\e013\";\n}\n.note-editor .glyphicon-remove:before {\n  content: \"\\e014\";\n}\n.note-editor .glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n.note-editor .glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n.note-editor .glyphicon-off:before {\n  content: \"\\e017\";\n}\n.note-editor .glyphicon-signal:before {\n  content: \"\\e018\";\n}\n.note-editor .glyphicon-cog:before {\n  content: \"\\e019\";\n}\n.note-editor .glyphicon-trash:before {\n  content: \"\\e020\";\n}\n.note-editor .glyphicon-home:before {\n  content: \"\\e021\";\n}\n.note-editor .glyphicon-file:before {\n  content: \"\\e022\";\n}\n.note-editor .glyphicon-time:before {\n  content: \"\\e023\";\n}\n.note-editor .glyphicon-road:before {\n  content: \"\\e024\";\n}\n.note-editor .glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n.note-editor .glyphicon-download:before {\n  content: \"\\e026\";\n}\n.note-editor .glyphicon-upload:before {\n  content: \"\\e027\";\n}\n.note-editor .glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n.note-editor .glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n.note-editor .glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n.note-editor .glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n.note-editor .glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n.note-editor .glyphicon-lock:before {\n  content: \"\\e033\";\n}\n.note-editor .glyphicon-flag:before {\n  content: \"\\e034\";\n}\n.note-editor .glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n.note-editor .glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n.note-editor .glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n.note-editor .glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n.note-editor .glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n.note-editor .glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n.note-editor .glyphicon-tag:before {\n  content: \"\\e041\";\n}\n.note-editor .glyphicon-tags:before {\n  content: \"\\e042\";\n}\n.note-editor .glyphicon-book:before {\n  content: \"\\e043\";\n}\n.note-editor .glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n.note-editor .glyphicon-print:before {\n  content: \"\\e045\";\n}\n.note-editor .glyphicon-camera:before {\n  content: \"\\e046\";\n}\n.note-editor .glyphicon-font:before {\n  content: \"\\e047\";\n}\n.note-editor .glyphicon-bold:before {\n  content: \"\\e048\";\n}\n.note-editor .glyphicon-italic:before {\n  content: \"\\e049\";\n}\n.note-editor .glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n.note-editor .glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n.note-editor .glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n.note-editor .glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n.note-editor .glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n.note-editor .glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n.note-editor .glyphicon-list:before {\n  content: \"\\e056\";\n}\n.note-editor .glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n.note-editor .glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n.note-editor .glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n.note-editor .glyphicon-picture:before {\n  content: \"\\e060\";\n}\n.note-editor .glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n.note-editor .glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n.note-editor .glyphicon-tint:before {\n  content: \"\\e064\";\n}\n.note-editor .glyphicon-edit:before {\n  content: \"\\e065\";\n}\n.note-editor .glyphicon-share:before {\n  content: \"\\e066\";\n}\n.note-editor .glyphicon-check:before {\n  content: \"\\e067\";\n}\n.note-editor .glyphicon-move:before {\n  content: \"\\e068\";\n}\n.note-editor .glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n.note-editor .glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n.note-editor .glyphicon-backward:before {\n  content: \"\\e071\";\n}\n.note-editor .glyphicon-play:before {\n  content: \"\\e072\";\n}\n.note-editor .glyphicon-pause:before {\n  content: \"\\e073\";\n}\n.note-editor .glyphicon-stop:before {\n  content: \"\\e074\";\n}\n.note-editor .glyphicon-forward:before {\n  content: \"\\e075\";\n}\n.note-editor .glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n.note-editor .glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n.note-editor .glyphicon-eject:before {\n  content: \"\\e078\";\n}\n.note-editor .glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n.note-editor .glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n.note-editor .glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n.note-editor .glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n.note-editor .glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n.note-editor .glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n.note-editor .glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n.note-editor .glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n.note-editor .glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n.note-editor .glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n.note-editor .glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n.note-editor .glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n.note-editor .glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n.note-editor .glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n.note-editor .glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n.note-editor .glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n.note-editor .glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n.note-editor .glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n.note-editor .glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n.note-editor .glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n.note-editor .glyphicon-gift:before {\n  content: \"\\e102\";\n}\n.note-editor .glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n.note-editor .glyphicon-fire:before {\n  content: \"\\e104\";\n}\n.note-editor .glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n.note-editor .glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n.note-editor .glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n.note-editor .glyphicon-plane:before {\n  content: \"\\e108\";\n}\n.note-editor .glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n.note-editor .glyphicon-random:before {\n  content: \"\\e110\";\n}\n.note-editor .glyphicon-comment:before {\n  content: \"\\e111\";\n}\n.note-editor .glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n.note-editor .glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n.note-editor .glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n.note-editor .glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n.note-editor .glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n.note-editor .glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n.note-editor .glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n.note-editor .glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n.note-editor .glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n.note-editor .glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n.note-editor .glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n.note-editor .glyphicon-bell:before {\n  content: \"\\e123\";\n}\n.note-editor .glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n.note-editor .glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n.note-editor .glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n.note-editor .glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n.note-editor .glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n.note-editor .glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n.note-editor .glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n.note-editor .glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n.note-editor .glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n.note-editor .glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n.note-editor .glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n.note-editor .glyphicon-globe:before {\n  content: \"\\e135\";\n}\n.note-editor .glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n.note-editor .glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n.note-editor .glyphicon-filter:before {\n  content: \"\\e138\";\n}\n.note-editor .glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n.note-editor .glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n.note-editor .glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n.note-editor .glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n.note-editor .glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n.note-editor .glyphicon-link:before {\n  content: \"\\e144\";\n}\n.note-editor .glyphicon-phone:before {\n  content: \"\\e145\";\n}\n.note-editor .glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n.note-editor .glyphicon-usd:before {\n  content: \"\\e148\";\n}\n.note-editor .glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n.note-editor .glyphicon-sort:before {\n  content: \"\\e150\";\n}\n.note-editor .glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n.note-editor .glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n.note-editor .glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n.note-editor .glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n.note-editor .glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n.note-editor .glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n.note-editor .glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n.note-editor .glyphicon-expand:before {\n  content: \"\\e158\";\n}\n.note-editor .glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n.note-editor .glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n.note-editor .glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n.note-editor .glyphicon-flash:before {\n  content: \"\\e162\";\n}\n.note-editor .glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n.note-editor .glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n.note-editor .glyphicon-record:before {\n  content: \"\\e165\";\n}\n.note-editor .glyphicon-save:before {\n  content: \"\\e166\";\n}\n.note-editor .glyphicon-open:before {\n  content: \"\\e167\";\n}\n.note-editor .glyphicon-saved:before {\n  content: \"\\e168\";\n}\n.note-editor .glyphicon-import:before {\n  content: \"\\e169\";\n}\n.note-editor .glyphicon-export:before {\n  content: \"\\e170\";\n}\n.note-editor .glyphicon-send:before {\n  content: \"\\e171\";\n}\n.note-editor .glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n.note-editor .glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n.note-editor .glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n.note-editor .glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n.note-editor .glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n.note-editor .glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n.note-editor .glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n.note-editor .glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n.note-editor .glyphicon-header:before {\n  content: \"\\e180\";\n}\n.note-editor .glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n.note-editor .glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n.note-editor .glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n.note-editor .glyphicon-tower:before {\n  content: \"\\e184\";\n}\n.note-editor .glyphicon-stats:before {\n  content: \"\\e185\";\n}\n.note-editor .glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n.note-editor .glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n.note-editor .glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n.note-editor .glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n.note-editor .glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n.note-editor .glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n.note-editor .glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n.note-editor .glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n.note-editor .glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n.note-editor .glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n.note-editor .glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n.note-editor .glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n.note-editor .glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n.note-editor .glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n.note-editor .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-left: 4px solid transparent;\n  border-bottom: 0 dotted;\n}\n.note-editor .dropdown {\n  position: relative;\n}\n.note-editor .dropdown-toggle:focus {\n  outline: 0;\n}\n.note-editor .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  list-style: none;\n  font-size: 14px;\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.note-editor .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.note-editor .dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.note-editor .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.note-editor .dropdown-menu > li > a:hover,\n.note-editor .dropdown-menu > li > a:focus {\n  text-decoration: none;\n  color: #262626;\n  background-color: #f5f5f5;\n}\n.note-editor .dropdown-menu > .active > a,\n.note-editor .dropdown-menu > .active > a:hover,\n.note-editor .dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #428bca;\n}\n.note-editor .dropdown-menu > .disabled > a,\n.note-editor .dropdown-menu > .disabled > a:hover,\n.note-editor .dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\n.note-editor .dropdown-menu > .disabled > a:hover,\n.note-editor .dropdown-menu > .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.note-editor .open > .dropdown-menu {\n  display: block;\n  left:0!important;\n    right:auto!important;\n}\n.note-editor .open > a {\n  outline: 0;\n}\n.note-editor .dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\n.note-editor .dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: 990;\n}\n.note-editor .pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n.note-editor .dropup .caret,\n.note-editor .navbar-fixed-bottom .dropdown .caret {\n  border-top: 0 dotted;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n.note-editor .dropup .dropdown-menu,\n.note-editor .navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n}\n.btn-default .note-editor .caret {\n  border-top-color: #333333;\n}\n.btn-primary .note-editor .caret,\n.btn-success .note-editor .caret,\n.btn-warning .note-editor .caret,\n.btn-danger .note-editor .caret,\n.btn-info .note-editor .caret {\n  border-top-color: #fff;\n}\n.note-editor .dropup .btn-default .caret {\n  border-bottom-color: #333333;\n}\n.note-editor .dropup .btn-primary .caret,\n.note-editor .dropup .btn-success .caret,\n.note-editor .dropup .btn-warning .caret,\n.note-editor .dropup .btn-danger .caret,\n.note-editor .dropup .btn-info .caret {\n  border-bottom-color: #fff;\n}\n.note-editor .btn-group,\n.note-editor .btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.note-editor .btn-group > .btn,\n.note-editor .btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n.note-editor .btn-group > .btn:hover,\n.note-editor .btn-group-vertical > .btn:hover,\n.note-editor .btn-group > .btn:focus,\n.note-editor .btn-group-vertical > .btn:focus,\n.note-editor .btn-group > .btn:active,\n.note-editor .btn-group-vertical > .btn:active,\n.note-editor .btn-group > .btn.active,\n.note-editor .btn-group-vertical > .btn.active {\n  z-index: 2;\n}\n.note-editor .btn-group > .btn:focus,\n.note-editor .btn-group-vertical > .btn:focus {\n  outline: none;\n}\n.note-editor .btn-group .btn + .btn,\n.note-editor .btn-group .btn + .btn-group,\n.note-editor .btn-group .btn-group + .btn,\n.note-editor .btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n.note-editor .btn-toolbar:before,\n.note-editor .btn-toolbar:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .btn-toolbar:after {\n  clear: both;\n}\n.note-editor .btn-toolbar:before,\n.note-editor .btn-toolbar:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .btn-toolbar:after {\n  clear: both;\n}\n.note-editor .btn-toolbar .btn-group {\n  float: left;\n}\n.note-editor .btn-toolbar > .btn + .btn,\n.note-editor .btn-toolbar > .btn-group + .btn,\n.note-editor .btn-toolbar > .btn + .btn-group,\n.note-editor .btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n.note-editor .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n.note-editor .btn-group > .btn:first-child {\n  margin-left: 0;\n}\n.note-editor .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.note-editor .btn-group > .btn:last-child:not(:first-child),\n.note-editor .btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .btn-group > .btn-group {\n  float: left;\n}\n.note-editor .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.note-editor .btn-group > .btn-group:first-child > .btn:last-child,\n.note-editor .btn-group > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.note-editor .btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .btn-group .dropdown-toggle:active,\n.note-editor .btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.note-editor .btn-group-xs > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n  padding: 1px 5px;\n}\n.note-editor .btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.note-editor .btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.note-editor .btn-group > .btn + .dropdown-toggle {\n  padding-left: 5px;\n  padding-right: 5px;\n}\n.note-editor .btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n.note-editor .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.note-editor .btn .caret {\n  margin-left: 0;\n}\n.note-editor .btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n.note-editor .dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n.note-editor .btn-group-vertical > .btn,\n.note-editor .btn-group-vertical > .btn-group {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.note-editor .btn-group-vertical > .btn-group:before,\n.note-editor .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.note-editor .btn-group-vertical > .btn-group:before,\n.note-editor .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.note-editor .btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\n.note-editor .btn-group-vertical > .btn + .btn,\n.note-editor .btn-group-vertical > .btn + .btn-group,\n.note-editor .btn-group-vertical > .btn-group + .btn,\n.note-editor .btn-group-vertical > .btn-group + .btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.note-editor .btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.note-editor .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.note-editor .btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-bottom-left-radius: 4px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.note-editor .btn-group-vertical > .btn-group:first-child > .btn:last-child,\n.note-editor .btn-group-vertical > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.note-editor .btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.note-editor .btn-group-justified .btn {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.note-editor [data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n.note-editor [data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n.note-editor .input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.note-editor .input-group.col {\n  float: none;\n  padding-left: 0;\n  padding-right: 0;\n}\n.note-editor .input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n.note-editor .input-group-lg > .form-control,\n.note-editor .input-group-lg > .input-group-addon,\n.note-editor .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}\nselect.note-editor .input-group-lg > .form-control,\nselect.note-editor .input-group-lg > .input-group-addon,\nselect.note-editor .input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  line-height: 45px;\n}\ntextarea.note-editor .input-group-lg > .form-control,\ntextarea.note-editor .input-group-lg > .input-group-addon,\ntextarea.note-editor .input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\n.note-editor .input-group-sm > .form-control,\n.note-editor .input-group-sm > .input-group-addon,\n.note-editor .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.note-editor .input-group-sm > .form-control,\nselect.note-editor .input-group-sm > .input-group-addon,\nselect.note-editor .input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.note-editor .input-group-sm > .form-control,\ntextarea.note-editor .input-group-sm > .input-group-addon,\ntextarea.note-editor .input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n.note-editor .input-group-addon,\n.note-editor .input-group-btn,\n.note-editor .input-group .form-control {\n  display: table-cell;\n}\n.note-editor .input-group-addon:not(:first-child):not(:last-child),\n.note-editor .input-group-btn:not(:first-child):not(:last-child),\n.note-editor .input-group .form-control:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.note-editor .input-group-addon,\n.note-editor .input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.note-editor .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.note-editor .input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n.note-editor .input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n.note-editor .input-group-addon input[type=\"radio\"],\n.note-editor .input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.note-editor .input-group .form-control:first-child,\n.note-editor .input-group-addon:first-child,\n.note-editor .input-group-btn:first-child > .btn,\n.note-editor .input-group-btn:first-child > .dropdown-toggle,\n.note-editor .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.note-editor .input-group-addon:first-child {\n  border-right: 0;\n}\n.note-editor .input-group .form-control:last-child,\n.note-editor .input-group-addon:last-child,\n.note-editor .input-group-btn:last-child > .btn,\n.note-editor .input-group-btn:last-child > .dropdown-toggle,\n.note-editor .input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .input-group-addon:last-child {\n  border-left: 0;\n}\n.note-editor .input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n.note-editor .input-group-btn:first-child > .btn {\n  margin-right: -1px;\n}\n.note-editor .input-group-btn:last-child > .btn {\n  margin-left: -1px;\n}\n.note-editor .input-group-btn > .btn {\n  position: relative;\n}\n.note-editor .input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n.note-editor .input-group-btn > .btn:hover,\n.note-editor .input-group-btn > .btn:active {\n  z-index: 2;\n}\n.note-editor .nav {\n  margin-bottom: 0;\n  padding-left: 0;\n  list-style: none;\n}\n.note-editor .nav:before,\n.note-editor .nav:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .nav:after {\n  clear: both;\n}\n.note-editor .nav:before,\n.note-editor .nav:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .nav:after {\n  clear: both;\n}\n.note-editor .nav > li {\n  position: relative;\n  display: block;\n}\n.note-editor .nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n.note-editor .nav > li > a:hover,\n.note-editor .nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.note-editor .nav > li.disabled > a {\n  color: #999999;\n}\n.note-editor .nav > li.disabled > a:hover,\n.note-editor .nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.note-editor .nav .open > a,\n.note-editor .nav .open > a:hover,\n.note-editor .nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #428bca;\n}\n.note-editor .nav .open > a .caret,\n.note-editor .nav .open > a:hover .caret,\n.note-editor .nav .open > a:focus .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n.note-editor .nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.note-editor .nav > li > a > img {\n  max-width: none;\n}\n.note-editor .nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n.note-editor .nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.note-editor .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.note-editor .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n.note-editor .nav-tabs > li.active > a,\n.note-editor .nav-tabs > li.active > a:hover,\n.note-editor .nav-tabs > li.active > a:focus {\n  color: #555555;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.note-editor .nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n.note-editor .nav-tabs.nav-justified > li {\n  float: none;\n}\n.note-editor .nav-tabs.nav-justified > li > a {\n  text-align: center;\n  margin-bottom: 5px;\n}\n@media (min-width: 768px) {\n  .note-editor .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .note-editor .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.note-editor .nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.note-editor .nav-tabs.nav-justified > .active > a,\n.note-editor .nav-tabs.nav-justified > .active > a:hover,\n.note-editor .nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n  .note-editor .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .note-editor .nav-tabs.nav-justified > .active > a,\n  .note-editor .nav-tabs.nav-justified > .active > a:hover,\n  .note-editor .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n.note-editor .nav-pills > li {\n  float: left;\n}\n.note-editor .nav-pills > li > a {\n  border-radius: 4px;\n}\n.note-editor .nav-pills > li + li {\n  margin-left: 2px;\n}\n.note-editor .nav-pills > li.active > a,\n.note-editor .nav-pills > li.active > a:hover,\n.note-editor .nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n.note-editor .nav-pills > li.active > a .caret,\n.note-editor .nav-pills > li.active > a:hover .caret,\n.note-editor .nav-pills > li.active > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n.note-editor .nav-stacked > li {\n  float: none;\n}\n.note-editor .nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n.note-editor .nav-justified {\n  width: 100%;\n}\n.note-editor .nav-justified > li {\n  float: none;\n}\n.note-editor .nav-justified > li > a {\n  text-align: center;\n  margin-bottom: 5px;\n}\n@media (min-width: 768px) {\n  .note-editor .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .note-editor .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.note-editor .nav-tabs-justified {\n  border-bottom: 0;\n}\n.note-editor .nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.note-editor .nav-tabs-justified > .active > a,\n.note-editor .nav-tabs-justified > .active > a:hover,\n.note-editor .nav-tabs-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n  .note-editor .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .note-editor .nav-tabs-justified > .active > a,\n  .note-editor .nav-tabs-justified > .active > a:hover,\n  .note-editor .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n.note-editor .tab-content > .tab-pane {\n  display: none;\n}\n.note-editor .tab-content > .active {\n  display: block;\n}\n.note-editor .nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n.note-editor .nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n.note-editor .nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .navbar {\n  position: relative;\n  z-index: 1000;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n.note-editor .navbar:before,\n.note-editor .navbar:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar:after {\n  clear: both;\n}\n.note-editor .navbar:before,\n.note-editor .navbar:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar:after {\n  clear: both;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar {\n    border-radius: 4px;\n  }\n}\n.note-editor .navbar-header:before,\n.note-editor .navbar-header:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar-header:after {\n  clear: both;\n}\n.note-editor .navbar-header:before,\n.note-editor .navbar-header:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar-header:after {\n  clear: both;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-header {\n    float: left;\n  }\n}\n.note-editor .navbar-collapse {\n  max-height: 340px;\n  overflow-x: visible;\n  padding-right: 15px;\n  padding-left: 15px;\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.note-editor .navbar-collapse:before,\n.note-editor .navbar-collapse:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar-collapse:after {\n  clear: both;\n}\n.note-editor .navbar-collapse:before,\n.note-editor .navbar-collapse:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .navbar-collapse:after {\n  clear: both;\n}\n.note-editor .navbar-collapse.in {\n  overflow-y: auto;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n  }\n  .note-editor .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .note-editor .navbar-collapse.in {\n    overflow-y: visible;\n  }\n  .note-editor .navbar-collapse .navbar-nav.navbar-left:first-child {\n    margin-left: -15px;\n  }\n  .note-editor .navbar-collapse .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n  .note-editor .navbar-collapse .navbar-text:last-child {\n    margin-right: 0;\n  }\n}\n.note-editor .container > .navbar-header,\n.note-editor .container > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .note-editor .container > .navbar-header,\n  .note-editor .container > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n.note-editor .navbar-static-top {\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-static-top {\n    border-radius: 0;\n  }\n}\n.note-editor .navbar-fixed-top,\n.note-editor .navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-fixed-top,\n  .note-editor .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n.note-editor .navbar-fixed-top {\n  z-index: 1030;\n  top: 0;\n}\n.note-editor .navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n}\n.note-editor .navbar-brand {\n  float: left;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.note-editor .navbar-brand:hover,\n.note-editor .navbar-brand:focus {\n  text-decoration: none;\n}\n@media (min-width: 768px) {\n  .navbar > .container .note-editor .navbar-brand {\n    margin-left: -15px;\n  }\n}\n.note-editor .navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 15px;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.note-editor .navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n.note-editor .navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-toggle {\n    display: none;\n  }\n}\n.note-editor .navbar-nav {\n  margin: 7.5px -15px;\n}\n.note-editor .navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n@media (max-width: 767px) {\n  .note-editor .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  .note-editor .navbar-nav .open .dropdown-menu > li > a,\n  .note-editor .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .note-editor .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .note-editor .navbar-nav .open .dropdown-menu > li > a:hover,\n  .note-editor .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .note-editor .navbar-nav > li {\n    float: left;\n  }\n  .note-editor .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-left {\n    float: left !important;\n  }\n  .note-editor .navbar-right {\n    float: right !important;\n  }\n}\n.note-editor .navbar-form {\n  margin-left: -15px;\n  margin-right: -15px;\n  padding: 10px 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  margin-top: 8px;\n  margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .note-editor .navbar-form .form-control {\n    display: inline-block;\n  }\n  .note-editor .navbar-form .radio,\n  .note-editor .navbar-form .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n  }\n  .note-editor .navbar-form .radio input[type=\"radio\"],\n  .note-editor .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n@media (max-width: 767px) {\n  .note-editor .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-form {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n}\n.note-editor .navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.note-editor .navbar-nav.pull-right > li > .dropdown-menu,\n.note-editor .navbar-nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n.note-editor .navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n.note-editor .navbar-text {\n  float: left;\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n  .note-editor .navbar-text {\n    margin-left: 15px;\n    margin-right: 15px;\n  }\n}\n.note-editor .navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.note-editor .navbar-default .navbar-brand {\n  color: #777777;\n}\n.note-editor .navbar-default .navbar-brand:hover,\n.note-editor .navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.note-editor .navbar-default .navbar-text {\n  color: #777777;\n}\n.note-editor .navbar-default .navbar-nav > li > a {\n  color: #777777;\n}\n.note-editor .navbar-default .navbar-nav > li > a:hover,\n.note-editor .navbar-default .navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n.note-editor .navbar-default .navbar-nav > .active > a,\n.note-editor .navbar-default .navbar-nav > .active > a:hover,\n.note-editor .navbar-default .navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n.note-editor .navbar-default .navbar-nav > .disabled > a,\n.note-editor .navbar-default .navbar-nav > .disabled > a:hover,\n.note-editor .navbar-default .navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n.note-editor .navbar-default .navbar-toggle {\n  border-color: #dddddd;\n}\n.note-editor .navbar-default .navbar-toggle:hover,\n.note-editor .navbar-default .navbar-toggle:focus {\n  background-color: #dddddd;\n}\n.note-editor .navbar-default .navbar-toggle .icon-bar {\n  background-color: #cccccc;\n}\n.note-editor .navbar-default .navbar-collapse,\n.note-editor .navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n.note-editor .navbar-default .navbar-nav > .dropdown > a:hover .caret,\n.note-editor .navbar-default .navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n.note-editor .navbar-default .navbar-nav > .open > a,\n.note-editor .navbar-default .navbar-nav > .open > a:hover,\n.note-editor .navbar-default .navbar-nav > .open > a:focus {\n  background-color: #e7e7e7;\n  color: #555555;\n}\n.note-editor .navbar-default .navbar-nav > .open > a .caret,\n.note-editor .navbar-default .navbar-nav > .open > a:hover .caret,\n.note-editor .navbar-default .navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n.note-editor .navbar-default .navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n@media (max-width: 767px) {\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777777;\n  }\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n  }\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .note-editor .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n.note-editor .navbar-default .navbar-link {\n  color: #777777;\n}\n.note-editor .navbar-default .navbar-link:hover {\n  color: #333333;\n}\n.note-editor .navbar-inverse {\n  background-color: #222222;\n  border-color: #080808;\n}\n.note-editor .navbar-inverse .navbar-brand {\n  color: #999999;\n}\n.note-editor .navbar-inverse .navbar-brand:hover,\n.note-editor .navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n.note-editor .navbar-inverse .navbar-text {\n  color: #999999;\n}\n.note-editor .navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n.note-editor .navbar-inverse .navbar-nav > li > a:hover,\n.note-editor .navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n.note-editor .navbar-inverse .navbar-nav > .active > a,\n.note-editor .navbar-inverse .navbar-nav > .active > a:hover,\n.note-editor .navbar-inverse .navbar-nav > .active > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n.note-editor .navbar-inverse .navbar-nav > .disabled > a,\n.note-editor .navbar-inverse .navbar-nav > .disabled > a:hover,\n.note-editor .navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444444;\n  background-color: transparent;\n}\n.note-editor .navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n.note-editor .navbar-inverse .navbar-toggle:hover,\n.note-editor .navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n.note-editor .navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\n.note-editor .navbar-inverse .navbar-collapse,\n.note-editor .navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n.note-editor .navbar-inverse .navbar-nav > .open > a,\n.note-editor .navbar-inverse .navbar-nav > .open > a:hover,\n.note-editor .navbar-inverse .navbar-nav > .open > a:focus {\n  background-color: #080808;\n  color: #ffffff;\n}\n.note-editor .navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n.note-editor .navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n.note-editor .navbar-inverse .navbar-nav > .open > a .caret,\n.note-editor .navbar-inverse .navbar-nav > .open > a:hover .caret,\n.note-editor .navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n@media (max-width: 767px) {\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999999;\n  }\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #ffffff;\n    background-color: transparent;\n  }\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #ffffff;\n    background-color: #080808;\n  }\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .note-editor .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444444;\n    background-color: transparent;\n  }\n}\n.note-editor .navbar-inverse .navbar-link {\n  color: #999999;\n}\n.note-editor .navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n.note-editor .breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n}\n.note-editor .breadcrumb > li {\n  display: inline-block;\n}\n.note-editor .breadcrumb > li + li:before {\n  content: \"/\\00a0\";\n  padding: 0 5px;\n  color: #cccccc;\n}\n.note-editor .breadcrumb > .active {\n  color: #999999;\n}\n.note-editor .pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n.note-editor .pagination > li {\n  display: inline;\n}\n.note-editor .pagination > li > a,\n.note-editor .pagination > li > span {\n  position: relative;\n  float: left;\n  padding: 6px 12px;\n  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  margin-left: -1px;\n}\n.note-editor .pagination > li:first-child > a,\n.note-editor .pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\n.note-editor .pagination > li:last-child > a,\n.note-editor .pagination > li:last-child > span {\n  border-bottom-right-radius: 4px;\n  border-top-right-radius: 4px;\n}\n.note-editor .pagination > li > a:hover,\n.note-editor .pagination > li > span:hover,\n.note-editor .pagination > li > a:focus,\n.note-editor .pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.note-editor .pagination > .active > a,\n.note-editor .pagination > .active > span,\n.note-editor .pagination > .active > a:hover,\n.note-editor .pagination > .active > span:hover,\n.note-editor .pagination > .active > a:focus,\n.note-editor .pagination > .active > span:focus {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n  cursor: default;\n}\n.note-editor .pagination > .disabled > span,\n.note-editor .pagination > .disabled > span:hover,\n.note-editor .pagination > .disabled > span:focus,\n.note-editor .pagination > .disabled > a,\n.note-editor .pagination > .disabled > a:hover,\n.note-editor .pagination > .disabled > a:focus {\n  color: #999999;\n  background-color: #ffffff;\n  border-color: #dddddd;\n  cursor: not-allowed;\n}\n.note-editor .pagination-lg > li > a,\n.note-editor .pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n.note-editor .pagination-lg > li:first-child > a,\n.note-editor .pagination-lg > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n.note-editor .pagination-lg > li:last-child > a,\n.note-editor .pagination-lg > li:last-child > span {\n  border-bottom-right-radius: 6px;\n  border-top-right-radius: 6px;\n}\n.note-editor .pagination-sm > li > a,\n.note-editor .pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n.note-editor .pagination-sm > li:first-child > a,\n.note-editor .pagination-sm > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n.note-editor .pagination-sm > li:last-child > a,\n.note-editor .pagination-sm > li:last-child > span {\n  border-bottom-right-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.note-editor .pager {\n  padding-left: 0;\n  margin: 20px 0;\n  list-style: none;\n  text-align: center;\n}\n.note-editor .pager:before,\n.note-editor .pager:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .pager:after {\n  clear: both;\n}\n.note-editor .pager:before,\n.note-editor .pager:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .pager:after {\n  clear: both;\n}\n.note-editor .pager li {\n  display: inline;\n}\n.note-editor .pager li > a,\n.note-editor .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.note-editor .pager li > a:hover,\n.note-editor .pager li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.note-editor .pager .next > a,\n.note-editor .pager .next > span {\n  float: right;\n}\n.note-editor .pager .previous > a,\n.note-editor .pager .previous > span {\n  float: left;\n}\n.note-editor .pager .disabled > a,\n.note-editor .pager .disabled > a:hover,\n.note-editor .pager .disabled > a:focus,\n.note-editor .pager .disabled > span {\n  color: #999999;\n  background-color: #ffffff;\n  cursor: not-allowed;\n}\n.note-editor .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.note-editor .label[href]:hover,\n.note-editor .label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.note-editor .label:empty {\n  display: none;\n}\n.note-editor .label-default {\n  background-color: #999999;\n}\n.note-editor .label-default[href]:hover,\n.note-editor .label-default[href]:focus {\n  background-color: #808080;\n}\n.note-editor .label-primary {\n  background-color: #428bca;\n}\n.note-editor .label-primary[href]:hover,\n.note-editor .label-primary[href]:focus {\n  background-color: #3071a9;\n}\n.note-editor .label-success {\n  background-color: #5cb85c;\n}\n.note-editor .label-success[href]:hover,\n.note-editor .label-success[href]:focus {\n  background-color: #449d44;\n}\n.note-editor .label-info {\n  background-color: #5bc0de;\n}\n.note-editor .label-info[href]:hover,\n.note-editor .label-info[href]:focus {\n  background-color: #31b0d5;\n}\n.note-editor .label-warning {\n  background-color: #f0ad4e;\n}\n.note-editor .label-warning[href]:hover,\n.note-editor .label-warning[href]:focus {\n  background-color: #ec971f;\n}\n.note-editor .label-danger {\n  background-color: #d9534f;\n}\n.note-editor .label-danger[href]:hover,\n.note-editor .label-danger[href]:focus {\n  background-color: #c9302c;\n}\n.note-editor .badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  color: #ffffff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 10px;\n}\n.note-editor .badge:empty {\n  display: none;\n}\n.note-editor a.badge:hover,\n.note-editor a.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.note-editor .btn .badge {\n  position: relative;\n  top: -1px;\n}\n.note-editor a.list-group-item.active > .badge,\n.note-editor .nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n.note-editor .nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n.note-editor .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.note-editor .jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n.note-editor .jumbotron p {\n  line-height: 1.4;\n}\n.container .note-editor .jumbotron {\n  border-radius: 6px;\n}\n@media screen and (min-width: 768px) {\n  .note-editor .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .note-editor .jumbotron {\n    padding-left: 60px;\n    padding-right: 60px;\n  }\n  .note-editor .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n.note-editor .thumbnail {\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  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  display: block;\n  margin-bottom: 20px;\n}\n.note-editor .thumbnail > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.note-editor a.thumbnail:hover,\n.note-editor a.thumbnail:focus,\n.note-editor a.thumbnail.active {\n  border-color: #428bca;\n}\n.note-editor .thumbnail > img {\n  margin-left: auto;\n  margin-right: auto;\n}\n.note-editor .thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n.note-editor .alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.note-editor .alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n.note-editor .alert .alert-link {\n  font-weight: bold;\n}\n.note-editor .alert > p,\n.note-editor .alert > ul {\n  margin-bottom: 0;\n}\n.note-editor .alert > p + p {\n  margin-top: 5px;\n}\n.note-editor .alert-dismissable {\n  padding-right: 35px;\n}\n.note-editor .alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n.note-editor .alert-success {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n  color: #468847;\n}\n.note-editor .alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.note-editor .alert-success .alert-link {\n  color: #356635;\n}\n.note-editor .alert-info {\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n  color: #3a87ad;\n}\n.note-editor .alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.note-editor .alert-info .alert-link {\n  color: #2d6987;\n}\n.note-editor .alert-warning {\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n  color: #c09853;\n}\n.note-editor .alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n.note-editor .alert-warning .alert-link {\n  color: #a47e3c;\n}\n.note-editor .alert-danger {\n  background-color: #f2dede;\n  border-color: #ebccd1;\n  color: #b94a48;\n}\n.note-editor .alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n.note-editor .alert-danger .alert-link {\n  color: #953b39;\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@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\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@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n.note-editor .progress {\n  overflow: hidden;\n  height: 20px;\n  margin-bottom: 20px;\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.note-editor .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.note-editor .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.note-editor .progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n  -moz-animation: progress-bar-stripes 2s linear infinite;\n  -ms-animation: progress-bar-stripes 2s linear infinite;\n  -o-animation: progress-bar-stripes 2s linear infinite;\n  animation: progress-bar-stripes 2s linear infinite;\n}\n.note-editor .progress-bar-success {\n  background-color: #5cb85c;\n}\n.progress-striped .note-editor .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.note-editor .progress-bar-info {\n  background-color: #5bc0de;\n}\n.progress-striped .note-editor .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.note-editor .progress-bar-warning {\n  background-color: #f0ad4e;\n}\n.progress-striped .note-editor .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.note-editor .progress-bar-danger {\n  background-color: #d9534f;\n}\n.progress-striped .note-editor .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.note-editor .media,\n.note-editor .media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n.note-editor .media,\n.note-editor .media .media {\n  margin-top: 15px;\n}\n.note-editor .media:first-child {\n  margin-top: 0;\n}\n.note-editor .media-object {\n  display: block;\n}\n.note-editor .media-heading {\n  margin: 0 0 5px;\n}\n.note-editor .media > .pull-left {\n  margin-right: 10px;\n}\n.note-editor .media > .pull-right {\n  margin-left: 10px;\n}\n.note-editor .media-list {\n  padding-left: 0;\n  list-style: none;\n}\n.note-editor .list-group {\n  margin-bottom: 20px;\n  padding-left: 0;\n}\n.note-editor .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.note-editor .list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\n.note-editor .list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.note-editor .list-group-item > .badge {\n  float: right;\n}\n.note-editor .list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\n.note-editor a.list-group-item {\n  color: #555555;\n}\n.note-editor a.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n.note-editor a.list-group-item:hover,\n.note-editor a.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.note-editor a.list-group-item.active,\n.note-editor a.list-group-item.active:hover,\n.note-editor a.list-group-item.active:focus {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.note-editor a.list-group-item.active .list-group-item-heading,\n.note-editor a.list-group-item.active:hover .list-group-item-heading,\n.note-editor a.list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\n.note-editor a.list-group-item.active .list-group-item-text,\n.note-editor a.list-group-item.active:hover .list-group-item-text,\n.note-editor a.list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n.note-editor .list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.note-editor .list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n.note-editor .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.note-editor .panel-body {\n  padding: 15px;\n}\n.note-editor .panel-body:before,\n.note-editor .panel-body:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .panel-body:after {\n  clear: both;\n}\n.note-editor .panel-body:before,\n.note-editor .panel-body:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.note-editor .panel-body:after {\n  clear: both;\n}\n.note-editor .panel > .list-group {\n  margin-bottom: 0;\n}\n.note-editor .panel > .list-group .list-group-item {\n  border-width: 1px 0;\n}\n.note-editor .panel > .list-group .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.note-editor .panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n.note-editor .panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n.note-editor .panel > .table,\n.note-editor .panel > .table-responsive {\n  margin-bottom: 0;\n}\n.note-editor .panel > .panel-body + .table,\n.note-editor .panel > .panel-body + .table-responsive {\n  border-top: 1px solid #dddddd;\n}\n.note-editor .panel > .table-bordered,\n.note-editor .panel > .table-responsive > .table-bordered {\n  border: 0;\n}\n.note-editor .panel > .table-bordered > thead > tr > th:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.note-editor .panel > .table-bordered > tbody > tr > th:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.note-editor .panel > .table-bordered > tfoot > tr > th:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.note-editor .panel > .table-bordered > thead > tr > td:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.note-editor .panel > .table-bordered > tbody > tr > td:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.note-editor .panel > .table-bordered > tfoot > tr > td:first-child,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.note-editor .panel > .table-bordered > thead > tr > th:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.note-editor .panel > .table-bordered > tbody > tr > th:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.note-editor .panel > .table-bordered > tfoot > tr > th:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.note-editor .panel > .table-bordered > thead > tr > td:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.note-editor .panel > .table-bordered > tbody > tr > td:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.note-editor .panel > .table-bordered > tfoot > tr > td:last-child,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.note-editor .panel > .table-bordered > thead > tr:last-child > th,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr:last-child > th,\n.note-editor .panel > .table-bordered > tbody > tr:last-child > th,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.note-editor .panel > .table-bordered > tfoot > tr:last-child > th,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n.note-editor .panel > .table-bordered > thead > tr:last-child > td,\n.note-editor .panel > .table-responsive > .table-bordered > thead > tr:last-child > td,\n.note-editor .panel > .table-bordered > tbody > tr:last-child > td,\n.note-editor .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.note-editor .panel > .table-bordered > tfoot > tr:last-child > td,\n.note-editor .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n  border-bottom: 0;\n}\n.note-editor .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.note-editor .panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n}\n.note-editor .panel-title > a {\n  color: inherit;\n}\n.note-editor .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.note-editor .panel-group .panel {\n  margin-bottom: 0;\n  border-radius: 4px;\n  overflow: hidden;\n}\n.note-editor .panel-group .panel + .panel {\n  margin-top: 5px;\n}\n.note-editor .panel-group .panel-heading {\n  border-bottom: 0;\n}\n.note-editor .panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #dddddd;\n}\n.note-editor .panel-group .panel-footer {\n  border-top: 0;\n}\n.note-editor .panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #dddddd;\n}\n.note-editor .panel-default {\n  border-color: #dddddd;\n}\n.note-editor .panel-default > .panel-heading {\n  color: #333333;\n  background-color: #f5f5f5;\n  border-color: #dddddd;\n}\n.note-editor .panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #dddddd;\n}\n.note-editor .panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #dddddd;\n}\n.note-editor .panel-primary {\n  border-color: #428bca;\n}\n.note-editor .panel-primary > .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.note-editor .panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n.note-editor .panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n.note-editor .panel-success {\n  border-color: #d6e9c6;\n}\n.note-editor .panel-success > .panel-heading {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.note-editor .panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n.note-editor .panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n.note-editor .panel-warning {\n  border-color: #faebcc;\n}\n.note-editor .panel-warning > .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.note-editor .panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #faebcc;\n}\n.note-editor .panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #faebcc;\n}\n.note-editor .panel-danger {\n  border-color: #ebccd1;\n}\n.note-editor .panel-danger > .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.note-editor .panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ebccd1;\n}\n.note-editor .panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ebccd1;\n}\n.note-editor .panel-info {\n  border-color: #bce8f1;\n}\n.note-editor .panel-info > .panel-heading {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.note-editor .panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n.note-editor .panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\n.note-editor .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.note-editor .well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.note-editor .well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n.note-editor .well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n.note-editor .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.note-editor .close:hover,\n.note-editor .close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\nbutton.note-editor .close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n.modal-open {\n  overflow: hidden;\n}\n.modal {\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\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.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  margin-left: auto;\n  margin-right: auto;\n  width: auto;\n  padding: 10px;\n  z-index: 1050;\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  -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  outline: none;\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.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n.modal-header {\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n  min-height: 16.428571429px;\n}\n.modal-header .close {\n  margin-top: -2px;\n}\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\n.modal-footer {\n  margin-top: 15px;\n  padding: 19px 20px 20px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n.modal-footer:before,\n.modal-footer:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.modal-footer:after {\n  clear: both;\n}\n.modal-footer:before,\n.modal-footer:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.modal-footer:after {\n  clear: both;\n}\n.modal-footer .btn + .btn {\n  margin-left: 5px;\n  margin-bottom: 0;\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 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.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  visibility: visible;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n.tooltip.in {\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n.tooltip.top {\n  margin-top: -3px;\n  padding: 5px 0;\n}\n.tooltip.right {\n  margin-left: 3px;\n  padding: 0 5px;\n}\n.tooltip.bottom {\n  margin-top: 3px;\n  padding: 5px 0;\n}\n.tooltip.left {\n  margin-left: -3px;\n  padding: 0 5px;\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.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: #000000;\n}\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000000;\n}\n.tooltip.top-right .tooltip-arrow {\n  bottom: 0;\n  right: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000000;\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: #000000;\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: #000000;\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: #000000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000000;\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  background-color: #ffffff;\n  background-clip: padding-box;\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  white-space: normal;\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  margin: 0;\n  padding: 8px 14px;\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  border-width: 10px;\n  content: \"\";\n}\n.popover.top .arrow {\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-width: 0;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  bottom: -11px;\n}\n.popover.top .arrow:after {\n  content: \" \";\n  bottom: 1px;\n  margin-left: -10px;\n  border-bottom-width: 0;\n  border-top-color: #ffffff;\n}\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-left-width: 0;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right .arrow:after {\n  content: \" \";\n  left: 1px;\n  bottom: -10px;\n  border-left-width: 0;\n  border-right-color: #ffffff;\n}\n.popover.bottom .arrow {\n  left: 50%;\n  margin-left: -11px;\n  border-top-width: 0;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  top: -11px;\n}\n.popover.bottom .arrow:after {\n  content: \" \";\n  top: 1px;\n  margin-left: -10px;\n  border-top-width: 0;\n  border-bottom-color: #ffffff;\n}\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-right-width: 0;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left .arrow:after {\n  content: \" \";\n  right: 1px;\n  border-right-width: 0;\n  border-left-color: #ffffff;\n  bottom: -10px;\n}\n.carousel {\n  position: relative;\n}\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n}\n.carousel-inner > .item {\n  display: none;\n  position: relative;\n  -webkit-transition: 0.6s ease-in-out left;\n  transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\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  left: 0;\n  bottom: 0;\n  width: 15%;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n  font-size: 20px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\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.carousel-control.right {\n  left: auto;\n  right: 0;\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.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.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  margin-left: -30%;\n  padding-left: 0;\n  list-style: none;\n  text-align: center;\n}\n.carousel-indicators li {\n  display: inline-block;\n  width: 10px;\n  height: 10px;\n  margin: 1px;\n  text-indent: -999px;\n  border: 1px solid #ffffff;\n  border-radius: 10px;\n  cursor: pointer;\n}\n.carousel-indicators .active {\n  margin: 0;\n  width: 12px;\n  height: 12px;\n  background-color: #ffffff;\n}\n.carousel-caption {\n  position: absolute;\n  left: 15%;\n  right: 15%;\n  bottom: 20px;\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.carousel-caption .btn {\n  text-shadow: none;\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    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n.clearfix:before,\n.clearfix:after {\n  content: \" \";\n  /* 1 */\n\n  display: table;\n  /* 2 */\n\n}\n.clearfix:after {\n  clear: both;\n}\n.center-block {\n  display: block;\n  margin-left: auto;\n  margin-right: 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,\ntr.visible-xs,\nth.visible-xs,\ntd.visible-xs {\n  display: none !important;\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@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@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@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.visible-sm,\ntr.visible-sm,\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\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@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@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@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.visible-md,\ntr.visible-md,\nth.visible-md,\ntd.visible-md {\n  display: none !important;\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@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@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@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.visible-lg,\ntr.visible-lg,\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\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@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@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@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.hidden-xs {\n  display: block !important;\n}\ntr.hidden-xs {\n  display: table-row !important;\n}\nth.hidden-xs,\ntd.hidden-xs {\n  display: table-cell !important;\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@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@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@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.hidden-sm {\n  display: block !important;\n}\ntr.hidden-sm {\n  display: table-row !important;\n}\nth.hidden-sm,\ntd.hidden-sm {\n  display: table-cell !important;\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@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@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@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.hidden-md {\n  display: block !important;\n}\ntr.hidden-md {\n  display: table-row !important;\n}\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\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@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@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@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.hidden-lg {\n  display: block !important;\n}\ntr.hidden-lg {\n  display: table-row !important;\n}\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\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@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@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@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.visible-print,\ntr.visible-print,\nth.visible-print,\ntd.visible-print {\n  display: none !important;\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}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/summernote/summernote.css",
    "content": ".note-editor {\n    height: 300px;\n}\n\n.note-editor .note-dropzone {\n    position: absolute;\n    z-index: 1;\n    display: none;\n    color: #87cefa;\n    background-color: white;\n    border: 2px dashed #87cefa;\n    opacity: .95;\n    pointer-event: none\n}\n\n.note-editor .note-dropzone .note-dropzone-message {\n    display: table-cell;\n    font-size: 28px;\n    font-weight: bold;\n    text-align: center;\n    vertical-align: middle\n}\n\n.note-editor .note-dropzone.hover {\n    color: #098ddf;\n    border: 2px dashed #098ddf\n}\n\n.note-editor.dragover .note-dropzone {\n    display: table\n}\n\n.note-editor.fullscreen {\n    position: fixed;\n    top: 0;\n    left: 0;\n    z-index: 1050;\n    width: 100%\n}\n\n.note-editor.fullscreen .note-editable {\n    background-color: white\n}\n\n.note-editor.fullscreen .note-resizebar {\n    display: none\n}\n\n.note-editor.codeview .note-editable {\n    display: none\n}\n\n.note-editor.codeview .note-codable {\n    display: block\n}\n\n.note-editor .note-toolbar {\n    padding-bottom: 5px;\n    padding-left: 10px;\n    padding-top: 5px;\n    margin: 0;\n    background-color: #f5f5f5;\n    border-bottom: 1px solid #E7EAEC\n}\n\n.note-editor .note-toolbar > .btn-group {\n    margin-top: 5px;\n    margin-right: 5px;\n    margin-left: 0\n}\n\n.note-editor .note-toolbar .note-table .dropdown-menu {\n    min-width: 0;\n    padding: 5px\n}\n\n.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker {\n    font-size: 18px\n}\n\n.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-mousecatcher {\n    position: absolute !important;\n    z-index: 3;\n    width: 10em;\n    height: 10em;\n    cursor: pointer\n}\n\n.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-unhighlighted {\n    position: relative !important;\n    z-index: 1;\n    width: 5em;\n    height: 5em;\n    background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat\n}\n\n.note-editor .note-toolbar .note-table .dropdown-menu .note-dimension-picker .note-dimension-picker-highlighted {\n    position: absolute !important;\n    z-index: 2;\n    width: 1em;\n    height: 1em;\n    background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIjd6vvD2f9LKLW+AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKwNDEVT0AAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC') repeat\n}\n\n.note-editor .note-toolbar .note-style h1, .note-editor .note-toolbar .note-style h2, .note-editor .note-toolbar .note-style h3, .note-editor .note-toolbar .note-style h4, .note-editor .note-toolbar .note-style h5, .note-editor .note-toolbar .note-style h6, .note-editor .note-toolbar .note-style blockquote {\n    margin: 0\n}\n\n.note-editor .note-toolbar .note-color .dropdown-toggle {\n    width: 20px;\n    padding-left: 5px\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu {\n    min-width: 290px\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu .btn-group {\n    margin: 0\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu .btn-group:first-child {\n    margin: 0 5px\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-palette-title {\n    margin: 2px 7px;\n    font-size: 12px;\n    text-align: center;\n    border-bottom: 1px solid #eee\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-color-reset {\n    padding: 0 3px;\n    margin: 5px;\n    font-size: 12px;\n    cursor: pointer;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px\n}\n\n.note-editor .note-toolbar .note-color .dropdown-menu .btn-group .note-color-reset:hover {\n    background: #eee\n}\n\n.note-editor .note-toolbar .note-para .dropdown-menu {\n    min-width: 216px;\n    padding: 5px\n}\n\n.note-editor .note-toolbar .note-para .dropdown-menu > div:first-child {\n    margin-right: 5px\n}\n\n.note-editor .note-statusbar {\n    background-color: #f5f5f5\n}\n\n.note-editor .note-statusbar .note-resizebar {\n    width: 100%;\n    height: 8px;\n    cursor: s-resize;\n    border-top: 1px solid #a9a9a9\n}\n\n.note-editor .note-statusbar .note-resizebar .note-icon-bar {\n    width: 20px;\n    margin: 1px auto;\n    border-top: 1px solid #a9a9a9\n}\n\n.note-editor .note-popover .popover {\n    max-width: none\n}\n\n.note-editor .note-popover .popover .popover-content {\n    padding: 5px\n}\n\n.note-editor .note-popover .popover .popover-content a {\n    display: inline-block;\n    max-width: 200px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    vertical-align: middle\n}\n\n.note-editor .note-popover .popover .popover-content .btn-group + .btn-group {\n    margin-left: 5px\n}\n\n.note-editor .note-popover .popover .arrow {\n    left: 20px\n}\n\n.note-editor .note-handle .note-control-selection {\n    position: absolute;\n    display: none;\n    border: 1px solid black\n}\n\n.note-editor .note-handle .note-control-selection > div {\n    position: absolute\n}\n\n.note-editor .note-handle .note-control-selection .note-control-selection-bg {\n    width: 100%;\n    height: 100%;\n    background-color: black;\n    -webkit-opacity: .3;\n    -khtml-opacity: .3;\n    -moz-opacity: .3;\n    opacity: .3;\n    -ms-filter: alpha(opacity=30);\n    filter: alpha(opacity=30)\n}\n\n.note-editor .note-handle .note-control-selection .note-control-handle {\n    width: 7px;\n    height: 7px;\n    border: 1px solid black\n}\n\n.note-editor .note-handle .note-control-selection .note-control-holder {\n    width: 7px;\n    height: 7px;\n    border: 1px solid black\n}\n\n.note-editor .note-handle .note-control-selection .note-control-sizing {\n    width: 7px;\n    height: 7px;\n    background-color: white;\n    border: 1px solid black\n}\n\n.note-editor .note-handle .note-control-selection .note-control-nw {\n    top: -5px;\n    left: -5px;\n    border-right: 0;\n    border-bottom: 0\n}\n\n.note-editor .note-handle .note-control-selection .note-control-ne {\n    top: -5px;\n    right: -5px;\n    border-bottom: 0;\n    border-left: none\n}\n\n.note-editor .note-handle .note-control-selection .note-control-sw {\n    bottom: -5px;\n    left: -5px;\n    border-top: 0;\n    border-right: 0\n}\n\n.note-editor .note-handle .note-control-selection .note-control-se {\n    right: -5px;\n    bottom: -5px;\n    cursor: se-resize\n}\n\n.note-editor .note-handle .note-control-selection .note-control-selection-info {\n    right: 0;\n    bottom: 0;\n    padding: 5px;\n    margin: 5px;\n    font-size: 12px;\n    color: white;\n    background-color: black;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n    -webkit-opacity: .7;\n    -khtml-opacity: .7;\n    -moz-opacity: .7;\n    opacity: .7;\n    -ms-filter: alpha(opacity=70);\n    filter: alpha(opacity=70)\n}\n\n.note-editor .note-dialog > div {\n    display: none\n}\n\n.note-editor .note-dialog .note-image-dialog .note-dropzone {\n    min-height: 100px;\n    margin-bottom: 10px;\n    font-size: 30px;\n    line-height: 4;\n    color: lightgray;\n    text-align: center;\n    border: 4px dashed lightgray\n}\n\n.note-editor .note-dialog .note-help-dialog {\n    font-size: 12px;\n    color: #ccc;\n    background: transparent;\n    background-color: #222 !important;\n    border: 0;\n    -webkit-opacity: .9;\n    -khtml-opacity: .9;\n    -moz-opacity: .9;\n    opacity: .9;\n    -ms-filter: alpha(opacity=90);\n    filter: alpha(opacity=90)\n}\n\n.note-editor .note-dialog .note-help-dialog .modal-content {\n    background: transparent;\n    border: 1px solid white;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none\n}\n\n.note-editor .note-dialog .note-help-dialog a {\n    font-size: 12px;\n    color: white\n}\n\n.note-editor .note-dialog .note-help-dialog .title {\n    padding-bottom: 5px;\n    font-size: 14px;\n    font-weight: bold;\n    color: white;\n    border-bottom: white 1px solid\n}\n\n.note-editor .note-dialog .note-help-dialog .modal-close {\n    font-size: 14px;\n    color: #dd0;\n    cursor: pointer\n}\n\n.note-editor .note-dialog .note-help-dialog .note-shortcut-layout {\n    width: 100%\n}\n\n.note-editor .note-dialog .note-help-dialog .note-shortcut-layout td {\n    vertical-align: top\n}\n\n.note-editor .note-dialog .note-help-dialog .note-shortcut {\n    margin-top: 8px\n}\n\n.note-editor .note-dialog .note-help-dialog .note-shortcut th {\n    font-size: 13px;\n    color: #dd0;\n    text-align: left\n}\n\n.note-editor .note-dialog .note-help-dialog .note-shortcut td:first-child {\n    min-width: 110px;\n    padding-right: 10px;\n    font-family: \"Courier New\";\n    color: #dd0;\n    text-align: right\n}\n\n.note-editor .note-editable {\n    padding: 20px;\n    overflow: auto;\n    outline: 0\n}\n\n.note-editor .note-editable[contenteditable=\"false\"] {\n    background-color: #e5e5e5\n}\n\n.note-editor .note-codable {\n    display: none;\n    width: 100%;\n    padding: 10px;\n    margin-bottom: 0;\n    font-family: Menlo, Monaco, monospace, sans-serif;\n    font-size: 14px;\n    color: #ccc;\n    background-color: #222;\n    border: 0;\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n    box-shadow: none;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n    resize: none\n}\n\n.note-editor .dropdown-menu {\n    min-width: 90px\n}\n\n.note-editor .dropdown-menu.right {\n    right: 0;\n    left: auto\n}\n\n.note-editor .dropdown-menu.right::before {\n    right: 9px;\n    left: auto !important\n}\n\n.note-editor .dropdown-menu.right::after {\n    right: 10px;\n    left: auto !important\n}\n\n.note-editor .dropdown-menu li a i {\n    color: deepskyblue;\n    visibility: hidden\n}\n\n.note-editor .dropdown-menu li a.checked i {\n    visibility: visible\n}\n\n.note-editor .note-fontsize-10 {\n    font-size: 10px\n}\n\n.note-editor .note-color-palette {\n    line-height: 1\n}\n\n.note-editor .note-color-palette div .note-color-btn {\n    width: 17px;\n    height: 17px;\n    padding: 0;\n    margin: 0;\n    border: 1px solid #fff\n}\n\n.note-editor .note-color-palette div .note-color-btn:hover {\n    border: 1px solid #000\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/sweetalert/sweetalert.css",
    "content": "body.stop-scrolling {\n  height: 100%;\n  overflow: hidden; }\n\n.sweet-overlay {\n  background-color: black;\n  /* IE8 */\n  -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)\";\n  /* IE8 */\n  background-color: rgba(0, 0, 0, 0.4);\n  position: fixed;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  display: none;\n  z-index: 10000; }\n\n.sweet-alert {\n  background-color: white;\n  font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n  width: 478px;\n  padding: 17px;\n  border-radius: 5px;\n  text-align: center;\n  position: fixed;\n  left: 50%;\n  top: 50%;\n  margin-left: -256px;\n  margin-top: -200px;\n  overflow: hidden;\n  display: none;\n  z-index: 99999; }\n  @media all and (max-width: 540px) {\n    .sweet-alert {\n      width: auto;\n      margin-left: 0;\n      margin-right: 0;\n      left: 15px;\n      right: 15px; } }\n  .sweet-alert h2 {\n    color: #575757;\n    font-size: 30px;\n    text-align: center;\n    font-weight: 600;\n    text-transform: none;\n    position: relative;\n    margin: 25px 0;\n    padding: 0;\n    line-height: 40px;\n    display: block; }\n  .sweet-alert p {\n    color: #797979;\n    font-size: 16px;\n    text-align: center;\n    font-weight: 300;\n    position: relative;\n    text-align: inherit;\n    float: none;\n    margin: 0;\n    padding: 0;\n    line-height: normal; }\n  .sweet-alert fieldset {\n    border: none;\n    position: relative; }\n  .sweet-alert .sa-error-container {\n    background-color: #f1f1f1;\n    margin-left: -17px;\n    margin-right: -17px;\n    overflow: hidden;\n    padding: 0 10px;\n    max-height: 0;\n    webkit-transition: padding 0.15s, max-height 0.15s;\n    transition: padding 0.15s, max-height 0.15s; }\n    .sweet-alert .sa-error-container.show {\n      padding: 10px 0;\n      max-height: 100px;\n      webkit-transition: padding 0.2s, max-height 0.2s;\n      transition: padding 0.25s, max-height 0.25s; }\n    .sweet-alert .sa-error-container .icon {\n      display: inline-block;\n      width: 24px;\n      height: 24px;\n      border-radius: 50%;\n      background-color: #ea7d7d;\n      color: white;\n      line-height: 24px;\n      text-align: center;\n      margin-right: 3px; }\n    .sweet-alert .sa-error-container p {\n      display: inline-block; }\n  .sweet-alert .sa-input-error {\n    position: absolute;\n    top: 29px;\n    right: 26px;\n    width: 20px;\n    height: 20px;\n    opacity: 0;\n    -webkit-transform: scale(0.5);\n    transform: scale(0.5);\n    -webkit-transform-origin: 50% 50%;\n    transform-origin: 50% 50%;\n    -webkit-transition: all 0.1s;\n    transition: all 0.1s; }\n    .sweet-alert .sa-input-error::before, .sweet-alert .sa-input-error::after {\n      content: \"\";\n      width: 20px;\n      height: 6px;\n      background-color: #f06e57;\n      border-radius: 3px;\n      position: absolute;\n      top: 50%;\n      margin-top: -4px;\n      left: 50%;\n      margin-left: -9px; }\n    .sweet-alert .sa-input-error::before {\n      -webkit-transform: rotate(-45deg);\n      transform: rotate(-45deg); }\n    .sweet-alert .sa-input-error::after {\n      -webkit-transform: rotate(45deg);\n      transform: rotate(45deg); }\n    .sweet-alert .sa-input-error.show {\n      opacity: 1;\n      -webkit-transform: scale(1);\n      transform: scale(1); }\n  .sweet-alert input {\n    width: 100%;\n    box-sizing: border-box;\n    border-radius: 3px;\n    border: 1px solid #d7d7d7;\n    height: 43px;\n    margin-top: 10px;\n    margin-bottom: 17px;\n    font-size: 18px;\n    box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.06);\n    padding: 0 12px;\n    display: none;\n    -webkit-transition: all 0.3s;\n    transition: all 0.3s; }\n    .sweet-alert input:focus {\n      outline: none;\n      box-shadow: 0px 0px 3px #c4e6f5;\n      border: 1px solid #b4dbed; }\n      .sweet-alert input:focus::-moz-placeholder {\n        transition: opacity 0.3s 0.03s ease;\n        opacity: 0.5; }\n      .sweet-alert input:focus:-ms-input-placeholder {\n        transition: opacity 0.3s 0.03s ease;\n        opacity: 0.5; }\n      .sweet-alert input:focus::-webkit-input-placeholder {\n        transition: opacity 0.3s 0.03s ease;\n        opacity: 0.5; }\n    .sweet-alert input::-moz-placeholder {\n      color: #bdbdbd; }\n    .sweet-alert input:-ms-input-placeholder {\n      color: #bdbdbd; }\n    .sweet-alert input::-webkit-input-placeholder {\n      color: #bdbdbd; }\n  .sweet-alert.show-input input {\n    display: block; }\n  .sweet-alert button {\n    background-color: #AEDEF4;\n    color: white;\n    border: none;\n    box-shadow: none;\n    font-size: 17px;\n    font-weight: 500;\n    -webkit-border-radius: 4px;\n    border-radius: 5px;\n    padding: 10px 32px;\n    margin: 26px 5px 0 5px;\n    cursor: pointer; }\n    .sweet-alert button:focus {\n      outline: none;\n      box-shadow: 0 0 2px rgba(128, 179, 235, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.05); }\n    .sweet-alert button:hover {\n      background-color: #a1d9f2; }\n    .sweet-alert button:active {\n      background-color: #81ccee; }\n    .sweet-alert button.cancel {\n      background-color: #D0D0D0; }\n      .sweet-alert button.cancel:hover {\n        background-color: #c8c8c8; }\n      .sweet-alert button.cancel:active {\n        background-color: #b6b6b6; }\n      .sweet-alert button.cancel:focus {\n        box-shadow: rgba(197, 205, 211, 0.8) 0px 0px 2px, rgba(0, 0, 0, 0.0470588) 0px 0px 0px 1px inset !important; }\n    .sweet-alert button::-moz-focus-inner {\n      border: 0; }\n  .sweet-alert[data-has-cancel-button=false] button {\n    box-shadow: none !important; }\n  .sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false] {\n    padding-bottom: 40px; }\n  .sweet-alert .sa-icon {\n    width: 80px;\n    height: 80px;\n    border: 4px solid gray;\n    -webkit-border-radius: 40px;\n    border-radius: 40px;\n    border-radius: 50%;\n    margin: 20px auto;\n    padding: 0;\n    position: relative;\n    box-sizing: content-box; }\n    .sweet-alert .sa-icon.sa-error {\n      border-color: #F27474; }\n      .sweet-alert .sa-icon.sa-error .sa-x-mark {\n        position: relative;\n        display: block; }\n      .sweet-alert .sa-icon.sa-error .sa-line {\n        position: absolute;\n        height: 5px;\n        width: 47px;\n        background-color: #F27474;\n        display: block;\n        top: 37px;\n        border-radius: 2px; }\n        .sweet-alert .sa-icon.sa-error .sa-line.sa-left {\n          -webkit-transform: rotate(45deg);\n          transform: rotate(45deg);\n          left: 17px; }\n        .sweet-alert .sa-icon.sa-error .sa-line.sa-right {\n          -webkit-transform: rotate(-45deg);\n          transform: rotate(-45deg);\n          right: 16px; }\n    .sweet-alert .sa-icon.sa-warning {\n      border-color: #F8BB86; }\n      .sweet-alert .sa-icon.sa-warning .sa-body {\n        position: absolute;\n        width: 5px;\n        height: 47px;\n        left: 50%;\n        top: 10px;\n        -webkit-border-radius: 2px;\n        border-radius: 2px;\n        margin-left: -2px;\n        background-color: #F8BB86; }\n      .sweet-alert .sa-icon.sa-warning .sa-dot {\n        position: absolute;\n        width: 7px;\n        height: 7px;\n        -webkit-border-radius: 50%;\n        border-radius: 50%;\n        margin-left: -3px;\n        left: 50%;\n        bottom: 10px;\n        background-color: #F8BB86; }\n    .sweet-alert .sa-icon.sa-info {\n      border-color: #C9DAE1; }\n      .sweet-alert .sa-icon.sa-info::before {\n        content: \"\";\n        position: absolute;\n        width: 5px;\n        height: 29px;\n        left: 50%;\n        bottom: 17px;\n        border-radius: 2px;\n        margin-left: -2px;\n        background-color: #C9DAE1; }\n      .sweet-alert .sa-icon.sa-info::after {\n        content: \"\";\n        position: absolute;\n        width: 7px;\n        height: 7px;\n        border-radius: 50%;\n        margin-left: -3px;\n        top: 19px;\n        background-color: #C9DAE1; }\n    .sweet-alert .sa-icon.sa-success {\n      border-color: #A5DC86; }\n      .sweet-alert .sa-icon.sa-success::before, .sweet-alert .sa-icon.sa-success::after {\n        content: '';\n        -webkit-border-radius: 40px;\n        border-radius: 40px;\n        border-radius: 50%;\n        position: absolute;\n        width: 60px;\n        height: 120px;\n        background: white;\n        -webkit-transform: rotate(45deg);\n        transform: rotate(45deg); }\n      .sweet-alert .sa-icon.sa-success::before {\n        -webkit-border-radius: 120px 0 0 120px;\n        border-radius: 120px 0 0 120px;\n        top: -7px;\n        left: -33px;\n        -webkit-transform: rotate(-45deg);\n        transform: rotate(-45deg);\n        -webkit-transform-origin: 60px 60px;\n        transform-origin: 60px 60px; }\n      .sweet-alert .sa-icon.sa-success::after {\n        -webkit-border-radius: 0 120px 120px 0;\n        border-radius: 0 120px 120px 0;\n        top: -11px;\n        left: 30px;\n        -webkit-transform: rotate(-45deg);\n        transform: rotate(-45deg);\n        -webkit-transform-origin: 0px 60px;\n        transform-origin: 0px 60px; }\n      .sweet-alert .sa-icon.sa-success .sa-placeholder {\n        width: 80px;\n        height: 80px;\n        border: 4px solid rgba(165, 220, 134, 0.2);\n        -webkit-border-radius: 40px;\n        border-radius: 40px;\n        border-radius: 50%;\n        box-sizing: content-box;\n        position: absolute;\n        left: -4px;\n        top: -4px;\n        z-index: 2; }\n      .sweet-alert .sa-icon.sa-success .sa-fix {\n        width: 5px;\n        height: 90px;\n        background-color: white;\n        position: absolute;\n        left: 28px;\n        top: 8px;\n        z-index: 1;\n        -webkit-transform: rotate(-45deg);\n        transform: rotate(-45deg); }\n      .sweet-alert .sa-icon.sa-success .sa-line {\n        height: 5px;\n        background-color: #A5DC86;\n        display: block;\n        border-radius: 2px;\n        position: absolute;\n        z-index: 2; }\n        .sweet-alert .sa-icon.sa-success .sa-line.sa-tip {\n          width: 25px;\n          left: 14px;\n          top: 46px;\n          -webkit-transform: rotate(45deg);\n          transform: rotate(45deg); }\n        .sweet-alert .sa-icon.sa-success .sa-line.sa-long {\n          width: 47px;\n          right: 8px;\n          top: 38px;\n          -webkit-transform: rotate(-45deg);\n          transform: rotate(-45deg); }\n    .sweet-alert .sa-icon.sa-custom {\n      background-size: contain;\n      border-radius: 0;\n      border: none;\n      background-position: center center;\n      background-repeat: no-repeat; }\n\n/*\n * Animations\n */\n@-webkit-keyframes showSweetAlert {\n  0% {\n    transform: scale(0.7);\n    -webkit-transform: scale(0.7); }\n  45% {\n    transform: scale(1.05);\n    -webkit-transform: scale(1.05); }\n  80% {\n    transform: scale(0.95);\n    -webkit-transform: scale(0.95); }\n  100% {\n    transform: scale(1);\n    -webkit-transform: scale(1); } }\n\n@keyframes showSweetAlert {\n  0% {\n    transform: scale(0.7);\n    -webkit-transform: scale(0.7); }\n  45% {\n    transform: scale(1.05);\n    -webkit-transform: scale(1.05); }\n  80% {\n    transform: scale(0.95);\n    -webkit-transform: scale(0.95); }\n  100% {\n    transform: scale(1);\n    -webkit-transform: scale(1); } }\n\n@-webkit-keyframes hideSweetAlert {\n  0% {\n    transform: scale(1);\n    -webkit-transform: scale(1); }\n  100% {\n    transform: scale(0.5);\n    -webkit-transform: scale(0.5); } }\n\n@keyframes hideSweetAlert {\n  0% {\n    transform: scale(1);\n    -webkit-transform: scale(1); }\n  100% {\n    transform: scale(0.5);\n    -webkit-transform: scale(0.5); } }\n\n@-webkit-keyframes slideFromTop {\n  0% {\n    top: 0%; }\n  100% {\n    top: 50%; } }\n\n@keyframes slideFromTop {\n  0% {\n    top: 0%; }\n  100% {\n    top: 50%; } }\n\n@-webkit-keyframes slideToTop {\n  0% {\n    top: 50%; }\n  100% {\n    top: 0%; } }\n\n@keyframes slideToTop {\n  0% {\n    top: 50%; }\n  100% {\n    top: 0%; } }\n\n@-webkit-keyframes slideFromBottom {\n  0% {\n    top: 70%; }\n  100% {\n    top: 50%; } }\n\n@keyframes slideFromBottom {\n  0% {\n    top: 70%; }\n  100% {\n    top: 50%; } }\n\n@-webkit-keyframes slideToBottom {\n  0% {\n    top: 50%; }\n  100% {\n    top: 70%; } }\n\n@keyframes slideToBottom {\n  0% {\n    top: 50%; }\n  100% {\n    top: 70%; } }\n\n.showSweetAlert[data-animation=pop] {\n  -webkit-animation: showSweetAlert 0.3s;\n  animation: showSweetAlert 0.3s; }\n\n.showSweetAlert[data-animation=none] {\n  -webkit-animation: none;\n  animation: none; }\n\n.showSweetAlert[data-animation=slide-from-top] {\n  -webkit-animation: slideFromTop 0.3s;\n  animation: slideFromTop 0.3s; }\n\n.showSweetAlert[data-animation=slide-from-bottom] {\n  -webkit-animation: slideFromBottom 0.3s;\n  animation: slideFromBottom 0.3s; }\n\n.hideSweetAlert[data-animation=pop] {\n  -webkit-animation: hideSweetAlert 0.2s;\n  animation: hideSweetAlert 0.2s; }\n\n.hideSweetAlert[data-animation=none] {\n  -webkit-animation: none;\n  animation: none; }\n\n.hideSweetAlert[data-animation=slide-from-top] {\n  -webkit-animation: slideToTop 0.4s;\n  animation: slideToTop 0.4s; }\n\n.hideSweetAlert[data-animation=slide-from-bottom] {\n  -webkit-animation: slideToBottom 0.3s;\n  animation: slideToBottom 0.3s; }\n\n@-webkit-keyframes animateSuccessTip {\n  0% {\n    width: 0;\n    left: 1px;\n    top: 19px; }\n  54% {\n    width: 0;\n    left: 1px;\n    top: 19px; }\n  70% {\n    width: 50px;\n    left: -8px;\n    top: 37px; }\n  84% {\n    width: 17px;\n    left: 21px;\n    top: 48px; }\n  100% {\n    width: 25px;\n    left: 14px;\n    top: 45px; } }\n\n@keyframes animateSuccessTip {\n  0% {\n    width: 0;\n    left: 1px;\n    top: 19px; }\n  54% {\n    width: 0;\n    left: 1px;\n    top: 19px; }\n  70% {\n    width: 50px;\n    left: -8px;\n    top: 37px; }\n  84% {\n    width: 17px;\n    left: 21px;\n    top: 48px; }\n  100% {\n    width: 25px;\n    left: 14px;\n    top: 45px; } }\n\n@-webkit-keyframes animateSuccessLong {\n  0% {\n    width: 0;\n    right: 46px;\n    top: 54px; }\n  65% {\n    width: 0;\n    right: 46px;\n    top: 54px; }\n  84% {\n    width: 55px;\n    right: 0px;\n    top: 35px; }\n  100% {\n    width: 47px;\n    right: 8px;\n    top: 38px; } }\n\n@keyframes animateSuccessLong {\n  0% {\n    width: 0;\n    right: 46px;\n    top: 54px; }\n  65% {\n    width: 0;\n    right: 46px;\n    top: 54px; }\n  84% {\n    width: 55px;\n    right: 0px;\n    top: 35px; }\n  100% {\n    width: 47px;\n    right: 8px;\n    top: 38px; } }\n\n@-webkit-keyframes rotatePlaceholder {\n  0% {\n    transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg); }\n  5% {\n    transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg); }\n  12% {\n    transform: rotate(-405deg);\n    -webkit-transform: rotate(-405deg); }\n  100% {\n    transform: rotate(-405deg);\n    -webkit-transform: rotate(-405deg); } }\n\n@keyframes rotatePlaceholder {\n  0% {\n    transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg); }\n  5% {\n    transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg); }\n  12% {\n    transform: rotate(-405deg);\n    -webkit-transform: rotate(-405deg); }\n  100% {\n    transform: rotate(-405deg);\n    -webkit-transform: rotate(-405deg); } }\n\n.animateSuccessTip {\n  -webkit-animation: animateSuccessTip 0.75s;\n  animation: animateSuccessTip 0.75s; }\n\n.animateSuccessLong {\n  -webkit-animation: animateSuccessLong 0.75s;\n  animation: animateSuccessLong 0.75s; }\n\n.sa-icon.sa-success.animate::after {\n  -webkit-animation: rotatePlaceholder 4.25s ease-in;\n  animation: rotatePlaceholder 4.25s ease-in; }\n\n@-webkit-keyframes animateErrorIcon {\n  0% {\n    transform: rotateX(100deg);\n    -webkit-transform: rotateX(100deg);\n    opacity: 0; }\n  100% {\n    transform: rotateX(0deg);\n    -webkit-transform: rotateX(0deg);\n    opacity: 1; } }\n\n@keyframes animateErrorIcon {\n  0% {\n    transform: rotateX(100deg);\n    -webkit-transform: rotateX(100deg);\n    opacity: 0; }\n  100% {\n    transform: rotateX(0deg);\n    -webkit-transform: rotateX(0deg);\n    opacity: 1; } }\n\n.animateErrorIcon {\n  -webkit-animation: animateErrorIcon 0.5s;\n  animation: animateErrorIcon 0.5s; }\n\n@-webkit-keyframes animateXMark {\n  0% {\n    transform: scale(0.4);\n    -webkit-transform: scale(0.4);\n    margin-top: 26px;\n    opacity: 0; }\n  50% {\n    transform: scale(0.4);\n    -webkit-transform: scale(0.4);\n    margin-top: 26px;\n    opacity: 0; }\n  80% {\n    transform: scale(1.15);\n    -webkit-transform: scale(1.15);\n    margin-top: -6px; }\n  100% {\n    transform: scale(1);\n    -webkit-transform: scale(1);\n    margin-top: 0;\n    opacity: 1; } }\n\n@keyframes animateXMark {\n  0% {\n    transform: scale(0.4);\n    -webkit-transform: scale(0.4);\n    margin-top: 26px;\n    opacity: 0; }\n  50% {\n    transform: scale(0.4);\n    -webkit-transform: scale(0.4);\n    margin-top: 26px;\n    opacity: 0; }\n  80% {\n    transform: scale(1.15);\n    -webkit-transform: scale(1.15);\n    margin-top: -6px; }\n  100% {\n    transform: scale(1);\n    -webkit-transform: scale(1);\n    margin-top: 0;\n    opacity: 1; } }\n\n.animateXMark {\n  -webkit-animation: animateXMark 0.5s;\n  animation: animateXMark 0.5s; }\n\n@-webkit-keyframes pulseWarning {\n  0% {\n    border-color: #F8D486; }\n  100% {\n    border-color: #F8BB86; } }\n\n@keyframes pulseWarning {\n  0% {\n    border-color: #F8D486; }\n  100% {\n    border-color: #F8BB86; } }\n\n.pulseWarning {\n  -webkit-animation: pulseWarning 0.75s infinite alternate;\n  animation: pulseWarning 0.75s infinite alternate; }\n\n@-webkit-keyframes pulseWarningIns {\n  0% {\n    background-color: #F8D486; }\n  100% {\n    background-color: #F8BB86; } }\n\n@keyframes pulseWarningIns {\n  0% {\n    background-color: #F8D486; }\n  100% {\n    background-color: #F8BB86; } }\n\n.pulseWarningIns {\n  -webkit-animation: pulseWarningIns 0.75s infinite alternate;\n  animation: pulseWarningIns 0.75s infinite alternate; }\n\n/* Internet Explorer 9 has some special quirks that are fixed here */\n/* The icons are not animated. */\n/* This file is automatically merged into sweet-alert.min.js through Gulp */\n/* Error icon */\n.sweet-alert .sa-icon.sa-error .sa-line.sa-left {\n  -ms-transform: rotate(45deg) \\9; }\n\n.sweet-alert .sa-icon.sa-error .sa-line.sa-right {\n  -ms-transform: rotate(-45deg) \\9; }\n\n/* Success icon */\n.sweet-alert .sa-icon.sa-success {\n  border-color: transparent\\9; }\n\n.sweet-alert .sa-icon.sa-success .sa-line.sa-tip {\n  -ms-transform: rotate(45deg) \\9; }\n\n.sweet-alert .sa-icon.sa-success .sa-line.sa-long {\n  -ms-transform: rotate(-45deg) \\9; }\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/switchery/switchery.css",
    "content": "/*\n *\n * Main stylesheet for Switchery.\n * http://abpetkov.github.io/switchery/\n *\n */\n\n.switchery {\n    background-color: #fff;\n    border: 1px solid #dfdfdf;\n    border-radius: 20px;\n    cursor: pointer;\n    display: inline-block;\n    height: 30px;\n    position: relative;\n    vertical-align: middle;\n    width: 50px;\n\n    -webkit-box-sizing: content-box;\n    -moz-box-sizing: content-box;\n    box-sizing: content-box;\n}\n\n.switchery > small {\n    background: #fff;\n    border-radius: 100%;\n    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);\n    height: 30px;\n    position: absolute;\n    top: 0;\n    width: 30px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/treeview/bootstrap-treeview.css",
    "content": "/* =========================================================\n * bootstrap-treeview.css v1.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.list-group-item {\n\tcursor: pointer;\n}\n\n/*.list-group-item:hover {\n  background-color: #f5f5f5;\n}*/\n\nspan.indent {\n\tmargin-left: 10px;\n\tmargin-right: 10px;\n}\n\nspan.icon {\n\tmargin-right: 5px;\n}\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/webuploader/webuploader.css",
    "content": ".webuploader-container {\n\tposition: relative;\n}\n.webuploader-element-invisible {\n\tposition: absolute !important;\n\tclip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n    clip: rect(1px,1px,1px,1px);\n}\n.webuploader-pick {\n\tposition: relative;\n\tdisplay: inline-block;\n\tcursor: pointer;\n\tbackground: #00b7ee;\n\tpadding: 10px 15px;\n\tcolor: #fff;\n\ttext-align: center;\n\tborder-radius: 3px;\n\toverflow: hidden;\n}\n.webuploader-pick-hover {\n\tbackground: #00a2d4;\n}\n\n.webuploader-pick-disable {\n\topacity: 0.6;\n\tpointer-events:none;\n}\n\n"
  },
  {
    "path": "src/main/resources/static/css/plugins/zTree/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: 14px;\n  font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif;\n  background-color: #ffffff;\n}\n.ztree {\n  margin: 0;\n  padding: 5px;\n  color: #333333;\n  background-color: #ffffff;\n}\n.ztree li {\n  padding: 3px;\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: #333333;\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: #ffffff;\n  background-color: #333333;\n  font-size: 12px;\n  border: 1px #585956 solid;\n  *border: 0px;\n}\n.ztree li a:hover {\n  background-color: #beebff;\n}\n.ztree li a.curSelectedNode {\n  padding-top: 0px;\n  background-color: #666666;\n  color: #f0f6e4;\n  height: 17px;\n  opacity: 0.8;\n}\n.ztree li a.curSelectedNode_Edit {\n  padding-top: 0px;\n  background-color: transparent;\n  color: #333333;\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: #333333;\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-left: 5px;\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: 15px;\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: #333333;\n  font-family: FontAwesome;\n  padding-top: 10px;\n}\n.ztree li span.button.chk {\n  margin: 0px;\n  cursor: auto;\n  width: 15px;\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: #333333;\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: #333333;\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n  color: #333333;\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: #333333;\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: #333333;\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: #333333;\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: #333333;\n}\n.ztree li span.button.center_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #333333;\n}\n.ztree li span.button.bottom_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #333333;\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: #333333;\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: #333333;\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: #333333;\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: #333333;\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 #333333 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": "src/main/resources/static/css/plugins/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/32px.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: -228px -4px;}\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:-36px -4px}\n.ztree li span.button.root_close{background-position:-103px -39px}\n.ztree li span.button.roots_open{background-position: -36px -4px;}\n.ztree li span.button.roots_close{background-position: -103px -39px;}\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": "src/main/resources/static/css/style.css",
    "content": "/*\n *\n *   H+ - 后台主题UI框架\n *   version 4.0\n *   修改记录\n *\t .checkbox-inline input[type=checkbox] 去掉margin-top:-4px\n *\t .checkbox-inline 添加font-size: 14px;默认是13px\n *   .onoffswitch-inner:before,    ;   /* height: 16px; 两处\n *\n *\t.file-control {\n *  \tcolor: inherit;\n * \t font-size: 14px;\n *\tadd nopadding class\n *\n *\n *\n*/\nh1, h2, h3, h4, h5, h6 {\n    font-weight: 100;\n}\n\nh1 {\n    font-size: 30px;\n}\n\nh2 {\n    font-size: 24px;\n}\n\nh3 {\n    font-size: 16px;\n}\n\nh4 {\n    font-size: 14px;\n}\n\nh5 {\n    font-size: 12px;\n}\n\nh6 {\n    font-size: 10px;\n}\n\nh3, h4, h5 {\n    margin-top: 5px;\n    font-weight: 600;\n}\n\na:focus {\n    outline: none;\n}\n\n.nav>li>a {\n    color: #a7b1c2;\n    font-weight: 600;\n    padding: 14px 20px 14px 25px;\n}\n\n.nav li>a {\n    display: block;\n    /*white-space: nowrap;*/\n}\n\n.nav.navbar-right>li>a {\n    color: #999c9e;\n}\n\n.nav>li.active>a {\n    color: #ffffff;\n}\n\n.navbar-default .nav>li>a:hover, .navbar-default .nav>li>a:focus {\n    background-color: #293846;\n    color: white;\n}\n\n.nav .open>a, .nav .open>a:hover, .nav .open>a:focus {\n    background: #fff;\n}\n\n.nav>li>a i {\n    margin-right: 6px;\n}\n\n.navbar {\n    border: 0;\n}\n\n.navbar-default {\n    background-color: transparent;\n    border-color: #2f4050;\n    position: relative;\n}\n\n.navbar-top-links li {\n    display: inline-block;\n}\n\n.navbar-top-links li:last-child {\n    margin-right: 30px;\n}\n\nbody.body-small .navbar-top-links li:last-child {\n    margin-right: 10px;\n}\n\n.navbar-top-links li a {\n    padding: 20px 10px;\n    min-height: 50px;\n}\n\n.dropdown-menu {\n    border: medium none;\n    display: none;\n    float: left;\n    font-size: 12px;\n    left: 0;\n    list-style: none outside none;\n    padding: 0;\n    position: absolute;\n    text-shadow: none;\n    top: 100%;\n    z-index: 1000;\n    border-radius: 0;\n    box-shadow: 0 0 3px rgba(86, 96, 117, 0.3);\n}\n\n.dropdown-menu>li>a {\n    border-radius: 3px;\n    color: inherit;\n    line-height: 25px;\n    margin: 4px;\n    text-align: left;\n    font-weight: normal;\n}\n\n.dropdown-menu>li>a.font-bold {\n    font-weight: 600;\n}\n\n.navbar-top-links .dropdown-menu li {\n    display: block;\n}\n\n.navbar-top-links .dropdown-menu li:last-child {\n    margin-right: 0;\n}\n\n.navbar-top-links .dropdown-menu li a {\n    padding: 3px 20px;\n    min-height: 0;\n}\n\n.navbar-top-links .dropdown-menu li a div {\n    white-space: normal;\n}\n\n.navbar-top-links .dropdown-messages, .navbar-top-links .dropdown-tasks,  .navbar-top-links .dropdown-alerts {\n    width: 310px;\n    min-width: 0;\n}\n\n.navbar-top-links .dropdown-messages {\n    margin-left: 5px;\n}\n\n.navbar-top-links .dropdown-tasks {\n    margin-left: -59px;\n}\n\n.navbar-top-links .dropdown-alerts {\n    margin-left: -123px;\n}\n\n.navbar-top-links .dropdown-user {\n    right: 0;\n    left: auto;\n}\n\n.dropdown-messages, .dropdown-alerts {\n    padding: 10px 10px 10px 10px;\n}\n\n.dropdown-messages li a, .dropdown-alerts li a {\n    font-size: 12px;\n}\n\n.dropdown-messages li em, .dropdown-alerts li em {\n    font-size: 10px;\n}\n\n.nav.navbar-top-links .dropdown-alerts a {\n    font-size: 12px;\n}\n\n.nav-header {\n    padding: 33px 25px;\n    background: url(\"patterns/header-profile.png\") no-repeat;\n}\n\n.pace-done .nav-header {\n    -webkit-transition: all 0.5s;\n    transition: all 0.5s;\n}\n\n.nav>li.active {\n    border-left: 4px solid #19aa8d;\n    background: #293846;\n}\n\n.nav.nav-second-level>li.active {\n    border: none;\n}\n\n.nav.nav-second-level.collapse[style] {\n    height: auto !important;\n}\n\n.nav-header a {\n    color: #DFE4ED;\n}\n\n.nav-header .text-muted {\n    color: #8095a8;\n}\n\n.minimalize-styl-2 {\n    padding: 4px 12px;\n    margin: 14px 5px 5px 20px;\n    font-size: 14px;\n    float: left;\n}\n\n.navbar-form-custom {\n    float: left;\n    height: 50px;\n    padding: 0;\n    width: 200px;\n    display: inline-table;\n}\n\n.navbar-form-custom .form-group {\n    margin-bottom: 0;\n}\n\n.nav.navbar-top-links a {\n    font-size: 14px;\n}\n\n.navbar-form-custom .form-control {\n    background: none repeat scroll 0 0 rgba(0, 0, 0, 0);\n    border: medium none;\n    font-size: 14px;\n    height: 60px;\n    margin: 0;\n    z-index: 2000;\n}\n\n.count-info .label {\n    line-height: 12px;\n    padding: 1px 5px;\n    position: absolute;\n    right: 6px;\n    top: 12px;\n}\n\n.arrow {\n    float: right;\n    margin-top: 2px;\n}\n\n.fa.arrow:before {\n    content: \"\\f104\";\n}\n\n.active>a>.fa.arrow:before {\n    content: \"\\f107\";\n}\n\n.nav-second-level li, .nav-third-level li {\n    border-bottom: none !important;\n}\n\n.nav-second-level li a {\n    padding: 7px 15px 7px 10px;\n    padding-left: 52px;\n}\n\n.nav-third-level li a {\n    padding-left: 62px;\n}\n\n.nav-second-level li:last-child {\n    margin-bottom: 10px;\n}\n\nbody:not(.fixed-sidebar ):not(.canvas-menu ).mini-navbar .nav li:hover>.nav-second-level,.mini-navbar .nav li:focus>.nav-second-level {\n    display: block;\n    border-radius: 0 2px 2px 0;\n    min-width: 140px;\n    height: auto;\n}\n\nbody.mini-navbar .navbar-default .nav>li>.nav-second-level li a {\n    font-size: 12px;\n    border-radius: 0 2px 2px 0;\n}\n\n.fixed-nav .slimScrollDiv #side-menu {\n    padding-bottom: 60px;\n    position: relative;\n}\n\n.fixed-sidebar.mini-navbar .slimScrollDiv>* {\n    overflow: visible!important;\n}\n\n.fixed-sidebar .slimScrollDiv>* {\n    overflow-y: hidden;\n    overflow-x: visible;\n}\n\n.mini-navbar .nav-second-level li a {\n    padding: 10px 10px 10px 15px;\n}\n\n.canvas-menu.mini-navbar .nav-second-level {\n    background: #293846;\n}\n\n.mini-navbar li.active .nav-second-level {\n    left: 65px;\n}\n\n.navbar-default .special_link a {\n    background: #1ab394;\n    color: white;\n}\n\n.navbar-default .special_link a:hover {\n    background: #17987e !important;\n    color: white;\n}\n\n.navbar-default .special_link a span.label {\n    background: #fff;\n    color: #1ab394;\n}\n\n.navbar-default .landing_link a {\n    background: #1cc09f;\n    color: white;\n}\n\n.navbar-default .landing_link a:hover {\n    background: #1ab394 !important;\n    color: white;\n}\n\n.navbar-default .landing_link a span.label {\n    background: #fff;\n    color: #1cc09f;\n}\n\n.logo-element {\n    text-align: center;\n    font-size: 18px;\n    font-weight: 600;\n    color: white;\n    display: none;\n    padding: 18px 0;\n}\n\n.pace-done .navbar-static-side, .pace-done .nav-header, .pace-done li.active,  .pace-done #page-wrapper, .pace-done .footer {\n    -webkit-transition: all 0.5s;\n    transition: all 0.5s;\n}\n\n.navbar-fixed-top {\n    background: #fff;\n    -webkit-transition-duration: 0.5s;\n    transition-duration: 0.5s;\n    z-index: 2030;\n}\n\n.navbar-fixed-top, .navbar-static-top {\n    background: #f3f3f4;\n}\n\n.fixed-nav #wrapper {\n    padding-top: 60px;\n    box-sizing: border-box;\n}\n\n.fixed-nav .minimalize-styl-2 {\n    margin: 14px 5px 5px 15px;\n}\n\n.body-small .navbar-fixed-top {\n    margin-left: 0px;\n}\n\nbody.mini-navbar .navbar-static-side {\n    width: 70px;\n}\n\nbody.mini-navbar .profile-element, body.mini-navbar .nav-label, body.mini-navbar .navbar-default .nav li a span {\n    display: none;\n}\n\nbody.canvas-menu .profile-element {\n    display: block;\n}\n\nbody:not(.fixed-sidebar ):not(.canvas-menu ).mini-navbar .nav-second-level {\n    display: none;\n}\n\nbody.mini-navbar .navbar-default .nav>li>a {\n    font-size: 16px;\n}\n\nbody.mini-navbar .logo-element {\n    display: block;\n}\n\nbody.canvas-menu .logo-element {\n    display: none;\n}\n\nbody.mini-navbar .nav-header {\n    padding: 0;\n    background-color: #1ab394;\n}\n\nbody.canvas-menu .nav-header {\n    padding: 33px 25px;\n}\n\nbody.mini-navbar #page-wrapper {\n    margin: 0 0 0 70px;\n}\n\nbody.canvas-menu.mini-navbar #page-wrapper, body.canvas-menu.mini-navbar .footer {\n    margin: 0 0 0 0;\n}\n\nbody.fixed-sidebar .navbar-static-side, body.canvas-menu .navbar-static-side {\n    position: fixed;\n    width: 220px;\n    z-index: 2001;\n    height: 100%;\n}\n\nbody.fixed-sidebar.mini-navbar .navbar-static-side {\n    width: 70px;\n}\n\nbody.fixed-sidebar.mini-navbar #page-wrapper {\n    margin: 0 0 0 70px;\n}\n\nbody.body-small.fixed-sidebar.mini-navbar #page-wrapper {\n    margin: 0 0 0 70px;\n}\n\nbody.body-small.fixed-sidebar.mini-navbar .navbar-static-side {\n    width: 70px;\n}\n\n.fixed-sidebar.mini-navbar .nav li>.nav-second-level {\n    display: none;\n}\n\n.fixed-sidebar.mini-navbar .nav li.active {\n    border-left-width: 0;\n}\n/*.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level, .canvas-menu.mini-navbar .nav li:hover>.nav-second-level*/\n/*{*/\n/*position: absolute;*/\n/*left: 70px;*/\n/*top: 40px;*/\n/*background-color: #2f4050;*/\n/*padding: 10px 10px 0 10px;*/\n/*font-size: 12px;*/\n/*display: block;*/\n/*min-width: 140px;*/\n/*border-radius: 2px;*/\n/*}*/\n\n/*伸缩菜单*/\n.fixed-sidebar.mini-navbar .nav li:hover>a> span.nav-label {\n    top: 0px;\n    padding: 10px 10px 10px 10px;\n    text-align: center;\n    background-color: #243747;\n    border-bottom: dashed 1px #fff;\n}\n\n.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level {\n    top: 40px;\n    font-size: 12px;\n    /*padding: 10px 10px 0 10px;*/\n    background-color: #2f4050;\n}\n\n.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level, .fixed-sidebar.mini-navbar .nav li:hover>a> span.nav-label {\n    position: absolute;\n    left: 70px;\n    display: block;\n    min-width: 140px;\n    border-radius: 2px;\n}\n/*伸缩菜单结束*/\n\nbody.fixed-sidebar.mini-navbar .navbar-default .nav>li>.nav-second-level li a {\n    font-size: 12px;\n    border-radius: 3px;\n}\n\nbody.canvas-menu.mini-navbar .navbar-default .nav>li>.nav-second-level li a {\n    font-size: 13px;\n    border-radius: 3px;\n}\n\n.fixed-sidebar.mini-navbar .nav-second-level li a, .canvas-menu.mini-navbar .nav-second-level li a {\n    padding: 10px 10px 10px 15px;\n}\n\n.fixed-sidebar.mini-navbar .nav-second-level, .canvas-menu.mini-navbar .nav-second-level {\n    position: relative;\n    padding: 0;\n    font-size: 13px;\n}\n\n.fixed-sidebar.mini-navbar li.active .nav-second-level, .canvas-menu.mini-navbar li.active .nav-second-level {\n    left: 0px;\n}\n\nbody.canvas-menu nav.navbar-static-side {\n    z-index: 2001;\n    background: #2f4050;\n    height: 100%;\n    position: fixed;\n    display: none;\n}\n\nbody.canvas-menu.mini-navbar nav.navbar-static-side {\n    display: block;\n    width: 70px;\n}\n\n.top-navigation #page-wrapper {\n    margin-left: 0;\n}\n\n.top-navigation .navbar-nav .dropdown-menu>.active>a {\n    background: white;\n    color: #1ab394;\n    font-weight: bold;\n}\n\n.white-bg .navbar-fixed-top, .white-bg .navbar-static-top {\n    background: #fff;\n}\n\n.top-navigation .navbar {\n    margin-bottom: 0;\n}\n\n.top-navigation .nav>li>a {\n    padding: 15px 20px;\n    color: #676a6c;\n}\n\n.top-navigation .nav>li a:hover, .top-navigation .nav>li a:focus {\n    background: #fff;\n    color: #1ab394;\n}\n\n.top-navigation .nav>li.active {\n    background: #fff;\n    border: none;\n}\n\n.top-navigation .nav>li.active>a {\n    color: #1ab394;\n}\n\n.top-navigation .navbar-right {\n    padding-right: 10px;\n}\n\n.top-navigation .navbar-nav .dropdown-menu {\n    box-shadow: none;\n    border: 1px solid #e7eaec;\n}\n\n.top-navigation .dropdown-menu>li>a {\n    margin: 0;\n    padding: 7px 20px;\n}\n\n.navbar .dropdown-menu {\n    margin-top: 0px;\n}\n\n.top-navigation .navbar-brand {\n    background: #1ab394;\n    color: #fff;\n    padding: 15px 25px;\n}\n\n.top-navigation .navbar-top-links li:last-child {\n    margin-right: 0;\n}\n\n.top-navigation.mini-navbar #page-wrapper, .top-navigation.body-small.fixed-sidebar.mini-navbar #page-wrapper,  .mini-navbar .top-navigation #page-wrapper, .body-small.fixed-sidebar.mini-navbar .top-navigation #page-wrapper,  .canvas-menu #page-wrapper {\n    margin: 0;\n}\n\n.top-navigation.fixed-nav #wrapper, .fixed-nav #wrapper.top-navigation {\n    margin-top: 50px;\n}\n\n.top-navigation .footer.fixed {\n    margin-left: 0 !important;\n}\n\n.top-navigation .wrapper.wrapper-content {\n    padding: 40px;\n}\n\n.top-navigation.body-small .wrapper.wrapper-content, .body-small .top-navigation .wrapper.wrapper-content {\n    padding: 40px 0px 40px 0px;\n}\n\n.navbar-toggle {\n    background-color: #1ab394;\n    color: #fff;\n    padding: 6px 12px;\n    font-size: 14px;\n}\n\n.top-navigation .navbar-nav .open .dropdown-menu>li>a, .top-navigation .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 10px 15px 10px 20px;\n}\n\n@media ( max-width : 768px) {\n    .top-navigation .navbar-header {\n        display: block;\n        float: none;\n    }\n}\n\n.menu-visible-lg, .menu-visible-md {\n    display: none !important;\n}\n\n@media ( min-width : 1200px) {\n    .menu-visible-lg {\n        display: block !important;\n    }\n}\n\n@media ( min-width : 992px) {\n    .menu-visible-md {\n        display: block !important;\n    }\n}\n\n@media ( max-width : 767px) {\n    .menu-visible-md {\n        display: block !important;\n    }\n\n    .menu-visible-lg {\n        display: block !important;\n    }\n}\n\n.btn {\n    border-radius: 3px;\n}\n\n.float-e-margins .btn {\n    margin-bottom: 5px;\n}\n\n.btn-w-m {\n    min-width: 120px;\n}\n\n.btn-primary.btn-outline {\n    color: #1ab394;\n}\n\n.btn-success.btn-outline {\n    color: #1c84c6;\n}\n\n.btn-info.btn-outline {\n    color: #23c6c8;\n}\n\n.btn-warning.btn-outline {\n    color: #f8ac59;\n}\n\n.btn-danger.btn-outline {\n    color: #ed5565;\n}\n\n.btn-primary.btn-outline:hover, .btn-success.btn-outline:hover,  .btn-info.btn-outline:hover, .btn-warning.btn-outline:hover,  .btn-danger.btn-outline:hover {\n    color: #fff;\n}\n\n.btn-primary {\n    background-color: #1ab394;\n    border-color: #1ab394;\n    color: #FFFFFF;\n}\n\n.btn-primary:hover, .btn-primary:focus, .btn-primary:active,  .btn-primary.active, .open .dropdown-toggle.btn-primary {\n    background-color: #18a689;\n    border-color: #18a689;\n    color: #FFFFFF;\n}\n\n.btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary {\n    background-image: none;\n}\n\n.btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus,  .btn-primary.disabled:active, .btn-primary.disabled.active,  .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus,  .btn-primary[disabled]:active, .btn-primary.active[disabled], fieldset[disabled] .btn-primary,  fieldset[disabled] .btn-primary:hover, fieldset[disabled] .btn-primary:focus,  fieldset[disabled] .btn-primary:active, fieldset[disabled] .btn-primary.active {\n    background-color: #1dc5a3;\n    border-color: #1dc5a3;\n}\n\n.btn-success {\n    background-color: #1c84c6;\n    border-color: #1c84c6;\n    color: #FFFFFF;\n}\n\n.btn-success:hover, .btn-success:focus, .btn-success:active,  .btn-success.active, .open .dropdown-toggle.btn-success {\n    background-color: #1a7bb9;\n    border-color: #1a7bb9;\n    color: #FFFFFF;\n}\n\n.btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {\n    background-image: none;\n}\n\n.btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus,  .btn-success.disabled:active, .btn-success.disabled.active,  .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus,  .btn-success[disabled]:active, .btn-success.active[disabled], fieldset[disabled] .btn-success,  fieldset[disabled] .btn-success:hover, fieldset[disabled] .btn-success:focus,  fieldset[disabled] .btn-success:active, fieldset[disabled] .btn-success.active {\n    background-color: #1f90d8;\n    border-color: #1f90d8;\n}\n\n.btn-info {\n    background-color: #23c6c8;\n    border-color: #23c6c8;\n    color: #FFFFFF;\n}\n\n.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active,  .open .dropdown-toggle.btn-info {\n    background-color: #21b9bb;\n    border-color: #21b9bb;\n    color: #FFFFFF;\n}\n\n.btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info {\n    background-image: none;\n}\n\n.btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus,  .btn-info.disabled:active, .btn-info.disabled.active, .btn-info[disabled],  .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled]:active,  .btn-info.active[disabled], fieldset[disabled] .btn-info, fieldset[disabled] .btn-info:hover,  fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:active,  fieldset[disabled] .btn-info.active {\n    background-color: #26d7d9;\n    border-color: #26d7d9;\n}\n\n.btn-default {\n    background-color: #c2c2c2;\n    border-color: #c2c2c2;\n    color: #FFFFFF;\n}\n\n.btn-default:hover, .btn-default:focus, .btn-default:active,  .btn-default.active, .open .dropdown-toggle.btn-default {\n    background-color: #bababa;\n    border-color: #bababa;\n    color: #FFFFFF;\n}\n\n.btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {\n    background-image: none;\n}\n\n.btn-default.disabled, .btn-default.disabled:hover, .btn-default.disabled:focus,  .btn-default.disabled:active, .btn-default.disabled.active,  .btn-default[disabled], .btn-default[disabled]:hover, .btn-default[disabled]:focus,  .btn-default[disabled]:active, .btn-default.active[disabled], fieldset[disabled] .btn-default,  fieldset[disabled] .btn-default:hover, fieldset[disabled] .btn-default:focus,  fieldset[disabled] .btn-default:active, fieldset[disabled] .btn-default.active {\n    background-color: #cccccc;\n    border-color: #cccccc;\n}\n\n.btn-warning {\n    background-color: #f8ac59;\n    border-color: #f8ac59;\n    color: #FFFFFF;\n}\n\n.btn-warning:hover, .btn-warning:focus, .btn-warning:active,  .btn-warning.active, .open .dropdown-toggle.btn-warning {\n    background-color: #f7a54a;\n    border-color: #f7a54a;\n    color: #FFFFFF;\n}\n\n.btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning {\n    background-image: none;\n}\n\n.btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus,  .btn-warning.disabled:active, .btn-warning.disabled.active,  .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus,  .btn-warning[disabled]:active, .btn-warning.active[disabled], fieldset[disabled] .btn-warning,  fieldset[disabled] .btn-warning:hover, fieldset[disabled] .btn-warning:focus,  fieldset[disabled] .btn-warning:active, fieldset[disabled] .btn-warning.active {\n    background-color: #f9b66d;\n    border-color: #f9b66d;\n}\n\n.btn-danger {\n    background-color: #ed5565;\n    border-color: #ed5565;\n    color: #FFFFFF;\n}\n\n.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active,  .open .dropdown-toggle.btn-danger {\n    background-color: #ec4758;\n    border-color: #ec4758;\n    color: #FFFFFF;\n}\n\n.btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger {\n    background-image: none;\n}\n\n.btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus,  .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger[disabled],  .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled]:active,  .btn-danger.active[disabled], fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger:hover,  fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:active,  fieldset[disabled] .btn-danger.active {\n    background-color: #ef6776;\n    border-color: #ef6776;\n}\n\n.btn-link {\n    color: inherit;\n}\n\n.btn-link:hover, .btn-link:focus, .btn-link:active, .btn-link.active,  .open .dropdown-toggle.btn-link {\n    color: #1ab394;\n    text-decoration: none;\n}\n\n.btn-link:active, .btn-link.active, .open .dropdown-toggle.btn-link {\n    background-image: none;\n}\n\n.btn-link.disabled, .btn-link.disabled:hover, .btn-link.disabled:focus,  .btn-link.disabled:active, .btn-link.disabled.active, .btn-link[disabled],  .btn-link[disabled]:hover, .btn-link[disabled]:focus, .btn-link[disabled]:active,  .btn-link.active[disabled], fieldset[disabled] .btn-link, fieldset[disabled] .btn-link:hover,  fieldset[disabled] .btn-link:focus, fieldset[disabled] .btn-link:active,  fieldset[disabled] .btn-link.active {\n    color: #cacaca;\n}\n\n.btn-white {\n    color: inherit;\n    background: white;\n    border: 1px solid #e7eaec;\n}\n\n.btn-white:hover, .btn-white:focus, .btn-white:active, .btn-white.active,  .open .dropdown-toggle.btn-white {\n    color: inherit;\n    border: 1px solid #d2d2d2;\n}\n\n.btn-white:active, .btn-white.active {\n    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15) inset;\n}\n\n.btn-white:active, .btn-white.active, .open .dropdown-toggle.btn-white {\n    background-image: none;\n}\n\n.btn-white.disabled, .btn-white.disabled:hover, .btn-white.disabled:focus,  .btn-white.disabled:active, .btn-white.disabled.active, .btn-white[disabled],  .btn-white[disabled]:hover, .btn-white[disabled]:focus, .btn-white[disabled]:active,  .btn-white.active[disabled], fieldset[disabled] .btn-white, fieldset[disabled] .btn-white:hover,  fieldset[disabled] .btn-white:focus, fieldset[disabled] .btn-white:active,  fieldset[disabled] .btn-white.active {\n    color: #cacaca;\n}\n\n.form-control, .form-control:focus, .has-error .form-control:focus,  .has-success .form-control:focus, .has-warning .form-control:focus,  .navbar-collapse, .navbar-form, .navbar-form-custom .form-control:focus,  .navbar-form-custom .form-control:hover, .open .btn.dropdown-toggle,  .panel, .popover, .progress, .progress-bar {\n    box-shadow: none;\n}\n\n.btn-outline {\n    color: inherit;\n    background-color: transparent;\n    -webkit-transition: all .5s;\n    transition: all .5s;\n}\n\n.btn-rounded {\n    border-radius: 50px;\n}\n\n.btn-large-dim {\n    width: 90px;\n    height: 90px;\n    font-size: 42px;\n}\n\nbutton.dim {\n    display: inline-block;\n    color: #fff;\n    text-decoration: none;\n    text-transform: uppercase;\n    text-align: center;\n    padding-top: 6px;\n    margin-right: 10px;\n    position: relative;\n    cursor: pointer;\n    border-radius: 5px;\n    font-weight: 600;\n    margin-bottom: 20px !important;\n}\n\nbutton.dim:active {\n    top: 3px;\n}\n\nbutton.btn-primary.dim {\n    box-shadow: inset 0px 0px 0px #16987e, 0px 5px 0px 0px #16987e, 0px 10px  5px #999999;\n}\n\nbutton.btn-primary.dim:active {\n    box-shadow: inset 0px 0px 0px #16987e, 0px 2px 0px 0px #16987e, 0px 5px  3px #999999;\n}\n\nbutton.btn-default.dim {\n    box-shadow: inset 0px 0px 0px #b3b3b3, 0px 5px 0px 0px #b3b3b3, 0px 10px  5px #999999;\n}\n\nbutton.btn-default.dim:active {\n    box-shadow: inset 0px 0px 0px #b3b3b3, 0px 2px 0px 0px #b3b3b3, 0px 5px  3px #999999;\n}\n\nbutton.btn-warning.dim {\n    box-shadow: inset 0px 0px 0px #f79d3c, 0px 5px 0px 0px #f79d3c, 0px 10px  5px #999999;\n}\n\nbutton.btn-warning.dim:active {\n    box-shadow: inset 0px 0px 0px #f79d3c, 0px 2px 0px 0px #f79d3c, 0px 5px  3px #999999;\n}\n\nbutton.btn-info.dim {\n    box-shadow: inset 0px 0px 0px #1eacae, 0px 5px 0px 0px #1eacae, 0px 10px  5px #999999;\n}\n\nbutton.btn-info.dim:active {\n    box-shadow: inset 0px 0px 0px #1eacae, 0px 2px 0px 0px #1eacae, 0px 5px  3px #999999;\n}\n\nbutton.btn-success.dim {\n    box-shadow: inset 0px 0px 0px #1872ab, 0px 5px 0px 0px #1872ab, 0px 10px  5px #999999;\n}\n\nbutton.btn-success.dim:active {\n    box-shadow: inset 0px 0px 0px #1872ab, 0px 2px 0px 0px #1872ab, 0px 5px  3px #999999;\n}\n\nbutton.btn-danger.dim {\n    box-shadow: inset 0px 0px 0px #ea394c, 0px 5px 0px 0px #ea394c, 0px 10px  5px #999999;\n}\n\nbutton.btn-danger.dim:active {\n    box-shadow: inset 0px 0px 0px #ea394c, 0px 2px 0px 0px #ea394c, 0px 5px  3px #999999;\n}\n\nbutton.dim:before {\n    font-size: 50px;\n    line-height: 1em;\n    font-weight: normal;\n    color: #fff;\n    display: block;\n    padding-top: 10px;\n}\n\nbutton.dim:active:before {\n    top: 7px;\n    font-size: 50px;\n}\n\n.label {\n    background-color: #d1dade;\n    color: #5e5e5e;\n    font-size: 10px;\n    font-weight: 600;\n    padding: 3px 8px;\n    text-shadow: none;\n}\n\n.badge {\n    background-color: #d1dade;\n    color: #5e5e5e;\n    font-size: 11px;\n    font-weight: 600;\n    padding-bottom: 4px;\n    padding-left: 6px;\n    padding-right: 6px;\n    text-shadow: none;\n}\n\n.label-primary, .badge-primary {\n    background-color: #1ab394;\n    color: #FFFFFF;\n}\n\n.label-success, .badge-success {\n    background-color: #1c84c6;\n    color: #FFFFFF;\n}\n\n.label-warning, .badge-warning {\n    background-color: #f8ac59;\n    color: #FFFFFF;\n}\n\n.label-warning-light, .badge-warning-light {\n    background-color: #f8ac59;\n    color: #ffffff;\n}\n\n.label-danger, .badge-danger {\n    background-color: #ed5565;\n    color: #FFFFFF;\n}\n\n.label-info, .badge-info {\n    background-color: #23c6c8;\n    color: #FFFFFF;\n}\n\n.label-inverse, .badge-inverse {\n    background-color: #262626;\n    color: #FFFFFF;\n}\n\n.label-white, .badge-white {\n    background-color: #FFFFFF;\n    color: #5E5E5E;\n}\n\n.label-white, .badge-disable {\n    background-color: #2A2E36;\n    color: #8B91A0;\n}\n/* TOOGLE SWICH */\n.onoffswitch {\n    position: relative;\n    width: 64px;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n}\n\n.onoffswitch-checkbox {\n    display: none;\n}\n\n.onoffswitch-label {\n    display: block;\n    overflow: hidden;\n    cursor: pointer;\n    border: 2px solid #1ab394;\n    border-radius: 2px;\n}\n\n.onoffswitch-inner {\n    width: 200%;\n    margin-left: -100%;\n    -webkit-transition: margin 0.3s ease-in 0s;\n    transition: margin 0.3s ease-in 0s;\n}\n\n.onoffswitch-inner:before, .onoffswitch-inner:after {\n    float: left;\n    width: 50%;\n    height: 20px;\n    padding: 0;\n    line-height: 20px;\n    font-size: 12px;\n    color: white;\n    font-family: Trebuchet, Arial, sans-serif;\n    font-weight: bold;\n    box-sizing: border-box;\n}\n\n.onoffswitch-inner:before {\n    content: \"ON\";\n    padding-left: 10px;\n    background-color: #1ab394;\n    color: #FFFFFF;\n}\n\n.onoffswitch-inner:after {\n    content: \"OFF\";\n    padding-right: 10px;\n    background-color: #FFFFFF;\n    color: #999999;\n    text-align: right;\n}\n\n.onoffswitch-switch {\n    width: 20px;\n    margin: 0px;\n    background: #FFFFFF;\n    border: 2px solid #1ab394;\n    border-radius: 2px;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    right: 44px;\n    -webkit-transition: all 0.3s ease-in 0s;\n    transition: all 0.3s ease-in 0s;\n}\n\n.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner {\n    margin-left: 0;\n}\n\n.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch {\n    right: 0px;\n}\n/* CHOSEN PLUGIN */\n.chosen-container-single .chosen-single {\n    background: #ffffff;\n    box-shadow: none;\n    -moz-box-sizing: border-box;\n    background-color: #FFFFFF;\n    border: 1px solid #CBD5DD;\n    border-radius: 2px;\n    cursor: text;\n    height: auto !important;\n    margin: 0;\n    min-height: 30px;\n    overflow: hidden;\n    padding: 4px 12px;\n    position: relative;\n    width: 100%;\n}\n\n.chosen-container-multi .chosen-choices li.search-choice {\n    background: #f1f1f1;\n    border: 1px solid #ededed;\n    border-radius: 2px;\n    box-shadow: none;\n    color: #333333;\n    cursor: default;\n    line-height: 13px;\n    margin: 3px 0 3px 5px;\n    padding: 3px 20px 3px 5px;\n    position: relative;\n}\n/* PAGINATIN */\n.pagination>.active>a, .pagination>.active>span, .pagination>.active>a:hover,  .pagination>.active>span:hover, .pagination>.active>a:focus,  .pagination>.active>span:focus {\n    background-color: #f4f4f4;\n    border-color: #DDDDDD;\n    color: inherit;\n    cursor: default;\n    z-index: 2;\n}\n\n.pagination>li>a, .pagination>li>span {\n    background-color: #FFFFFF;\n    border: 1px solid #DDDDDD;\n    color: inherit;\n    float: left;\n    line-height: 1.42857;\n    margin-left: -1px;\n    padding: 4px 10px;\n    position: relative;\n    text-decoration: none;\n}\n/* TOOLTIPS */\n.tooltip-inner {\n    background-color: #2F4050;\n}\n\n.tooltip.top .tooltip-arrow {\n    border-top-color: #2F4050;\n}\n\n.tooltip.right .tooltip-arrow {\n    border-right-color: #2F4050;\n}\n\n.tooltip.bottom .tooltip-arrow {\n    border-bottom-color: #2F4050;\n}\n\n.tooltip.left .tooltip-arrow {\n    border-left-color: #2F4050;\n}\n/* EASY PIE CHART*/\n.easypiechart {\n    position: relative;\n    text-align: center;\n}\n\n.easypiechart .h2 {\n    margin-left: 10px;\n    margin-top: 10px;\n    display: inline-block;\n}\n\n.easypiechart canvas {\n    top: 0;\n    left: 0;\n}\n\n.easypiechart .easypie-text {\n    line-height: 1;\n    position: absolute;\n    top: 33px;\n    width: 100%;\n    z-index: 1;\n}\n\n.easypiechart img {\n    margin-top: -4px;\n}\n\n.jqstooltip {\n    box-sizing: content-box;\n}\n/* FULLCALENDAR */\n.fc-state-default {\n    background-color: #ffffff;\n    background-image: none;\n    background-repeat: repeat-x;\n    box-shadow: none;\n    color: #333333;\n    text-shadow: none;\n}\n\n.fc-state-default {\n    border: 1px solid;\n}\n\n.fc-button {\n    color: inherit;\n    border: 1px solid #e7eaec;\n    cursor: pointer;\n    display: inline-block;\n    height: 1.9em;\n    line-height: 1.9em;\n    overflow: hidden;\n    padding: 0 0.6em;\n    position: relative;\n    white-space: nowrap;\n}\n\n.fc-state-active {\n    background-color: #1ab394;\n    border-color: #1ab394;\n    color: #ffffff;\n}\n\n.fc-header-title h2 {\n    font-size: 16px;\n    font-weight: 600;\n    color: inherit;\n}\n\n.fc-content .fc-widget-header, .fc-content .fc-widget-content {\n    border-color: #e7eaec;\n    font-weight: normal;\n}\n\n.fc-border-separate tbody {\n    background-color: #F8F8F8;\n}\n\n.fc-state-highlight {\n    background: none repeat scroll 0 0 #FCF8E3;\n}\n\n.external-event {\n    padding: 5px 10px;\n    border-radius: 2px;\n    cursor: pointer;\n    margin-bottom: 5px;\n}\n\n.fc-ltr .fc-event-hori.fc-event-end, .fc-rtl .fc-event-hori.fc-event-start {\n    border-radius: 2px;\n}\n\n.fc-event, .fc-agenda .fc-event-time, .fc-event a {\n    padding: 4px 6px;\n    background-color: #1ab394;\n    /* background color */\n    border-color: #1ab394;\n    /* border color */\n}\n\n.fc-event-time, .fc-event-title {\n    color: #717171;\n    padding: 0 1px;\n}\n\n.ui-calendar .fc-event-time, .ui-calendar .fc-event-title {\n    color: #fff;\n}\n/* Chat */\n.chat-activity-list .chat-element {\n    border-bottom: 1px solid #e7eaec;\n}\n\n.chat-element:first-child {\n    margin-top: 0;\n}\n\n.chat-element {\n    padding-bottom: 15px;\n}\n\n.chat-element, .chat-element .media {\n    margin-top: 15px;\n}\n\n.chat-element, .media-body {\n    overflow: hidden;\n}\n\n.media-body {\n    display: block;\n    width: auto;\n}\n\n.chat-element>.pull-left {\n    margin-right: 10px;\n}\n\n.chat-element img.img-circle, .dropdown-messages-box img.img-circle {\n    width: 38px;\n    height: 38px;\n}\n\n.chat-element .well {\n    border: 1px solid #e7eaec;\n    box-shadow: none;\n    margin-top: 10px;\n    margin-bottom: 5px;\n    padding: 10px 20px;\n    font-size: 11px;\n    line-height: 16px;\n}\n\n.chat-element .actions {\n    margin-top: 10px;\n}\n\n.chat-element .photos {\n    margin: 10px 0;\n}\n\n.right.chat-element>.pull-right {\n    margin-left: 10px;\n}\n\n.chat-photo {\n    max-height: 180px;\n    border-radius: 4px;\n    overflow: hidden;\n    margin-right: 10px;\n    margin-bottom: 10px;\n}\n\n.chat {\n    margin: 0;\n    padding: 0;\n    list-style: none;\n}\n\n.chat li {\n    margin-bottom: 10px;\n    padding-bottom: 5px;\n    border-bottom: 1px dotted #B3A9A9;\n}\n\n.chat li.left .chat-body {\n    margin-left: 60px;\n}\n\n.chat li.right .chat-body {\n    margin-right: 60px;\n}\n\n.chat li .chat-body p {\n    margin: 0;\n    color: #777777;\n}\n\n.panel .slidedown .glyphicon, .chat .glyphicon {\n    margin-right: 5px;\n}\n\n.chat-panel .panel-body {\n    height: 350px;\n    overflow-y: scroll;\n}\n/* LIST GROUP */\na.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus {\n    background-color: #1ab394;\n    border-color: #1ab394;\n    color: #FFFFFF;\n    z-index: 2;\n}\n\n.list-group-item-heading {\n    margin-top: 10px;\n}\n\n.list-group-item-text {\n    margin: 0 0 10px;\n    color: inherit;\n    font-size: 12px;\n    line-height: inherit;\n}\n\n.no-padding .list-group-item {\n    border-left: none;\n    border-right: none;\n    border-bottom: none;\n}\n\n.no-padding .list-group-item:first-child {\n    border-left: none;\n    border-right: none;\n    border-bottom: none;\n    border-top: none;\n}\n\n.no-padding .list-group {\n    margin-bottom: 0;\n}\n\n.list-group-item {\n    background-color: inherit;\n    border: 1px solid #e7eaec;\n    display: block;\n    margin-bottom: -1px;\n    padding: 10px 15px;\n    position: relative;\n}\n\n.elements-list .list-group-item {\n    border-left: none;\n    border-right: none;\n    /*border-top: none;*/\n    padding: 15px 25px;\n}\n\n.elements-list .list-group-item:first-child {\n    border-left: none;\n    border-right: none;\n    border-top: none !important;\n}\n\n.elements-list .list-group {\n    margin-bottom: 0;\n}\n\n.elements-list a {\n    color: inherit;\n}\n\n.elements-list .list-group-item.active, .elements-list .list-group-item:hover {\n    background: #f3f3f4;\n    color: inherit;\n    border-color: #e7eaec;\n    /*border-bottom: 1px solid #e7eaec;*/\n    /*border-top: 1px solid #e7eaec;*/\n    border-radius: 0;\n}\n\n.elements-list li.active {\n    -webkit-transition: none;\n    transition: none;\n}\n\n.element-detail-box {\n    padding: 25px;\n}\n/* FLOT CHART  */\n.flot-chart {\n    display: block;\n    height: 200px;\n}\n\n.widget .flot-chart.dashboard-chart {\n    display: block;\n    height: 120px;\n    margin-top: 40px;\n}\n\n.flot-chart.dashboard-chart {\n    display: block;\n    height: 180px;\n    margin-top: 40px;\n}\n\n.flot-chart-content {\n    width: 100%;\n    height: 100%;\n}\n\n.flot-chart-pie-content {\n    width: 200px;\n    height: 200px;\n    margin: auto;\n}\n\n.jqstooltip {\n    position: absolute;\n    display: block;\n    left: 0px;\n    top: 0px;\n    visibility: hidden;\n    background: #2b303a;\n    background-color: rgba(43, 48, 58, 0.8);\n    color: white;\n    text-align: left;\n    white-space: nowrap;\n    z-index: 10000;\n    padding: 5px 5px 5px 5px;\n    min-height: 22px;\n    border-radius: 3px;\n}\n\n.jqsfield {\n    color: white;\n    text-align: left;\n}\n\n.h-200 {\n    min-height: 200px;\n}\n\n.legendLabel {\n    padding-left: 5px;\n}\n\n.stat-list li:first-child {\n    margin-top: 0;\n}\n\n.stat-list {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n}\n\n.stat-percent {\n    float: right;\n}\n\n.stat-list li {\n    margin-top: 15px;\n    position: relative;\n}\n/* DATATABLES */\ntable.dataTable thead .sorting, table.dataTable thead .sorting_asc:after,  table.dataTable thead .sorting_desc, table.dataTable thead .sorting_asc_disabled,  table.dataTable thead .sorting_desc_disabled {\n    background: transparent;\n}\n\ntable.dataTable thead .sorting_asc:after {\n    float: right;\n    font-family: fontawesome;\n}\n\ntable.dataTable thead .sorting_desc:after {\n    content: \"\\f0dd\";\n    float: right;\n    font-family: fontawesome;\n}\n\ntable.dataTable thead .sorting:after {\n    content: \"\\f0dc\";\n    float: right;\n    font-family: fontawesome;\n    color: rgba(50, 50, 50, 0.5);\n}\n\n.dataTables_wrapper {\n    padding-bottom: 30px;\n}\n/* CIRCLE */\n.img-circle {\n    border-radius: 50%;\n}\n\n.btn-circle {\n    width: 30px;\n    height: 30px;\n    padding: 6px 0;\n    border-radius: 15px;\n    text-align: center;\n    font-size: 12px;\n    line-height: 1.428571429;\n}\n\n.btn-circle.btn-lg {\n    width: 50px;\n    height: 50px;\n    padding: 10px 16px;\n    border-radius: 25px;\n    font-size: 18px;\n    line-height: 1.33;\n}\n\n.btn-circle.btn-xl {\n    width: 70px;\n    height: 70px;\n    padding: 10px 16px;\n    border-radius: 35px;\n    font-size: 24px;\n    line-height: 1.33;\n}\n\n.show-grid [class^=\"col-\"] {\n    padding-top: 10px;\n    padding-bottom: 10px;\n    border: 1px solid #ddd;\n    background-color: #eee !important;\n}\n\n.show-grid {\n    margin: 15px 0;\n}\n/* ANIMATION */\n.css-animation-box h1 {\n    font-size: 44px;\n}\n\n.animation-efect-links a {\n    padding: 4px 6px;\n    font-size: 12px;\n}\n\n#animation_box {\n    background-color: #f9f8f8;\n    border-radius: 16px;\n    width: 80%;\n    margin: 0 auto;\n    padding-top: 80px;\n}\n\n.animation-text-box {\n    position: absolute;\n    margin-top: 40px;\n    left: 50%;\n    margin-left: -100px;\n    width: 200px;\n}\n\n.animation-text-info {\n    position: absolute;\n    margin-top: -60px;\n    left: 50%;\n    margin-left: -100px;\n    width: 200px;\n    font-size: 10px;\n}\n\n.animation-text-box h2 {\n    font-size: 54px;\n    font-weight: 600;\n    margin-bottom: 5px;\n}\n\n.animation-text-box p {\n    font-size: 12px;\n    text-transform: uppercase;\n}\n/* PEACE */\n.pace {\n    -webkit-pointer-events: none;\n    pointer-events: none;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n}\n\n.pace-inactive {\n    display: none;\n}\n\n.pace .pace-progress {\n    background: #1ab394;\n    position: fixed;\n    z-index: 2000;\n    top: 0;\n    width: 100%;\n    height: 2px;\n}\n\n.pace-inactive {\n    display: none;\n}\n/* WIDGETS */\n.widget {\n    border-radius: 5px;\n    padding: 15px 20px;\n    margin-bottom: 10px;\n    margin-top: 10px;\n}\n\n.widget.style1 h2 {\n    font-size: 30px;\n}\n\n.widget h2, .widget h3 {\n    margin-top: 5px;\n    margin-bottom: 0;\n}\n\n.widget-text-box {\n    padding: 20px;\n    border: 1px solid #e7eaec;\n    background: #ffffff;\n}\n\n.widget-head-color-box {\n    border-radius: 5px 5px 0px 0px;\n    margin-top: 10px;\n}\n\n.widget .flot-chart {\n    height: 100px;\n}\n\n.vertical-align div {\n    display: inline-block;\n    vertical-align: middle;\n}\n\n.vertical-align h2, .vertical-align h3 {\n    margin: 0;\n}\n\n.todo-list {\n    list-style: none outside none;\n    margin: 0;\n    padding: 0;\n    font-size: 14px;\n}\n\n.todo-list.small-list {\n    font-size: 12px;\n}\n\n.todo-list.small-list>li {\n    background: #f3f3f4;\n    border-left: none;\n    border-right: none;\n    border-radius: 4px;\n    color: inherit;\n    margin-bottom: 2px;\n    padding: 6px 6px 6px 12px;\n}\n\n.todo-list.small-list .btn-xs, .todo-list.small-list .btn-group-xs>.btn {\n    border-radius: 5px;\n    font-size: 10px;\n    line-height: 1.5;\n    padding: 1px 2px 1px 5px;\n}\n\n.todo-list>li {\n    background: #f3f3f4;\n    border-left: 6px solid #e7eaec;\n    border-right: 6px solid #e7eaec;\n    border-radius: 4px;\n    color: inherit;\n    margin-bottom: 2px;\n    padding: 10px;\n}\n\n.todo-list .handle {\n    cursor: move;\n    display: inline-block;\n    font-size: 16px;\n    margin: 0 5px;\n}\n\n.todo-list>li .label {\n    font-size: 9px;\n    margin-left: 10px;\n}\n\n.check-link {\n    font-size: 16px;\n}\n\n.todo-completed {\n    text-decoration: line-through;\n}\n\n.geo-statistic h1 {\n    font-size: 36px;\n    margin-bottom: 0;\n}\n\n.glyphicon.fa {\n    font-family: \"FontAwesome\";\n}\n/* INPUTS */\n.inline {\n    display: inline-block !important;\n}\n\n.input-s-sm {\n    width: 120px;\n}\n\n.input-s {\n    width: 200px;\n}\n\n.input-s-lg {\n    width: 250px;\n}\n\n.i-checks {\n    padding-left: 0;\n}\n\n.form-control, .single-line {\n    background: #FFFFFF none;\n    border: 1px solid #e5e6e7;\n    border-radius: 1px;\n    color: inherit;\n    display: block;\n    padding: 6px 12px;\n    -webkit-transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s  ease-in-out 0s;\n    transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s  ease-in-out 0s;\n    width: 100%;\n    font-size: 14px;\n}\n\n.form-control:focus, .single-line:focus {\n    border-color: #1ab394 !important;\n}\n\n.has-success .form-control {\n    border-color: #1ab394;\n}\n\n.has-warning .form-control {\n    border-color: #f8ac59;\n}\n\n.has-error .form-control {\n    border-color: #ed5565;\n}\n\n.has-success .control-label {\n    color: #1ab394;\n}\n\n.has-warning .control-label {\n    color: #f8ac59;\n}\n\n.has-error .control-label {\n    color: #ed5565;\n}\n\n.input-group-addon {\n    background-color: #fff;\n    border: 1px solid #E5E6E7;\n    border-radius: 1px;\n    color: inherit;\n    font-size: 14px;\n    font-weight: 400;\n    line-height: 1;\n    padding: 6px 12px;\n    text-align: center;\n}\n\n.spinner-buttons.input-group-btn .btn-xs {\n    line-height: 1.13;\n}\n\n.spinner-buttons.input-group-btn {\n    width: 20%;\n}\n\n.noUi-connect {\n    background: none repeat scroll 0 0 #1ab394;\n    box-shadow: none;\n}\n\n.slider_red .noUi-connect {\n    background: none repeat scroll 0 0 #ed5565;\n    box-shadow: none;\n}\n/* UI Sortable */\n.ui-sortable .ibox-title {\n    cursor: move;\n}\n\n.ui-sortable-placeholder {\n    border: 1px dashed #cecece !important;\n    visibility: visible !important;\n    background: #e7eaec;\n}\n\n.ibox.ui-sortable-placeholder {\n    margin: 0px 0px 23px !important;\n}\n/* Tabs */\n.tabs-container .panel-body {\n    background: #fff;\n    border: 1px solid #e7eaec;\n    border-radius: 2px;\n    padding: 20px;\n    position: relative;\n}\n\n.tabs-container .nav-tabs>li.active>a, .tabs-container .nav-tabs>li.active>a:hover,  .tabs-container .nav-tabs>li.active>a:focus {\n    border: 1px solid #e7eaec;\n    border-bottom-color: transparent;\n    background-color: #fff;\n}\n\n.tabs-container .nav-tabs>li {\n    float: left;\n    margin-bottom: -1px;\n}\n\n.tabs-container .tab-pane .panel-body {\n    border-top: none;\n}\n\n.tabs-container .nav-tabs>li.active>a, .tabs-container .nav-tabs>li.active>a:hover,  .tabs-container .nav-tabs>li.active>a:focus {\n    border: 1px solid #e7eaec;\n    border-bottom-color: transparent;\n}\n\n.tabs-container .nav-tabs {\n    border-bottom: 1px solid #e7eaec;\n}\n\n.tabs-container .tab-pane .panel-body {\n    border-top: none;\n}\n\n.tabs-container .tabs-left .tab-pane .panel-body, .tabs-container .tabs-right .tab-pane .panel-body {\n    border-top: 1px solid #e7eaec;\n}\n\n.tabs-container .nav-tabs>li a:hover {\n    background: transparent;\n    border-color: transparent;\n}\n\n.tabs-container .tabs-below>.nav-tabs, .tabs-container .tabs-right>.nav-tabs,  .tabs-container .tabs-left>.nav-tabs {\n    border-bottom: 0;\n}\n\n.tabs-container .tabs-left .panel-body {\n    position: static;\n}\n\n.tabs-container .tabs-left>.nav-tabs, .tabs-container .tabs-right>.nav-tabs {\n    width: 20%;\n}\n\n.tabs-container .tabs-left .panel-body {\n    width: 80%;\n    margin-left: 20%;\n}\n\n.tabs-container .tabs-right .panel-body {\n    width: 80%;\n    margin-right: 20%;\n}\n\n.tabs-container .tab-content>.tab-pane, .tabs-container .pill-content>.pill-pane {\n    display: none;\n}\n\n.tabs-container .tab-content>.active, .tabs-container .pill-content>.active {\n    display: block;\n}\n\n.tabs-container .tabs-below>.nav-tabs {\n    border-top: 1px solid #e7eaec;\n}\n\n.tabs-container .tabs-below>.nav-tabs>li {\n    margin-top: -1px;\n    margin-bottom: 0;\n}\n\n.tabs-container .tabs-below>.nav-tabs>li>a {\n    border-radius: 0 0 4px 4px;\n}\n\n.tabs-container .tabs-below>.nav-tabs>li>a:hover, .tabs-container .tabs-below>.nav-tabs>li>a:focus {\n    border-top-color: #e7eaec;\n    border-bottom-color: transparent;\n}\n\n.tabs-container .tabs-left>.nav-tabs>li, .tabs-container .tabs-right>.nav-tabs>li {\n    float: none;\n}\n\n.tabs-container .tabs-left>.nav-tabs>li>a, .tabs-container .tabs-right>.nav-tabs>li>a {\n    min-width: 74px;\n    margin-right: 0;\n    margin-bottom: 3px;\n}\n\n.tabs-container .tabs-left>.nav-tabs {\n    float: left;\n    margin-right: 19px;\n}\n\n.tabs-container .tabs-left>.nav-tabs>li>a {\n    margin-right: -1px;\n    border-radius: 4px 0 0 4px;\n}\n\n.tabs-container .tabs-left>.nav-tabs .active>a, .tabs-container .tabs-left>.nav-tabs .active>a:hover,  .tabs-container .tabs-left>.nav-tabs .active>a:focus {\n    border-color: #e7eaec transparent #e7eaec #e7eaec;\n    border-right-color: #ffffff;\n}\n\n.tabs-container .tabs-right>.nav-tabs {\n    float: right;\n    margin-left: 19px;\n}\n\n.tabs-container .tabs-right>.nav-tabs>li>a {\n    margin-left: -1px;\n    border-radius: 0 4px 4px 0;\n}\n\n.tabs-container .tabs-right>.nav-tabs .active>a, .tabs-container .tabs-right>.nav-tabs .active>a:hover,  .tabs-container .tabs-right>.nav-tabs .active>a:focus {\n    border-color: #e7eaec #e7eaec #e7eaec transparent;\n    border-left-color: #ffffff;\n    z-index: 1;\n}\n/*SWITCHES */\n\n.onoffswitch{\n    position: relative;\n    width: 54px;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n}\n\n.onoffswitch-checkbox {\n    display: none;\n}\n\n.onoffswitch-label {\n    display: block;\n    overflow: hidden;\n    cursor: pointer;\n    border: 2px solid #1AB394;\n    border-radius: 3px;\n}\n\n.onoffswitch-inner {\n    display: block;\n    width: 200%;\n    margin-left: -100%;\n    -webkit-transition: margin 0.3s ease-in 0s;\n    transition: margin 0.3s ease-in 0s;\n}\n\n.onoffswitch-inner:before, .onoffswitch-inner:after {\n    display: block;\n    float: left;\n    width: 50%;\n    /* height: 16px; */\n    padding: 0;\n    /*  line-height: 16px; */\n    font-size: 10px;\n    color: white;\n    font-family: Trebuchet, Arial, sans-serif;\n    font-weight: bold;\n    box-sizing: border-box;\n}\n\n.onoffswitch-inner:before {\n    content: \"ON\";\n    padding-left: 7px;\n    background-color: #1AB394;\n    color: #FFFFFF;\n}\n\n.onoffswitch-inner:after {\n    content: \"OFF\";\n    padding-right: 7px;\n    background-color: #FFFFFF;\n    color: #919191;\n    text-align: right;\n}\n\n.onoffswitch-switch {\n    display: block;\n    width: 18px;\n    margin: 0px;\n    background: #FFFFFF;\n    border: 2px solid #1AB394;\n    border-radius: 3px;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    right: 36px;\n    -webkit-transition: all 0.3s ease-in 0s;\n    transition: all 0.3s ease-in 0s;\n}\n\n.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner {\n    margin-left: 0;\n}\n\n.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch {\n    right: 0px;\n}\n/* Nestable list */\n.dd {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n    font-size: 13px;\n    line-height: 20px;\n}\n\n.dd-list {\n    display: block;\n    position: relative;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n}\n\n.dd-list .dd-list {\n    padding-left: 30px;\n}\n\n.dd-collapsed .dd-list {\n    display: none;\n}\n\n.dd-item, .dd-empty, .dd-placeholder {\n    display: block;\n    position: relative;\n    margin: 0;\n    padding: 0;\n    min-height: 20px;\n    font-size: 13px;\n    line-height: 20px;\n}\n\n.dd-handle {\n    display: block;\n    margin: 5px 0;\n    padding: 5px 10px;\n    color: #333;\n    text-decoration: none;\n    border: 1px solid #e7eaec;\n    background: #f5f5f5;\n    border-radius: 3px;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n}\n\n.dd-handle span {\n    font-weight: bold;\n}\n\n.dd-handle:hover {\n    background: #f0f0f0;\n    cursor: pointer;\n    font-weight: bold;\n}\n\n.dd-item>button {\n    display: block;\n    position: relative;\n    cursor: pointer;\n    float: left;\n    width: 25px;\n    height: 20px;\n    margin: 5px 0;\n    padding: 0;\n    text-indent: 100%;\n    white-space: nowrap;\n    overflow: hidden;\n    border: 0;\n    background: transparent;\n    font-size: 12px;\n    line-height: 1;\n    text-align: center;\n    font-weight: bold;\n}\n\n.dd-item>button:before {\n    content: '+';\n    display: block;\n    position: absolute;\n    width: 100%;\n    text-align: center;\n    text-indent: 0;\n}\n\n.dd-item>button[data-action=\"collapse\"]:before {\n    content: '-';\n}\n\n#nestable2 .dd-item>button {\n    font-family: FontAwesome;\n    height: 34px;\n    width: 33px;\n    color: #c1c1c1;\n}\n\n#nestable2 .dd-item>button:before {\n    content: \"\\f067\";\n}\n\n#nestable2 .dd-item>button[data-action=\"collapse\"]:before {\n    content: \"\\f068\";\n}\n\n.dd-placeholder, .dd-empty {\n    margin: 5px 0;\n    padding: 0;\n    min-height: 30px;\n    background: #f2fbff;\n    border: 1px dashed #b6bcbf;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n}\n\n.dd-empty {\n    border: 1px dashed #bbb;\n    min-height: 100px;\n    background-color: #e5e5e5;\n    background-image: -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent  75%, #ffffff 75%, #ffffff),  -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent  75%, #ffffff 75%, #ffffff);\n    background-image: linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%,  #ffffff 75%, #ffffff),  linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%,  #ffffff 75%, #ffffff);\n    background-size: 60px 60px;\n    background-position: 0 0, 30px 30px;\n}\n\n.dd-dragel {\n    position: absolute;\n    z-index: 9999;\n    pointer-events: none;\n}\n\n.dd-dragel>.dd-item .dd-handle {\n    margin-top: 0;\n}\n\n.dd-dragel .dd-handle {\n    box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1);\n}\n/**\n* Nestable Extras\n*/\n.nestable-lists {\n    display: block;\n    clear: both;\n    padding: 30px 0;\n    width: 100%;\n    border: 0;\n    border-top: 2px solid #ddd;\n    border-bottom: 2px solid #ddd;\n}\n\n#nestable-menu {\n    padding: 0;\n    margin: 10px 0 20px 0;\n}\n\n#nestable-output, #nestable2-output {\n    width: 100%;\n    font-size: 0.75em;\n    line-height: 1.333333em;\n    font-family: lucida grande, lucida sans unicode, helvetica, arial,  sans-serif;\n    padding: 5px;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n}\n\n#nestable2 .dd-handle {\n    color: inherit;\n    border: 1px dashed #e7eaec;\n    background: #f3f3f4;\n    padding: 10px;\n}\n\n#nestable2 .dd-handle:hover {\n    /*background: #bbb;*/\n}\n\n#nestable2 span.label {\n    margin-right: 10px;\n}\n\n#nestable-output, #nestable2-output {\n    font-size: 12px;\n    padding: 25px;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n}\n/* CodeMirror */\n.CodeMirror {\n    border: 1px solid #eee;\n    height: auto;\n}\n\n.CodeMirror-scroll {\n    overflow-y: hidden;\n    overflow-x: auto;\n}\n/* Google Maps */\n.google-map {\n    height: 300px;\n}\n/* Validation */\nlabel.error {\n    color: #cc5965;\n    display: inline-block;\n    margin-left: 5px;\n}\n\n.form-control.error {\n    border: 1px dotted #cc5965;\n}\n/* ngGrid */\n.gridStyle {\n    border: 1px solid #d4d4d4;\n    width: 100%;\n    height: 400px;\n}\n\n.gridStyle2 {\n    border: 1px solid #d4d4d4;\n    width: 500px;\n    height: 300px;\n}\n\n.ngH eaderCell {\n    border-right: none;\n    border-bottom: 1px solid #e7eaec;\n}\n\n.ngCell {\n    border-right: none;\n}\n\n.ngTopPanel {\n    background: #F5F5F6;\n}\n\n.ngRow.even {\n    background: #f9f9f9;\n}\n\n.ngRow.selected {\n    background: #EBF2F1;\n}\n\n.ngRow {\n    border-bottom: 1px solid #e7eaec;\n}\n\n.ngCell {\n    background-color: transparent;\n}\n\n.ngHeaderCell {\n    border-right: none;\n}\n/* Toastr custom style */\n#toast-container>.toast {\n    background-image: none !important;\n}\n\n#toast-container>.toast:before {\n    position: fixed;\n    font-family: FontAwesome;\n    font-size: 24px;\n    line-height: 24px;\n    float: left;\n    color: #FFF;\n    padding-right: 0.5em;\n    margin: auto 0.5em auto -1.5em;\n}\n\n#toast-container>div {\n    box-shadow: 0 0 3px #999;\n    opacity: .9;\n    -ms-filter: alpha(opacity = 90);\n    filter: alpha(opacity = 90);\n}\n\n#toast-container>:hover {\n    box-shadow: 0 0 4px #999;\n    opacity: 1;\n    -ms-filter: alpha(opacity = 100);\n    filter: alpha(opacity = 100);\n    cursor: pointer;\n}\n\n.toast {\n    background-color: #1ab394;\n}\n\n.toast-success {\n    background-color: #1ab394;\n}\n\n.toast-error {\n    background-color: #ed5565;\n}\n\n.toast-info {\n    background-color: #23c6c8;\n}\n\n.toast-warning {\n    background-color: #f8ac59;\n}\n\n.toast-top-full-width {\n    margin-top: 20px;\n}\n\n.toast-bottom-full-width {\n    margin-bottom: 20px;\n}\n/* Image cropper style */\n.img-container, .img-preview {\n    overflow: hidden;\n    text-align: center;\n    width: 100%;\n}\n\n.img-preview-sm {\n    height: 130px;\n    width: 200px;\n}\n/* Forum styles  */\n.forum-post-container .media {\n    margin: 10px 10px 10px 10px;\n    padding: 20px 10px 20px 10px;\n    border-bottom: 1px solid #f1f1f1;\n}\n\n.forum-avatar {\n    float: left;\n    margin-right: 20px;\n    text-align: center;\n    width: 110px;\n}\n\n.forum-avatar .img-circle {\n    height: 48px;\n    width: 48px;\n}\n\n.author-info {\n    color: #676a6c;\n    font-size: 11px;\n    margin-top: 5px;\n    text-align: center;\n}\n\n.forum-post-info {\n    padding: 9px 12px 6px 12px;\n    background: #f9f9f9;\n    border: 1px solid #f1f1f1;\n}\n\n.media-body>.media {\n    background: #f9f9f9;\n    border-radius: 3px;\n    border: 1px solid #f1f1f1;\n}\n\n.forum-post-container .media-body .photos {\n    margin: 10px 0;\n}\n\n.forum-photo {\n    max-width: 140px;\n    border-radius: 3px;\n}\n\n.media-body>.media .forum-avatar {\n    width: 70px;\n    margin-right: 10px;\n}\n\n.media-body>.media .forum-avatar .img-circle {\n    height: 38px;\n    width: 38px;\n}\n\n.mid-icon {\n    font-size: 66px;\n}\n\n.forum-item {\n    margin: 10px 0;\n    padding: 10px 0 20px;\n    border-bottom: 1px solid #f1f1f1;\n}\n\n.views-number {\n    font-size: 24px;\n    line-height: 18px;\n    font-weight: 400;\n}\n\n.forum-container, .forum-post-container {\n    padding: 30px !important;\n}\n\n.forum-item small {\n    color: #999;\n}\n\n.forum-item .forum-sub-title {\n    color: #999;\n    margin-left: 50px;\n}\n\n.forum-title {\n    margin: 15px 0 15px 0;\n}\n\n.forum-info {\n    text-align: center;\n}\n\n.forum-desc {\n    color: #999;\n}\n\n.forum-icon {\n    float: left;\n    width: 30px;\n    margin-right: 20px;\n    text-align: center;\n}\n\na.forum-item-title {\n    color: inherit;\n    display: block;\n    font-size: 18px;\n    font-weight: 600;\n}\n\na.forum-item-title:hover {\n    color: inherit;\n}\n\n.forum-icon .fa {\n    font-size: 30px;\n    margin-top: 8px;\n    color: #9b9b9b;\n}\n\n.forum-item.active .fa {\n    color: #1ab394;\n}\n\n.forum-item.active a.forum-item-title {\n    color: #1ab394;\n}\n\n@media ( max-width : 992px) {\n    .forum-info {\n        margin: 15px 0 10px 0px;\n        /* Comment this is you want to show forum info in small devices */\n        display: none;\n    }\n\n    .forum-desc {\n        float: none !important;\n    }\n}\n/* New Timeline style */\n.vertical-container {\n    /* this class is used to give a max-width to the element it is applied to, and center it horizontally when it reaches that max-width */\n    width: 90%;\n    max-width: 1170px;\n    margin: 0 auto;\n}\n\n.vertical-container::after {\n    /* clearfix */\n    content: '';\n    display: table;\n    clear: both;\n}\n\n#vertical-timeline {\n    position: relative;\n    padding: 0;\n    margin-top: 2em;\n    margin-bottom: 2em;\n}\n\n#vertical-timeline::before {\n    content: '';\n    position: absolute;\n    top: 0;\n    left: 18px;\n    height: 100%;\n    width: 4px;\n    background: #f1f1f1;\n}\n\n.vertical-timeline-content .btn {\n    float: right;\n}\n\n#vertical-timeline.light-timeline:before {\n    background: #e7eaec;\n}\n\n.dark-timeline .vertical-timeline-content:before {\n    border-color: transparent #f5f5f5 transparent transparent;\n}\n\n.dark-timeline.center-orientation .vertical-timeline-content:before {\n    border-color: transparent transparent transparent #f5f5f5;\n}\n\n.dark-timeline .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before,  .dark-timeline.center-orientation .vertical-timeline-block:nth-child(2n) .vertical-timeline-content:before {\n    border-color: transparent #f5f5f5 transparent transparent;\n}\n\n.dark-timeline .vertical-timeline-content, .dark-timeline.center-orientation .vertical-timeline-content {\n    background: #f5f5f5;\n}\n\n@media only screen and (min-width: 1170px) {\n    #vertical-timeline.center-orientation {\n        margin-top: 3em;\n        margin-bottom: 3em;\n    }\n\n    #vertical-timeline.center-orientation:before {\n        left: 50%;\n        margin-left: -2px;\n    }\n}\n\n@media only screen and (max-width: 1170px) {\n    .center-orientation.dark-timeline .vertical-timeline-content:before {\n        border-color: transparent #f5f5f5 transparent transparent;\n    }\n}\n\n.vertical-timeline-block {\n    position: relative;\n    margin: 2em 0;\n}\n\n.vertical-timeline-block:after {\n    content: \"\";\n    display: table;\n    clear: both;\n}\n\n.vertical-timeline-block:first-child {\n    margin-top: 0;\n}\n\n.vertical-timeline-block:last-child {\n    margin-bottom: 0;\n}\n\n@media only screen and (min-width: 1170px) {\n    .center-orientation .vertical-timeline-block {\n        margin: 4em 0;\n    }\n\n    .center-orientation .vertical-timeline-block:first-child {\n        margin-top: 0;\n    }\n\n    .center-orientation .vertical-timeline-block:last-child {\n        margin-bottom: 0;\n    }\n}\n\n.vertical-timeline-icon {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 40px;\n    height: 40px;\n    border-radius: 50%;\n    font-size: 16px;\n    border: 3px solid #f1f1f1;\n    text-align: center;\n}\n\n.vertical-timeline-icon i {\n    display: block;\n    width: 24px;\n    height: 24px;\n    position: relative;\n    left: 50%;\n    top: 50%;\n    margin-left: -12px;\n    margin-top: -9px;\n}\n\n@media only screen and (min-width: 1170px) {\n    .center-orientation .vertical-timeline-icon {\n        width: 50px;\n        height: 50px;\n        left: 50%;\n        margin-left: -25px;\n        -webkit-transform: translateZ(0);\n        -webkit-backface-visibility: hidden;\n        font-size: 19px;\n    }\n\n    .center-orientation .vertical-timeline-icon i {\n        margin-left: -12px;\n        margin-top: -10px;\n    }\n\n    .center-orientation .cssanimations .vertical-timeline-icon.is-hidden {\n        visibility: hidden;\n    }\n}\n\n.vertical-timeline-content {\n    position: relative;\n    margin-left: 60px;\n    background: white;\n    border-radius: 0.25em;\n    padding: 1em;\n}\n\n.vertical-timeline-content:after {\n    content: \"\";\n    display: table;\n    clear: both;\n}\n\n.vertical-timeline-content h2 {\n    font-weight: 400;\n    margin-top: 4px;\n}\n\n.vertical-timeline-content p {\n    margin: 1em 0;\n    line-height: 1.6;\n}\n\n.vertical-timeline-content .vertical-date {\n    float: left;\n    font-weight: 500;\n}\n\n.vertical-date small {\n    color: #1ab394;\n    font-weight: 400;\n}\n\n.vertical-timeline-content::before {\n    content: '';\n    position: absolute;\n    top: 16px;\n    right: 100%;\n    height: 0;\n    width: 0;\n    border: 7px solid transparent;\n    border-right: 7px solid white;\n}\n\n@media only screen and (min-width: 768px) {\n    .vertical-timeline-content h2 {\n        font-size: 18px;\n    }\n\n    .vertical-timeline-content p {\n        font-size: 13px;\n    }\n}\n\n@media only screen and (min-width: 1170px) {\n    .center-orientation .vertical-timeline-content {\n        margin-left: 0;\n        padding: 1.6em;\n        width: 45%;\n    }\n\n    .center-orientation .vertical-timeline-content::before {\n        top: 24px;\n        left: 100%;\n        border-color: transparent;\n        border-left-color: white;\n    }\n\n    .center-orientation .vertical-timeline-content .btn {\n        float: left;\n    }\n\n    .center-orientation .vertical-timeline-content .vertical-date {\n        position: absolute;\n        width: 100%;\n        left: 122%;\n        top: 2px;\n        font-size: 14px;\n    }\n\n    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content {\n        float: right;\n    }\n\n    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content::before {\n        top: 24px;\n        left: auto;\n        right: 100%;\n        border-color: transparent;\n        border-right-color: white;\n    }\n\n    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .btn {\n        float: right;\n    }\n\n    .center-orientation .vertical-timeline-block:nth-child(even) .vertical-timeline-content .vertical-date {\n        left: auto;\n        right: 122%;\n        text-align: right;\n    }\n\n    .center-orientation .cssanimations .vertical-timeline-content.is-hidden {\n        visibility: hidden;\n    }\n}\n\n.sidebard-panel {\n    width: 220px;\n    background: #ebebed;\n    padding: 10px 20px;\n    position: absolute;\n    right: 0;\n}\n\n.sidebard-panel .feed-element img.img-circle {\n    width: 32px;\n    height: 32px;\n}\n\n.sidebard-panel .feed-element, .media-body, .sidebard-panel p {\n    font-size: 12px;\n}\n\n.sidebard-panel .feed-element {\n    margin-top: 20px;\n    padding-bottom: 0;\n}\n\n.sidebard-panel .list-group {\n    margin-bottom: 10px;\n}\n\n.sidebard-panel .list-group .list-group-item {\n    padding: 5px 0;\n    font-size: 12px;\n    border: 0;\n}\n\n.sidebar-content .wrapper, .wrapper.sidebar-content {\n    padding-right: 240px !important;\n}\n\n#right-sidebar {\n    background-color: #fff;\n    border-left: 1px solid #e7eaec;\n    border-top: 1px solid #e7eaec;\n    overflow: hidden;\n    position: fixed;\n    top: 60px;\n    width: 260px !important;\n    z-index: 1009;\n    bottom: 0;\n    right: -260px;\n}\n\n#right-sidebar.sidebar-open {\n    right: 0;\n}\n\n#right-sidebar.sidebar-open.sidebar-top {\n    top: 0;\n    border-top: none;\n}\n\n.sidebar-container ul.nav-tabs {\n    border: none;\n}\n\n.sidebar-container ul.nav-tabs.navs-4 li {\n    width: 25%;\n}\n\n.sidebar-container ul.nav-tabs.navs-3 li {\n    width: 33.3333%;\n}\n\n.sidebar-container ul.nav-tabs.navs-2 li {\n    width: 50%;\n}\n\n.sidebar-container ul.nav-tabs li {\n    border: none;\n}\n\n.sidebar-container ul.nav-tabs li a {\n    border: none;\n    padding: 12px 10px;\n    margin: 0;\n    border-radius: 0;\n    background: #2f4050;\n    color: #fff;\n    text-align: center;\n    border-right: 1px solid #334556;\n}\n\n.sidebar-container ul.nav-tabs li.active a {\n    border: none;\n    background: #f9f9f9;\n    color: #676a6c;\n    font-weight: bold;\n}\n\n.sidebar-container .nav-tabs>li.active>a:hover, .sidebar-container .nav-tabs>li.active>a:focus {\n    border: none;\n}\n\n.sidebar-container ul.sidebar-list {\n    margin: 0;\n    padding: 0;\n}\n\n.sidebar-container ul.sidebar-list li {\n    border-bottom: 1px solid #e7eaec;\n    padding: 15px 20px;\n    list-style: none;\n    font-size: 12px;\n}\n\n.sidebar-container .sidebar-message:nth-child(2n+2) {\n    background: #f9f9f9;\n}\n\n.sidebar-container ul.sidebar-list li a {\n    text-decoration: none;\n    color: inherit;\n}\n\n.sidebar-container .sidebar-content {\n    padding: 15px 20px;\n    font-size: 12px;\n}\n\n.sidebar-container .sidebar-title {\n    background: #f9f9f9;\n    padding: 20px;\n    border-bottom: 1px solid #e7eaec;\n}\n\n.sidebar-container .sidebar-title h3 {\n    margin-bottom: 3px;\n    padding-left: 2px;\n}\n\n.sidebar-container .tab-content h4 {\n    margin-bottom: 5px;\n}\n\n.sidebar-container .sidebar-message>a>.pull-left {\n    margin-right: 10px;\n}\n\n.sidebar-container .sidebar-message>a {\n    text-decoration: none;\n    color: inherit;\n}\n\n.sidebar-container .sidebar-message {\n    padding: 15px 20px;\n}\n\n.sidebar-container .sidebar-message .message-avatar {\n    height: 38px;\n    width: 38px;\n    border-radius: 50%;\n}\n\n.sidebar-container .setings-item {\n    padding: 15px 20px;\n    border-bottom: 1px solid #e7eaec;\n}\n\nbody {\n    font-family: \"open sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 13px;\n    color: #676a6c;\n    overflow-x: hidden;\n}\n\nhtml, body {\n    height: 100%;\n}\n\nbody.full-height-layout #wrapper, body.full-height-layout #page-wrapper {\n    height: 100%;\n}\n\n#page-wrapper {\n    min-height: auto;\n}\n\nbody.boxed-layout {\n    background: url('patterns/shattered.png');\n}\n\nbody.boxed-layout #wrapper {\n    background-color: #2f4050;\n    max-width: 1200px;\n    margin: 0 auto;\n}\n\n.top-navigation.boxed-layout #wrapper, .boxed-layout #wrapper.top-navigation {\n    max-width: 1300px !important;\n}\n\n.block {\n    display: block;\n}\n\n.clear {\n    display: block;\n    overflow: hidden;\n}\n\na {\n    cursor: pointer;\n}\n\na:hover, a:focus {\n    text-decoration: none;\n}\n\n.border-bottom {\n    border-bottom: 1px solid #e7eaec !important;\n}\n\n.font-bold {\n    font-weight: 600;\n}\n\n.font-noraml {\n    font-weight: 400;\n}\n\n.text-uppercase {\n    text-transform: uppercase;\n}\n\n.b-r {\n    border-right: 1px solid #e7eaec;\n}\n\n.hr-line-dashed {\n    border-top: 1px dashed #e7eaec;\n    color: #ffffff;\n    background-color: #ffffff;\n    height: 1px;\n    margin: 20px 0;\n}\n\n.hr-line-solid {\n    border-bottom: 1px solid #e7eaec;\n    background-color: rgba(0, 0, 0, 0);\n    border-style: solid !important;\n    margin-top: 15px;\n    margin-bottom: 15px;\n}\n\nvideo {\n    width: 100% !important;\n    height: auto !important;\n}\n/* GALLERY */\n.gallery>.row>div {\n    margin-bottom: 15px;\n}\n\n.fancybox img {\n    margin-bottom: 5px;\n    /* Only for demo */\n    width: 24%;\n}\n/* Summernote text editor  */\n.note-editor {\n    height: auto !important;\n    min-height: 100px;\n    border: solid 1px #e5e6e7;\n}\n/* MODAL */\n.modal-content {\n    background-clip: padding-box;\n    background-color: #FFFFFF;\n    border: 1px solid rgba(0, 0, 0, 0);\n    border-radius: 4px;\n    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n    outline: 0 none;\n}\n\n.modal-dialog {\n    z-index: 1200;\n}\n\n.modal-body {\n    padding: 20px 30px 30px 30px;\n}\n\n.inmodal .modal-body {\n    background: #f8fafb;\n}\n\n.inmodal .modal-header {\n    padding: 30px 15px;\n    text-align: center;\n}\n\n.animated.modal.fade .modal-dialog {\n    -webkit-transform: none;\n    -ms-transform: none;\n    transform: none;\n}\n\n.inmodal .modal-title {\n    font-size: 26px;\n}\n\n.inmodal .modal-icon {\n    font-size: 84px;\n    color: #e2e3e3;\n}\n\n.modal-footer {\n    margin-top: 0;\n}\n/* WRAPPERS */\n#wrapper {\n    width: 100%;\n    overflow-x: hidden;\n    background-color: #2f4050;\n}\n\n.wrapper {\n    padding: 0 20px;\n}\n\n.wrapper-content {\n    padding: 20px;\n}\n\n#page-wrapper {\n    padding: 0 15px;\n    position: inherit;\n    margin: 0 0 0 220px;\n}\n\n.title-action {\n    text-align: right;\n    padding-top: 30px;\n}\n\n.ibox-content h1, .ibox-content h2, .ibox-content h3, .ibox-content h4,  .ibox-content h5, .ibox-title h1, .ibox-title h2, .ibox-title h3,  .ibox-title h4, .ibox-title h5 {\n    margin-top: 5px;\n}\n\nul.unstyled, ol.unstyled {\n    list-style: none outside none;\n    margin-left: 0;\n}\n\n.big-icon {\n    font-size: 160px;\n    color: #e5e6e7;\n}\n/* FOOTER */\n.footer {\n    background: none repeat scroll 0 0 white;\n    border-top: 1px solid #e7eaec;\n    overflow: hidden;\n    padding: 10px 20px;\n    margin: 0 -15px;\n    height: 36px;\n}\n\n.footer.fixed_full {\n    position: fixed;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    z-index: 1000;\n    padding: 10px 20px;\n    background: white;\n    border-top: 1px solid #e7eaec;\n}\n\n.footer.fixed {\n    position: fixed;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    z-index: 1000;\n    padding: 10px 20px;\n    background: white;\n    border-top: 1px solid #e7eaec;\n    margin-left: 220px;\n}\n\nbody.mini-navbar .footer.fixed, body.body-small.mini-navbar .footer.fixed {\n    margin: 0 0 0 70px;\n}\n\nbody.mini-navbar.canvas-menu .footer.fixed, body.canvas-menu .footer.fixed {\n    margin: 0 !important;\n}\n\nbody.fixed-sidebar.body-small.mini-navbar .footer.fixed {\n    margin: 0 0 0 220px;\n}\n\nbody.body-small .footer.fixed {\n    margin-left: 0px;\n}\n/* PANELS */\n.page-heading {\n    border-top: 0;\n    padding: 0px 20px 20px;\n}\n\n.panel-heading h1, .panel-heading h2 {\n    margin-bottom: 5px;\n}\n/*CONTENTTABS*/\n.content-tabs {\n    position: relative;\n    height: 42px;\n    background: #fafafa;\n    line-height: 40px;\n}\n\n.content-tabs .roll-nav, .page-tabs-list {\n    position: absolute;\n    width: 40px;\n    height: 40px;\n    text-align: center;\n    color: #999;\n    z-index: 2;\n    top: 0;\n}\n\n.content-tabs .roll-left {\n    left: 0;\n    border-right: solid 1px #eee;\n}\n\n.content-tabs .roll-right {\n    right: 0;\n    border-left: solid 1px #eee;\n}\n\n.content-tabs button {\n    background: #fff;\n    border: 0;\n    height: 40px;\n    width: 40px;\n    outline: none;\n}\n\n.content-tabs button:hover {\n    background: #fafafa;\n}\n\nnav.page-tabs {\n    margin-left: 40px;\n    width: 100000px;\n    height: 40px;\n    overflow: hidden;\n}\n\nnav.page-tabs .page-tabs-content {\n    float: left;\n}\n\n.page-tabs a {\n    display: block;\n    float: left;\n    border-right: solid 1px #eee;\n    padding: 0 15px;\n}\n\n.page-tabs a i:hover {\n    color: #c00;\n}\n\n.page-tabs a:hover, .content-tabs .roll-nav:hover {\n    color: #777;\n    background: #f2f2f2;\n    cursor: pointer;\n}\n\n.roll-right.J_tabRight {\n    right: 140px;\n}\n\n.roll-right.btn-group {\n    right: 60px;\n    width: 80px;\n    padding: 0;\n}\n\n.roll-right.btn-group button {\n    width: 80px;\n}\n\n.roll-right.J_tabExit {\n    background: #fff;\n    height: 40px;\n    width: 60px;\n    outline: none;\n}\n\n.dropdown-menu-right {\n    left: auto;\n}\n\n#content-main {\n    height: calc(100% - 140px);\n    overflow: hidden;\n}\n\n.fixed-nav #content-main {\n    height: calc(100% - 80px);\n    overflow: hidden;\n}\n/* TABLES */\n.table-bordered {\n    border: 1px solid #EBEBEB;\n}\n\n.table-bordered>thead>tr>th, .table-bordered>thead>tr>td {\n    background-color: #F5F5F6;\n    border-bottom-width: 1px;\n}\n\n.table-bordered>thead>tr>th, .table-bordered>tbody>tr>th,  .table-bordered>tfoot>tr>th, .table-bordered>thead>tr>td,  .table-bordered>tbody>tr>td, .table-bordered>tfoot>tr>td {\n    border: 1px solid #e7e7e7;\n}\n\n.table>thead>tr>th {\n    border-bottom: 1px solid #DDDDDD;\n    vertical-align: bottom;\n}\n\n.table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td,  .table>tbody>tr>td, .table>tfoot>tr>td {\n    border-top: 1px solid #e7eaec;\n    line-height: 1.42857;\n    padding: 8px;\n    vertical-align: middle;\n}\n/* PANELS */\n.panel.blank-panel {\n    background: none;\n    margin: 0;\n}\n\n.blank-panel .panel-heading {\n    padding-bottom: 0;\n}\n\n.nav-tabs>li.active>a, .nav-tabs>li.active>a:hover, .nav-tabs>li.active>a:focus {\n    -moz-border-bottom-colors: none;\n    -moz-border-left-colors: none;\n    -moz-border-right-colors: none;\n    -moz-border-top-colors: none;\n    background: none;\n    border-color: #dddddd #dddddd rgba(0, 0, 0, 0);\n    border-bottom: #f3f3f4;\n    -webkit-border-image: none;\n    -o-border-image: none;\n    border-image: none;\n    border-style: solid;\n    border-width: 1px;\n    color: #555555;\n    cursor: default;\n}\n\n.nav.nav-tabs li {\n    background: none;\n    border: none;\n}\n\n.nav-tabs>li>a {\n    color: #A7B1C2;\n    font-weight: 600;\n    padding: 10px 20px 10px 25px;\n}\n\n.nav-tabs>li>a:hover, .nav-tabs>li>a:focus {\n    background-color: #e6e6e6;\n    color: #676a6c;\n}\n\n.ui-tab .tab-content {\n    padding: 20px 0px;\n}\n/* GLOBAL  */\n.no-padding {\n    padding: 0 !important;\n}\n\n.no-borders {\n    border: none !important;\n}\n\n.no-margins {\n    margin: 0 !important;\n}\n\n.no-top-border {\n    border-top: 0 !important;\n}\n\n.ibox-content.text-box {\n    padding-bottom: 0px;\n    padding-top: 15px;\n}\n\n.border-left-right {\n    border-left: 1px solid #e7eaec;\n    border-right: 1px solid #e7eaec;\n    border-top: none;\n    border-bottom: none;\n}\n\n.border-left {\n    border-left: 1px solid #e7eaec;\n    border-right: none;\n    border-top: none;\n    border-bottom: none;\n}\n\n.border-right {\n    border-left: none;\n    border-right: 1px solid #e7eaec;\n    border-top: none;\n    border-bottom: none;\n}\n\n.full-width {\n    width: 100% !important;\n}\n\n.link-block {\n    font-size: 12px;\n    padding: 10px;\n}\n\n.nav.navbar-top-links .link-block a {\n    font-size: 12px;\n}\n\n.link-block a {\n    font-size: 10px;\n    color: inherit;\n}\n\nbody.mini-navbar .branding {\n    display: none;\n}\n\nimg.circle-border {\n    border: 6px solid #FFFFFF;\n    border-radius: 50%;\n}\n\n.branding {\n    float: left;\n    color: #FFFFFF;\n    font-size: 18px;\n    font-weight: 600;\n    padding: 17px 20px;\n    text-align: center;\n    background-color: #1ab394;\n}\n\n.login-panel {\n    margin-top: 25%;\n}\n\n.page-header {\n    padding: 20px 0 9px;\n    margin: 0 0 20px;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.fontawesome-icon-list {\n    margin-top: 22px;\n}\n\n.fontawesome-icon-list .fa-hover a {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    display: block;\n    color: #222222;\n    line-height: 32px;\n    height: 32px;\n    padding-left: 10px;\n    border-radius: 4px;\n}\n\n.fontawesome-icon-list .fa-hover a .fa {\n    width: 32px;\n    font-size: 14px;\n    display: inline-block;\n    text-align: right;\n    margin-right: 10px;\n}\n\n.fontawesome-icon-list .fa-hover a:hover {\n    background-color: #1d9d74;\n    color: #ffffff;\n    text-decoration: none;\n}\n\n.fontawesome-icon-list .fa-hover a:hover .fa {\n    font-size: 30px;\n    vertical-align: -6px;\n}\n\n.fontawesome-icon-list .fa-hover a:hover .text-muted {\n    color: #bbe2d5;\n}\n\n.feature-list .col-md-4 {\n    margin-bottom: 22px;\n}\n\n.feature-list h4 .fa:before {\n    vertical-align: -10%;\n    font-size: 28px;\n    display: inline-block;\n    width: 1.07142857em;\n    text-align: center;\n    margin-right: 5px;\n}\n\n.ui-draggable .ibox-title {\n    cursor: move;\n}\n\n.breadcrumb {\n    background-color: #ffffff;\n    padding: 0;\n    margin-bottom: 0;\n}\n\n.breadcrumb>li a {\n    color: inherit;\n}\n\n.breadcrumb>.active {\n    color: inherit;\n}\n\ncode {\n    background-color: #F9F2F4;\n    border-radius: 4px;\n    color: #ca4440;\n    font-size: 90%;\n    padding: 2px 4px;\n    white-space: nowrap;\n}\n\n.ibox {\n    clear: both;\n    margin-bottom: 25px;\n    margin-top: 0;\n    padding: 0;\n}\n\n.ibox.collapsed .ibox-content {\n    display: none;\n}\n\n.ibox.collapsed .fa.fa-chevron-up:before {\n    content: \"\\f078\";\n}\n\n.ibox.collapsed .fa.fa-chevron-down:before {\n    content: \"\\f077\";\n}\n\n.ibox:after, .ibox:before {\n    display: table;\n}\n\n.ibox-title {\n    -moz-border-bottom-colors: none;\n    -moz-border-left-colors: none;\n    -moz-border-right-colors: none;\n    -moz-border-top-colors: none;\n    background-color: #ffffff;\n    border-color: #e7eaec;\n    -webkit-border-image: none;\n    -o-border-image: none;\n    border-image: none;\n    border-style: solid solid none;\n    border-width: 4px 0px 0;\n    color: inherit;\n    margin-bottom: 0;\n    padding: 14px 15px 7px;\n    min-height: 48px;\n}\n\n.ibox-content {\n    background-color: #ffffff;\n    color: inherit;\n    padding: 15px 20px 20px 20px;\n    border-color: #e7eaec;\n    -webkit-border-image: none;\n    -o-border-image: none;\n    border-image: none;\n    border-style: solid solid none;\n    border-width: 1px 0px;\n}\n\ntable.table-mail tr td {\n    padding: 12px;\n}\n\n.table-mail .check-mail {\n    padding-left: 20px;\n}\n\n.table-mail .mail-date {\n    padding-right: 20px;\n}\n\n.star-mail, .check-mail {\n    width: 40px;\n}\n\n.unread td a, .unread td {\n    font-weight: 600;\n    color: inherit;\n}\n\n.read td a, .read td {\n    font-weight: normal;\n    color: inherit;\n}\n\n.unread td {\n    background-color: #f9f8f8;\n}\n\n.ibox-content {\n    clear: both;\n}\n\n.ibox-heading {\n    background-color: #f3f6fb;\n    border-bottom: none;\n}\n\n.ibox-heading h3 {\n    font-weight: 200;\n    font-size: 24px;\n}\n\n.ibox-title h5 {\n    display: inline-block;\n    font-size: 14px;\n    margin: 0 0 7px;\n    padding: 0;\n    text-overflow: ellipsis;\n    float: left;\n}\n\n.ibox-title .label {\n    float: left;\n    margin-left: 4px;\n}\n\n.ibox-tools {\n    display: inline-block;\n    float: right;\n    margin-top: 0;\n    position: relative;\n    padding: 0;\n}\n\n.ibox-tools a {\n    cursor: pointer;\n    margin-left: 5px;\n    color: #c4c4c4;\n}\n\n.ibox-tools a.btn-primary {\n    color: #fff;\n}\n\n.ibox-tools .dropdown-menu>li>a {\n    padding: 4px 10px;\n    font-size: 12px;\n}\n\n.ibox .open>.dropdown-menu {\n    left: auto;\n    right: 0;\n}\n/* BACKGROUNDS */\n.gray-bg {\n    background-color: #f3f3f4;\n}\n\n.white-bg {\n    background-color: #ffffff;\n}\n\n.navy-bg {\n    background-color: #1ab394;\n    color: #ffffff;\n}\n\n.blue-bg {\n    background-color: #1c84c6;\n    color: #ffffff;\n}\n\n.lazur-bg {\n    background-color: #23c6c8;\n    color: #ffffff;\n}\n\n.yellow-bg {\n    background-color: #f8ac59;\n    color: #ffffff;\n}\n\n.red-bg {\n    background-color: #ed5565;\n    color: #ffffff;\n}\n\n.black-bg {\n    background-color: #262626;\n}\n\n.panel-primary {\n    border-color: #1ab394;\n}\n\n.panel-primary>.panel-heading {\n    background-color: #1ab394;\n    border-color: #1ab394;\n}\n\n.panel-success {\n    border-color: #1c84c6;\n}\n\n.panel-success>.panel-heading {\n    background-color: #1c84c6;\n    border-color: #1c84c6;\n    color: #ffffff;\n}\n\n.panel-info {\n    border-color: #23c6c8;\n}\n\n.panel-info>.panel-heading {\n    background-color: #23c6c8;\n    border-color: #23c6c8;\n    color: #ffffff;\n}\n\n.panel-warning {\n    border-color: #f8ac59;\n}\n\n.panel-warning>.panel-heading {\n    background-color: #f8ac59;\n    border-color: #f8ac59;\n    color: #ffffff;\n}\n\n.panel-danger {\n    border-color: #ed5565;\n}\n\n.panel-danger>.panel-heading {\n    background-color: #ed5565;\n    border-color: #ed5565;\n    color: #ffffff;\n}\n\n.progress-bar {\n    background-color: #1ab394;\n}\n\n.progress-small, .progress-small .progress-bar {\n    height: 10px;\n}\n\n.progress-small, .progress-mini {\n    margin-top: 5px;\n}\n\n.progress-mini, .progress-mini .progress-bar {\n    height: 5px;\n    margin-bottom: 0px;\n}\n\n.progress-bar-navy-light {\n    background-color: #3dc7ab;\n}\n\n.progress-bar-success {\n    background-color: #1c84c6;\n}\n\n.progress-bar-info {\n    background-color: #23c6c8;\n}\n\n.progress-bar-warning {\n    background-color: #f8ac59;\n}\n\n.progress-bar-danger {\n    background-color: #ed5565;\n}\n\n.panel-title {\n    font-size: inherit;\n}\n\n.jumbotron {\n    border-radius: 6px;\n    padding: 40px;\n}\n\n.jumbotron h1 {\n    margin-top: 0;\n}\n/* COLORS */\n.text-navy {\n    color: #1ab394;\n}\n\n.text-primary {\n    color: inherit;\n}\n\n.text-success {\n    color: #1c84c6;\n}\n\n.text-info {\n    color: #23c6c8;\n}\n\n.text-warning {\n    color: #f8ac59;\n}\n\n.text-danger {\n    color: #ed5565;\n}\n\n.text-muted {\n    color: #888888;\n}\n\n.simple_tag {\n    background-color: #f3f3f4;\n    border: 1px solid #e7eaec;\n    border-radius: 2px;\n    color: inherit;\n    font-size: 10px;\n    margin-right: 5px;\n    margin-top: 5px;\n    padding: 5px 12px;\n    display: inline-block;\n}\n\n.img-shadow {\n    box-shadow: 0px 0px 3px 0px #919191;\n}\n/* For handle diferent bg color in AngularJS version */\n.dashboards\\.dashboard_2 nav.navbar, .dashboards\\.dashboard_3 nav.navbar,  .mailbox\\.inbox nav.navbar, .mailbox\\.email_view nav.navbar,  .mailbox\\.email_compose nav.navbar, .dashboards\\.dashboard_4_1 nav.navbar {\n    background: #fff;\n}\n/* For handle diferent bg color in MVC version */\n.Dashboard_2 .navbar.navbar-static-top, .Dashboard_3 .navbar.navbar-static-top,  .Dashboard_4_1 .navbar.navbar-static-top, .ComposeEmail .navbar.navbar-static-top,  .EmailView .navbar.navbar-static-top, .Inbox .navbar.navbar-static-top {\n    background: #fff;\n}\n\na.close-canvas-menu {\n    position: absolute;\n    top: 10px;\n    right: 15px;\n    z-index: 1011;\n    color: #a7b1c2;\n}\n\na.close-canvas-menu:hover {\n    color: #fff;\n}\n/* FULL HEIGHT */\n.full-height {\n    height: 100%;\n}\n\n.fh-breadcrumb {\n    height: calc(100% - 196px);\n    margin: 0 -15px;\n    position: relative;\n}\n\n.fh-no-breadcrumb {\n    height: calc(100% - 99px);\n    margin: 0 -15px;\n    position: relative;\n}\n\n.fh-column {\n    background: #fff;\n    height: 100%;\n    width: 240px;\n    float: left;\n}\n\n.modal-backdrop {\n    z-index: 2040 !important;\n}\n\n.modal {\n    z-index: 2050 !important;\n}\n\n.spiner-example {\n    height: 200px;\n    padding-top: 70px;\n}\n/* MARGINS & PADDINGS */\n.p-xxs {\n    padding: 5px;\n}\n\n.p-xs {\n    padding: 10px;\n}\n\n.p-sm {\n    padding: 15px;\n}\n\n.p-m {\n    padding: 20px;\n}\n\n.p-md {\n    padding: 25px;\n}\n\n.p-lg {\n    padding: 30px;\n}\n\n.p-xl {\n    padding: 40px;\n}\n\n.m-xxs {\n    margin: 2px 4px;\n}\n\n.m-xs {\n    margin: 5px;\n}\n\n.m-sm {\n    margin: 10px;\n}\n\n.m {\n    margin: 15px;\n}\n\n.m-md {\n    margin: 20px;\n}\n\n.m-lg {\n    margin: 30px;\n}\n\n.m-xl {\n    margin: 50px;\n}\n\n.m-n {\n    margin: 0 !important;\n}\n\n.m-l-none {\n    margin-left: 0;\n}\n\n.m-l-xs {\n    margin-left: 5px;\n}\n\n.m-l-sm {\n    margin-left: 10px;\n}\n\n.m-l {\n    margin-left: 15px;\n}\n\n.m-l-md {\n    margin-left: 20px;\n}\n\n.m-l-lg {\n    margin-left: 30px;\n}\n\n.m-l-xl {\n    margin-left: 40px;\n}\n\n.m-l-n-xxs {\n    margin-left: -1px;\n}\n\n.m-l-n-xs {\n    margin-left: -5px;\n}\n\n.m-l-n-sm {\n    margin-left: -10px;\n}\n\n.m-l-n {\n    margin-left: -15px;\n}\n\n.m-l-n-md {\n    margin-left: -20px;\n}\n\n.m-l-n-lg {\n    margin-left: -30px;\n}\n\n.m-l-n-xl {\n    margin-left: -40px;\n}\n\n.m-t-none {\n    margin-top: 0;\n}\n\n.m-t-xxs {\n    margin-top: 1px;\n}\n\n.m-t-xs {\n    margin-top: 5px;\n}\n\n.m-t-sm {\n    margin-top: 10px;\n}\n\n.m-t {\n    margin-top: 15px;\n}\n\n.m-t-md {\n    margin-top: 20px;\n}\n\n.m-t-lg {\n    margin-top: 30px;\n}\n\n.m-t-xl {\n    margin-top: 40px;\n}\n\n.m-t-n-xxs {\n    margin-top: -1px;\n}\n\n.m-t-n-xs {\n    margin-top: -5px;\n}\n\n.m-t-n-sm {\n    margin-top: -10px;\n}\n\n.m-t-n {\n    margin-top: -15px;\n}\n\n.m-t-n-md {\n    margin-top: -20px;\n}\n\n.m-t-n-lg {\n    margin-top: -30px;\n}\n\n.m-t-n-xl {\n    margin-top: -40px;\n}\n\n.m-r-none {\n    margin-right: 0;\n}\n\n.m-r-xxs {\n    margin-right: 1px;\n}\n\n.m-r-xs {\n    margin-right: 5px;\n}\n\n.m-r-sm {\n    margin-right: 10px;\n}\n\n.m-r {\n    margin-right: 15px;\n}\n\n.m-r-md {\n    margin-right: 20px;\n}\n\n.m-r-lg {\n    margin-right: 30px;\n}\n\n.m-r-xl {\n    margin-right: 40px;\n}\n\n.m-r-n-xxs {\n    margin-right: -1px;\n}\n\n.m-r-n-xs {\n    margin-right: -5px;\n}\n\n.m-r-n-sm {\n    margin-right: -10px;\n}\n\n.m-r-n {\n    margin-right: -15px;\n}\n\n.m-r-n-md {\n    margin-right: -20px;\n}\n\n.m-r-n-lg {\n    margin-right: -30px;\n}\n\n.m-r-n-xl {\n    margin-right: -40px;\n}\n\n.m-b-none {\n    margin-bottom: 0;\n}\n\n.m-b-xxs {\n    margin-bottom: 1px;\n}\n\n.m-b-xs {\n    margin-bottom: 5px;\n}\n\n.m-b-sm {\n    margin-bottom: 10px;\n}\n\n.m-b {\n    margin-bottom: 15px;\n}\n\n.m-b-md {\n    margin-bottom: 20px;\n}\n\n.m-b-lg {\n    margin-bottom: 30px;\n}\n\n.m-b-xl {\n    margin-bottom: 40px;\n}\n\n.m-b-n-xxs {\n    margin-bottom: -1px;\n}\n\n.m-b-n-xs {\n    margin-bottom: -5px;\n}\n\n.m-b-n-sm {\n    margin-bottom: -10px;\n}\n\n.m-b-n {\n    margin-bottom: -15px;\n}\n\n.m-b-n-md {\n    margin-bottom: -20px;\n}\n\n.m-b-n-lg {\n    margin-bottom: -30px;\n}\n\n.m-b-n-xl {\n    margin-bottom: -40px;\n}\n\n.space-15 {\n    margin: 15px 0;\n}\n\n.space-20 {\n    margin: 20px 0;\n}\n\n.space-25 {\n    margin: 25px 0;\n}\n\n.space-30 {\n    margin: 30px 0;\n}\n\nbody.modal-open {\n    padding-right: inherit !important;\n}\n/* SEARCH PAGE */\n.search-form {\n    margin-top: 10px;\n}\n\n.search-result h3 {\n    margin-bottom: 0;\n    color: #1E0FBE;\n}\n\n.search-result .search-link {\n    color: #006621;\n}\n\n.search-result p {\n    font-size: 12px;\n    margin-top: 5px;\n}\n/* CONTACTS */\n.contact-box {\n    background-color: #ffffff;\n    border: 1px solid #e7eaec;\n    padding: 20px;\n    margin-bottom: 20px;\n}\n\n.contact-box a {\n    color: inherit;\n}\n\n/* INVOICE */\n.invoice-table tbody>tr>td:last-child, .invoice-table tbody>tr>td:nth-child(4),  .invoice-table tbody>tr>td:nth-child(3), .invoice-table tbody>tr>td:nth-child(2) {\n    text-align: right;\n}\n\n.invoice-table thead>tr>th:last-child, .invoice-table thead>tr>th:nth-child(4),  .invoice-table thead>tr>th:nth-child(3), .invoice-table thead>tr>th:nth-child(2) {\n    text-align: right;\n}\n\n.invoice-total>tbody>tr>td:first-child {\n    text-align: right;\n}\n\n.invoice-total>tbody>tr>td {\n    border: 0 none;\n}\n\n.invoice-total>tbody>tr>td:last-child {\n    border-bottom: 1px solid #DDDDDD;\n    text-align: right;\n    width: 15%;\n}\n/* ERROR & LOGIN & LOCKSCREEN*/\n.middle-box {\n    max-width: 400px;\n    z-index: 100;\n    margin: 0 auto;\n    padding-top: 40px;\n}\n\n.lockscreen.middle-box {\n    width: 200px;\n    padding-top: 110px;\n}\n\n.loginscreen.middle-box {\n    width: 300px;\n}\n\n.loginColumns {\n    max-width: 800px;\n    margin: 0 auto;\n    padding: 100px 20px 20px 20px;\n}\n\n.passwordBox {\n    max-width: 460px;\n    margin: 0 auto;\n    padding: 100px 20px 20px 20px;\n}\n\n.logo-name {\n    color: #e6e6e6;\n    font-size: 180px;\n    font-weight: 800;\n    letter-spacing: -10px;\n    margin-bottom: 0px;\n}\n\n.middle-box h1 {\n    font-size: 170px;\n}\n\n.wrapper .middle-box {\n    margin-top: 140px;\n}\n\n.lock-word {\n    z-index: 10;\n    position: absolute;\n    top: 110px;\n    left: 50%;\n    margin-left: -470px;\n}\n\n.lock-word span {\n    font-size: 100px;\n    font-weight: 600;\n    color: #e9e9e9;\n    display: inline-block;\n}\n\n.lock-word .first-word {\n    margin-right: 160px;\n}\n/* DASBOARD */\n.dashboard-header {\n    border-top: 0;\n    padding: 20px 20px 20px 20px;\n}\n\n.dashboard-header h2 {\n    margin-top: 10px;\n    font-size: 26px;\n}\n\n.fist-item {\n    border-top: none !important;\n}\n\n.statistic-box {\n    margin-top: 40px;\n}\n\n.dashboard-header .list-group-item span.label {\n    margin-right: 10px;\n}\n\n.list-group.clear-list .list-group-item {\n    border-top: 1px solid #e7eaec;\n    border-bottom: 0;\n    border-right: 0;\n    border-left: 0;\n    padding: 10px 0;\n}\n\nul.clear-list:first-child {\n    border-top: none !important;\n}\n/* Intimeline */\n.timeline-item .date i {\n    position: absolute;\n    top: 0;\n    right: 0;\n    padding: 5px;\n    width: 30px;\n    text-align: center;\n    border-top: 1px solid #e7eaec;\n    border-bottom: 1px solid #e7eaec;\n    border-left: 1px solid #e7eaec;\n    background: #f8f8f8;\n}\n\n.timeline-item .date {\n    text-align: right;\n    width: 110px;\n    position: relative;\n    padding-top: 30px;\n}\n\n.timeline-item .content {\n    border-left: 1px solid #e7eaec;\n    border-top: 1px solid #e7eaec;\n    padding-top: 10px;\n    min-height: 100px;\n}\n\n.timeline-item .content:hover {\n    background: #f6f6f6;\n}\n/* PIN BOARD */\nul.notes li, ul.tag-list li {\n    list-style: none;\n}\n\nul.notes li h4 {\n    margin-top: 20px;\n    font-size: 16px;\n}\n\nul.notes li div {\n    text-decoration: none;\n    color: #000;\n    background: #ffc;\n    display: block;\n    height: 140px;\n    width: 140px;\n    padding: 1em;\n    position: relative;\n}\n\nul.notes li div small {\n    position: absolute;\n    top: 5px;\n    right: 5px;\n    font-size: 10px;\n}\n\nul.notes li div a {\n    position: absolute;\n    right: 10px;\n    bottom: 10px;\n    color: inherit;\n}\n\nul.notes li {\n    margin: 10px 40px 50px 0px;\n    float: left;\n}\n\nul.notes li div p {\n    font-size: 12px;\n}\n\nul.notes li div {\n    text-decoration: none;\n    color: #000;\n    background: #ffc;\n    display: block;\n    height: 140px;\n    width: 140px;\n    padding: 1em;\n    /* Firefox */\n    /* Safari+Chrome */\n    /* Opera */\n    box-shadow: 5px 5px 2px rgba(33, 33, 33, 0.7);\n}\n\nul.notes li div {\n    -webkit-transform: rotate(-6deg);\n    -o-transform: rotate(-6deg);\n    -moz-transform: rotate(-6deg);\n}\n\nul.notes li:nth-child(even) div {\n    -o-transform: rotate(4deg);\n    -webkit-transform: rotate(4deg);\n    -moz-transform: rotate(4deg);\n    position: relative;\n    top: 5px;\n}\n\nul.notes li:nth-child(3n) div {\n    -o-transform: rotate(-3deg);\n    -webkit-transform: rotate(-3deg);\n    -moz-transform: rotate(-3deg);\n    position: relative;\n    top: -5px;\n}\n\nul.notes li:nth-child(5n) div {\n    -o-transform: rotate(5deg);\n    -webkit-transform: rotate(5deg);\n    -moz-transform: rotate(5deg);\n    position: relative;\n    top: -10px;\n}\n\nul.notes li div:hover, ul.notes li div:focus {\n    -webkit-transform: scale(1.1);\n    -moz-transform: scale(1.1);\n    -o-transform: scale(1.1);\n    position: relative;\n    z-index: 5;\n}\n\nul.notes li div {\n    text-decoration: none;\n    color: #000;\n    background: #ffc;\n    display: block;\n    height: 210px;\n    width: 210px;\n    padding: 1em;\n    box-shadow: 5px 5px 7px rgba(33, 33, 33, 0.7);\n    -webkit-transition: -webkit-transform 0.15s linear;\n}\n/* FILE MANAGER */\n.file-box {\n    float: left;\n    width: 220px;\n}\n\n.file-manager h5 {\n    text-transform: uppercase;\n}\n\n.file-manager {\n    list-style: none outside none;\n    margin: 0;\n    padding: 0;\n}\n\n.folder-list li a {\n    color: #666666;\n    display: block;\n    padding: 5px 0;\n}\n\n.folder-list li {\n    border-bottom: 1px solid #e7eaec;\n    display: block;\n}\n\n.folder-list li i {\n    margin-right: 8px;\n    color: #3d4d5d;\n}\n\n.category-list li a {\n    color: #666666;\n    display: block;\n    padding: 5px 0;\n}\n\n.category-list li {\n    display: block;\n}\n\n.category-list li i {\n    margin-right: 8px;\n    color: #3d4d5d;\n}\n\n.category-list li a .text-navy {\n    color: #1ab394;\n}\n\n.category-list li a .text-primary {\n    color: #1c84c6;\n}\n\n.category-list li a .text-info {\n    color: #23c6c8;\n}\n\n.category-list li a .text-danger {\n    color: #EF5352;\n}\n\n.category-list li a .text-warning {\n    color: #F8AC59;\n}\n\n.file-manager h5.tag-title {\n    margin-top: 20px;\n}\n\n.tag-list li {\n    float: left;\n}\n\n.tag-list li a {\n    font-size: 10px;\n    background-color: #f3f3f4;\n    padding: 5px 12px;\n    color: inherit;\n    border-radius: 2px;\n    border: 1px solid #e7eaec;\n    margin-right: 5px;\n    margin-top: 5px;\n    display: block;\n}\n\n.file {\n    border: 1px solid #e7eaec;\n    padding: 0;\n    background-color: #ffffff;\n    position: relative;\n    margin-bottom: 20px;\n    margin-right: 20px;\n}\n\n.file-manager .hr-line-dashed {\n    margin: 15px 0;\n}\n\n.file .icon, .file .image {\n    height: 100px;\n    overflow: hidden;\n}\n\n.file .icon {\n    padding: 15px 10px;\n    text-align: center;\n}\n\n.file-control {\n    color: inherit;\n    font-size: 14px;\n    margin-right: 10px;\n}\n\n.file-control.active {\n    text-decoration: underline;\n}\n\n.file .icon i {\n    font-size: 70px;\n    color: #dadada;\n}\n\n.file .file-name {\n    padding: 10px;\n    background-color: #f8f8f8;\n    border-top: 1px solid #e7eaec;\n}\n\n.file-name small {\n    color: #676a6c;\n}\n\n.corner {\n    position: absolute;\n    display: inline-block;\n    width: 0;\n    height: 0;\n    line-height: 0;\n    border: 0.6em solid transparent;\n    border-right: 0.6em solid #f1f1f1;\n    border-bottom: 0.6em solid #f1f1f1;\n    right: 0em;\n    bottom: 0em;\n}\n\na.compose-mail {\n    padding: 8px 10px;\n}\n\n.mail-search {\n    max-width: 300px;\n}\n/* PROFILE */\n.profile-content {\n    border-top: none !important;\n}\n\n.feed-activity-list .feed-element {\n    border-bottom: 1px solid #e7eaec;\n}\n\n.feed-element:first-child {\n    margin-top: 0;\n}\n\n.feed-element {\n    padding-bottom: 15px;\n}\n\n.feed-element, .feed-element .media {\n    margin-top: 15px;\n}\n\n.feed-element, .media-body {\n    overflow: hidden;\n}\n\n.feed-element>.pull-left {\n    margin-right: 10px;\n}\n\n.feed-element img.img-circle, .dropdown-messages-box img.img-circle {\n    width: 38px;\n    height: 38px;\n}\n\n.feed-element .well {\n    border: 1px solid #e7eaec;\n    box-shadow: none;\n    margin-top: 10px;\n    margin-bottom: 5px;\n    padding: 10px 20px;\n    font-size: 11px;\n    line-height: 16px;\n}\n\n.feed-element .actions {\n    margin-top: 10px;\n}\n\n.feed-element .photos {\n    margin: 10px 0;\n}\n\n.feed-photo {\n    max-height: 180px;\n    border-radius: 4px;\n    overflow: hidden;\n    margin-right: 10px;\n    margin-bottom: 10px;\n}\n/* MAILBOX */\n.mail-box {\n    background-color: #ffffff;\n    border: 1px solid #e7eaec;\n    border-top: 0;\n    padding: 0px;\n    margin-bottom: 20px;\n}\n\n.mail-box-header {\n    background-color: #ffffff;\n    border: 1px solid #e7eaec;\n    border-bottom: 0;\n    padding: 30px 20px 20px 20px;\n}\n\n.mail-box-header h2 {\n    margin-top: 0px;\n}\n\n.mailbox-content .tag-list li a {\n    background: #ffffff;\n}\n\n.mail-body {\n    border-top: 1px solid #e7eaec;\n    padding: 20px;\n}\n\n.mail-text {\n    border-top: 1px solid #e7eaec;\n}\n\n.mail-text .note-toolbar {\n    padding: 10px 15px;\n}\n\n.mail-body .form-group {\n    margin-bottom: 5px;\n}\n\n.mail-text .note-editor .note-toolbar {\n    background-color: #F9F8F8;\n}\n\n.mail-attachment {\n    border-top: 1px solid #e7eaec;\n    padding: 20px;\n    font-size: 12px;\n}\n\n.mailbox-content {\n    background: none;\n    border: none;\n    padding: 10px;\n}\n\n.mail-ontact {\n    width: 23%;\n}\n/* PROJECTS */\n.project-people, .project-actions {\n    text-align: right;\n    vertical-align: middle;\n}\n\ndd.project-people {\n    text-align: left;\n    margin-top: 5px;\n}\n\n.project-people img {\n    width: 32px;\n    height: 32px;\n}\n\n.project-title a {\n    font-size: 14px;\n    color: #676a6c;\n    font-weight: 600;\n}\n\n.project-list table tr td {\n    border-top: none;\n    border-bottom: 1px solid #e7eaec;\n    padding: 15px 10px;\n    vertical-align: middle;\n}\n\n.project-manager .tag-list li a {\n    font-size: 10px;\n    background-color: white;\n    padding: 5px 12px;\n    color: inherit;\n    border-radius: 2px;\n    border: 1px solid #e7eaec;\n    margin-right: 5px;\n    margin-top: 5px;\n    display: block;\n}\n\n.project-files li a {\n    font-size: 11px;\n    color: #676a6c;\n    margin-left: 10px;\n    line-height: 22px;\n}\n/* FAQ */\n.faq-item {\n    padding: 20px;\n    margin-bottom: 2px;\n    background: #fff;\n}\n\n.faq-question {\n    font-size: 18px;\n    font-weight: 600;\n    color: #1ab394;\n    display: block;\n}\n\n.faq-question:hover {\n    color: #179d82;\n}\n\n.faq-answer {\n    margin-top: 10px;\n    background: #f3f3f4;\n    border: 1px solid #e7eaec;\n    border-radius: 3px;\n    padding: 15px;\n}\n\n.faq-item .tag-item {\n    background: #f3f3f4;\n    padding: 2px 6px;\n    font-size: 10px;\n    text-transform: uppercase;\n}\n/* Chat view */\n.message-input {\n    height: 90px !important;\n}\n\n.chat-avatar {\n    white: 36px;\n    height: 36px;\n    float: left;\n    margin-right: 10px;\n}\n\n.chat-user-name {\n    padding: 10px;\n}\n\n.chat-user {\n    padding: 8px 10px;\n    border-bottom: 1px solid #e7eaec;\n}\n\n.chat-user a {\n    color: inherit;\n}\n\n.chat-view {\n    z-index: 20012;\n}\n\n.chat-users, .chat-statistic {\n    margin-left: -30px;\n}\n\n@media ( max-width : 992px) {\n    .chat-users, .chat-statistic {\n        margin-left: 0px;\n    }\n}\n\n.chat-view .ibox-content {\n    padding: 0;\n}\n\n.chat-message {\n    padding: 10px 20px;\n}\n\n.message-avatar {\n    height: 48px;\n    width: 48px;\n    border: 1px solid #e7eaec;\n    border-radius: 4px;\n    margin-top: 1px;\n}\n\n.chat-discussion .chat-message:nth-child(2n+1) .message-avatar {\n    float: left;\n    margin-right: 10px;\n}\n\n.chat-discussion .chat-message:nth-child(2n) .message-avatar {\n    float: right;\n    margin-left: 10px;\n}\n\n.message {\n    background-color: #fff;\n    border: 1px solid #e7eaec;\n    text-align: left;\n    display: block;\n    padding: 10px 20px;\n    position: relative;\n    border-radius: 4px;\n}\n\n.chat-discussion .chat-message:nth-child(2n+1) .message-date {\n    float: right;\n}\n\n.chat-discussion .chat-message:nth-child(2n) .message-date {\n    float: left;\n}\n\n.chat-discussion .chat-message:nth-child(2n+1) .message {\n    text-align: left;\n    margin-left: 55px;\n}\n\n.chat-discussion .chat-message:nth-child(2n) .message {\n    text-align: right;\n    margin-right: 55px;\n}\n\n.message-date {\n    font-size: 10px;\n    color: #888888;\n}\n\n.message-content {\n    display: block;\n}\n\n.chat-discussion {\n    background: #eee;\n    padding: 15px;\n    height: 400px;\n    overflow-y: auto;\n}\n\n.chat-users {\n    overflow-y: auto;\n    height: 400px;\n}\n\n.chat-message-form .form-group {\n    margin-bottom: 0;\n}\n/* jsTree */\n.jstree-open>.jstree-anchor>.fa-folder:before {\n    content: \"\\f07c\";\n}\n\n.jstree-default .jstree-icon.none {\n    width: 0;\n}\n/* CLIENTS */\n.clients-list {\n    margin-top: 20px;\n}\n\n.clients-list .tab-pane {\n    position: relative;\n    height: 600px;\n}\n\n.client-detail {\n    position: relative;\n    height: 620px;\n}\n\n.clients-list table tr td {\n    height: 46px;\n    vertical-align: middle;\n    border: none;\n}\n\n.client-link {\n    font-weight: 600;\n    color: inherit;\n}\n\n.client-link:hover {\n    color: inherit;\n}\n\n.client-avatar {\n    width: 42px;\n}\n\n.client-avatar img {\n    width: 28px;\n    height: 28px;\n    border-radius: 50%;\n}\n\n.contact-type {\n    width: 20px;\n    color: #c1c3c4;\n}\n\n.client-status {\n    text-align: left;\n}\n\n.client-detail .vertical-timeline-content p {\n    margin: 0;\n}\n\n.client-detail .vertical-timeline-icon.gray-bg {\n    color: #a7aaab;\n}\n\n.clients-list .nav-tabs>li.active>a, .clients-list .nav-tabs>li.active>a:hover,  .clients-list .nav-tabs>li.active>a:focus {\n    border-bottom: 1px solid #fff;\n}\n/* BLOG ARTICLE */\n.blog h2 {\n    font-weight: 700;\n}\n\n.blog h5 {\n    margin: 0 0 5px 0;\n}\n\n.blog .btn {\n    margin: 0 0 5px 0;\n}\n\n.article h1 {\n    font-size: 48px;\n    font-weight: 700;\n    color: #2F4050;\n}\n\n.article p {\n    font-size: 15px;\n    line-height: 26px;\n}\n\n.article-title {\n    text-align: center;\n    margin: 60px 0 40px 0;\n}\n\n.article .ibox-content {\n    padding: 40px;\n}\n/* ISSUE TRACKER */\n.issue-tracker .btn-link {\n    color: #1ab394;\n}\n\ntable.issue-tracker tbody tr td {\n    vertical-align: middle;\n    height: 50px;\n}\n\n.issue-info {\n    width: 50%;\n}\n\n.issue-info a {\n    font-weight: 600;\n    color: #676a6c;\n}\n\n.issue-info small {\n    display: block;\n}\n/* TEAMS */\n.team-members {\n    margin: 10px 0;\n}\n\n.team-members img.img-circle {\n    width: 42px;\n    height: 42px;\n    margin-bottom: 5px;\n}\n/* AGILE BOARD */\n.sortable-list {\n    padding: 10px 0;\n}\n\n.agile-list {\n    list-style: none;\n    margin: 0;\n}\n\n.agile-list li {\n    background: #FAFAFB;\n    border: 1px solid #e7eaec;\n    margin: 0px 0 10px 0;\n    padding: 10px;\n    border-radius: 2px;\n}\n\n.agile-list li:hover {\n    cursor: pointer;\n    background: #fff;\n}\n\n.agile-list li.warning-element {\n    border-left: 3px solid #f8ac59;\n}\n\n.agile-list li.danger-element {\n    border-left: 3px solid #ed5565;\n}\n\n.agile-list li.info-element {\n    border-left: 3px solid #1c84c6;\n}\n\n.agile-list li.success-element {\n    border-left: 3px solid #1ab394;\n}\n\n.agile-detail {\n    margin-top: 5px;\n    font-size: 12px;\n}\n/* DIFF */\nins {\n    background-color: #c6ffc6;\n    text-decoration: none;\n}\n\ndel {\n    background-color: #ffc6c6;\n}\n\n#small-chat {\n    position: fixed;\n    bottom: 50px;\n    right: 26px;\n    z-index: 100;\n}\n\n#small-chat .badge {\n    position: absolute;\n    top: -3px;\n    right: -4px;\n}\n\n.open-small-chat {\n    height: 38px;\n    width: 38px;\n    display: block;\n    background: #1ab394;\n    padding: 9px 8px;\n    text-align: center;\n    color: #fff;\n    border-radius: 50%;\n}\n\n.open-small-chat:hover {\n    color: white;\n    background: #1ab394;\n}\n\n.small-chat-box {\n    display: none;\n    position: fixed;\n    bottom: 50px;\n    right: 80px;\n    background: #fff;\n    border: 1px solid #e7eaec;\n    width: 230px;\n    height: 320px;\n    border-radius: 4px;\n}\n\n.small-chat-box.ng-small-chat {\n    display: block;\n}\n\n.body-small .small-chat-box {\n    bottom: 70px;\n    right: 20px;\n}\n\n.small-chat-box.active {\n    display: block;\n}\n\n.small-chat-box .heading {\n    background: #2f4050;\n    padding: 8px 15px;\n    font-weight: bold;\n    color: #fff;\n}\n\n.small-chat-box .chat-date {\n    opacity: 0.6;\n    font-size: 10px;\n    font-weight: normal;\n}\n\n.small-chat-box .content {\n    padding: 15px 15px;\n}\n\n.small-chat-box .content .author-name {\n    font-weight: bold;\n    margin-bottom: 3px;\n    font-size: 11px;\n}\n\n.small-chat-box .content>div {\n    padding-bottom: 20px;\n}\n\n.small-chat-box .content .chat-message {\n    padding: 5px 10px;\n    border-radius: 6px;\n    font-size: 11px;\n    line-height: 14px;\n    max-width: 80%;\n    background: #f3f3f4;\n    margin-bottom: 10px;\n}\n\n.small-chat-box .content .chat-message.active {\n    background: #1ab394;\n    color: #fff;\n}\n\n.small-chat-box .content .left {\n    text-align: left;\n    clear: both;\n}\n\n.small-chat-box .content .left .chat-message {\n    float: left;\n}\n\n.small-chat-box .content .right {\n    text-align: right;\n    clear: both;\n}\n\n.small-chat-box .content .right .chat-message {\n    float: right;\n}\n\n.small-chat-box .form-chat {\n    padding: 10px 10px;\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-rotating-plane\"></div>\n *\n */\n.sk-spinner-rotating-plane.sk-spinner {\n    width: 30px;\n    height: 30px;\n    background-color: #1ab394;\n    margin: 0 auto;\n    -webkit-animation: sk-rotatePlane 1.2s infinite ease-in-out;\n    animation: sk-rotatePlane 1.2s infinite ease-in-out;\n}\n\n@-webkit-keyframes sk-rotatePlane {\n    0% {\n        -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);\n        transform: perspective(120px) rotateX(0deg) rotateY(0deg);\n    }\n\n    50% {\n        -webkit-transform: perspective(120px)  rotateX(-180 .1deg )  rotateY(0deg);\n        transform: perspective(120px)  rotateX(-180 .1deg )  rotateY(0deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(120px)  rotateX(-180deg)  rotateY(-180deg);\n        transform: perspective(120px)  rotateX(-180deg)  rotateY(-180deg);\n    }\n}\n\n@keyframes sk-rotatePlane {\n    0% {\n        -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);\n        transform: perspective(120px) rotateX(0deg) rotateY(0deg);\n    }\n\n    50% {\n        -webkit-transform: perspective(120px)  rotateX(-180 .1deg)  rotateY(0deg);\n        transform: perspective(120px)  rotateX(-180 .1deg)  rotateY(0deg);\n    }\n\n    100% {\n        -webkit-transform: perspective(120px)  rotateX(-180deg)  rotateY(-179 .9deg );\n        transform: perspective(120px)  rotateX(-180deg)  rotateY(-179 .9deg );\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-double-bounce\">\n *      <div class=\"sk-double-bounce1\"></div>\n *      <div class=\"sk-double-bounce2\"></div>\n *    </div>\n *\n */\n.sk-spinner-double-bounce.sk-spinner {\n    width: 40px;\n    height: 40px;\n    position: relative;\n    margin: 0 auto;\n}\n\n.sk-spinner-double-bounce .sk-double-bounce1, .sk-spinner-double-bounce .sk-double-bounce2 {\n    width: 100%;\n    height: 100%;\n    border-radius: 50%;\n    background-color: #1ab394;\n    opacity: 0.6;\n    position: absolute;\n    top: 0;\n    left: 0;\n    -webkit-animation: sk-doubleBounce 2s infinite ease-in-out;\n    animation: sk-doubleBounce 2s infinite ease-in-out;\n}\n\n.sk-spinner-double-bounce .sk-double-bounce2 {\n    -webkit-animation-delay: -1s;\n    animation-delay: -1s;\n}\n\n@-webkit-keyframes sk-doubleBounce {\n    0%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    50% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes sk-doubleBounce {\n    0%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    50% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-wave\">\n *      <div class=\"sk-rect1\"></div>\n *      <div class=\"sk-rect2\"></div>\n *      <div class=\"sk-rect3\"></div>\n *      <div class=\"sk-rect4\"></div>\n *      <div class=\"sk-rect5\"></div>\n *    </div>\n *\n */\n.sk-spinner-wave.sk-spinner {\n    margin: 0 auto;\n    width: 50px;\n    height: 30px;\n    text-align: center;\n    font-size: 10px;\n}\n\n.sk-spinner-wave div {\n    background-color: #1ab394;\n    height: 100%;\n    width: 6px;\n    display: inline-block;\n    -webkit-animation: sk-waveStretchDelay 1.2s infinite ease-in-out;\n    animation: sk-waveStretchDelay 1.2s infinite ease-in-out;\n}\n\n.sk-spinner-wave .sk-rect2 {\n    -webkit-animation-delay: -1.1s;\n    animation-delay: -1.1s;\n}\n\n.sk-spinner-wave .sk-rect3 {\n    -webkit-animation-delay: -1s;\n    animation-delay: -1s;\n}\n\n.sk-spinner-wave .sk-rect4 {\n    -webkit-animation-delay: -0.9s;\n    animation-delay: -0.9s;\n}\n\n.sk-spinner-wave .sk-rect5 {\n    -webkit-animation-delay: -0.8s;\n    animation-delay: -0.8s;\n}\n\n@-webkit-keyframes sk-waveStretchDelay {\n    0%, 40%, 100% {\n        -webkit-transform: scaleY(0.4);\n        transform: scaleY(0.4);\n    }\n\n    20% {\n        -webkit-transform: scaleY(1);\n        transform: scaleY(1);\n    }\n}\n\n@keyframes sk-waveStretchDelay {\n    0%, 40%, 100% {\n        -webkit-transform: scaleY(0.4);\n        transform: scaleY(0.4);\n    }\n\n    20% {\n        -webkit-transform: scaleY(1);\n        transform: scaleY(1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-wandering-cubes\">\n *      <div class=\"sk-cube1\"></div>\n *      <div class=\"sk-cube2\"></div>\n *    </div>\n *\n */\n.sk-spinner-wandering-cubes.sk-spinner {\n    margin: 0 auto;\n    width: 32px;\n    height: 32px;\n    position: relative;\n}\n\n.sk-spinner-wandering-cubes .sk-cube1, .sk-spinner-wandering-cubes .sk-cube2 {\n    background-color: #1ab394;\n    width: 10px;\n    height: 10px;\n    position: absolute;\n    top: 0;\n    left: 0;\n    -webkit-animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;\n    animation: sk-wanderingCubeMove 1.8s infinite ease-in-out;\n}\n\n.sk-spinner-wandering-cubes .sk-cube2 {\n    -webkit-animation-delay: -0.9s;\n    animation-delay: -0.9s;\n}\n\n@-webkit-keyframes sk-wanderingCubeMove {\n    25% {\n        -webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);\n        transform: translateX(42px) rotate(-90deg) scale(0.5);\n    }\n\n    50% {\n        /* Hack to make FF rotate in the right direction */\n        -webkit-transform: translateX(42px)  translateY(42px)  rotate(-179deg);\n        transform: translateX(42px)  translateY(42px)  rotate(-179deg);\n    }\n\n    50.1% {\n    -webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);\n    transform: translateX(42px) translateY(42px) rotate(-180deg);\n}\n\n75% {\n    -webkit-transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );\n    transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );\n}\n\n100% {\n    -webkit-transform: rotate(-360deg);\n    transform: rotate(-360deg);\n}\n}\n\n@keyframes sk-wanderingCubeMove {\n    25% {\n        -webkit-transform: translateX(42px) rotate(-90deg) scale(0.5);\n        transform: translateX(42px) rotate(-90deg) scale(0.5);\n    }\n\n    50% {\n        /* Hack to make FF rotate in the right direction */\n        -webkit-transform: translateX(42px)  translateY(42px)  rotate(-179deg);\n        transform: translateX(42px)  translateY(42px)  rotate(-179deg);\n    }\n\n    50.1%{\n        -webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);\n        transform: translateX(42px) translateY(42px) rotate(-180deg);\n    }\n\n    75% {\n        -webkit-transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );\n        transform: translateX(0px)  translateY(42px)  rotate(-270deg)  scale(0 .5 );\n    }\n\n    100% {\n        -webkit-transform: rotate(-360deg);\n        transform: rotate(-360deg);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-pulse\"></div>\n *\n */\n.sk-spinner-pulse.sk-spinner {\n    width: 40px;\n    height: 40px;\n    margin: 0 auto;\n    background-color: #1ab394;\n    border-radius: 100%;\n    -webkit-animation: sk-pulseScaleOut 1s infinite ease-in-out;\n    animation: sk-pulseScaleOut 1s infinite ease-in-out;\n}\n\n@-webkit-keyframes sk-pulseScaleOut {\n    0% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n        opacity: 0;\n    }\n}\n\n@keyframes sk-pulseScaleOut {\n    0% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    100% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n        opacity: 0;\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-chasing-dots\">\n *      <div class=\"sk-dot1\"></div>\n *      <div class=\"sk-dot2\"></div>\n *    </div>\n *\n */\n.sk-spinner-chasing-dots.sk-spinner {\n    margin: 0 auto;\n    width: 40px;\n    height: 40px;\n    position: relative;\n    text-align: center;\n    -webkit-animation: sk-chasingDotsRotate 2s infinite linear;\n    animation: sk-chasingDotsRotate 2s infinite linear;\n}\n\n.sk-spinner-chasing-dots .sk-dot1, .sk-spinner-chasing-dots .sk-dot2 {\n    width: 60%;\n    height: 60%;\n    display: inline-block;\n    position: absolute;\n    top: 0;\n    background-color: #1ab394;\n    border-radius: 100%;\n    -webkit-animation: sk-chasingDotsBounce 2s infinite ease-in-out;\n    animation: sk-chasingDotsBounce 2s infinite ease-in-out;\n}\n\n.sk-spinner-chasing-dots .sk-dot2 {\n    top: auto;\n    bottom: 0px;\n    -webkit-animation-delay: -1s;\n    animation-delay: -1s;\n}\n\n@-webkit-keyframes sk-chasingDotsRotate {\n    100% {\n        -webkit-transform: rotate(360deg);\n        transform: rotate(360deg);\n    }\n}\n\n@keyframes sk-chasingDotsRotate {\n    100% {\n        -webkit-transform: rotate(360deg);\n        transform: rotate(360deg);\n    }\n}\n\n@-webkit-keyframes sk-chasingDotsBounce {\n    0%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    50% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes sk-chasingDotsBounce {\n    0%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    50% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-three-bounce\">\n *      <div class=\"sk-bounce1\"></div>\n *      <div class=\"sk-bounce2\"></div>\n *      <div class=\"sk-bounce3\"></div>\n *    </div>\n *\n */\n.sk-spinner-three-bounce.sk-spinner {\n    margin: 0 auto;\n    width: 70px;\n    text-align: center;\n}\n\n.sk-spinner-three-bounce div {\n    width: 18px;\n    height: 18px;\n    background-color: #1ab394;\n    border-radius: 100%;\n    display: inline-block;\n    -webkit-animation: sk-threeBounceDelay 1.4s infinite ease-in-out;\n    animation: sk-threeBounceDelay 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.sk-spinner-three-bounce .sk-bounce1 {\n    -webkit-animation-delay: -0.32s;\n    animation-delay: -0.32s;\n}\n\n.sk-spinner-three-bounce .sk-bounce2 {\n    -webkit-animation-delay: -0.16s;\n    animation-delay: -0.16s;\n}\n\n@-webkit-keyframes sk-threeBounceDelay {\n    0%, 80%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    40% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes sk-threeBounceDelay {\n    0%, 80%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    40% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-circle\">\n *      <div class=\"sk-circle1 sk-circle\"></div>\n *      <div class=\"sk-circle2 sk-circle\"></div>\n *      <div class=\"sk-circle3 sk-circle\"></div>\n *      <div class=\"sk-circle4 sk-circle\"></div>\n *      <div class=\"sk-circle5 sk-circle\"></div>\n *      <div class=\"sk-circle6 sk-circle\"></div>\n *      <div class=\"sk-circle7 sk-circle\"></div>\n *      <div class=\"sk-circle8 sk-circle\"></div>\n *      <div class=\"sk-circle9 sk-circle\"></div>\n *      <div class=\"sk-circle10 sk-circle\"></div>\n *      <div class=\"sk-circle11 sk-circle\"></div>\n *      <div class=\"sk-circle12 sk-circle\"></div>\n *    </div>\n *\n */\n.sk-spinner-circle.sk-spinner {\n    margin: 0 auto;\n    width: 22px;\n    height: 22px;\n    position: relative;\n}\n\n.sk-spinner-circle .sk-circle {\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    left: 0;\n    top: 0;\n}\n\n.sk-spinner-circle .sk-circle:before {\n    content: '';\n    display: block;\n    margin: 0 auto;\n    width: 20%;\n    height: 20%;\n    background-color: #1ab394;\n    border-radius: 100%;\n    -webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out;\n    animation: sk-circleBounceDelay 1.2s 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.sk-spinner-circle .sk-circle2 {\n    -webkit-transform: rotate(30deg);\n    -ms-transform: rotate(30deg);\n    transform: rotate(30deg);\n}\n\n.sk-spinner-circle .sk-circle3 {\n    -webkit-transform: rotate(60deg);\n    -ms-transform: rotate(60deg);\n    transform: rotate(60deg);\n}\n\n.sk-spinner-circle .sk-circle4 {\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n}\n\n.sk-spinner-circle .sk-circle5 {\n    -webkit-transform: rotate(120deg);\n    -ms-transform: rotate(120deg);\n    transform: rotate(120deg);\n}\n\n.sk-spinner-circle .sk-circle6 {\n    -webkit-transform: rotate(150deg);\n    -ms-transform: rotate(150deg);\n    transform: rotate(150deg);\n}\n\n.sk-spinner-circle .sk-circle7 {\n    -webkit-transform: rotate(180deg);\n    -ms-transform: rotate(180deg);\n    transform: rotate(180deg);\n}\n\n.sk-spinner-circle .sk-circle8 {\n    -webkit-transform: rotate(210deg);\n    -ms-transform: rotate(210deg);\n    transform: rotate(210deg);\n}\n\n.sk-spinner-circle .sk-circle9 {\n    -webkit-transform: rotate(240deg);\n    -ms-transform: rotate(240deg);\n    transform: rotate(240deg);\n}\n\n.sk-spinner-circle .sk-circle10 {\n    -webkit-transform: rotate(270deg);\n    -ms-transform: rotate(270deg);\n    transform: rotate(270deg);\n}\n\n.sk-spinner-circle .sk-circle11 {\n    -webkit-transform: rotate(300deg);\n    -ms-transform: rotate(300deg);\n    transform: rotate(300deg);\n}\n\n.sk-spinner-circle .sk-circle12 {\n    -webkit-transform: rotate(330deg);\n    -ms-transform: rotate(330deg);\n    transform: rotate(330deg);\n}\n\n.sk-spinner-circle .sk-circle2:before {\n    -webkit-animation-delay: -1.1s;\n    animation-delay: -1.1s;\n}\n\n.sk-spinner-circle .sk-circle3:before {\n    -webkit-animation-delay: -1s;\n    animation-delay: -1s;\n}\n\n.sk-spinner-circle .sk-circle4:before {\n    -webkit-animation-delay: -0.9s;\n    animation-delay: -0.9s;\n}\n\n.sk-spinner-circle .sk-circle5:before {\n    -webkit-animation-delay: -0.8s;\n    animation-delay: -0.8s;\n}\n\n.sk-spinner-circle .sk-circle6:before {\n    -webkit-animation-delay: -0.7s;\n    animation-delay: -0.7s;\n}\n\n.sk-spinner-circle .sk-circle7:before {\n    -webkit-animation-delay: -0.6s;\n    animation-delay: -0.6s;\n}\n\n.sk-spinner-circle .sk-circle8:before {\n    -webkit-animation-delay: -0.5s;\n    animation-delay: -0.5s;\n}\n\n.sk-spinner-circle .sk-circle9:before {\n    -webkit-animation-delay: -0.4s;\n    animation-delay: -0.4s;\n}\n\n.sk-spinner-circle .sk-circle10:before {\n    -webkit-animation-delay: -0.3s;\n    animation-delay: -0.3s;\n}\n\n.sk-spinner-circle .sk-circle11:before {\n    -webkit-animation-delay: -0.2s;\n    animation-delay: -0.2s;\n}\n\n.sk-spinner-circle .sk-circle12:before {\n    -webkit-animation-delay: -0.1s;\n    animation-delay: -0.1s;\n}\n\n@-webkit-keyframes sk-circleBounceDelay {\n    0%, 80%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    40% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n@keyframes sk-circleBounceDelay {\n    0%, 80%, 100% {\n        -webkit-transform: scale(0);\n        transform: scale(0);\n    }\n\n    40% {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-cube-grid\">\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *      <div class=\"sk-cube\"></div>\n *    </div>\n *\n */\n.sk-spinner-cube-grid {\n    /*\n       * Spinner positions\n       * 1 2 3\n       * 4 5 6\n       * 7 8 9\n       */\n}\n\n.sk-spinner-cube-grid.sk-spinner {\n    width: 30px;\n    height: 30px;\n    margin: 0 auto;\n}\n\n.sk-spinner-cube-grid .sk-cube {\n    width: 33%;\n    height: 33%;\n    background-color: #1ab394;\n    float: left;\n    -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;\n    animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(1) {\n    -webkit-animation-delay: 0.2s;\n    animation-delay: 0.2s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(2) {\n    -webkit-animation-delay: 0.3s;\n    animation-delay: 0.3s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(3) {\n    -webkit-animation-delay: 0.4s;\n    animation-delay: 0.4s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(4) {\n    -webkit-animation-delay: 0.1s;\n    animation-delay: 0.1s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(5) {\n    -webkit-animation-delay: 0.2s;\n    animation-delay: 0.2s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(6) {\n    -webkit-animation-delay: 0.3s;\n    animation-delay: 0.3s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(7) {\n    -webkit-animation-delay: 0s;\n    animation-delay: 0s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(8) {\n    -webkit-animation-delay: 0.1s;\n    animation-delay: 0.1s;\n}\n\n.sk-spinner-cube-grid .sk-cube:nth-child(9) {\n    -webkit-animation-delay: 0.2s;\n    animation-delay: 0.2s;\n}\n\n@-webkit-keyframes sk-cubeGridScaleDelay {\n    0%, 70%, 100% {\n        -webkit-transform: scale3D(1, 1, 1);\n        transform: scale3D(1, 1, 1);\n    }\n\n    35% {\n        -webkit-transform: scale3D(0, 0, 1);\n        transform: scale3D(0, 0, 1);\n    }\n}\n\n@keyframes sk-cubeGridScaleDelay {\n    0%, 70%, 100% {\n        -webkit-transform: scale3D(1, 1, 1);\n        transform: scale3D(1, 1, 1);\n    }\n\n    35% {\n        -webkit-transform: scale3D(0, 0, 1);\n        transform: scale3D(0, 0, 1);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-wordpress\">\n *      <span class=\"sk-inner-circle\"></span>\n *    </div>\n *\n */\n.sk-spinner-wordpress.sk-spinner {\n    background-color: #1ab394;\n    width: 30px;\n    height: 30px;\n    border-radius: 30px;\n    position: relative;\n    margin: 0 auto;\n    -webkit-animation: sk-innerCircle 1s linear infinite;\n    animation: sk-innerCircle 1s linear infinite;\n}\n\n.sk-spinner-wordpress .sk-inner-circle {\n    display: block;\n    background-color: #fff;\n    width: 8px;\n    height: 8px;\n    position: absolute;\n    border-radius: 8px;\n    top: 5px;\n    left: 5px;\n}\n\n@-webkit-keyframes sk-innerCircle {\n    0% {\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n    }\n\n    100% {\n        -webkit-transform: rotate(360deg);\n        transform: rotate(360deg);\n    }\n}\n\n@keyframes sk-innerCircle {\n    0% {\n        -webkit-transform: rotate(0);\n        transform: rotate(0);\n    }\n\n    100% {\n        -webkit-transform: rotate(360deg);\n        transform: rotate(360deg);\n    }\n}\n/*\n *  Usage:\n *\n *    <div class=\"sk-spinner sk-spinner-fading-circle\">\n *      <div class=\"sk-circle1 sk-circle\"></div>\n *      <div class=\"sk-circle2 sk-circle\"></div>\n *      <div class=\"sk-circle3 sk-circle\"></div>\n *      <div class=\"sk-circle4 sk-circle\"></div>\n *      <div class=\"sk-circle5 sk-circle\"></div>\n *      <div class=\"sk-circle6 sk-circle\"></div>\n *      <div class=\"sk-circle7 sk-circle\"></div>\n *      <div class=\"sk-circle8 sk-circle\"></div>\n *      <div class=\"sk-circle9 sk-circle\"></div>\n *      <div class=\"sk-circle10 sk-circle\"></div>\n *      <div class=\"sk-circle11 sk-circle\"></div>\n *      <div class=\"sk-circle12 sk-circle\"></div>\n *    </div>\n *\n */\n.sk-spinner-fading-circle.sk-spinner {\n    margin: 0 auto;\n    width: 22px;\n    height: 22px;\n    position: relative;\n}\n\n.sk-spinner-fading-circle .sk-circle {\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    left: 0;\n    top: 0;\n}\n\n.sk-spinner-fading-circle .sk-circle:before {\n    content: '';\n    display: block;\n    margin: 0 auto;\n    width: 18%;\n    height: 18%;\n    background-color: #1ab394;\n    border-radius: 100%;\n    -webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out;\n    animation: sk-circleFadeDelay 1.2s 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.sk-spinner-fading-circle .sk-circle2 {\n    -webkit-transform: rotate(30deg);\n    -ms-transform: rotate(30deg);\n    transform: rotate(30deg);\n}\n\n.sk-spinner-fading-circle .sk-circle3 {\n    -webkit-transform: rotate(60deg);\n    -ms-transform: rotate(60deg);\n    transform: rotate(60deg);\n}\n\n.sk-spinner-fading-circle .sk-circle4 {\n    -webkit-transform: rotate(90deg);\n    -ms-transform: rotate(90deg);\n    transform: rotate(90deg);\n}\n\n.sk-spinner-fading-circle .sk-circle5 {\n    -webkit-transform: rotate(120deg);\n    -ms-transform: rotate(120deg);\n    transform: rotate(120deg);\n}\n\n.sk-spinner-fading-circle .sk-circle6 {\n    -webkit-transform: rotate(150deg);\n    -ms-transform: rotate(150deg);\n    transform: rotate(150deg);\n}\n\n.sk-spinner-fading-circle .sk-circle7 {\n    -webkit-transform: rotate(180deg);\n    -ms-transform: rotate(180deg);\n    transform: rotate(180deg);\n}\n\n.sk-spinner-fading-circle .sk-circle8 {\n    -webkit-transform: rotate(210deg);\n    -ms-transform: rotate(210deg);\n    transform: rotate(210deg);\n}\n\n.sk-spinner-fading-circle .sk-circle9 {\n    -webkit-transform: rotate(240deg);\n    -ms-transform: rotate(240deg);\n    transform: rotate(240deg);\n}\n\n.sk-spinner-fading-circle .sk-circle10 {\n    -webkit-transform: rotate(270deg);\n    -ms-transform: rotate(270deg);\n    transform: rotate(270deg);\n}\n\n.sk-spinner-fading-circle .sk-circle11 {\n    -webkit-transform: rotate(300deg);\n    -ms-transform: rotate(300deg);\n    transform: rotate(300deg);\n}\n\n.sk-spinner-fading-circle .sk-circle12 {\n    -webkit-transform: rotate(330deg);\n    -ms-transform: rotate(330deg);\n    transform: rotate(330deg);\n}\n\n.sk-spinner-fading-circle .sk-circle2:before {\n    -webkit-animation-delay: -1.1s;\n    animation-delay: -1.1s;\n}\n\n.sk-spinner-fading-circle .sk-circle3:before {\n    -webkit-animation-delay: -1s;\n    animation-delay: -1s;\n}\n\n.sk-spinner-fading-circle .sk-circle4:before {\n    -webkit-animation-delay: -0.9s;\n    animation-delay: -0.9s;\n}\n\n.sk-spinner-fading-circle .sk-circle5:before {\n    -webkit-animation-delay: -0.8s;\n    animation-delay: -0.8s;\n}\n\n.sk-spinner-fading-circle .sk-circle6:before {\n    -webkit-animation-delay: -0.7s;\n    animation-delay: -0.7s;\n}\n\n.sk-spinner-fading-circle .sk-circle7:before {\n    -webkit-animation-delay: -0.6s;\n    animation-delay: -0.6s;\n}\n\n.sk-spinner-fading-circle .sk-circle8:before {\n    -webkit-animation-delay: -0.5s;\n    animation-delay: -0.5s;\n}\n\n.sk-spinner-fading-circle .sk-circle9:before {\n    -webkit-animation-delay: -0.4s;\n    animation-delay: -0.4s;\n}\n\n.sk-spinner-fading-circle .sk-circle10:before {\n    -webkit-animation-delay: -0.3s;\n    animation-delay: -0.3s;\n}\n\n.sk-spinner-fading-circle .sk-circle11:before {\n    -webkit-animation-delay: -0.2s;\n    animation-delay: -0.2s;\n}\n\n.sk-spinner-fading-circle .sk-circle12:before {\n    -webkit-animation-delay: -0.1s;\n    animation-delay: -0.1s;\n}\n\n@-webkit-keyframes sk-circleFadeDelay {\n    0%, 39%, 100% {\n        opacity: 0;\n    }\n\n    40% {\n        opacity: 1;\n    }\n}\n\n@keyframes sk-circleFadeDelay {\n    0%,39%,100% {\n        opacity: 0;\n    }\n\n    40% {\n        opacity: 1;\n    }\n}\n\nbody.rtls {\n    /* Theme config */\n}\n\nbody.rtls #page-wrapper {\n    margin: 0 220px 0 0;\n}\n\nbody.rtls .nav-second-level li a {\n    padding: 7px 35px 7px 10px;\n}\n\nbody.rtls .ibox-title h5 {\n    float: right;\n}\n\nbody.rtls .pull-right {\n    float: left !important;\n}\n\nbody.rtls .pull-left {\n    float: right !important;\n}\n\nbody.rtls .ibox-tools {\n    float: left;\n}\n\nbody.rtls .stat-percent {\n    float: left;\n}\n\nbody.rtls .navbar-right {\n    float: left !important;\n}\n\nbody.rtls .navbar-top-links li:last-child {\n    margin-left: 40px;\n    margin-right: 0;\n}\n\nbody.rtls .minimalize-styl-2 {\n    float: right;\n    margin: 14px 20px 5px 5px;\n}\n\nbody.rtls .feed-element>.pull-left {\n    margin-left: 10px;\n    margin-right: 0;\n}\n\nbody.rtls .timeline-item .date {\n    text-align: left;\n}\n\nbody.rtls .timeline-item .date i {\n    left: 0;\n    right: auto;\n}\n\nbody.rtls .timeline-item .content {\n    border-right: 1px solid #e7eaec;\n    border-left: none;\n}\n\nbody.rtls .toast-close-button {\n    float: left;\n}\n\nbody.rtls #toast-container>.toast:before {\n    margin: auto -1.5em auto 0.5em;\n}\n\nbody.rtls #toast-container>div {\n    padding: 15px 50px 15px 15px;\n}\n\nbody.rtls .center-orientation .vertical-timeline-icon i {\n    margin-left: 0;\n    margin-right: -12px;\n}\n\nbody.rtls .vertical-timeline-icon i {\n    right: 50%;\n    left: auto;\n    margin-left: auto;\n    margin-right: -12px;\n}\n\nbody.rtls .file-box {\n    float: right;\n}\n\nbody.rtls ul.notes li {\n    float: right;\n}\n\nbody.rtls .chat-users, body.rtls .chat-statistic {\n    margin-right: -30px;\n    margin-left: auto;\n}\n\nbody.rtls .dropdown-menu>li>a {\n    text-align: right;\n}\n\nbody.rtls .b-r {\n    border-left: 1px solid #e7eaec;\n    border-right: none;\n}\n\nbody.rtls .dd-list .dd-list {\n    padding-right: 30px;\n    padding-left: 0;\n}\n\nbody.rtls .dd-item>button {\n    float: right;\n}\n\nbody.rtls .skin-setttings {\n    margin-right: 40px;\n    margin-left: 0;\n}\n\nbody.rtls .skin-setttings {\n    direction: ltr;\n}\n\nbody.rtls .footer.fixed {\n    margin-right: 220px;\n    margin-left: 0;\n}\n\n@media ( max-width : 992px) {\n    body.rtls .chat-users, body.rtls .chat-statistic {\n        margin-right: 0px;\n    }\n}\n\nbody.rtls.mini-navbar .footer.fixed, body.body-small.mini-navbar .footer.fixed {\n    margin: 0 70px 0 0;\n}\n\nbody.rtls.mini-navbar.fixed-sidebar .footer.fixed, body.body-small.mini-navbar .footer.fixed {\n    margin: 0 0 0 0;\n}\n\nbody.rtls.top-navigation .navbar-toggle {\n    float: right;\n    margin-left: 15px;\n    margin-right: 15px;\n}\n\n.body-small.rtls.top-navigation .navbar-header {\n    float: none;\n}\n\nbody.rtls.top-navigation #page-wrapper {\n    margin: 0;\n}\n\nbody.rtls.mini-navbar #page-wrapper {\n    margin: 0 70px 0 0;\n}\n\nbody.rtls.mini-navbar.fixed-sidebar #page-wrapper {\n    margin: 0 0 0 0;\n}\n\nbody.rtls.body-small.fixed-sidebar.mini-navbar #page-wrapper {\n    margin: 0 220px 0 0;\n}\n\nbody.rtls.body-small.fixed-sidebar.mini-navbar .navbar-static-side {\n    width: 220px;\n}\n\n.body-small.rtls .navbar-fixed-top {\n    margin-right: 0px;\n}\n\n.body-small.rtls .navbar-header {\n    float: right;\n}\n\nbody.rtls .navbar-top-links li:last-child {\n    margin-left: 20px;\n}\n\nbody.rtls .top-navigation #page-wrapper, body.rtls.mini-navbar .top-navigation #page-wrapper,  body.rtls.mini-navbar.top-navigation #page-wrapper {\n    margin: 0;\n}\n\nbody.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed {\n    margin: 0;\n}\n\n@media ( max-width : 768px) {\n    body.rtls .navbar-top-links li:last-child {\n        margin-left: 20px;\n    }\n\n    .body-small.rtls #page-wrapper {\n        position: inherit;\n        margin: 0 0 0 0px;\n        min-height: 1000px;\n    }\n\n    .body-small.rtls .navbar-static-side {\n        display: none;\n        z-index: 2001;\n        position: absolute;\n        width: 70px;\n    }\n\n    .body-small.rtls.mini-navbar .navbar-static-side {\n        display: block;\n    }\n\n    .rtls.fixed-sidebar.body-small .navbar-static-side {\n        display: none;\n        z-index: 2001;\n        position: fixed;\n        width: 220px;\n    }\n\n    .rtls.fixed-sidebar.body-small.mini-navbar .navbar-static-side {\n        display: block;\n    }\n}\n\n.rtls .ltr-support {\n    direction: ltr;\n}\n/*\n *\n *   This is style for skin config\n *   Use only in demo theme\n *\n*/\n.skin-setttings .title {\n    background: #efefef;\n    text-align: center;\n    text-transform: uppercase;\n    font-weight: 600;\n    display: block;\n    padding: 10px 15px;\n    font-size: 12px;\n}\n\n.setings-item {\n    padding: 10px 30px;\n}\n\n.setings-item.nb {\n    border: none;\n}\n\n.setings-item.skin {\n    text-align: center;\n}\n\n.setings-item .switch {\n    float: right;\n}\n\n.skin-name a {\n    text-transform: uppercase;\n}\n\n.setings-item a {\n    color: #fff;\n}\n\n.default-skin, .blue-skin, .ultra-skin, .yellow-skin {\n    text-align: center;\n}\n\n.default-skin {\n    font-weight: 600;\n    background: #1ab394;\n}\n\n.default-skin:hover {\n    background: #199d82;\n}\n\n.blue-skin {\n    font-weight: 600;\n    background: url(\"patterns/header-profile-skin-1.png\") repeat scroll 0 0;\n}\n\n.blue-skin:hover {\n    background: #0d8ddb;\n}\n\n.yellow-skin {\n    font-weight: 600;\n    background: url(\"patterns/header-profile-skin-3.png\") repeat scroll 0  100%;\n}\n\n.yellow-skin:hover {\n    background: #ce8735;\n}\n\n.content-tabs {\n    border-bottom: solid 2px #2f4050;\n}\n\n.page-tabs a {\n    color: #999;\n}\n\n.page-tabs a i {\n    color: #ccc;\n}\n\n.page-tabs a.active {\n    background: #2f4050;\n    color: #a7b1c2;\n}\n\n.page-tabs a.active:hover, .page-tabs a.active i:hover {\n    background: #293846;\n    color: #fff;\n}\n/*\n *\n *   SKIN 1 - H+ - 后台主题UI框架\n *   NAME - Blue light\n *\n*/\n.skin-1 .minimalize-styl-2 {\n    margin: 14px 5px 5px 30px;\n}\n\n.skin-1 .navbar-top-links li:last-child {\n    margin-right: 30px;\n}\n\n.skin-1.fixed-nav .minimalize-styl-2 {\n    margin: 14px 5px 5px 15px;\n}\n\n.skin-1 .spin-icon {\n    background: #0e9aef !important;\n}\n\n.skin-1 .nav-header {\n    background: #0e9aef;\n    background: url('patterns/header-profile-skin-1.png');\n}\n\n.skin-1.mini-navbar .nav-second-level {\n    background: #3e495f;\n}\n\n.skin-1 .breadcrumb {\n    background: transparent;\n}\n\n.skin-1 .page-heading {\n    border: none;\n}\n\n.skin-1 .nav>li.active {\n    background: #3a4459;\n}\n\n.skin-1 .nav>li>a {\n    color: #9ea6b9;\n}\n\n.skin-1 .nav>li.active>a {\n    color: #fff;\n}\n\n.skin-1 .navbar-minimalize {\n    background: #0e9aef;\n    border-color: #0e9aef;\n}\n\nbody.skin-1 {\n    background: #3e495f;\n}\n\n.skin-1 .navbar-static-top {\n    background: #ffffff;\n}\n\n.skin-1 .dashboard-header {\n    background: transparent;\n    border-bottom: none !important;\n    border-top: none;\n    padding: 20px 30px 10px 30px;\n}\n\n.fixed-nav.skin-1 .navbar-fixed-top {\n    background: #fff;\n}\n\n.skin-1 .wrapper-content {\n    padding: 30px 15px;\n}\n\n.skin-1 #page-wrapper {\n    background: #f4f6fa;\n}\n\n.skin-1 .ibox-title, .skin-1 .ibox-content {\n    border-width: 1px;\n}\n\n.skin-1 .ibox-content:last-child {\n    border-style: solid solid solid solid;\n}\n\n.skin-1 .nav>li.active {\n    border: none;\n}\n\n.skin-1 .nav-header {\n    padding: 35px 25px 25px 25px;\n}\n\n.skin-1 .nav-header a.dropdown-toggle {\n    color: #fff;\n    margin-top: 10px;\n}\n\n.skin-1 .nav-header a.dropdown-toggle .text-muted {\n    color: #fff;\n    opacity: 0.8;\n}\n\n.skin-1 .profile-element {\n    text-align: center;\n}\n\n.skin-1 .img-circle {\n    border-radius: 5px;\n}\n\n.skin-1 .navbar-default .nav>li>a:hover, .skin-1 .navbar-default .nav>li>a:focus {\n    background: #39aef5;\n    color: #fff;\n}\n\n.skin-1 .nav.nav-tabs>li.active>a {\n    color: #555;\n}\n\n.skin-1 .content-tabs {\n    border-bottom: solid 2px #39aef5;\n}\n\n.skin-1 .nav.nav-tabs>li.active {\n    background: transparent;\n}\n\n.skin-1 .page-tabs a.active {\n    background: #39aef5;\n    color: #fff;\n}\n\n.skin-1 .page-tabs a.active:hover, .skin-1 .page-tabs a.active i:hover {\n    background: #0e9aef;\n    color: #fff;\n}\n/*\n *\n *   SKIN 3 - H+ - 后台主题UI框架\n *   NAME - Yellow/purple\n *\n*/\n.skin-3 .minimalize-styl-2 {\n    margin: 14px 5px 5px 30px;\n}\n\n.skin-3 .navbar-top-links li:last-child {\n    margin-right: 30px;\n}\n\n.skin-3.fixed-nav .minimalize-styl-2 {\n    margin: 14px 5px 5px 15px;\n}\n\n.skin-3 .spin-icon {\n    background: #ecba52 !important;\n}\n\nbody.boxed-layout.skin-3 #wrapper {\n    background: #3e2c42;\n}\n\n.skin-3 .nav-header {\n    background: #ecba52;\n    background: url('patterns/header-profile-skin-3.png');\n}\n\n.skin-3.mini-navbar .nav-second-level {\n    background: #3e2c42;\n}\n\n.skin-3 .breadcrumb {\n    background: transparent;\n}\n\n.skin-3 .page-heading {\n    border: none;\n}\n\n.skin-3 .nav>li.active {\n    background: #38283c;\n}\n\n.fixed-nav.skin-3 .navbar-fixed-top {\n    background: #fff;\n}\n\n.skin-3 .nav>li>a {\n    color: #948b96;\n}\n\n.skin-3 .nav>li.active>a {\n    color: #fff;\n}\n\n.skin-3 .navbar-minimalize {\n    background: #ecba52;\n    border-color: #ecba52;\n}\n\nbody.skin-3 {\n    background: #3e2c42;\n}\n\n.skin-3 .navbar-static-top {\n    background: #ffffff;\n}\n\n.skin-3 .dashboard-header {\n    background: transparent;\n    border-bottom: none !important;\n    border-top: none;\n    padding: 20px 30px 10px 30px;\n}\n\n.skin-3 .wrapper-content {\n    padding: 30px 15px;\n}\n\n.skin-3 #page-wrapper {\n    background: #f4f6fa;\n}\n\n.skin-3 .ibox-title, .skin-3 .ibox-content {\n    border-width: 1px;\n}\n\n.skin-3 .ibox-content:last-child {\n    border-style: solid solid solid solid;\n}\n\n.skin-3 .nav>li.active {\n    border: none;\n}\n\n.skin-3 .nav-header {\n    padding: 35px 25px 25px 25px;\n}\n\n.skin-3 .nav-header a.dropdown-toggle {\n    color: #fff;\n    margin-top: 10px;\n}\n\n.skin-3 .nav-header a.dropdown-toggle .text-muted {\n    color: #fff;\n    opacity: 0.8;\n}\n\n.skin-3 .profile-element {\n    text-align: center;\n}\n\n.skin-3 .img-circle {\n    border-radius: 5px;\n}\n\n.skin-3 .navbar-default .nav>li>a:hover, .skin-3 .navbar-default .nav>li>a:focus {\n    background: #38283c;\n    color: #fff;\n}\n\n.skin-3 .nav.nav-tabs>li.active>a {\n    color: #555;\n}\n\n.skin-3 .nav.nav-tabs>li.active {\n    background: transparent;\n}\n\n.skin-3 .content-tabs {\n    border-bottom: solid 2px #3e2c42;\n}\n\n.skin-3 .nav.nav-tabs>li.active {\n    background: transparent;\n}\n\n.skin-3 .page-tabs a.active {\n    background: #3e2c42;\n    color: #fff;\n}\n\n.skin-3 .page-tabs a.active:hover, .skin-3 .page-tabs a.active i:hover {\n    background: #38283c;\n    color: #fff;\n}\n\n@media ( min-width : 768px) {\n    .navbar-top-links .dropdown-messages, .navbar-top-links .dropdown-tasks,  .navbar-top-links .dropdown-alerts {\n        margin-left: auto;\n    }\n}\n\n@media ( max-width : 768px) {\n    body.fixed-sidebar .navbar-static-side {\n        display: none;\n    }\n\n    body.fixed-sidebar.mini-navbar .navbar-static-side {\n        width: 70px;\n    }\n\n    .lock-word {\n        display: none;\n    }\n\n    .navbar-form-custom {\n        display: none;\n    }\n\n    .navbar-header {\n        display: inline;\n        float: left;\n    }\n\n    .sidebard-panel {\n        z-index: 2;\n        position: relative;\n        width: auto;\n        min-height: 100% !important;\n    }\n\n    .sidebar-content .wrapper {\n        padding-right: 0px;\n        z-index: 1;\n    }\n\n    .fixed-sidebar.body-small .navbar-static-side {\n        display: none;\n        z-index: 2001;\n        position: fixed;\n        width: 220px;\n    }\n\n    .fixed-sidebar.body-small.mini-navbar .navbar-static-side {\n        display: block;\n    }\n\n    .ibox-tools {\n        float: none;\n        text-align: right;\n        display: block;\n    }\n\n    .content-tabs {\n        display: none;\n    }\n\n    #content-main {\n        height: calc(100% - 100px);\n    }\n\n    .fixed-nav #content-main {\n        height: calc(100% - 38px);\n    }\n}\n\n.navbar-static-side {\n    background: #2f4050;\n}\n\n.nav-close {\n    padding: 10px;\n    display: block;\n    position: absolute;\n    right: 5px;\n    top: 5px;\n    font-size: 1.4em;\n    cursor: pointer;\n    z-index: 10;\n    display: none;\n    color: rgba(255, 255, 255, .3);\n}\n\n@media ( max-width : 350px) {\n    body.fixed-sidebar.mini-navbar .navbar-static-side {\n        width: 0;\n    }\n\n    .nav-close {\n        display: block;\n    }\n\n    #page-wrapper {\n        margin-left: 0 !important;\n    }\n\n    .timeline-item .date {\n        text-align: left;\n        width: 110px;\n        position: relative;\n        padding-top: 30px;\n    }\n\n    .timeline-item .date i {\n        position: absolute;\n        top: 0;\n        left: 15px;\n        padding: 5px;\n        width: 30px;\n        text-align: center;\n        border: 1px solid #e7eaec;\n        background: #f8f8f8;\n    }\n\n    .timeline-item .content {\n        border-left: none;\n        border-top: 1px solid #e7eaec;\n        padding-top: 10px;\n        min-height: 100px;\n    }\n\n    .nav.navbar-top-links li.dropdown {\n        display: none;\n    }\n\n    .ibox-tools {\n        float: none;\n        text-align: left;\n        display: inline-block;\n    }\n}\n/*JQGRID*/\n.ui-jqgrid-titlebar {\n    height: 40px;\n    line-height: 24px;\n    color: #676a6c;\n    background-color: #F9F9F9;\n    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n\n.ui-jqgrid .ui-jqgrid-title {\n    float: left;\n    margin-left: 5px;\n    font-weight: 700;\n}\n\n.ui-jqgrid .ui-jqgrid-titlebar {\n    position: relative;\n    border-left: 0px solid;\n    border-right: 0px solid;\n    border-top: 0px solid;\n}\n/* Social feed */\n.social-feed-separated .social-feed-box {\n    margin-left: 62px;\n}\n\n.social-feed-separated .social-avatar {\n    float: left;\n    padding: 0;\n}\n\n.social-feed-separated .social-avatar img {\n    width: 52px;\n    height: 52px;\n    border: 1px solid #e7eaec;\n}\n\n.social-feed-separated .social-feed-box .social-avatar {\n    padding: 15px 15px 0 15px;\n    float: none;\n}\n\n.social-feed-box {\n    /*padding: 15px;*/\n    border: 1px solid #e7eaec;\n    background: #fff;\n    margin-bottom: 15px;\n}\n\n.article .social-feed-box {\n    margin-bottom: 0;\n    border-bottom: none;\n}\n\n.article .social-feed-box:last-child {\n    margin-bottom: 0;\n    border-bottom: 1px solid #e7eaec;\n}\n\n.article .social-feed-box p {\n    font-size: 13px;\n    line-height: 18px;\n}\n\n.social-action {\n    margin: 15px;\n}\n\n.social-avatar {\n    padding: 15px 15px 0 15px;\n}\n\n.social-comment .social-comment {\n    margin-left: 45px;\n}\n\n.social-avatar img {\n    height: 40px;\n    width: 40px;\n    margin-right: 10px;\n}\n\n.social-avatar .media-body a {\n    font-size: 14px;\n    display: block;\n}\n\n.social-body {\n    padding: 15px;\n}\n\n.social-body img {\n    margin-bottom: 10px;\n}\n\n.social-footer {\n    border-top: 1px solid #e7eaec;\n    padding: 10px 15px;\n    background: #f9f9f9;\n}\n\n.social-footer .social-comment img {\n    width: 32px;\n    margin-right: 10px;\n}\n\n.social-comment:first-child {\n    margin-top: 0;\n}\n\n.social-comment {\n    margin-top: 15px;\n}\n\n.social-comment textarea {\n    font-size: 12px;\n}\n\n.checkbox input[type=checkbox], .checkbox-inline input[type=checkbox],  .radio input[type=radio], .radio-inline input[type=radio] {\n    /* margin-top: -4px; */\n}\n\n/* Only demo */\n@media ( max-width : 1000px) {\n    .welcome-message {\n        display: none;\n    }\n}\n/* ECHARTS  */\n.echarts {\n    height: 240px;\n}\n\n.checkbox-inline, .radio-inline, .checkbox-inline+.checkbox-inline,  .radio-inline+.radio-inline {\n    margin: 0 15px 0 0;\n    font-size: 14px;\n}\n\n.navbar-toggle {\n    background-color: #fff;\n}\n\n.J_menuTab {\n    -webkit-transition: all .3s ease-out 0s;\n    transition: all .3s ease-out 0s;\n}\n\n::-webkit-scrollbar-track {\n    background-color: #F5F5F5;\n}\n\n::-webkit-scrollbar {\n    width: 6px;\n    background-color: #F5F5F5;\n}\n\n::-webkit-scrollbar-thumb {\n    background-color: #999;\n}\n/*GO HOME*/\n.gohome {\n    position: fixed;\n    top: 20px;\n    right: 20px;\n    z-index: 100;\n}\n\n.gohome a {\n    height: 38px;\n    width: 38px;\n    display: block;\n    background: #2f4050;\n    padding: 9px 8px;\n    text-align: center;\n    color: #fff;\n    border-radius: 50%;\n    opacity: .5;\n}\n\n.gohome a:hover {\n    opacity: 1;\n}\n\n@media only screen and (-webkit-min-device-pixel-ratio : 2) {\n    #content-main {\n        -webkit-overflow-scrolling: touch;\n    }\n}\n\n.navbar-header {\n    width: 60%;\n}\n\n.bs-glyphicons {\n    margin: 0 -10px 20px;\n    overflow: hidden\n}\n\n.bs-glyphicons-list {\n    padding-left: 0;\n    list-style: none\n}\n\n.bs-glyphicons li {\n    float: left;\n    width: 25%;\n    height: 115px;\n    padding: 10px;\n    font-size: 10px;\n    line-height: 1.4;\n    text-align: center;\n    background-color: #f9f9f9;\n    border: 1px solid #fff\n}\n\n.bs-glyphicons .glyphicon {\n    margin-top: 5px;\n    margin-bottom: 10px;\n    font-size: 24px\n}\n\n.bs-glyphicons .glyphicon-class {\n    display: block;\n    text-align: center;\n    word-wrap: break-word\n}\n\n.bs-glyphicons li:hover {\n    color: #fff;\n    background-color: #1ab394;\n}\n\n@media ( min-width : 768px) {\n    .bs-glyphicons {\n        margin-right: 0;\n        margin-left: 0\n    }\n\n    .bs-glyphicons li {\n        width: 12.5%;\n        font-size: 12px\n    }\n}\n\n.t-bar {\n    padding-bottom: 10px;\n}\n.nopadding{\n    padding:0;\n}\n\n/*编辑器按钮样式冲突*/\n.note-editor .btn-default {\n    color: #333333!important;\n    background-color: #ffffff!important;\n    border-color: #cccccc!important;\n}\n\n"
  },
  {
    "path": "src/main/resources/static/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' : '/activity',\n};\n"
  },
  {
    "path": "src/main/resources/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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        \t//window.location.href = \"./\";\n            var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n            parent.layer.close(index);\n            parent.reLoad();\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    \t\t//window.location.href = \"./\";\n            var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n            parent.layer.close(index);\n            parent.reLoad();\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\n        // Update\n        $http({    method: 'PUT',\n            data: params,\n            ignoreErrors: true,\n            headers: {'Accept': 'application/json',\n                      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},\n            transformRequest: 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": "src/main/resources/static/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": "src/main/resources/static/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';\n    },\n\n    getStencilSet: function() {\n        return ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now();\n    },\n\n    putModel: function(modelId) {\n        return ACTIVITI.CONFIG.contextRoot + '/model/' + modelId + '/save';\n    }\n};"
  },
  {
    "path": "src/main/resources/static/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: 180px;\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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/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": "src/main/resources/static/editor-app/editor/i18n/translation_de.js",
    "content": "/**\n * @author 郑保乐\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": "src/main/resources/static/editor-app/editor/i18n/translation_en_us.js",
    "content": "/**\n * @author 郑保乐\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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/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 郑保乐\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 郑保乐\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 郑保乐\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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/editor-app/i18n/en.json",
    "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": "src/main/resources/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": "src/main/resources/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 common 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 common 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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/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": "src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author 郑保乐\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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.gitignore",
    "content": "node_modules\n.DS_Store\n"
  },
  {
    "path": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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 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\"),\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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js",
    "content": "function implement() {\n    throw 'Not implemented';\n}"
  },
  {
    "path": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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 common 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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/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": "src/main/resources/static/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 common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn core_concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlength = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\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 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\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 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\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 common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ){\n\tjQuery.fn[ type ] = function( fn ){\n\t\treturn this.on( type, fn );\n\t};\n});\n\njQuery.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": "src/main/resources/static/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": "src/main/resources/static/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 common 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": "src/main/resources/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/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": "src/main/resources/static/js/ajax-util.js",
    "content": "// (function($) {\n//     // 首先备份下jquery的ajax方法\n//     var _ajax = $.ajax;\n//\n//     // 重写jquery的ajax方法\n//     $.ajax = function(options) {\n//         // 备份opt中error和success方法\n//         var callback = {\n//             \"beforeSend\" : function(XHR) {\n//             },\n//             \"complete\" : function(XHR, TS) {\n//             },\n//             \"error\" : function(XMLHttpRequest, textStatus, errorThrown) {\n//             },\n//             \"success\" : function(data, textStatus) {\n//             }\n//         }\n//\n//         // 判断参数中是否有beforeSend回调函数\n//         if (options.beforeSend) {\n//             callback.beforeSend = options.beforeSend;\n//         }\n//\n//         // 判断参数中是否有complete回调函数\n//         if (options.complete) {\n//             callback.complete = options.complete;\n//         }\n//\n//         // 判断参数中是否有error回调函数\n//         if (options.error) {\n//             callback.error = options.error;\n//         }\n//\n//         // 判断参数中是否有success回调函数\n//         if (options.success) {\n//             callback.success = options.success;\n//         }\n//\n//         // 扩展增强处理\n//         var _opt = $.extend(options, {\n//             error : function(XMLHttpRequest, textStatus, errorThrown) {\n//                 // 错误方法增强处理\n//                 callback.error(XMLHttpRequest, textStatus, errorThrown);\n//             },\n//             success : function(data,textStatus) {\n//                 // 成功回调方法增强处理\n//                 if(403==data.code){\n//                     parent.location.href = '/login';\n//                 }\n//                 callback.success(data);\n//             },\n//             beforeSend : function(XHR) {\n//                 // 提交前回调方法\n//                 var index = layer.load(1, {\n//                     shade: [0.1,'#fff'] //0.1透明度的白色背景\n//                 });\n//                 callback.beforeSend(XHR);\n//             },\n//             complete : function(XHR, TS) {\n//                 // 请求完成后回调函数 (请求成功或失败之后均调用)。\n//                 layer.closeAll('loading');\n//                 callback.complete(XHR, TS);\n//             }\n//         });\n//\n//         // 返回重写的ajax\n//         return _ajax(_opt);\n//     };\n// })(jQuery);\n//\n//\n//\n//\n\n\n//全站ajax加载提示\n(function ($) {\n    $(document).ajaxStart(function () {\n        var index = layer.load(1, {\n            shade: [0.1, '#fff'] //0.1透明度的白色背景\n        });\n    });\n    $(document).ajaxStop(function () {\n        layer.closeAll('loading');\n    });\n    //登录过期，shiro返回登录页面\n    $.ajaxSetup({\n        complete: function (xhr, status,dataType) {\n            if('text/html;charset=UTF-8'==xhr.getResponseHeader('Content-Type')){\n                top.location.href = '/login';\n            }\n        }\n    });\n})(jQuery);\n\n\n\n\n\n"
  },
  {
    "path": "src/main/resources/static/js/app.js",
    "content": "//自定义js\n\n//公共配置\n\n\n$(document).ready(function () {\n\n    // MetsiMenu\n    $('#side-menu').metisMenu();\n\n    // 打开右侧边栏\n    $('.right-sidebar-toggle').click(function () {\n        $('#right-sidebar').toggleClass('sidebar-open');\n    });\n\n    // 右侧边栏使用slimscroll\n    $('.sidebar-container').slimScroll({\n        height: '100%',\n        railOpacity: 0.4,\n        wheelStep: 10\n    });\n\n    // 打开聊天窗口\n    $('.open-small-chat').click(function () {\n        $(this).children().toggleClass('fa-comments').toggleClass('fa-remove');\n        $('.small-chat-box').toggleClass('active');\n    });\n\n    // 聊天窗口使用slimscroll\n    $('.small-chat-box .content').slimScroll({\n        height: '234px',\n        railOpacity: 0.4\n    });\n\n    // Small todo handler\n    $('.check-link').click(function () {\n        var button = $(this).find('i');\n        var label = $(this).next('span');\n        button.toggleClass('fa-check-square').toggleClass('fa-square-o');\n        label.toggleClass('todo-completed');\n        return false;\n    });\n\n    //固定菜单栏\n    $(function () {\n        $('.sidebar-collapse').slimScroll({\n            height: '100%',\n            railOpacity: 0.9,\n            alwaysVisible: false\n        });\n    });\n\n\n    // 菜单切换\n    $('.navbar-minimalize').click(function () {\n        $(\"body\").toggleClass(\"mini-navbar\");\n        SmoothlyMenu();\n    });\n\n\n    // 侧边栏高度\n    function fix_height() {\n        var heightWithoutNavbar = $(\"body > #wrapper\").height() - 61;\n        $(\".sidebard-panel\").css(\"min-height\", heightWithoutNavbar + \"px\");\n    }\n    fix_height();\n\n    $(window).bind(\"load resize click scroll\", function () {\n        if (!$(\"body\").hasClass('body-small')) {\n            fix_height();\n        }\n    });\n\n    //侧边栏滚动\n    $(window).scroll(function () {\n        if ($(window).scrollTop() > 0 && !$('body').hasClass('fixed-nav')) {\n            $('#right-sidebar').addClass('sidebar-top');\n        } else {\n            $('#right-sidebar').removeClass('sidebar-top');\n        }\n    });\n\n    $('.full-height-scroll').slimScroll({\n        height: '100%'\n    });\n\n    $('#side-menu>li').click(function () {\n        if ($('body').hasClass('mini-navbar')) {\n            NavToggle();\n        }\n    });\n    $('#side-menu>li li a').click(function () {\n        if ($(window).width() < 769) {\n            NavToggle();\n        }\n    });\n\n    $('.nav-close').click(NavToggle);\n\n    //ios浏览器兼容性处理\n    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {\n        $('#content-main').css('overflow-y', 'auto');\n    }\n\n});\n\n$(window).bind(\"load resize\", function () {\n    if ($(this).width() < 769) {\n        $('body').addClass('mini-navbar');\n        $('.navbar-static-side').fadeIn();\n    }\n});\n\nfunction NavToggle() {\n    $('.navbar-minimalize').trigger('click');\n}\n\nfunction SmoothlyMenu() {\n    if (!$('body').hasClass('mini-navbar')) {\n        $('#side-menu').hide();\n        setTimeout(\n            function () {\n                $('#side-menu').fadeIn(500);\n            }, 100);\n    } else if ($('body').hasClass('fixed-sidebar')) {\n        $('#side-menu').hide();\n        setTimeout(\n            function () {\n                $('#side-menu').fadeIn(500);\n            }, 300);\n    } else {\n        $('#side-menu').removeAttr('style');\n    }\n}\n\n\n//主题设置\n$(function () {\n\n    // 顶部菜单固定\n    $('#fixednavbar').click(function () {\n        if ($('#fixednavbar').is(':checked')) {\n            $(\".navbar-static-top\").removeClass('navbar-static-top').addClass('navbar-fixed-top');\n            $(\"body\").removeClass('boxed-layout');\n            $(\"body\").addClass('fixed-nav');\n            $('#boxedlayout').prop('checked', false);\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"boxedlayout\", 'off');\n            }\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"fixednavbar\", 'on');\n            }\n        } else {\n            $(\".navbar-fixed-top\").removeClass('navbar-fixed-top').addClass('navbar-static-top');\n            $(\"body\").removeClass('fixed-nav');\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"fixednavbar\", 'off');\n            }\n        }\n    });\n\n\n    // 收起左侧菜单\n    $('#collapsemenu').click(function () {\n        if ($('#collapsemenu').is(':checked')) {\n            $(\"body\").addClass('mini-navbar');\n            SmoothlyMenu();\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"collapse_menu\", 'on');\n            }\n\n        } else {\n            $(\"body\").removeClass('mini-navbar');\n            SmoothlyMenu();\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"collapse_menu\", 'off');\n            }\n        }\n    });\n\n    // 固定宽度\n    $('#boxedlayout').click(function () {\n        if ($('#boxedlayout').is(':checked')) {\n            $(\"body\").addClass('boxed-layout');\n            $('#fixednavbar').prop('checked', false);\n            $(\".navbar-fixed-top\").removeClass('navbar-fixed-top').addClass('navbar-static-top');\n            $(\"body\").removeClass('fixed-nav');\n            if (localStorageSupport) {\n                localStorage.setItem(\"fixednavbar\", 'off');\n            }\n\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"boxedlayout\", 'on');\n            }\n        } else {\n            $(\"body\").removeClass('boxed-layout');\n\n            if (localStorageSupport) {\n                localStorage.setItem(\"boxedlayout\", 'off');\n            }\n        }\n    });\n\n    // 默认主题\n    $('.s-skin-0').click(function () {\n        $(\"body\").removeClass(\"skin-1\");\n        $(\"body\").removeClass(\"skin-2\");\n        $(\"body\").removeClass(\"skin-3\");\n        return false;\n    });\n\n    // 蓝色主题\n    $('.s-skin-1').click(function () {\n        $(\"body\").removeClass(\"skin-2\");\n        $(\"body\").removeClass(\"skin-3\");\n        $(\"body\").addClass(\"skin-1\");\n        return false;\n    });\n\n    // 黄色主题\n    $('.s-skin-3').click(function () {\n        $(\"body\").removeClass(\"skin-1\");\n        $(\"body\").removeClass(\"skin-2\");\n        $(\"body\").addClass(\"skin-3\");\n        return false;\n    });\n\n    if (localStorageSupport) {\n        var collapse = localStorage.getItem(\"collapse_menu\");\n        var fixednavbar = localStorage.getItem(\"fixednavbar\");\n        var boxedlayout = localStorage.getItem(\"boxedlayout\");\n\n        if (collapse == 'on') {\n            $('#collapsemenu').prop('checked', 'checked')\n        }\n        if (fixednavbar == 'on') {\n            $('#fixednavbar').prop('checked', 'checked')\n        }\n        if (boxedlayout == 'on') {\n            $('#boxedlayout').prop('checked', 'checked')\n        }\n    }\n\n    if (localStorageSupport) {\n\n        var collapse = localStorage.getItem(\"collapse_menu\");\n        var fixednavbar = localStorage.getItem(\"fixednavbar\");\n        var boxedlayout = localStorage.getItem(\"boxedlayout\");\n\n        var body = $('body');\n\n        if (collapse == 'on') {\n            if (!body.hasClass('body-small')) {\n                body.addClass('mini-navbar');\n            }\n        }\n\n        if (fixednavbar == 'on') {\n            $(\".navbar-static-top\").removeClass('navbar-static-top').addClass('navbar-fixed-top');\n            body.addClass('fixed-nav');\n        }\n\n        if (boxedlayout == 'on') {\n            body.addClass('boxed-layout');\n        }\n    }\n});\n\n//判断浏览器是否支持html5本地存储\nfunction localStorageSupport() {\n    return (('localStorage' in window) && window['localStorage'] !== null)\n}\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/SalaryAdjustment/form.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\tvar procDefId = $(\"#procDefId\").val();\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl :\"/act/salary/start/\"+procDefId,\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tlaryer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"保存成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\t\t}\n\t});\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/model/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction getCheckedRoles() {\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction save() {\n\t$(\"#roleIds\").val(getCheckedRoles());\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/user/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2,\n\t\t\t\tremote : {\n\t\t\t\t\turl : \"/sys/user/exit\", // 后台处理程序\n\t\t\t\t\ttype : \"post\", // 数据发送方式\n\t\t\t\t\tdataType : \"json\", // 接受数据格式\n\t\t\t\t\tdata : { // 要传递的数据\n\t\t\t\t\t\tusername : function() {\n\t\t\t\t\t\t\treturn $(\"#username\").val();\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\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\",\n\t\t\t\tremote : icon + \"用户名已经存在\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\n\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/model/edit.js",
    "content": "// 以下为官方示例\n$().ready(function() {\n\tvalidateRule();\n\t// $(\"#signupForm\").validate();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$(\"#roleIds\").val(getCheckedRoles());\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/user/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\talert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction getCheckedRoles() {\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction setCheckedRoles() {\n\tvar roleIds = $(\"#roleIds\").val();\n\talert(roleIds);\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/model/model.js",
    "content": "var prefix = \"/activity/model\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t// showRefresh : true,\n\t\t\t\t// showToggle : true,\n\t\t\t\t// showColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t// \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\tname : $('#searchName').val(),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'id', // 列字段名\n\t\t\t\t\t\ttitle : '模型id' // 列标题\n\t\t\t\t\t},\n                    {\n                        field : 'key', // 列字段名\n                        title : '模型标识' // 列标题\n                    },\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'name',\n\t\t\t\t\t\ttitle : '模型名称'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'version',\n\t\t\t\t\t\ttitle : '版本号'\n\t\t\t\t\t},\n                    {\n                        field : 'createTime',\n                        title : '创建时间'\n                    },\n                    {\n                        field : 'lastUpdateTime',\n                        title : '最后更新时间'\n                    },\n\t\t\t\t\t{\n\t\t\t\t\t\tfield:'is',\n\t\t\t\t\t\ttitle:'导出xml',\n\t\t\t\t\t\tvisible:false,\n\t\t\t\t\t\tformatter:function(value, row, index){\n\t\t\t\t\t\t\treturn '<a href=\"/activity/model/export/'+row.id+'\" target=\"_blank\">xml</a>';\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\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a  class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit \"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm ' + s_resetPwd_h + '\" href=\"#\" title=\"部署流程\"  mce_href=\"#\" onclick=\"deploy(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-plug\"></i></a> ';\n\t\t\t\t\t\t\treturn e + d + f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n    var page = layer.open({\n\t\ttype : 2,\n\t\ttitle : '新建模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '100%', '100%' ],\n\t\tcontent : prefix + '/add',\n        closeBtn: 0, //不显示关闭按钮\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/\"+id,\n\t\t\ttype : \"delete\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\nfunction edit(id) {\n\tvar page = layer.open({\n\t\ttype : 2,\n\t\ttitle : '修改模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false,\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id\n\t});\n\tlayer.full(page);\n}\n\nfunction deploy(id) {\n    layer.confirm('确定要部署选中的模型吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            url : prefix+\"/deploy/\"+id,\n            type : \"post\",\n            data : {\n                'id' : id\n            },\n            success : function(r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/process/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\n\nfunction save() {\n    var formData = new FormData($(\"#signupForm\")[0]);\n    $.ajax({\n\t\ttype : \"POST\",\n\t\turl : \"/activity/process/save\",\n        data: formData,\n        async: false,\n        cache: false,\n        contentType: false,\n        processData: false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(\"操作失败\")\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2,\n\t\t\t\tremote : {\n\t\t\t\t\turl : \"/sys/user/exit\", // 后台处理程序\n\t\t\t\t\ttype : \"post\", // 数据发送方式\n\t\t\t\t\tdataType : \"json\", // 接受数据格式\n\t\t\t\t\tdata : { // 要传递的数据\n\t\t\t\t\t\tusername : function() {\n\t\t\t\t\t\t\treturn $(\"#username\").val();\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\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\",\n\t\t\t\tremote : icon + \"用户名已经存在\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\n\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/process/edit.js",
    "content": "// 以下为官方示例\n$().ready(function() {\n\tvalidateRule();\n\t// $(\"#signupForm\").validate();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$(\"#roleIds\").val(getCheckedRoles());\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/user/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\talert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction getCheckedRoles() {\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction setCheckedRoles() {\n\tvar roleIds = $(\"#roleIds\").val();\n\talert(roleIds);\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/process/process.js",
    "content": "var prefix = \"/activity/process\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t// showRefresh : true,\n\t\t\t\t// showToggle : true,\n\t\t\t\t// showColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t// \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\tname : $('#searchName').val(),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n                    {\n                        field : 'id', // 列字段名\n                        title : '编号' // 列标题\n                    },\n                    {\n                        field : 'deploymentId', // 列字段名\n                        title : '部署编号' // 列标题\n                    },\n\n                    {\n                        field : 'name',\n                        title : '流程名称'\n                    },\n\n                    {\n                        field : 'id',\n                        title : '流程XML',\n\t\t\t\t\t\tformatter:function (value,row,index) {\n                            var e = '<a   href=\"/activity/process/resource/read/xml/'+row.id+'\"  title=\"xml\" target=\"_blank\">xml</a> ';\n                            return e;\n                        }\n                    },\n                    {\n                        field : 'id',\n                        title : '流程XML',\n                        formatter:function (value,row,index) {\n                            var e = '<a   href=\"/activity/process/resource/read/image/'+row.id+'\"  title=\"图片\" target=\"_blank\">图片</a> ';\n                            return e;\n                        }\n                    },\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a  class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit \"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.deploymentId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm ' + s_resetPwd_h + '\" href=\"#\" title=\"转为模型\"  mce_href=\"#\" onclick=\"covertToModel(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-cube\"></i></a> ';\n\t\t\t\t\t\t\treturn d + f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\t// iframe层\n\tvar page = layer.open({\n\t\ttype : 2,\n\t\ttitle : '新建模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add'\n\t});\n    layer.full(page);\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\nfunction edit(id) {\n\tvar page = layer.open({\n\t\ttype : 2,\n\t\ttitle : '修改模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false,\n\t\tarea : [ '100%', '100%' ],\n\t\tcontent : prefix + '/edit/' + id\n\t});\n}\n\nfunction covertToModel(id) {\n    layer.confirm('确定要把流程转转换成流程吗吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            url : prefix+\"/convertToModel/\"+id,\n            type : \"get\",\n            success : function(r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}\nfunction getTreeData() {\n\t$.ajax({\n\t\ttype : \"GET\",\n\t\turl : \"/system/sysDept/tree\",\n\t\tsuccess : function(tree) {\n\t\t\tloadTree(tree);\n\t\t}\n\t});\n}\nfunction loadTree(tree) {\n\t$('#jstree').jstree({\n\t\t'core' : {\n\t\t\t'data' : tree\n\t\t},\n\t\t\"plugins\" : [ \"search\" ]\n\t});\n\t$('#jstree').jstree().open_all();\n}\n$('#jstree').on(\"changed.jstree\", function(e, data) {\n\tif (data.selected == -1) {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : '',\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t} else {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : data.selected[0],\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh',opt);\n\t}\n\n});"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/salary/add.js",
    "content": "$().ready(function () {\n    validateRule();\n\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\n$(\"#userName\").click(function () {\n    layer.open({\n        type: 2,\n        title: '选择人员',\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n});\n\nfunction loadUser(id,name){\n    console.log(id+name);\n    $(\"#userId\").val(id);\n    $(\"#userName\").val(name);\n}\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/act/salary/save\",\n        data: $('#signupForm').serialize(),// 你的formid\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    var icon = \"<i class='fa fa-times-circle'></i> \";\n    $(\"#signupForm\").validate({\n        rules: {\n            name: {\n                required: true\n            }\n        },\n        messages: {\n            name: {\n                required: icon + \"\"\n            }\n        }\n    })\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/salary/edit.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/act/salary/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/salary/salary.js",
    "content": "\nvar prefix = \"/activity/salary\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t\t//\tshowToggle : true,\n\t\t\t\t\t//\tshowColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\t\t\tlimit: params.limit,\n\t\t\t\t\t\t\t\toffset:params.offset\n\t\t\t\t\t           // name:$('#searchName').val(),\n\t\t\t\t\t           // username:$('#searchName').val()\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\n\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{\n\t\t\t\t\t\t\t\t\tfield : 'id', \n\t\t\t\t\t\t\t\t\ttitle : '编号' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'procInsId', \n\t\t\t\t\t\t\t\t\ttitle : '流程实例ID' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'userId', \n\t\t\t\t\t\t\t\t\ttitle : '变动用户' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'officeId', \n\t\t\t\t\t\t\t\t\ttitle : '归属部门' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'post', \n\t\t\t\t\t\t\t\t\ttitle : '岗位' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'age', \n\t\t\t\t\t\t\t\t\ttitle : '性别' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'edu', \n\t\t\t\t\t\t\t\t\ttitle : '学历' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'content', \n\t\t\t\t\t\t\t\t\ttitle : '调整原因' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'olda', \n\t\t\t\t\t\t\t\t\ttitle : '现行标准 薪酬档级' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'oldb', \n\t\t\t\t\t\t\t\t\ttitle : '现行标准 月工资额' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'oldc', \n\t\t\t\t\t\t\t\t\ttitle : '现行标准 年薪总额' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'newa', \n\t\t\t\t\t\t\t\t\ttitle : '调整后标准 薪酬档级' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'newb', \n\t\t\t\t\t\t\t\t\ttitle : '调整后标准 月工资额' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'newc', \n\t\t\t\t\t\t\t\t\ttitle : '调整后标准 年薪总额' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'addNum', \n\t\t\t\t\t\t\t\t\ttitle : '月增资' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'exeDate', \n\t\t\t\t\t\t\t\t\ttitle : '执行时间' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'hrText', \n\t\t\t\t\t\t\t\t\ttitle : '人力资源部门意见' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'leadText', \n\t\t\t\t\t\t\t\t\ttitle : '分管领导意见' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'mainLeadText', \n\t\t\t\t\t\t\t\t\ttitle : '集团主要领导意见' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'createBy', \n\t\t\t\t\t\t\t\t\ttitle : '创建者' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'createDate', \n\t\t\t\t\t\t\t\t\ttitle : '创建时间' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'updateBy', \n\t\t\t\t\t\t\t\t\ttitle : '更新者' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'updateDate', \n\t\t\t\t\t\t\t\t\ttitle : '更新时间' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'remarks', \n\t\t\t\t\t\t\t\t\ttitle : '备注信息' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'delFlag', \n\t\t\t\t\t\t\t\t\ttitle : '删除标记' \n\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{\n\t\t\t\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm '+s_edit_h+'\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm '+s_remove_h+'\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn e + d ;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code==0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t}else{\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {\n\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/task/gotoTask.js",
    "content": "var prefix = \"/activity/task\"\n$(function() {\n\tload3();\n});\n\nfunction load3() {\n\t$('#exampleTable3')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/gotoList\", // 服务器数据的加载地址\n\t\t\t\t// showRefresh : true,\n\t\t\t\t// showToggle : true,\n\t\t\t\t// showColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t// \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\tname : $('#searchName').val(),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n                    {\n                        field : 'id', // 列字段名\n                        title : '编号' // 列标题\n                    },\n\n                    {\n                        field : 'name',\n                        title : '流程名称'\n                    },\n\n\n                    {\n                        field : 'id',\n                        title : '流程图',\n                        formatter:function (value,row,index) {\n                            var e = '<a   href=\"/activity/process/resource/read/image/'+row.id+'\"  title=\"图片\" target=\"_blank\">图片</a> ';\n                            return e;\n                        }\n                    },\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm ' + s_resetPwd_h + '\" href=\"#\" title=\"发起任务\"  mce_href=\"#\" onclick=\"form3(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa  fa-paper-plane\"></i></a> ';\n\t\t\t\t\t\t\treturn f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\n\nfunction form3(id) {\n    layer.open({\n        type : 2,\n        title : '发起流程',\n        maxmin : true,\n        shadeClose : false,\n        area : [ '100%', '100%' ],\n        content : prefix +'/form/'+id\n    })\n}\n\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/act/task/totoTask.js",
    "content": "var prefix = \"/activity/task\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/todoList\", // 服务器数据的加载地址\n\t\t\t\t// showRefresh : true,\n\t\t\t\t// showToggle : true,\n\t\t\t\t// showColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"client\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t// \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\tname : $('#searchName').val(),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n                    {\n                        field : 'id', // 列字段名\n                        title : '任务' // 列标题\n                    },\n                    {\n                        field : 'key', // 列字段名\n                        title : '任务key' // 列标题\n                    },\n                    {\n                        field : 'processId', // 列字段名\n                        title : '流程编号' // 列标题\n                    },\n                    {\n                        field : 'processDefinitionId', // 列字段名\n                        title : '流程定义编号' // 列标题\n                    },\n                    {\n                        field : 'name',\n                        title : '任务名称'\n                    },\n                    {\n                        field : 'executionId',\n                        title : '跟踪',\n\t\t\t\t\t\tformatter:function(value,row,index){\n                        \treturn '<a href=\"/activity/task/trace/photo/'+row.processDefinitionId+'/'+row.executionId+'\">跟踪</a>';\n\t\t\t\t\t\t}\n                    },\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-primary btn-sm \" href=\"#\" title=\"签收任务\"  mce_href=\"#\" onclick=\"form(\\''\n\t\t\t\t\t\t\t\t+ row.processDefinitionId+'\\',\\''+row.id\n\t\t\t\t\t\t\t\t+ '\\')\">审批<i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\treturn f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\t// iframe层\n\tvar page = layer.open({\n\t\ttype : 2,\n\t\ttitle : '新建模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add'\n\t});\n    layer.full(page);\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '修改模型',\n\t\tmaxmin : true,\n\t\tshadeClose : false,\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id\n\t});\n\tlayer.full(page);\n}\n\nfunction form(proId,id) {\n    layer.open({\n        type : 2,\n        title : '发起流程',\n        maxmin : true,\n        shadeClose : false,\n        area : [ '100%', '100%' ],\n        content : prefix + '/form/'+ proId+'/'+id\n    })\n}\n\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['userId'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/consumer/add.js",
    "content": "$().ready(function () {\n    validateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/consumer/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n        //限定范围\n        max: 0\n    });\n}\n\nvar openUser = function () {\n    layer.open({\n        type: 2,\n        title: \"选择人员\",\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/consumer/edit.js",
    "content": "$().ready(function () {\n    validateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"PUT\",\n        url: \"/consumer/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n        //限定范围\n        max: 0\n    });\n}\n\nvar openUser = function () {\n    layer.open({\n        type: 2,\n        title: \"选择人员\",\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/consumer/index.js",
    "content": "var prefix = \"/consumer\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'name',\n                        title: '姓名'\n                    },\n                    {\n                        field: 'tel',\n                        title: '联系电话'\n                    },\n                    // {\n                    // \tfield : 'status',\n                    // \ttitle : '状态',\n                    // \talign :'center',\n                    // \tformatter : function(value, row, index){\n                    // \t\tif(value==0){\n                    // \t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n                    // \t\t}else if(value==1){\n                    // \t\t\treturn '<span class=\"label label-primary\">发布</span>';\n                    // \t\t}\n                    // \t}\n                    // },\n                    {\n                        title: '操作',\n                        field: 'operation',\n                        align: 'center',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm ' + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm ' + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            var f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                            return e + d;\n                        }\n                    }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '添加顾客',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '350px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '350px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove/\" + id,\n            type: \"delete\",\n            // data: {\n            //     'id': id\n            // },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drug/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/drug/save\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\t$(\"#signupForm\").validate({\n\n\t})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n\t\t//限定范围\n\t\tmax: 0\n    });\n}\n\nvar openUser = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择人员\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/sys/user/treeView\"\n\t})\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drug/edit.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"PUT\",\n\t\turl : \"/drug/save\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\t$(\"#signupForm\").validate({\n\n\t})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n\t\t//限定范围\n\t\tmax: 0\n    });\n}\n\nvar openUser = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择人员\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/sys/user/treeView\"\n\t})\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drug/index.js",
    "content": "var prefix = \"/drug\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'id',\n                        title: '药品编号'\n                    },\n\n                    {\n                        field: 'name',\n                        title: '药品名称'\n                    },\n                    {\n                        field: 'specification',\n                        title: '规格'\n                    },\n                    {\n                        field: 'qualityGuaranteePeriod',\n                        title: '保质期（月）'\n                    },\n                    {\n                        field: 'price',\n                        title: '单价',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'quantity',\n                        title: '当前库存'\n                    },\n                    {\n                        field: 'lowerLimit',\n                        title: '库存阈值'\n                    },\n                    {\n                        field: 'supplier',\n                        title: '供应商'\n                    },\n                    // {\n                    // \tfield : 'status',\n                    // \ttitle : '状态',\n                    // \talign :'center',\n                    // \tformatter : function(value, row, index){\n                    // \t\tif(value==0){\n                    // \t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n                    // \t\t}else if(value==1){\n                    // \t\t\treturn '<span class=\"label label-primary\">发布</span>';\n                    // \t\t}\n                    // \t}\n                    // },\n                    {\n                    \ttitle : '操作',\n                    \tfield : 'operation',\n                    \talign : 'center',\n                    \tformatter : function(value, row, index) {\n                    \t\tvar e = '<a class=\"btn btn-primary btn-sm ' +  '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                    \t\t\t+ row.id\n                    \t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                    \t\tvar d = '<a class=\"btn btn-warning btn-sm ' + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                    \t\t\t+ row.id\n                    \t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                    \t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                    \t\t\t+ row.id\n                    \t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                    \t\treturn e + d;\n                    \t}\n                    }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '添加药品',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '520px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove/\"+id,\n            type: \"delete\",\n            // data: {\n            //     'id': id\n            // },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drugin/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/inventory/drugin/save\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\t$(\"#signupForm\").validate({\n\n\t})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n\t\t//限定范围\n\t\tmax: 0\n    });\n}\n\nvar openUser = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择人员\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/sys/user/treeView\"\n\t})\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drugin/drugin.js",
    "content": "var prefix = \"/inventory\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'drugId',\n                        title: '药品编号'\n                    },\n\n                    {\n                        field: 'drugName',\n                        title: '药品名称'\n                        // formatter: function(value,row,index){\n                        // \treturn '<a href=\"#\" onclick=\"edit(\\''+row.id+'\\')\">'+row.title+'</a>';\n                        // }\n                    },\n                    {\n                        field: 'specification',\n                        title: '规格'\n                    },\n                    {\n                        field: 'quantity',\n                        title: '入库数量'\n                    },\n                    {\n                        field: 'quantityNow',\n                        title: '实时库存'\n                    },\n                    {\n                        field: 'price',\n                        title: '单价',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n\n                    {\n                        field: 'ammount',\n                        title: '总金额',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    // {\n                    // \tfield : 'status',\n                    // \ttitle : '状态',\n                    // \talign :'center',\n                    // \tformatter : function(value, row, index){\n                    // \t\tif(value==0){\n                    // \t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n                    // \t\t}else if(value==1){\n                    // \t\t\treturn '<span class=\"label label-primary\">发布</span>';\n                    // \t\t}\n                    // \t}\n                    // },\n                    {\n                        field: 'type',\n                        title: '类别',\n                        formatter: function (value, row, index) {\n                            switch (value) {\n                                case '1':\n                                    return '进货入库';\n                                case '2':\n                                    return '顾客退货';\n                            }\n                        }\n                    },\n                    {\n                        field: 'supplierName',\n                        title: '供应商'\n                    }, {\n                        field: 'manager',\n                        title: '经办人'\n                    },\n                    {\n                        field: 'gmtCreated',\n                        title: '入库时间'\n                    }\n                    // {\n                    // \ttitle : '操作',\n                    // \tfield : 'operation',\n                    // \talign : 'center',\n                    // \tformatter : function(value, row, index) {\n                    // \t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                    // \t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                    // \t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                    // \t\treturn e + d;\n                    // \t}\n                    // }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '入库登记',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '520px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction resetPwd(id) {\n}\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drugout/drugout.js",
    "content": "var prefix = \"/inventory\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/listout\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'drugId',\n                        title: '药品编号'\n                    },\n\n                    {\n                        field: 'drugName',\n                        title: '药品名称'\n                    },\n                    {\n                        field: 'specification',\n                        title: '规格'\n                    },\n                    {\n                        field: 'quantity',\n                        title: '出库数量'\n                    },\n                    {\n                        field: 'quantityNow',\n                        title: '实时库存'\n                    },\n                    {\n                        field: 'price',\n                        title: '单价',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'ammount',\n                        title: '总金额',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'comment',\n                        title: '备注'\n                    },\n                    {\n                        field: 'supplierName',\n                        title: '供应商'\n                    }, {\n                        field: 'manager',\n                        title: '经办人'\n                    },\n                    {\n                        field: 'gmtCreated',\n                        title: '出库时间'\n                    }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '出库登记',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '520px'],\n        content: prefix + '/out' // iframe的url\n    });\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction resetPwd(id) {\n}\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/drugout/out.js",
    "content": "$().ready(function () {\n    validateRule();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/inventory/drugout/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({\n\n    })\n}\n\nvar openUser = function () {\n    layer.open({\n        type: 2,\n        title: \"选择人员\",\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n}\n\nfunction loadUser(userIds, userNames) {\n    $(\"#userIds\").val(userIds);\n    $(\"#userNames\").val(userNames);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/sale/add.js",
    "content": "$().ready(function () {\n    validateRule();\n    loadSelect();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/sale/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}\n\nfunction loadSelect() {\n    $(\"#consumer\").select2({\n        ajax: {\n            url: '/consumer/search',\n            dataType: 'json'\n        },\n        language: \"zh-CN\",\n        minimumInputLength: 1,\n        maximumSelectionLength: 20\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/sale/back.js",
    "content": "$().ready(function () {\n    validateRule();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/sale/back\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/sale/index.js",
    "content": "var prefix = \"/sale\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'orderId',\n                        title: '流水号'\n                    },\n                    {\n                        field: 'drugId',\n                        title: '药品编号'\n                    },\n                    {\n                        field: 'drugName',\n                        title: '药品名称'\n                    },\n                    {\n                        field: 'quantity',\n                        title: '售出数量'\n                    },\n                    {\n                        field: 'quantityNow',\n                        title: '实时库存'\n                    },\n                    {\n                        field: 'specification',\n                        title: '规格'\n                    },\n                    {\n                        field: 'price',\n                        title: '单价',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'ammount',\n                        title: '总金额',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'manager',\n                        title: '售货人'\n                    },\n                    {\n                        field: 'consumer',\n                        title: '顾客姓名'\n                    },\n                    {\n                        field: 'gmtCreated',\n                        title: '售出时间'\n                    }\n                    // {\n                    // \ttitle : '操作',\n                    // \tfield : 'operation',\n                    // \talign : 'center',\n                    // \tformatter : function(value, row, index) {\n                    // \t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                    // \t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                    // \t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                    // \t\treturn e + d;\n                    // \t}\n                    // }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '销售登记',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '400px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction back() {\n    layer.open({\n        type: 2,\n        title: '退货登记',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '450px'],\n        content: prefix + '/back' // iframe的url\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/sale-detail/index.js",
    "content": "var prefix = \"/sale\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'orderId',\n                        title: '流水号'\n                    },\n                    {\n                        field: 'drugId',\n                        title: '药品编号'\n                    },\n                    {\n                        field: 'drugName',\n                        title: '药品名称'\n                    },\n                    {\n                        field: 'quantity',\n                        title: '售出数量'\n                    },\n                    {\n                        field: 'quantityNow',\n                        title: '实时库存'\n                    },\n                    {\n                        field: 'specification',\n                        title: '规格'\n                    },\n                    {\n                        field: 'price',\n                        title: '单价',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'ammount',\n                        title: '总金额',\n                        formatter: function (v) {\n                            return v.toFixed(2);\n                        }\n                    },\n                    {\n                        field: 'manager',\n                        title: '售货人'\n                    },\n                    {\n                        field: 'consumer',\n                        title: '顾客姓名'\n                    },\n                    {\n                        field: 'gmtCreated',\n                        title: '售出时间'\n                    }\n                    // {\n                    // \ttitle : '操作',\n                    // \tfield : 'operation',\n                    // \talign : 'center',\n                    // \tformatter : function(value, row, index) {\n                    // \t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                    // \t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                    // \t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                    // \t\t\t+ row.id\n                    // \t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                    // \t\treturn e + d;\n                    // \t}\n                    // }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/statistics/index.js",
    "content": "var prefix = \"/sale\";\n// 几月几日\nvar days = [];\n// 几月\nvar months = [];\n// 哪年\nvar years = [];\n// 每日销量\nvar vSaleCountDay = [];\n// 每月销量\nvar vSaleCountMonth = [];\n// 每年销量\nvar vSaleCountYear = [];\n\n\n$(function () {\n    getData();\n});\n\nfunction getData() {\n    $.ajax({\n        type: \"GET\",\n        url: \"/sale/sta_sale_day\",\n        dataType: 'json',\n        async: true,\n        error: function (request) {\n            layer.alert(\"获取数据失败\");\n        },\n        success: function (data) {\n            $.each(data, function (i, v) {\n                days.push(v.dateUnit);\n                vSaleCountDay.push(v.saleCount);\n            });\n            loadDay();\n        }\n    });\n    $.ajax({\n        type: \"GET\",\n        url: \"/sale/sta_sale_month\",\n        dataType: 'json',\n        async: true,\n        error: function (request) {\n            layer.alert(\"获取数据失败\");\n        },\n        success: function (data) {\n            $.each(data, function (i, v) {\n                months.push(v.dateUnit);\n                vSaleCountMonth.push(v.saleCount);\n            });\n            loadMonth();\n        }\n    });\n    $.ajax({\n        type: \"GET\",\n        url: \"/sale/sta_sale_year\",\n        dataType: 'json',\n        async: true,\n        error: function (request) {\n            layer.alert(\"获取数据失败\");\n        },\n        success: function (data) {\n            $.each(data, function (i, v) {\n                years.push(v.dateUnit);\n                vSaleCountYear.push(v.saleCount);\n            });\n            loadYear();\n        }\n    });\n}\n\nfunction loadDay() {\n    // 基于准备好的dom，初始化echarts实例\n    var myChart = echarts.init(document.getElementById('id_day'));\n\n    // 指定图表的配置项和数据\n    var option = {\n        title: {\n            text: '近30天日销量统计',\n            left: 'center'\n        },\n        tooltip: {\n            trigger: 'axis',\n            formatter: '{b0}: {c0} 件'\n        },\n        xAxis: {\n            type: 'category',\n            boundaryGap: false,\n            data: days\n        },\n        yAxis: {\n            type: 'value'\n        },\n        series: [{\n            name: 'count',\n            type: 'line',\n            // smooth: true,\n            areaStyle: {\n                normal: {\n                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{\n                        offset: 0,\n                        color: 'rgb(255, 158, 68)'\n                    }, {\n                        offset: 1,\n                        color: 'rgb(255, 70, 131)'\n                    }])\n                }\n            },\n            data: vSaleCountDay\n        }\n        ]\n    };\n\n    // 使用刚指定的配置项和数据显示图表。\n    myChart.setOption(option);\n}\n\nfunction loadMonth() {\n    // 基于准备好的dom，初始化echarts实例\n    var myChart = echarts.init(document.getElementById('id_month'));\n\n    // 指定图表的配置项和数据\n    var option = {\n        title: {\n            text: '今年每月销量统计',\n            left: 'center'\n        },\n        tooltip: {\n            trigger: 'axis',\n            formatter: '{b0}: {c0} 件'\n        },\n        xAxis: {\n            type: 'category',\n            boundaryGap: false,\n            data: months\n        },\n        yAxis: {\n            type: 'value'\n        },\n        series: [{\n            name: 'count',\n            type: 'line',\n            // smooth: true,\n            areaStyle: {\n                normal: {\n                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{\n                        offset: 0,\n                        color: 'rgb(255, 158, 68)'\n                    }, {\n                        offset: 1,\n                        color: 'rgb(255, 70, 131)'\n                    }])\n                }\n            },\n            data: vSaleCountMonth\n        }\n        ]\n    };\n\n    // 使用刚指定的配置项和数据显示图表。\n    myChart.setOption(option);\n}\n\nfunction loadYear() {\n    // 基于准备好的dom，初始化echarts实例\n    var myChart = echarts.init(document.getElementById('id_year'));\n\n    // 指定图表的配置项和数据\n    var option = {\n        title: {\n            text: '近5年销量统计',\n            left: 'center'\n        },\n        tooltip: {\n            trigger: 'axis',\n            formatter: '{b0}: {c0} 件'\n        },\n        xAxis: {\n            type: 'category',\n            boundaryGap: false,\n            data: years\n        },\n        yAxis: {\n            type: 'value'\n        },\n        series: [{\n            name: 'count',\n            type: 'line',\n            // smooth: true,\n            areaStyle: {\n                normal: {\n                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{\n                        offset: 0,\n                        color: 'rgb(255, 158, 68)'\n                    }, {\n                        offset: 1,\n                        color: 'rgb(255, 70, 131)'\n                    }])\n                }\n            },\n            data: vSaleCountYear\n        }\n        ]\n    };\n\n    // 使用刚指定的配置项和数据显示图表。\n    myChart.setOption(option);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/supplier/add.js",
    "content": "$().ready(function () {\n    validateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"POST\",\n        url: \"/supplier/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n        //限定范围\n        max: 0\n    });\n}\n\nvar openUser = function () {\n    layer.open({\n        type: 2,\n        title: \"选择人员\",\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/supplier/edit.js",
    "content": "$().ready(function () {\n    validateRule();\n    initDatePicker();\n});\n\n$.validator.setDefaults({\n    submitHandler: function () {\n        save();\n    }\n});\n\nfunction save() {\n    $.ajax({\n        cache: true,\n        type: \"PUT\",\n        url: \"/supplier/save\",\n        data: $('#signupForm').serialize(),\n        async: false,\n        error: function (request) {\n            parent.layer.alert(\"Connection error\");\n        },\n        success: function (data) {\n            if (data.code == 0) {\n                parent.layer.msg(\"操作成功\");\n                parent.reLoad();\n                var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n                parent.layer.close(index);\n\n            } else {\n                parent.layer.alert(data.msg)\n            }\n\n        }\n    });\n\n}\n\nfunction validateRule() {\n    $(\"#signupForm\").validate({})\n}\n\nfunction initDatePicker() {\n    laydate.render({\n        //指定元素\n        elem: '#madeDate',\n        //限定范围\n        max: 0\n    });\n}\n\nvar openUser = function () {\n    layer.open({\n        type: 2,\n        title: \"选择人员\",\n        area: ['300px', '450px'],\n        content: \"/sys/user/treeView\"\n    })\n};"
  },
  {
    "path": "src/main/resources/static/js/appjs/app/supplier/index.js",
    "content": "var prefix = \"/supplier\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                showRefresh: true,\n                // showToggle : true,\n                //\tshowColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                //search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n                queryParams: function (params) {\n                    return {\n                        //说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        field: 'id',\n                        title: '编号'\n                    },\n\n                    {\n                        field: 'name',\n                        title: '名称'\n                    },\n                    // {\n                    // \tfield : 'status',\n                    // \ttitle : '状态',\n                    // \talign :'center',\n                    // \tformatter : function(value, row, index){\n                    // \t\tif(value==0){\n                    // \t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n                    // \t\t}else if(value==1){\n                    // \t\t\treturn '<span class=\"label label-primary\">发布</span>';\n                    // \t\t}\n                    // \t}\n                    // },\n                    {\n                        title: '操作',\n                        field: 'operation',\n                        align: 'center',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm ' + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm ' + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            var f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                            return e + d;\n                        }\n                    }\n                ]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '添加供应商',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '350px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['500px', '350px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove/\" + id,\n            type: \"delete\",\n            // data: {\n            //     'id': id\n            // },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/blog/bComments/add.js",
    "content": "$().ready(function() {\n\t$('.summernote').summernote({\n\t\theight:'220px',\n\t\tlang : 'zh-CN'\n\t});\n\tvalidateRule();\n});\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\tvar content_sn = $(\"#content_sn\").code();\n\t$(\"#content\").val(content_sn);\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/blog/bComments/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\ttitle : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\ttitle : {\n\t\t\t\trequired : icon + \"请输入标题\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/blog/bComments/bComments.js",
    "content": "\nvar prefix = \"/blog/bComments\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t\t//\tshowToggle : true,\n\t\t\t\t\t//\tshowColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\t\t\tlimit: params.limit,\n\t\t\t\t\t\t\t\toffset:params.offset\n\t\t\t\t\t            //name:$('#searchName').val(),\n\t\t\t\t\t          //  username:$('#searchName').val()\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\n\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{\n\t\t\t\t\t\t\t\t\tfield : 'id', \n\t\t\t\t\t\t\t\t\ttitle : '主键' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'coid', \n\t\t\t\t\t\t\t\t\ttitle : '' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'created', \n\t\t\t\t\t\t\t\t\ttitle : '创建者' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'author', \n\t\t\t\t\t\t\t\t\ttitle : '作者' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'authorId', \n\t\t\t\t\t\t\t\t\ttitle : '作者编号' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'ownerId', \n\t\t\t\t\t\t\t\t\ttitle : '归属人编号' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'email', \n\t\t\t\t\t\t\t\t\ttitle : '邮箱' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'url', \n\t\t\t\t\t\t\t\t\ttitle : '链接地址' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'ip', \n\t\t\t\t\t\t\t\t\ttitle : 'ip地址' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'agent', \n\t\t\t\t\t\t\t\t\ttitle : '代理人' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'content', \n\t\t\t\t\t\t\t\t\ttitle : '内容' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'type', \n\t\t\t\t\t\t\t\t\ttitle : '类型' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'status', \n\t\t\t\t\t\t\t\t\ttitle : '状态' \n\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{\n\t\t\t\t\t\t\t\t\tfield : 'parent', \n\t\t\t\t\t\t\t\t\ttitle : '原始文章' \n\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{\n\t\t\t\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn e + d ;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\t$(\"#content\").val($('#content').code());\n\tvar perContent= layer.open({\n\t\ttype : 2,\n\t\ttitle : '发布文章',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n\t layer.full(perContent);\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code==0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t}else{\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\t\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\t\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {\n\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/blog/bContent/add.js",
    "content": "$().ready(function() {\n\n\t$('.summernote').summernote({\n\t\theight : '220px',\n\t\tlang : 'zh-CN',\n\t\tcallbacks: {\n            onImageUpload: function(files, editor, $editable) {\n                sendFile(files);\n            }\n        }\n\t});\n\tvalidateRule();\n});\n\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave(1);\n\t}\n});\nfunction save(status) {\n\t$(\"#status\").val(status);\n\tvar content_sn = $(\"#content_sn\").summernote('code');\n\t$(\"#content\").val(content_sn);\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/blog/bContent/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(r) {\n\t\t\tif (r.code == 0) {\n\t\t\t\tparent.layer.msg(r.msg);\n\t\t\t\tparent.reLoad();\n\t\t\t\t$(\"#cid\").val(r.cid);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(r.msg)\n\t\t\t}\n\t\t}\n\t});\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\ttitle : \"required\",\n\t\t\tauthor : \"required\",\n\t\t\tcontent : \"required\"\n\t\t},\n\t\tmessages : {\n\t\t\ttitle : \"请填写文章标题\",\n\t\t\tauthor : \"请填写文章作者\",\n\t\t\tcontent : \"请填写文章内容\"\n\t\t}\n\t});\n}\n\nfunction returnList() {\n\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\tparent.layer.close(index);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/blog/bContent/bContent.js",
    "content": "var prefix = \"/blog/bContent\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t\t// showRefresh : true,\n\t\t\t\t\t\t// showToggle : true,\n\t\t\t\t\t\tshowColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\t\t\t//showColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t\t\t// \"server\"\n\n\t\t\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\t\t\toffset : params.offset\n\t\t\t\t\t\t\t// name:$('#searchName').val(),\n\t\t\t\t\t\t\t// username:$('#searchName').val()\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'cid',\n\t\t\t\t\t\t\t\t\ttitle : ''\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\tfield : 'title',\n\t\t\t\t\t\t\t\t\ttitle : '标题',\n\t\t\t\t\t\t\t\t\twidth :320,\n                                    formatter:function (value,row,index) {\n                                        return '<a href=\"#\" onclick=\"preview(\\''+ row.cid+ '\\')\">'+row.title+'</a>';\n                                    }\n                                },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfield : 'author',\n\t\t\t\t\t\t\t\t\ttitle : '作者'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'slug',\n\t\t\t\t\t\t\t\t\ttitle : 'slug'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'created',\n\t\t\t\t\t\t\t\t\ttitle : '创建人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\t\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'modified',\n\t\t\t\t\t\t\t\t\ttitle : '最近修改人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\t\tvisible : true,\n\t\t\t\t\t\t\t\t\tfield : 'gtmModified',\n\t\t\t\t\t\t\t\t\ttitle : '最近修改时间'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'content',\n\t\t\t\t\t\t\t\t\ttitle : '内容'\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{\n\t\t\t\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'type',\n\t\t\t\t\t\t\t\t\ttitle : '类型'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'tags',\n\t\t\t\t\t\t\t\t\ttitle : '标签'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'categories',\n\t\t\t\t\t\t\t\t\ttitle : '分类'\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\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'hits',\n\t\t\t\t\t\t\t\t\ttitle : ''\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\tfield : 'commentsNum',\n\t\t\t\t\t\t\t\t\ttitle : '评论数量',\n\t\t\t\t\t\t\t\t\twidth :40\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\tfield : 'status',\n\t\t\t\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tif (value == '0') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n\t\t\t\t\t\t\t\t\t\t} else if (value == '1') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">发布</span>';\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{\n\t\t\t\t\t\t\t\t\tfield : 'allowComment',\n\t\t\t\t\t\t\t\t\ttitle : '开启评论',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tif (value == '0') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">否</span>';\n\t\t\t\t\t\t\t\t\t\t} else if (value == '1') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">是</span>';\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{\n\t\t\t\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\t\t\t\tfield : 'allowPing',\n\t\t\t\t\t\t\t\t\ttitle : '允许ping',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tif (value == '0') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">否</span>';\n\t\t\t\t\t\t\t\t\t\t} else if (value == '1') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">是</span>';\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{\n\t\t\t\t\t\t\t\t\tfield : 'allowFeed',\n\t\t\t\t\t\t\t\t\ttitle : '允许订阅',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tif (value == '0') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">否</span>';\n\t\t\t\t\t\t\t\t\t\t} else if (value == '1') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">是</span>';\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{\n\t\t\t\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm '+s_edit_h+'\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.cid\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm '+s_remove_h+'\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.cid\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"预览\"  mce_href=\"#\" onclick=\"preview(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.cid\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-rocket\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn e + d +f;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\tvar addPage = layer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n\tlayer.full(addPage);\n}\nfunction edit(cid) {\n\tvar editPage = layer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + cid // iframe的url\n\t});\n\tlayer.full(editPage);\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix + \"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction preview(id) {\n\twindow.open(\"/blog/open/post/\"+id);   \n\t//window.location.href=\"/blog/open/post/\"+id;\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['cid'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {\n\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/blog/bContent/edit.js",
    "content": "$().ready(function() {\n\t$('.summernote').summernote({\n\t\theight : '220px',\n\t\tlang : 'zh-CN',\n        callbacks: {\n            onImageUpload: function(files, editor, $editable) {\n                console.log(\"onImageUpload\");\n                sendFile(files);\n            }\n        }\n    });\n\tvar content = $(\"#content\").val();\n\n\t$('#content_sn').summernote('code', content);\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save(status) {\n\t$(\"#status\").val(status);\n\n\tvar content_sn = $(\"#content_sn\").summernote('code');\n\t$(\"#content\").val(content_sn);\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/blog/bContent/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\t\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction returnList() {\n\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\tparent.layer.close(index);\n}\n\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/dict/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/common/dict/save\",\n\t\tdata : $('#signupForm').serialize(), // 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"网络超时\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name);\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/dict/dict.js",
    "content": "\nvar prefix = \"/common/dict\"\n$(function() {\n\t\n\t//\tvar config = {\n\t//\t\t'.chosen-select' : {},\n\t//\t\t'.chosen-select-deselect' : {\n\t//\t\t\tallow_single_deselect : true\n\t//\t\t},\n\t//\t\t'.chosen-select-no-single' : {\n\t//\t\t\tdisable_search_threshold : 10\n\t//\t\t},\n\t//\t\t'.chosen-select-no-results' : {\n\t//\t\t\tno_results_text : '没有数据'\n\t//\t\t},\n\t//\t\t'.chosen-select-width' : {\n\t//\t\t\twidth : \"95%\"\n\t//\t\t}\n\t//\t}\n\t//\tfor (var selector in config) {\n\t//\t\t$(selector).chosen(config[selector]);\n\t//\t}\n\tload();\n});\nfunction selectLoad() {\n\tvar html = \"\";\n\t$.ajax({\n\t\turl : '/common/dict/type',\n\t\tsuccess : function(data) {\n\t\t\t//加载数据\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\thtml += '<option value=\"' + data[i].type + '\">' + data[i].description + '</option>'\n\t\t\t}\n\t\t\t$(\".chosen-select\").append(html);\n\t\t\t$(\".chosen-select\").chosen({\n\t\t\t\tmaxHeight : 200\n\t\t\t});\n\t\t\t//点击事件\n\t\t\t$('.chosen-select').on('change', function(e, params) {\n\t\t\t\tconsole.log(params.selected);\n\t\t\t\tvar opt = {\n\t\t\t\t\tquery : {\n\t\t\t\t\t\ttype : params.selected,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t\t\t});\n\t\t}\n\t});\n}\nfunction load() {\n\tselectLoad();\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t//\tshowToggle : true,\n\t\t\t\t//\tshowColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\t// name:$('#searchName').val(),\n\t\t\t\t\t\ttype : $('#searchName').val(),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\ttitle : '编号'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'name',\n\t\t\t\t\t\ttitle : '标签名'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'value',\n\t\t\t\t\t\ttitle : '数据值',\n\t\t\t\t\t\twidth : '100px'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'type',\n\t\t\t\t\t\ttitle : '类型'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'description',\n\t\t\t\t\t\ttitle : '描述'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'sort',\n\t\t\t\t\t\ttitle : '排序（升序）'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'parentId',\n\t\t\t\t\t\ttitle : '父级编号'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createBy',\n\t\t\t\t\t\ttitle : '创建者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createDate',\n\t\t\t\t\t\ttitle : '创建时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateBy',\n\t\t\t\t\t\ttitle : '更新者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateDate',\n\t\t\t\t\t\ttitle : '更新时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'remarks',\n\t\t\t\t\t\ttitle : '备注信息'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'delFlag',\n\t\t\t\t\t\ttitle : '删除标记'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm ' + s_add_h + '\" href=\"#\" title=\"增加\"  mce_href=\"#\" onclick=\"addD(\\''\n\t\t\t\t\t\t\t\t+ row.type +'\\',\\''+row.description\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-plus\"></i></a> ';\n\t\t\t\t\t\t\treturn e + d +f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\tvar opt = {\n\t\tquery : {\n\t\t\ttype : $('.chosen-select').val(),\n\t\t}\n\t}\n\t$('#exampleTable').bootstrapTable('refresh', opt);\n}\nfunction add() {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix + \"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction addD(type,description) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add/'+type+'/'+description // iframe的url\n\t});\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/dict/edit.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/common/dict/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/generator/edit.js",
    "content": "// 以下为官方示例\n$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tconsole.log('提交修改');\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/common/generator/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"网络连接超时\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(data.msg);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tauthor : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t},\n\t\t\tpackage : {\n\t\t\t\trequired : true,\n\t\t\t},\n\t\t\t\n\t\t},\n\t\tmessages : {\n\n\t\t\tauthor : {\n\t\t\t\trequired : icon + \"请输入作者\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : icon + \"请输入email\",\n\t\t\t},\n\t\t\tpackage : {\n\t\t\t\trequired : icon + \"请输入包名\",\n\t\t\t},\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/generator/list.js",
    "content": "var prefix = \"/common/generator\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t\tshowRefresh : true,\n\t\t\t\t\t\tshowToggle : true,\n\t\t\t\t\t\tshowColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\tsearch : true, // 是否显示搜索框\n\t\t\t\t\t\tshowColumns : true, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"client\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t\t\t// \"server\"\n\t\t\t\t\t\t// queryParams : queryParams,\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\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\tfield : 'tableName', // 列字段名\n\t\t\t\t\t\t\t\t\ttitle : '表名称' // 列标题\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\tfield : 'engine',\n\t\t\t\t\t\t\t\t\ttitle : 'engine'\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\tfield : 'tableComment',\n\t\t\t\t\t\t\t\t\ttitle : '表描述'\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\tfield : 'createTime',\n\t\t\t\t\t\t\t\t\ttitle : '创建时间'\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\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm\" href=\"#\" mce_href=\"#\" title=\"生成代码\" onclick=\"code(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.tableName\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-code\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn e;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction code(tableName) {\n\tlocation.href = prefix + \"/code/\" + tableName;\n}\nfunction batchCode() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要生成代码的表\");\n\t\treturn;\n\t}\n\tvar tables = new Array();\n\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t$.each(rows, function(i, row) {\n\t\ttables[i] = row['tableName'];\n\t});\n\tlocation.href = prefix + \"/batchCode?tables=\" + JSON.stringify(tables);\n}\n\nfunction edit(){\n\tconsole.log('打开配置页面');\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, \n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit'\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/job/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl :\"/common/job/save\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tlaryer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"保存成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\t\t}\n\t});\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/job/edit.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl :\"/common/job/update\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tlayer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"保存成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\t\t}\n\t});\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/job/job.js",
    "content": "var prefix = \"/common/job\"\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                // showRefresh : true,\n                // showToggle : true,\n                // showColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                // search : true, // 是否显示搜索框\n                showColumns: false, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n                // \"server\"\n                queryParams: function (params) {\n                    return {\n                        // 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n                        limit: params.limit,\n                        offset: params.offset\n                        // name:$('#searchName').val(),\n                        // username:$('#searchName').val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        checkbox: true\n                    },\n                    {\n                        field: 'id',\n                        title: 'id'\n                    },\n                    {\n                        field: 'jobName',\n                        title: '任务名称'\n                    },\n                    {\n                        field: 'jobGroup',\n                        title: '任务分组'\n                    },\n                    {\n                        field: 'beanClass',\n                        title: '任务类'\n                    },\n                    {\n                        field: 'cronExpression',\n                        title: 'cron表达式'\n                    },\n                    {\n                        visible: false,\n                        field: 'methodName',\n                        title: '方法名称'\n                    },\n                    {\n                        visible: false,\n                        field: 'isConcurrent',\n                        title: '任务是否有状态'\n                    },\n                    {\n                        visible: false,\n                        field: 'description',\n                        title: '任务描述'\n                    },\n                    {\n                        visible: false,\n                        field: 'updateBy',\n                        title: '更新者'\n                    },\n\n                    {\n                        visible: false,\n                        field: 'createDate',\n                        title: '创建时间'\n                    },\n\n\n                    {\n                        visible: false,\n                        field: 'updateDate',\n                        title: '更新时间'\n                    },\n                    {\n                        visible: false,\n                        field: 'createBy',\n                        title: '创建者'\n                    },\n                    {\n                        visible: false,\n                        field: 'springBean',\n                        title: 'Spring bean'\n                    },\n\n                    {\n                        field: 'jobStatus',\n                        title: '停起操作',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-success btn-xs\" href=\"#\" mce_href=\"#\" title=\"点击开启\" onclick=\"changeStatus(\\''\n                                + row.id + '\\',\\'' + row.jobStatus\n                                + '\\')\"><i class=\"fa fa-hourglass-start\"></i>开启</a> ';\n                            var f = '<a class=\"btn btn-danger btn-xs\" href=\"#\" mce_href=\"#\" title=\"点击关闭\" onclick=\"changeStatus(\\''\n                                + row.id + '\\',\\'' + row.jobStatus\n                                + '\\')\"><i class=\"fa fa-square-o\">关闭</i></a> ';\n                            if (row.jobStatus == 0) {\n                                return e;\n                            } else {\n                                return f;\n                            }\n\n                        }\n                    },\n\n                    {\n                        title: '操作',\n                        field: 'id',\n                        align: 'center',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + row.id + '\\',\\'' + row.jobStatus\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            var f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"开启\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                            return e + d;\n                        }\n                    }]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    layer.open({\n        type: 2,\n        title: '增加',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction edit(id, status) {\n    if (status == '1') {\n        layer.alert('修改之前请先停止任务');\n        return;\n    }\n    layer.open({\n        type: 2,\n        title: '编辑',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction changeStatus(id, status) {\n    var actCh;\n    var cmd;\n    if (status == 0) {\n        cmd = 'start';\n        actCh = \"确认要开启任务吗？\";\n    } else {\n        cmd = 'stop';\n        actCh = \"确认要停止任务吗？\";\n    }\n    layer.confirm(actCh, {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/changeJobStatus\",\n            type: \"post\",\n            data: {\n                'id': id,\n                'cmd': cmd\n            },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/common/log/log.js",
    "content": "var prefix = \"/common/log\"\n$(function () {\n    load();\n\n});\n$('#exampleTable').on('load-success.bs.table', function (e, data) {\n    if (data.total && !data.rows.length) {\n        $('#exampleTable').bootstrapTable('selectPage').bootstrapTable('refresh');\n    }\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                // showRefresh : true,\n                // showToggle : true,\n                // showColumns : true,\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                // search : true, // 是否显示搜索框\n                // showColumns : true, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n                // \"server\"\n                queryParams: function (params) {\n                    return {\n                        limit: params.limit,\n                        offset: params.offset,\n                        name: $('#searchName').val(),\n                        sort: 'gmt_create',\n                        order: 'desc',\n                        operation: $(\"#searchOperation\").val(),\n                        username: $(\"#searchUsername\").val()\n                    };\n                },\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    {\n                        checkbox: true\n                    },\n                    {\n                        field: 'id', // 列字段名\n                        title: '序号' // 列标题\n                    },\n                    {\n                        field: 'userId',\n                        title: '用户Id'\n                    },\n                    {\n                        field: 'username',\n                        title: '用户名'\n                    },\n                    {\n                        field: 'operation',\n                        title: '操作'\n                    },\n                    {\n                        field: 'time',\n                        title: '用时'\n                    },\n                    {\n                        field: 'method',\n                        title: '方法'\n                    },\n                    {\n                        field: 'params',\n                        title: '参数'\n                    },\n                    {\n                        field: 'ip',\n                        title: 'IP地址'\n                    },\n                    {\n                        field: 'gmtCreate',\n                        title: '创建时间'\n                    },\n                    {\n                        title: '操作',\n                        field: 'id',\n                        align: 'center',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + row.userId\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + row.id\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            var f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"重置密码\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n                                + row.userId\n                                + '\\')\"><i class=\"fa fa-key\"></i></a> ';\n                            return d;\n                        }\n                    }]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            beforeSend: function (request) {\n                index = layer.load();\n            },\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.close(index);\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction batchRemove() {\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n        // 按钮\n    }, function () {\n        var ids = new Array();\n        // 遍历所有选择的行数据，取每条数据对应的ID\n        $.each(rows, function (i, row) {\n            ids[i] = row['id'];\n        });\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/notify/add.js",
    "content": "$().ready(function() {\n\tloadType();\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/oa/notify/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}\nfunction loadType(){\n\tvar html = \"\";\n\t$.ajax({\n\t\turl : '/common/dict/list/oa_notify_type',\n\t\tsuccess : function(data) {\n\t\t\t//加载数据\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\thtml += '<option value=\"' + data[i].value + '\">' + data[i].name + '</option>'\n\t\t\t}\n\t\t\t$(\".chosen-select\").append(html);\n\t\t\t$(\".chosen-select\").chosen({\n\t\t\t\tmaxHeight : 200\n\t\t\t});\n\t\t\t//点击事件\n\t\t\t$('.chosen-select').on('change', function(e, params) {\n\t\t\t\tconsole.log(params.selected);\n\t\t\t\tvar opt = {\n\t\t\t\t\tquery : {\n\t\t\t\t\t\ttype : params.selected,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t\t\t});\n\t\t}\n\t});\n}\n\nvar openUser = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择人员\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/sys/user/treeView\"\n\t})\n}\n\nfunction loadUser(userIds,userNames){\n\t$(\"#userIds\").val(userIds);\n\t$(\"#userNames\").val(userNames);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/notify/edit.js",
    "content": "$().ready(function() {\n\t//loadType();\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/oa/notify/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction loadType(){\n\tvar html = \"\";\n\t$.ajax({\n\t\turl : '/common/dict/list/oa_notify_type',\n\t\tsuccess : function(data) {\n\t\t\t// 加载数据\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\thtml += '<option value=\"' + data[i].value + '\">' + data[i].name + '</option>'\n\t\t\t}\n\t\t\t$(\".chosen-select\").append(html);\n\t\t\t$(\".chosen-select\").chosen({\n\t\t\t\tmaxHeight : 200\n\t\t\t});\n\t\t\t$(\".chosen-select\").val($(\"#Ttype\").val());\n\t\t\t$(\".chosen-select\").trigger(\"chosen:updated\");\n\t\t\t// 点击事件\n\t\t\t$('.chosen-select').on('change', function(e, params) {\n\t\t\t\t\n\t\t\t});\n\t\t}\n\t});\n}\n\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/notify/notify.js",
    "content": "\nvar prefix = \"/oa/notify\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t//\tshowToggle : true,\n\t\t\t\t//\tshowColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset\n\t\t\t\t\t// name:$('#searchName').val(),\n\t\t\t\t\t// username:$('#searchName').val()\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible :false,\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\ttitle : '编号'\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'title',\n\t\t\t\t\t\ttitle : '标题',\n\t\t\t\t\t\tformatter: function(value,row,index){\n\t\t\t\t\t\t\treturn '<a href=\"#\" onclick=\"edit(\\''+row.id+'\\')\">'+row.title+'</a>';\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\tfield : 'type',\n\t\t\t\t\t\ttitle : '类型'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'content',\n\t\t\t\t\t\ttitle : '内容'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'files',\n\t\t\t\t\t\ttitle : '附件'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'status',\n\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\talign :'center',\n\t\t\t\t\t\tformatter : function(value, row, index){\n\t\t\t\t\t\t\tif(value==0){\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">草稿</span>';\n\t\t\t\t\t\t\t}else if(value==1){\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">发布</span>';\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\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createBy',\n\t\t\t\t\t\ttitle : '创建者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createDate',\n\t\t\t\t\t\ttitle : '创建时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateBy',\n\t\t\t\t\t\ttitle : '更新者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateDate',\n\t\t\t\t\t\ttitle : '更新时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'remarks',\n\t\t\t\t\t\ttitle : '备注信息'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'delFlag',\n\t\t\t\t\t\ttitle : '删除标记'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'operation',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\treturn e + d;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix + \"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/notify/read.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/oa/notify/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/notify/selfNotify.js",
    "content": "\nvar prefix = \"/oa/notify\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/selfList\", // 服务器数据的加载地址\n\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t//\tshowToggle : true,\n\t\t\t\t//\tshowColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset\n\t\t\t\t\t// name:$('#searchName').val(),\n\t\t\t\t\t// username:$('#searchName').val()\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\ttitle : '编号'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible :false,\n\t\t\t\t\t\tfield : 'type',\n\t\t\t\t\t\ttitle : '类型'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'title',\n\t\t\t\t\t\twidth: '20%',\n\t\t\t\t\t\ttitle : '标题',\n\t\t\t\t\t\tformatter:function (value,row,index) {\n                            return '<a href=\"#\" onclick=\"read(\\''+ row.id+ '\\')\">'+row.title+'</a>';\n                        }\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'content',\n\t\t\t\t\t\twidth: '30%',\n\t\t\t\t\t\ttitle : '内容'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'files',\n\t\t\t\t\t\ttitle : '附件'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'isRead',\n\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\talign :'center',\n\t\t\t\t\t\tformatter : function(value, row, index){\n\t\t\t\t\t\t\tif(value==0){\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-warning\">未读</span>';\n\t\t\t\t\t\t\t}else if(value==1){\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">已读</span>';\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\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createBy',\n\t\t\t\t\t\ttitle : '创建者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'createDate',\n\t\t\t\t\t\ttitle : '创建时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateBy',\n\t\t\t\t\t\ttitle : '更新者'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'updateDate',\n\t\t\t\t\t\ttitle : '更新时间'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'remarks',\n\t\t\t\t\t\ttitle : '备注信息'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\tfield : 'delFlag',\n\t\t\t\t\t\ttitle : '删除标记'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'opera',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm\" href=\"#\" mce_href=\"#\" title=\"打开\" onclick=\"read(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-book\"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\treturn e ;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n}\nfunction read(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '查看',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/read/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix + \"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['id'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/oa/webSocket/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6.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: Thu May 12 15:04:36 2011 -0400\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// (both of which we optimize for)\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// Check for digits\n\trdigit = /\\d/,\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// 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.6.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.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( 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.resolveWith( 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\" ).unbind( \"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._Deferred();\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\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( 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\t// Not own constructor property must be Object\n\t\tif ( obj.constructor &&\n\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\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 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\t// (xml & tmp used internally)\n\tparseXML: function( data , xml , tmp ) {\n\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\n\t\ttmp = xml.documentElement;\n\n\t\tif ( ! tmp || ! tmp.nodeName || tmp.nodeName === \"parsererror\" ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\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\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 common 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// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\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 ) {\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\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 be optionally by executed if its 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\n// Expose jQuery to the global object\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\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// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\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// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = 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().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action ]( returned );\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\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = 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\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\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\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 ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\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 deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\tbodyStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\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// 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 click() {\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\tdiv.detachEvent( \"onclick\", click );\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's 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.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\t// We use our own, invisible, body\n\tbody = document.createElement( \"body\" );\n\tbodyStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\t// Set background to avoid IE crashes when removing (#9028)\n\t\tbackground: \"none\"\n\t};\n\tfor ( i in bodyStyle ) {\n\t\tbody.style[ i ] = bodyStyle[ i ];\n\t}\n\tbody.appendChild( div );\n\tdocumentElement.insertBefore( body, documentElement.firstChild );\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\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\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\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\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 ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\tbody.innerHTML = \"\";\n\tdocumentElement.removeChild( body );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/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\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([a-z])([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\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 internalKey = jQuery.expando, getByName = typeof name === \"string\", thisCache,\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[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\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 || (pvt && id && !cache[ id ][ internalKey ])) && 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[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// 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 ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's 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[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\treturn getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache;\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 internalKey = jQuery.expando, isNode = 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[ jQuery.expando ] : jQuery.expando;\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\t\t\tvar thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\t\t\t\tdelete thisCache[ name ];\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 ( !isEmptyDataObject(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 ][ internalKey ];\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\tvar internalCache = cache[ id ][ internalKey ];\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\tif ( jQuery.support.deleteExpando || cache != window ) {\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 entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we 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\t} else if ( 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[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = 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 data = 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 ) {\n\t\t\t    var attr = this[0].attributes, name;\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}\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\tvar parts = 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 $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.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\t\tvar name = \"data-\" + key.replace( rmultiDash, \"$1-$2\" ).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\t!jQuery.isNaN( 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// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\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, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\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, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\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,undefined,true) || 0) + 1, true );\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, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\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\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\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), true );\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\tdefer;\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\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", 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() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\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._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( 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\trinvalidChar = /\\:/,\n\tformHook, boolHook;\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\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\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\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.addClass( value.call(this, i, self.attr(\"class\") || \"\") );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = this[i];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar className = \" \" + elem.className + \" \",\n\t\t\t\t\t\t\tsetClass = elem.className;\n\n\t\t\t\t\t\tfor ( var c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( className.indexOf( \" \" + classNames[c] + \" \" ) < 0 ) {\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\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.removeClass( value.call(this, i, self.attr(\"class\")) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = 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\tvar className = (\" \" + elem.className + \" \").replace(rclass, \" \");\n\t\t\t\t\t\tfor ( var 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\tvar self = jQuery(this);\n\t\t\t\tself.toggleClass( value.call(this, i, self.attr(\"class\"), 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\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( (\" \" + 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,\n\t\t\telem = this[0];\n\t\t\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\treturn (elem.value || \"\").replace(rreturn, \"\");\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = 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,\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\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = 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\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\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 undefined;\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 ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Normalize the name if needed\n\t\tname = notxml && jQuery.attrFix[ name ] || name;\n\n\t\thooks = jQuery.attrHooks[ name ];\n\n\t\tif ( !hooks ) {\n\t\t\t// Use boolHook for boolean attributes\n\t\t\tif ( rboolean.test( name ) &&\n\t\t\t\t(typeof value === \"boolean\" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) {\n\n\t\t\t\thooks = boolHook;\n\n\t\t\t// Use formHook for forms and if the name contains certain characters\n\t\t\t} else if ( formHook && (jQuery.nodeName( elem, \"form\" ) || rinvalidChar.test( name )) ) {\n\t\t\t\thooks = formHook;\n\t\t\t}\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 undefined;\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 ) {\n\t\t\treturn hooks.get( elem, name );\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, name ) {\n\t\tvar propName;\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\t\t\n\t\t\tif ( jQuery.support.getSetAttribute ) {\n\t\t\t\t// Use removeAttribute in browsers that support it\n\t\t\t\telem.removeAttribute( name );\n\t\t\t} else {\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttributeNode( elem.getAttributeNode( name ) );\n\t\t\t}\n\n\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\telem[ propName ] = false;\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\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\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\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = 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 undefined;\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Try to normalize/fix the name\n\t\tname = notxml && jQuery.propFix[ name ] || name;\n\t\t\n\t\thooks = jQuery.propHooks[ name ];\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 )) !== undefined ) {\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\t\n\tpropHooks: {}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\treturn elem[ jQuery.propFix[ name ] || name ] ?\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 ] = value;\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// Use the value property for back compat\n// Use the formHook for button elements in IE6/7 (#1954)\njQuery.attrHooks.value = {\n\tget: function( elem, name ) {\n\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\treturn formHook.get( elem, name );\n\t\t}\n\t\treturn elem.value;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\treturn formHook.set( elem, value, name );\n\t\t}\n\t\t// Does not return so that setAttribute is also used\n\t\telem.value = value;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\n\t// propFix is more comprehensive and contains all fixes\n\tjQuery.attrFix = jQuery.propFix;\n\t\n\t// Use this for any attribute on a form in IE6/7\n\tformHook = jQuery.attrHooks.name = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if nodeValue is empty string\n\t\t\treturn ret && ret.nodeValue !== \"\" ?\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// Check form objects in IE (multiple bugs related)\n\t\t\t// Only use nodeValue if the attribute node exists on the form\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret ) {\n\t\t\t\tret.nodeValue = value;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\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}\n\t});\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 hasOwn = Object.prototype.hasOwnProperty,\n\trnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\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 function being executed has a unique ID\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\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\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.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// 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 the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have 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, pos ) {\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\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\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\n\t\t\t\t\tif ( pos != null ) {\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\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\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\tret = null;\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\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\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// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\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.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\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// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === 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// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\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\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\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\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\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\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.preventDefault ) {\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// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.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// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar parent = event.relatedTarget;\n\n\t// set the correct event type\n\tevent.type = event.data;\n\n\t// Firefox sometimes assigns relatedTarget a XUL element\n\t// which we cannot access the parentNode property of\n\ttry {\n\n\t\t// Chrome does something similar, the parentNode property\n\t\t// can be accessed but is null.\n\t\tif ( parent && parent !== document && !parent.parentNode ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Traverse up the tree\n\t\twhile ( parent && parent !== this ) {\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\tif ( parent !== this ) {\n\t\t\t// handle event if we actually just moused on to a non sub-element\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\t\t}\n\n\t// assuming we've left the element since we most likely mousedover a xul element\n\t} catch(e) { }\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = elem.type, val = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\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\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\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, 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\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\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\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\").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.bind( name, 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\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\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/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 );\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 );\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;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = 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\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 ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\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 ( var 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\tvar pass = 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 \"Syntax error, unrecognized expression: \" + msg;\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 || Sizzle.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 type = 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\tvar first = match[2],\n\t\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\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 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.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = 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.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 = Expr.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\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// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\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.sizcache === 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.sizcache = 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.sizcache === 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.sizcache = 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 ) {\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 );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\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 && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\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\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\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\t\tif ( !elem || typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0],\n\t\t\t\t// If it receives a string, the selector is used\n\t\t\t\t// If it receives nothing, the siblings are used\n\t\t\t\telem ? jQuery( elem ) : this.parent().children() );\n\t\t}\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\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\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, args.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\nvar rinlinejQuery = / 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\trnocache = /<(?:script|object|embed|option|style)/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\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\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( 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(arguments[0]);\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(arguments[0]).toArray() );\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\" && !rnocache.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 internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\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\t}\n\t\t\t}\n\t\t}\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,\n\t\tdoc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);\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\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\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[ args[0] ] = 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 ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( \"querySelectorAll\" in elem ) {\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\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( elem.getElementsByTagName ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\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\n\t\t\t// 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\tcloneFixAttributes( 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\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\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// 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, cache = jQuery.cache, internalKey = jQuery.expando, special = 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 ] && cache[ id ][ internalKey ];\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\trdashAlpha = /-([a-z])/ig,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^[+\\-]=/,\n\trrelNumFilter = /[^+\\-\\.\\de]+/g,\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\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\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\"zIndex\": true,\n\t\t\"fontWeight\": true,\n\t\t\"opacity\": true,\n\t\t\"zoom\": true,\n\t\t\"lineHeight\": true,\n\t\t\"widows\": true,\n\t\t\"orphans\": 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// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( type === \"number\" && isNaN( value ) || value == null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && rrelNum.test( value ) ) {\n\t\t\t\tvalue = +value.replace( rrelNumFilter, \"\" ) + parseFloat( jQuery.css( elem, name ) );\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\tcamelCase: function( string ) {\n\t\treturn string.replace( rdashAlpha, fcamelCase );\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\tval = getWH( elem, name, extra );\n\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\tif ( val <= 0 ) {\n\t\t\t\t\tval = curCSS( elem, name, name );\n\n\t\t\t\t\tif ( val === \"0px\" && currentStyle ) {\n\t\t\t\t\t\tval = currentStyle( elem, name, name );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( val != null ) {\n\t\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( val < 0 || val == null ) {\n\t\t\t\t\tval = elem.style[ name ];\n\n\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t}\n\n\t\t\t\treturn typeof val === \"string\" ? val : val + \"px\";\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\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// Set the alpha filter to set the opacity\n\t\t\tvar opacity = jQuery.isNaN( value ) ?\n\t\t\t\t\"\" :\n\t\t\t\t\"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\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\treturn undefined;\n\t\t}\n\n\t\tif ( (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,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\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\t\t\t// Remember the original values\n\t\t\tleft = style.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\tvar which = name === \"width\" ? cssWidth : cssHeight,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight;\n\n\tif ( extra === \"border\" ) {\n\t\treturn val;\n\t}\n\n\tjQuery.each( which, function() {\n\t\tif ( !extra ) {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"padding\" + this )) || 0;\n\t\t}\n\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += parseFloat(jQuery.css( elem, \"margin\" + this )) || 0;\n\n\t\t} else {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"border\" + this + \"Width\" )) || 0;\n\t\t}\n\t});\n\n\treturn val;\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.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|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|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// #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\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 common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( 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// Only one parameter, we extend ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.extend( true, jQuery.ajaxSettings, settings );\n\t\t} else {\n\t\t\t// target was provided, we extend into it\n\t\t\tjQuery.extend( true, target, jQuery.ajaxSettings, settings );\n\t\t}\n\t\t// Flatten fields we don't want deep extended\n\t\tfor( var field in { context: 1, url: 1 } ) {\n\t\t\tif ( field in settings ) {\n\t\t\t\ttarget[ field ] = settings[ field ];\n\t\t\t} else if( field in jQuery.ajaxSettings ) {\n\t\t\t\ttarget[ field ] = jQuery.ajaxSettings[ field ];\n\t\t\t}\n\t\t}\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\"*\": \"*/*\"\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\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._Deferred(),\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, statusText, 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 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\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 = 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.resolveWith( 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.done;\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}\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 ] !== \"*\" ? \", */*; 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 ( status < 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\tjQuery.error( 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\trequestAnimationFrame = window.webkitRequestAnimationFrame ||\n\t    window.mozRequestAnimationFrame ||\n\t    window.oRequestAnimationFrame;\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\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"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\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\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,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\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\n\t\t\t\t\t// 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\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\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\tdisplay = defaultDisplay( this.nodeName );\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\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\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\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\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\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\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\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\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// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( 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\t\t\traf;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\t// Use requestAnimationFrame instead of setInterval if available\n\t\t\tif ( requestAnimationFrame ) {\n\t\t\t\ttimerId = 1;\n\t\t\t\traf = function() {\n\t\t\t\t\t// When timerId gets set to null at any point, this stops\n\t\t\t\t\tif ( timerId ) {\n\t\t\t\t\t\trequestAnimationFrame( raf );\n\t\t\t\t\t\tfx.tick();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequestAnimationFrame( raf );\n\t\t\t} else {\n\t\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: 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.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\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\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.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 t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\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 ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== 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 ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\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\toptions.complete.call( elem );\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\tfor ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {\n\t\t\tif ( !timers[i]() ) {\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.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : 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\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 elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( \"body\" ),\n\t\t\tdisplay = elem.css( \"display\" );\n\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\tdocument.body.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( \"<!doctype><html><body></body></html>\" );\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\n\t\t\tdocument.body.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\tjQuery.offset.initialize();\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.offset.supportsFixedPosition && 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.offset.doesNotAddBorder && !(jQuery.offset.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.offset.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.offset.supportsFixedPosition && 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\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.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\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 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\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[\"outer\" + name] = function( margin ) {\n\t\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, margin ? \"margin\" : \"border\" ) ) :\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\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\telem.document.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.isNaN( ret ) ? orig : ret;\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\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/menu/add.js",
    "content": "var prefix = \"/sys/menu\"\n$(function() {\n\tvalidateRule();\n\t//打开图标列表\n    $(\"#ico-btn\").click(function(){\n        layer.open({\n            type: 2,\n\t\t\ttitle:'图标列表',\n            content: '/FontIcoList.html',\n            area: ['480px', '90%'],\n            success: function(layero, index){\n                //var body = layer.getChildFrame('.ico-list', index);\n                //console.log(layero, index);\n            }\n        });\n    });\n});\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsubmit01();\n\t}\n});\nfunction submit01() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : prefix + \"/save\",\n\t\tdata : $('#signupForm').serialize(),\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tlaryer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"保存成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tlayer.alert(data.msg)\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入菜单名\"\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : icon + \"请选择菜单类型\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/menu/edit.js",
    "content": "var prefix = \"/sys/menu\"\n$(function() {\n\tvalidateRule();\n\n\t//打开图标列表\n    $(\"#ico-btn\").click(function(){\n        layer.open({\n            type: 2,\n\t\t\ttitle:'图标列表',\n            content: '/FontIcoList.html',\n            area: ['480px', '90%'],\n            success: function(layero, index){\n                //var body = layer.getChildFrame('.ico-list', index);\n                //console.log(layero, index);\n            }\n        });\n    });\n\n});\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : prefix + \"/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tlaryer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"保存成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tlayer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validate() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入菜单名\"\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : icon + \"请选择菜单类型\"\n\t\t\t}\n\t\t}\n\t})\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入菜单名\"\n\t\t\t},\n\t\t\ttype : {\n\t\t\t\trequired : icon + \"请选择菜单类型\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/menu/menu.js",
    "content": "var prefix = \"/sys/menu\"\n$(document).ready(function () {\n    load();\n});\nvar load = function () {\n    $('#exampleTable')\n        .bootstrapTreeTable(\n            {\n                id: 'menuId',\n                code: 'menuId',\n                parentCode: 'parentId',\n                type: \"GET\", // 请求数据的ajax类型\n                url: prefix + '/list', // 请求数据的ajax的url\n                ajaxParams: {sort:'order_num'}, // 请求数据的ajax的data属性\n                expandColumn: '1',// 在哪一列上面显示展开按钮\n                striped: true, // 是否各行渐变色\n                bordered: true, // 是否显示边框\n                expandAll: false, // 是否全部展开\n                // toolbar : '#exampleToolbar',\n                columns: [\n                    {\n                        title: '编号',\n                        field: 'menuId',\n                        visible: false,\n                        align: 'center',\n                        valign: 'center',\n                        width: '5%'\n                    },\n                    {\n                        title: '名称',\n                        valign: 'center',\n                        field: 'name',\n                        width: '20%'\n                    },\n\n                    {\n                        title: '图标',\n                        field: 'icon',\n                        align: 'center',\n                        valign: 'center',\n                        width : '5%',\n                        formatter: function (item, index) {\n                            return item.icon == null ? ''\n                                : '<i class=\"' + item.icon\n                                + ' fa-lg\"></i>';\n                        }\n                    },\n                    {\n                        title: '类型',\n                        field: 'type',\n                        align: 'center',\n                        valign: 'center',\n                        width : '10%',\n                        formatter: function (item, index) {\n                            if (item.type === 0) {\n                                return '<span class=\"label label-primary\">目录</span>';\n                            }\n                            if (item.type === 1) {\n                                return '<span class=\"label label-success\">菜单</span>';\n                            }\n                            if (item.type === 2) {\n                                return '<span class=\"label label-warning\">按钮</span>';\n                            }\n                        }\n                    },\n                    {\n                        title: '地址',\n                        valign: 'center',\n                        width : '20%',\n                        field: 'url'\n                    },\n                    {\n                        title: '权限标识',\n                        valign: 'center',\n                        width : '20%',\n                        field: 'perms'\n                    },\n                    {\n                        title: '操作',\n                        field: 'id',\n                        align: 'center',\n                        valign: 'center',\n                        formatter: function (item, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm '\n                                + s_edit_h\n                                + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + item.menuId\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var p = '<a class=\"btn btn-primary btn-sm '\n                                + s_add_h\n                                + '\" href=\"#\" mce_href=\"#\" title=\"添加下级\" onclick=\"add(\\''\n                                + item.menuId\n                                + '\\')\"><i class=\"fa fa-plus\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm '\n                                + s_remove_h\n                                + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + item.menuId\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            return e + d + p;\n                        }\n                    }]\n            });\n}\n\nfunction reLoad() {\n    load();\n}\n\nfunction add(pId) {\n    layer.open({\n        type: 2,\n        title: '增加菜单',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/add/' + pId // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            success: function (data) {\n                if (data.code == 0) {\n                    layer.msg(\"删除成功\");\n                    reLoad();\n                } else {\n                    layer.msg(data.msg);\n                }\n            }\n        });\n    })\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '菜单修改',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction batchRemove() {\n    // var rows = $('#exampleTable').bootstrapTable('getSelections');\n\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/online/online.js",
    "content": "var prefix = \"/sys/online\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t\t// showRefresh : true,\n\t\t\t\t\t\t// showToggle : true,\n\t\t\t\t\t\t// showColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"client\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t\t\t// \"server\"\n\t\t\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\t\t\tname : $('#searchName').val()\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\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\tfield : 'id', // 列字段名\n\t\t\t\t\t\t\t\t\ttitle : '序号' // 列标题\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\tfield : 'username',\n\t\t\t\t\t\t\t\t\ttitle : '用户名'\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\tfield : 'host',\n\t\t\t\t\t\t\t\t\ttitle : '主机'\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\tfield : 'startTimestamp',\n\t\t\t\t\t\t\t\t\ttitle : '登录时间'\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\tfield : 'lastAccessTime',\n\t\t\t\t\t\t\t\t\ttitle : '最后访问时间'\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\tfield : 'timeout',\n\t\t\t\t\t\t\t\t\ttitle : '过期时间'\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\tfield : 'status',\n\t\t\t\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tif (value == 'on_line') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-success\">在线</span>';\n\t\t\t\t\t\t\t\t\t\t} else if (value == 'off_line') {\n\t\t\t\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">离线</span>';\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{\n\t\t\t\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"forceLogout(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.id\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn d;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\t// iframe层\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加用户',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add'\n\t});\n}\nfunction forceLogout(id) {\n\tlayer.confirm('确定要强制选中用户下线吗？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/forceLogout/\" + id,\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '用户修改',\n\t\tmaxmin : true,\n\t\tshadeClose : true, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction resetPwd(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '重置密码',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '400px', '260px' ],\n\t\tcontent : prefix + '/resetPwd/' + id // iframe的url\n\t});\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['userId'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {\n\t});\n}\nfunction getTreeData() {\n\t$.ajax({\n\t\ttype : \"GET\",\n\t\turl : \"/system/sysDept/tree\",\n\t\tsuccess : function(tree) {\n\t\t\tloadTree(tree);\n\t\t}\n\t});\n}\nfunction loadTree(tree) {\n\t$('#jstree').jstree({\n\t\t'core' : {\n\t\t\t'data' : tree\n\t\t},\n\t\t\"plugins\" : [ \"search\" ]\n\t});\n\t$('#jstree').jstree().open_all();\n}\n$('#jstree').on(\"changed.jstree\", function(e, data) {\n\tif (data.selected == -1) {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : '',\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t} else {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : data.selected[0],\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t}\n\n});"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/role/add.js",
    "content": "//var menuTree;\n\nvar menuIds;\n$(function() {\n\tgetMenuTreeData();\n\tvalidateRule();\n});\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tgetAllSelectNodes();\n\t\tsave();\n\t}\n});\n\nfunction getAllSelectNodes() {\n\tvar ref = $('#menuTree').jstree(true); // 获得整个树\n\n\tmenuIds = ref.get_selected(); // 获得所有选中节点的，返回值为数组\n\n\t$(\"#menuTree\").find(\".jstree-undetermined\").each(function(i, element) {\n\t\tmenuIds.push($(element).closest('.jstree-node').attr(\"id\"));\n\t});\n}\nfunction getMenuTreeData() {\n\t$.ajax({\n\t\ttype : \"GET\",\n\t\turl : \"/sys/menu/tree\",\n\t\tsuccess : function(menuTree) {\n\t\t\tloadMenuTree(menuTree);\n\t\t}\n\t});\n}\nfunction loadMenuTree(menuTree) {\n\t$('#menuTree').jstree({\n\t\t'core' : {\n\t\t\t'data' : menuTree\n\t\t},\n\t\t\"checkbox\" : {\n\t\t\t\"three_state\" : true,\n\t\t},\n\t\t\"plugins\" : [ \"wholerow\", \"checkbox\" ]\n\t});\n\t//$('#menuTree').jstree(\"open_all\");\n\n}\n\nfunction save() {\n\t$('#menuIds').val(menuIds);\n\tvar role = $('#signupForm').serialize();\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/role/save\",\n\t\tdata : role, // 你的formid\n\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\talert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\troleName : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\troleName : {\n\t\t\t\trequired : icon + \"请输入角色名\"\n\t\t\t}\n\t\t}\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/role/edit.js",
    "content": "var menuIds;\n$(function() {\n\tgetMenuTreeData();\n\tvalidateRule();\n});\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tgetAllSelectNodes();\n\t\tupdate();\n\t}\n});\nfunction loadMenuTree(menuTree) {\n\t$('#menuTree').jstree({\n\t\t\"plugins\" : [ \"wholerow\", \"checkbox\" ],\n\t\t'core' : {\n\t\t\t'data' : menuTree\n\t\t},\n\t\t\"checkbox\" : {\n\t\t\t//\"keep_selected_style\" : false,\n\t\t\t//\"undetermined\" : true\n\t\t\t//\"three_state\" : false,\n\t\t\t//\"cascade\" : ' up'\n\t\t}\n\t});\n\t$('#menuTree').jstree('open_all');\n}\nfunction getAllSelectNodes() {\n\tvar ref = $('#menuTree').jstree(true); // 获得整个树\n\tmenuIds = ref.get_selected(); // 获得所有选中节点的，返回值为数组\n\t$(\"#menuTree\").find(\".jstree-undetermined\").each(function(i, element) {\n\t\tmenuIds.push($(element).closest('.jstree-node').attr(\"id\"));\n\t});\n\tconsole.log(menuIds); \n}\nfunction getMenuTreeData() {\n\tvar roleId = $('#roleId').val();\n\t$.ajax({\n\t\ttype : \"GET\",\n\t\turl : \"/sys/menu/tree/\" + roleId,\n\t\tsuccess : function(data) {\n\t\t\tloadMenuTree(data);\n\t\t}\n\t});\n}\nfunction update() {\n\t$('#menuIds').val(menuIds);\n\tvar role = $('#signupForm').serialize();\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/role/update\",\n\t\tdata : role, // 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\talert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(r) {\n\t\t\tif (r.code == 0) {\n\t\t\t\tparent.layer.msg(r.msg);\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(r.msg);\n\t\t\t}\n\n\t\t}\n\t});\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\troleName : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\troleName : {\n\t\t\t\trequired : icon + \"请输入角色名\"\n\t\t\t}\n\t\t}\n\t});\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/role/role.js",
    "content": "var prefix = \"/sys/role\";\n$(function () {\n    load();\n});\n\nfunction load() {\n    $('#exampleTable')\n        .bootstrapTable(\n            {\n                method: 'get', // 服务器数据的请求方式 get or post\n                url: prefix + \"/list\", // 服务器数据的加载地址\n                striped: true, // 设置为true会有隔行变色效果\n                dataType: \"json\", // 服务器返回的数据类型\n                pagination: true, // 设置为true会在底部显示分页条\n                // queryParamsType : \"limit\",\n                // //设置为limit则会发送符合RESTFull格式的参数\n                singleSelect: false, // 设置为true将禁止多选\n                iconSize: 'outline',\n                toolbar: '#exampleToolbar',\n                // contentType : \"application/x-www-form-urlencoded\",\n                // //发送到服务器的数据编码类型\n                pageSize: 10, // 如果设置了分页，每页数据条数\n                pageNumber: 1, // 如果设置了分布，首页页码\n                search: true, // 是否显示搜索框\n                showColumns: true, // 是否显示内容下拉框（选择显示的列）\n                sidePagination: \"client\", // 设置在哪里进行分页，可选值为\"client\" 或者\n                // \"server\"\n                // queryParams : queryParams,\n                // //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n                // queryParamsType = 'limit' ,返回参数必须包含\n                // limit, offset, search, sort, order 否则, 需要包含:\n                // pageSize, pageNumber, searchText, sortName,\n                // sortOrder.\n                // 返回false将会终止请求\n                columns: [\n                    { // 列配置项\n                        // 数据类型，详细参数配置参见文档http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/\n                        checkbox: true\n                        // 列表中显示复选框\n                    },\n                    {\n                        field: 'roleId', // 列字段名\n                        title: '序号' // 列标题\n                    },\n                    {\n                        field: 'roleName',\n                        title: '角色名'\n                    },\n                    {\n                        field: 'remark',\n                        title: '备注'\n                    },\n                    {\n                        field: '',\n                        title: '权限'\n                    },\n                    {\n                        title: '操作',\n                        field: 'roleId',\n                        align: 'center',\n                        formatter: function (value, row, index) {\n                            var e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n                                + row.roleId\n                                + '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n                            var d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n                                + row.roleId\n                                + '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n                            return e + d;\n                        }\n                    }]\n            });\n}\n\nfunction reLoad() {\n    $('#exampleTable').bootstrapTable('refresh');\n}\n\nfunction add() {\n    // iframe层\n    layer.open({\n        type: 2,\n        title: '添加角色',\n        maxmin: true,\n        shadeClose: false, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/add' // iframe的url\n    });\n}\n\nfunction remove(id) {\n    layer.confirm('确定要删除选中的记录？', {\n        btn: ['确定', '取消']\n    }, function () {\n        $.ajax({\n            url: prefix + \"/remove\",\n            type: \"post\",\n            data: {\n                'id': id\n            },\n            success: function (r) {\n                if (r.code === 0) {\n                    layer.msg(\"删除成功\");\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    })\n\n}\n\nfunction edit(id) {\n    layer.open({\n        type: 2,\n        title: '角色修改',\n        maxmin: true,\n        shadeClose: true, // 点击遮罩关闭层\n        area: ['800px', '520px'],\n        content: prefix + '/edit/' + id // iframe的url\n    });\n}\n\nfunction batchRemove() {\n\n    var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n    if (rows.length == 0) {\n        layer.msg(\"请选择要删除的数据\");\n        return;\n    }\n    layer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n        btn: ['确定', '取消']\n    }, function () {\n        var ids = new Array();\n        $.each(rows, function (i, row) {\n            ids[i] = row['roleId'];\n        });\n        console.log(ids);\n        $.ajax({\n            type: 'POST',\n            data: {\n                \"ids\": ids\n            },\n            url: prefix + '/batchRemove',\n            success: function (r) {\n                if (r.code == 0) {\n                    layer.msg(r.msg);\n                    reLoad();\n                } else {\n                    layer.msg(r.msg);\n                }\n            }\n        });\n    }, function () {\n    });\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/user/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction getCheckedRoles() {\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction save() {\n\t$(\"#roleIds\").val(getCheckedRoles());\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/user/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2,\n\t\t\t\tremote : {\n\t\t\t\t\turl : \"/sys/user/exit\", // 后台处理程序\n\t\t\t\t\ttype : \"post\", // 数据发送方式\n\t\t\t\t\tdataType : \"json\", // 接受数据格式\n\t\t\t\t\tdata : { // 要传递的数据\n\t\t\t\t\t\tusername : function() {\n\t\t\t\t\t\t\treturn $(\"#username\").val();\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\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\",\n\t\t\t\tremote : icon + \"用户名已经存在\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\n\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/user/edit.js",
    "content": "// 以下为官方示例\n$().ready(function() {\n\tvalidateRule();\n\t// $(\"#signupForm\").validate();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$(\"#roleIds\").val(getCheckedRoles());\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/sys/user/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\talert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction getCheckedRoles() {\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction setCheckedRoles() {\n\tvar roleIds = $(\"#roleIds\").val();\n\talert(roleIds);\n\tvar adIds = \"\";\n\t$(\"input:checkbox[name=role]:checked\").each(function(i) {\n\t\tif (0 == i) {\n\t\t\tadIds = $(this).val();\n\t\t} else {\n\t\t\tadIds += (\",\" + $(this).val());\n\t\t}\n\t});\n\treturn adIds;\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : true,\n\t\t\t\tminlength : 6,\n\t\t\t\tequalTo : \"#password\"\n\t\t\t},\n\t\t\temail : {\n\t\t\t\trequired : true,\n\t\t\t\temail : true\n\t\t\t},\n\t\t\ttopic : {\n\t\t\t\trequired : \"#newsletter:checked\",\n\t\t\t\tminlength : 2\n\t\t\t},\n\t\t\tagree : \"required\"\n\t\t},\n\t\tmessages : {\n\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t},\n\t\t\tusername : {\n\t\t\t\trequired : icon + \"请输入您的用户名\",\n\t\t\t\tminlength : icon + \"用户名必须两个字符以上\"\n\t\t\t},\n\t\t\tpassword : {\n\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t},\n\t\t\tconfirm_password : {\n\t\t\t\trequired : icon + \"请再次输入密码\",\n\t\t\t\tminlength : icon + \"密码必须6个字符以上\",\n\t\t\t\tequalTo : icon + \"两次输入的密码不一致\"\n\t\t\t},\n\t\t\temail : icon + \"请输入您的E-mail\",\n\t\t}\n\t})\n}\nvar openDept = function(){\n\tlayer.open({\n\t\ttype:2,\n\t\ttitle:\"选择部门\",\n\t\tarea : [ '300px', '450px' ],\n\t\tcontent:\"/system/sysDept/treeView\"\n\t})\n}\nfunction loadDept( deptId,deptName){\n\t$(\"#deptId\").val(deptId);\n\t$(\"#deptName\").val(deptName);\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/user/gg-bootdo.js",
    "content": "/*this file is used for the bootdo project, it is a unique js file*/\n$(function(){\n\t//初始化icheck插件\n\t$(\".i-checks\").iCheck({\n\t\tcheckboxClass: 'icheckbox_square-green',\n\t\tradioClass: 'iradio_square-green'\n\t});\n\t$(\".gg-faeye\").on('mouseover',function(){\n\t\t$('#pwdOld').prop('type', 'text'); \n\t\t$('#pwd').prop('type', 'text');\n\t\t$('#confirm_password').prop('type', 'text'); \n\t});\n\t$(\".gg-faeye\").on('mouseout',function(){\n\t\t$('#pwdOld').prop('type', 'password');\n\t\t$('#pwd').prop('type', 'password'); \n\t\t$('#confirm_password').prop('type', 'password');\n\t});\n});\n/*头像裁剪*/\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    define(['jquery'], factory);\n  } else if (typeof exports === 'object') {\n    // Node / CommonJS\n    factory(require('jquery'));\n  } else {\n    factory(jQuery);\n  }\n})(function ($) {\n\n  'use strict';\n\n  var console = window.console || { log: function () {} };\n\n  function CropAvatar($element) {\n    this.$ggcontainer = $element;\n    this.$loading = this.$ggcontainer.find('.loading');\n\t\n    this.$avatarForm = this.$ggcontainer.find('.avatar-form');\n    this.$avatar = this.$avatarForm.find('img');\n    this.$avatarUpload = this.$avatarForm.find('.avatar-upload');\n    this.$avatarSrc = this.$avatarForm.find('.avatar-src');\n    this.$avatarData = this.$avatarForm.find('.avatar-data');\n    this.$avatarInput = this.$avatarForm.find('.avatar-input');\n    this.$avatarSave = this.$avatarForm.find('.avatar-save');\n    this.$avatarBtns = this.$avatarForm.find('.avatar-btns');\n\n    this.$avatarWrapper = this.$avatarForm.find('.avatar-wrapper');\n    this.$avatarPreview = this.$avatarForm.find('.avatar-preview');\n\n    this.init();\n    console.log(this);\n  }\n\n  CropAvatar.prototype = {\n    constructor: CropAvatar,\n\n    support: {\n      fileList: !!$('<input type=\"file\">').prop('files'),\n      blobURLs: !!window.URL && URL.createObjectURL,\n      formData: !!window.FormData\n    },\n\n    init: function () {\n      this.support.datauri = this.support.fileList && this.support.blobURLs;\n\n      if (!this.support.formData) {\n        this.initIframe();\n      }\n\n      this.addListener();\n    },\n\n    addListener: function () {\n      this.$avatarInput.on('change', $.proxy(this.change, this));\n      this.$avatarForm.on('submit', $.proxy(this.submit, this));\n      this.$avatarBtns.on('click', $.proxy(this.rotate, this));\n    },\n    \n    initPreview: function () {\n      var url = this.$avatar.attr('src');\n\n      this.$avatarPreview.empty().html('<img src=\"' + url + '\">');\n    },\n\n    initIframe: function () {\n      var target = 'upload-iframe-' + (new Date()).getTime(),\n          $iframe = $('<iframe>').attr({\n            name: target,\n            src: ''\n          }),\n          _this = this;\n\n      // Ready ifrmae\n      $iframe.one('load', function () {\n\n        // respond response\n        $iframe.on('load', function () {\n          var data;\n\n          try {\n            data = $(this).contents().find('body').text();\n          } catch (e) {\n            console.log(e.message);\n          }\n\n          if (data) {\n            try {\n              data = $.parseJSON(data);\n            } catch (e) {\n              console.log(e.message);\n            }\n\n            _this.submitDone(data);\n          } else {\n            _this.submitFail('Image upload failed!');\n          }\n\n          _this.submitEnd();\n\n        });\n      });\n\n      this.$iframe = $iframe;\n      this.$avatarForm.attr('target', target).after($iframe.hide());\n    },\n    \n    change: function () {\n      var files,\n          file;\n\n      if (this.support.datauri) {\n        files = this.$avatarInput.prop('files');\n\n        if (files.length > 0) {\n          file = files[0];\n\n          if (this.isImageFile(file)) {\n            if (this.url) {\n              URL.revokeObjectURL(this.url);// Revoke the old one\n                console.log(this.url);\n            }\n\n            this.url = URL.createObjectURL(file);\n            console.log(this.url);\n            this.startCropper();\n          }\n        }\n      } else {\n        file = this.$avatarInput.val();\n\n        if (this.isImageFile(file)) {\n          this.syncUpload();\n        }\n      }\n    },\n\n    submit: function () {\n      if (!this.$avatarSrc.val() && !this.$avatarInput.val()) {\n        return false;\n      }\n\n      if (this.support.formData) {\n        this.ajaxUpload();\n        return false;\n      }\n    },\n\n    rotate: function (e) {\n      var data;\n\n      if (this.active) {\n        data = $(e.target).data();\n\n        if (data.method) {\n          this.$img.cropper(data.method, data.option);\n        }\n      }\n    },\n\n    isImageFile: function (file) {\n      if (file.type) {\n        return /^image\\/\\w+$/.test(file.type);\n      } else {\n        return /\\.(jpg|jpeg|png|gif)$/.test(file);\n      }\n    },\n\n    startCropper: function () {\n      var _this = this;\n      if (this.active) {\n        this.$img.cropper('replace', this.url);\n      } else {\n        this.$img = $('<img src=\"' + this.url + '\">');\n        this.$avatarWrapper.empty().html(this.$img);\n        this.$img.cropper({\n          aspectRatio: 1,\n          preview: this.$avatarPreview.selector,\n          strict: false,\n          crop: function (data) {\n              var json = [\n                  '{\"x\":' + data.x,\n                  '\"y\":' + data.y,\n                  '\"height\":' + data.height,\n                  '\"width\":' + data.width,\n                  '\"rotate\":' + data.rotate + '}'\n              ].join();\n\n            _this.$avatarData.val(json);\n          }\n        });\n\n        this.active = true;\n      }\n    },\n\n    stopCropper: function () {\n      if (this.active) {\n        this.$img.cropper('destroy');\n        this.$img.remove();\n        this.active = false;\n      }\n    },\n\n    ajaxUpload: function () {\n      var url = this.$avatarForm.attr('action'),\n          data = new FormData(this.$avatarForm[0]),\n          _this = this;\n\n      $.ajax(url, {\n        type: 'post',\n        data: data,\n        dataType: 'json',\n        processData: false,\n        contentType: false,\n\n        beforeSend: function () {\n          _this.submitStart();\n        },\n\n        success: function (data) {\n          _this.submitDone(data);\n        },\n\n        error: function (XMLHttpRequest, textStatus, errorThrown) {\n          _this.submitFail(textStatus || errorThrown);\n        },\n\n        complete: function () {\n          _this.submitEnd();\n        }\n      });\n    },\n\n    syncUpload: function () {\n      this.$avatarSave.click();\n    },\n\n    submitStart: function () {\n      this.$loading.fadeIn();\n    },\n\n    submitDone: function (data) {\n      console.log(data);\n\n      if ($.isPlainObject(data) && data.code === 0) {\n        if (data.url) {\n          this.url = data.url;\n\n          if (this.support.datauri || this.uploaded) {\n            this.uploaded = false;\n            this.cropDone();\n          } else {\n            this.uploaded = true;\n            this.$avatarSrc.val(this.url);\n            this.startCropper();\n          }\n\n          this.$avatarInput.val('');\n          this.alert(1,data.msg);\n        } else if (data.msg) {\n          this.alert(2,data.msg);\n        }\n      } else {\n        this.alert(2,'Failed to response');\n      }\n    },\n\n    submitFail: function (msg) {\n      this.alert(2,msg);\n    },\n\n    submitEnd: function () {\n      this.$loading.fadeOut();\n    },\n\n    cropDone: function () {\n      this.$avatarForm.get(0).reset();\n      this.$avatar.attr('src', this.url);\n      this.stopCropper();\n    },\n\n    alert: function (code,msg) {\n        var alertClass=\"\";\n      if(code==1){\n        alertClass=\"alert-success\";\n      }else if(code==2){\n          alertClass=\"alert-danger\";\n      }\n      var $alert = [\n            '<div class=\"alert '+alertClass+' avater-alert\">',\n              '<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>',\n              msg,\n            '</div>'\n          ].join('');\n\n      this.$avatarUpload.after($alert);\n    }\n  };\n\n  $(function () {\n    return new CropAvatar($('#crop-avatar'));\n  });\n\n});\n\n"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/user/personal.js",
    "content": "var prefix = \"/sys/user\"\n$(function () {\n    laydate({\n        elem : '#birth'\n    });\n});\n/**\n * 基本信息提交\n */\n$(\"#base_save\").click(function () {\n    var hobbyStr = getHobbyStr();\n    $(\"#hobby\").val(hobbyStr);\n    if($(\"#basicInfoForm\").valid()){\n            $.ajax({\n                cache : true,\n                type : \"POST\",\n                url :\"/sys/user/updatePeronal\",\n                data : $('#basicInfoForm').serialize(),\n                async : false,\n                error : function(request) {\n                    laryer.alert(\"Connection error\");\n                },\n                success : function(data) {\n                    if (data.code == 0) {\n                        parent.layer.msg(\"更新成功\");\n                    } else {\n                        parent.layer.alert(data.msg)\n                    }\n                }\n            });\n        }\n\n});\n$(\"#pwd_save\").click(function () {\n    if($(\"#modifyPwd\").valid()){\n        $.ajax({\n            cache : true,\n            type : \"POST\",\n            url :\"/sys/user/resetPwd\",\n            data : $('#modifyPwd').serialize(),\n            async : false,\n            error : function(request) {\n                parent.laryer.alert(\"Connection error\");\n            },\n            success : function(data) {\n                if (data.code == 0) {\n                    parent.layer.alert(\"更新密码成功\");\n                    $(\"#photo_info\").click();\n                } else {\n                    parent.layer.alert(data.msg)\n                }\n            }\n        });\n    }\n});\nfunction getHobbyStr(){\n    var hobbyStr =\"\";\n    $(\".hobby\").each(function () {\n        if($(this).is(\":checked\")){\n            hobbyStr+=$(this).val()+\";\";\n        }\n    });\n   return hobbyStr;\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/sys/user/user.js",
    "content": "var prefix = \"/sys/user\"\n$(function() {\n\tvar deptId = '';\n\tgetTreeData();\n\tload(deptId);\n});\n\nfunction load(deptId) {\n\t$('#exampleTable')\n\t\t.bootstrapTable(\n\t\t\t{\n\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t// showRefresh : true,\n\t\t\t\t// showToggle : true,\n\t\t\t\t// showColumns : true,\n\t\t\t\ticonSize : 'outline',\n\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t// search : true, // 是否显示搜索框\n\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者\n\t\t\t\t// \"server\"\n\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t// 说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\tlimit : params.limit,\n\t\t\t\t\t\toffset : params.offset,\n\t\t\t\t\t\tname : $('#searchName').val(),\n\t\t\t\t\t\tdeptId : deptId\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t// sortOrder.\n\t\t\t\t// 返回false将会终止请求\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'userId', // 列字段名\n\t\t\t\t\t\ttitle : '序号' // 列标题\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'name',\n\t\t\t\t\t\ttitle : '姓名'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'username',\n\t\t\t\t\t\ttitle : '用户名'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'email',\n\t\t\t\t\t\ttitle : '邮箱'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'status',\n\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tif (value == '0') {\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">禁用</span>';\n\t\t\t\t\t\t\t} else if (value == '1') {\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">正常</span>';\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\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\tvar e = '<a  class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ row.userId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit \"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t+ row.userId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm ' + s_resetPwd_h + '\" href=\"#\" title=\"重置密码\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t+ row.userId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\treturn e + d + f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\t// iframe层\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加用户',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add'\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : \"/sys/user/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'id' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '用户修改',\n\t\tmaxmin : true,\n\t\tshadeClose : false,\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction resetPwd(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '重置密码',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '400px', '260px' ],\n\t\tcontent : prefix + '/resetPwd/' + id // iframe的url\n\t});\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['userId'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}\nfunction getTreeData() {\n\t$.ajax({\n\t\ttype : \"GET\",\n\t\turl : \"/system/sysDept/tree\",\n\t\tsuccess : function(tree) {\n\t\t\tloadTree(tree);\n\t\t}\n\t});\n}\nfunction loadTree(tree) {\n\t$('#jstree').jstree({\n\t\t'core' : {\n\t\t\t'data' : tree\n\t\t},\n\t\t\"plugins\" : [ \"search\" ]\n\t});\n\t$('#jstree').jstree().open_all();\n}\n$('#jstree').on(\"changed.jstree\", function(e, data) {\n\tif (data.selected == -1) {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : '',\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh', opt);\n\t} else {\n\t\tvar opt = {\n\t\t\tquery : {\n\t\t\t\tdeptId : data.selected[0],\n\t\t\t}\n\t\t}\n\t\t$('#exampleTable').bootstrapTable('refresh',opt);\n\t}\n\n});"
  },
  {
    "path": "src/main/resources/static/js/appjs/system/sysDept/add.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/system/sysDept/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/system/sysDept/edit.js",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/system/sysDept/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/static/js/appjs/system/sysDept/sysDept.js",
    "content": "\nvar prefix = \"/system/sysDept\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t.bootstrapTreeTable(\n\t\t\t{\n\t\t\t\tid : 'deptId',\n\t\t\t\tcode : 'deptId',\n                parentCode : 'parentId',\n\t\t\t\ttype : \"GET\", // 请求数据的ajax类型\n\t\t\t\turl : prefix + '/list', // 请求数据的ajax的url\n\t\t\t\tajaxParams : {}, // 请求数据的ajax的data属性\n\t\t\t\texpandColumn : '1', // 在哪一列上面显示展开按钮\n\t\t\t\tstriped : true, // 是否各行渐变色\n\t\t\t\tbordered : true, // 是否显示边框\n\t\t\t\texpandAll : false, // 是否全部展开\n\t\t\t\t// toolbar : '#exampleToolbar',\n\t\t\t\tcolumns : [\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle : '编号',\n\t\t\t\t\t\tfield : 'deptId',\n\t\t\t\t\t\tvisible : false,\n\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\tvalign : 'center',\n\t\t\t\t\t\twidth : '50px',\n\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'name',\n\t\t\t\t\t\ttitle : '部门名称',\n                        valign : 'center',\n\t\t\t\t\t\twitth :20\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'orderNum',\n\t\t\t\t\t\ttitle : '排序',\n                        align : 'center',\n                        valign : 'center',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfield : 'delFlag',\n\t\t\t\t\t\ttitle : '状态',\n\t\t\t\t\t\talign : 'center',\n                        valign : 'center',\n\t\t\t\t\t\tformatter : function(item, index) {\n\t\t\t\t\t\t\tif (item.delFlag == '0') {\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-danger\">禁用</span>';\n\t\t\t\t\t\t\t} else if (item.delFlag == '1') {\n\t\t\t\t\t\t\t\treturn '<span class=\"label label-primary\">正常</span>';\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\t\ttitle : '操作',\n\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\talign : 'center',\n                        valign : 'center',\n\t\t\t\t\t\tformatter : function(item, index) {\n\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm ' + s_edit_h + '\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t+ item.deptId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\tvar a = '<a class=\"btn btn-primary btn-sm ' + s_add_h + '\" href=\"#\" title=\"增加下級\"  mce_href=\"#\" onclick=\"add(\\''\n\t\t\t\t\t\t\t\t+ item.deptId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-plus\"></i></a> ';\n\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm ' + s_remove_h + '\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"removeone(\\''\n\t\t\t\t\t\t\t\t+ item.deptId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm＂ href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t+ item.deptId\n\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\treturn e + a + d;\n\t\t\t\t\t\t}\n\t\t\t\t\t} ]\n\t\t\t});\n}\nfunction reLoad() {\n\tload();\n}\nfunction add(pId) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add/' + pId\n\t});\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction removeone(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix + \"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'deptId' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['deptId'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {});\n}\n\n"
  },
  {
    "path": "src/main/resources/static/js/contabs.js",
    "content": "\n$(function () {\n    //计算元素集合的总宽度\n    function calSumWidth(elements) {\n        var width = 0;\n        $(elements).each(function () {\n            width += $(this).outerWidth(true);\n        });\n        return width;\n    }\n    //滚动到指定选项卡\n    function scrollToTab(element) {\n        var marginLeftVal = calSumWidth($(element).prevAll()), marginRightVal = calSumWidth($(element).nextAll());\n        // 可视区域非tab宽度\n        var tabOuterWidth = calSumWidth($(\".content-tabs\").children().not(\".J_menuTabs\"));\n        //可视区域tab宽度\n        var visibleWidth = $(\".content-tabs\").outerWidth(true) - tabOuterWidth;\n        //实际滚动宽度\n        var scrollVal = 0;\n        if ($(\".page-tabs-content\").outerWidth() < visibleWidth) {\n            scrollVal = 0;\n        } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {\n            if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {\n                scrollVal = marginLeftVal;\n                var tabElement = element;\n                while ((scrollVal - $(tabElement).outerWidth()) > ($(\".page-tabs-content\").outerWidth() - visibleWidth)) {\n                    scrollVal -= $(tabElement).prev().outerWidth();\n                    tabElement = $(tabElement).prev();\n                }\n            }\n        } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {\n            scrollVal = marginLeftVal - $(element).prev().outerWidth(true);\n        }\n        $('.page-tabs-content').animate({\n            marginLeft: 0 - scrollVal + 'px'\n        }, \"fast\");\n    }\n    //查看左侧隐藏的选项卡\n    function scrollTabLeft() {\n        var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));\n        // 可视区域非tab宽度\n        var tabOuterWidth = calSumWidth($(\".content-tabs\").children().not(\".J_menuTabs\"));\n        //可视区域tab宽度\n        var visibleWidth = $(\".content-tabs\").outerWidth(true) - tabOuterWidth;\n        //实际滚动宽度\n        var scrollVal = 0;\n        if ($(\".page-tabs-content\").width() < visibleWidth) {\n            return false;\n        } else {\n            var tabElement = $(\".J_menuTab:first\");\n            var offsetVal = 0;\n            while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {//找到离当前tab最近的元素\n                offsetVal += $(tabElement).outerWidth(true);\n                tabElement = $(tabElement).next();\n            }\n            offsetVal = 0;\n            if (calSumWidth($(tabElement).prevAll()) > visibleWidth) {\n                while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {\n                    offsetVal += $(tabElement).outerWidth(true);\n                    tabElement = $(tabElement).prev();\n                }\n                scrollVal = calSumWidth($(tabElement).prevAll());\n            }\n        }\n        $('.page-tabs-content').animate({\n            marginLeft: 0 - scrollVal + 'px'\n        }, \"fast\");\n    }\n    //查看右侧隐藏的选项卡\n    function scrollTabRight() {\n        var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));\n        // 可视区域非tab宽度\n        var tabOuterWidth = calSumWidth($(\".content-tabs\").children().not(\".J_menuTabs\"));\n        //可视区域tab宽度\n        var visibleWidth = $(\".content-tabs\").outerWidth(true) - tabOuterWidth;\n        //实际滚动宽度\n        var scrollVal = 0;\n        if ($(\".page-tabs-content\").width() < visibleWidth) {\n            return false;\n        } else {\n            var tabElement = $(\".J_menuTab:first\");\n            var offsetVal = 0;\n            while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {//找到离当前tab最近的元素\n                offsetVal += $(tabElement).outerWidth(true);\n                tabElement = $(tabElement).next();\n            }\n            offsetVal = 0;\n            while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {\n                offsetVal += $(tabElement).outerWidth(true);\n                tabElement = $(tabElement).next();\n            }\n            scrollVal = calSumWidth($(tabElement).prevAll());\n            if (scrollVal > 0) {\n                $('.page-tabs-content').animate({\n                    marginLeft: 0 - scrollVal + 'px'\n                }, \"fast\");\n            }\n        }\n    }\n\n    //通过遍历给菜单项加上data-index属性\n    $(\".J_menuItem\").each(function (index) {\n        if (!$(this).attr('data-index')) {\n            $(this).attr('data-index', index);\n        }\n    });\n\n    function menuItem() {\n        // 获取标识数据\n        var dataUrl = $(this).attr('href'),\n            dataIndex = $(this).data('index'),\n            menuName = $.trim($(this).text()),\n            flag = true;\n        if (dataUrl == undefined || $.trim(dataUrl).length == 0)return false;\n\n        // 选项卡菜单已存在\n        $('.J_menuTab').each(function () {\n            if ($(this).data('id') == dataUrl) {\n                if (!$(this).hasClass('active')) {\n                    $(this).addClass('active').siblings('.J_menuTab').removeClass('active');\n                    scrollToTab(this);\n                    // 显示tab对应的内容区\n                    $('.J_mainContent .J_iframe').each(function () {\n                        if ($(this).data('id') == dataUrl) {\n                            $(this).show().siblings('.J_iframe').hide();\n                            return false;\n                        }\n                    });\n                }\n                flag = false;\n                return false;\n            }\n        });\n\n        // 选项卡菜单不存在\n        if (flag) {\n            var str = '<a href=\"javascript:;\" class=\"active J_menuTab\" data-id=\"' + dataUrl + '\">' + menuName + ' <i class=\"fa fa-times-circle\"></i></a>';\n            $('.J_menuTab').removeClass('active');\n\n            // 添加选项卡对应的iframe\n            var str1 = '<iframe class=\"J_iframe\" name=\"iframe' + dataIndex + '\" width=\"100%\" height=\"100%\" src=\"' + dataUrl + '\" frameborder=\"0\" data-id=\"' + dataUrl + '\" seamless></iframe>';\n            $('.J_mainContent').find('iframe.J_iframe').hide().parents('.J_mainContent').append(str1);\n\n            //显示loading提示\n//            var loading = layer.load();\n//\n//            $('.J_mainContent iframe:visible').load(function () {\n//                //iframe加载完成后隐藏loading提示\n//                layer.close(loading);\n//            });\n            // 添加选项卡\n            $('.J_menuTabs .page-tabs-content').append(str);\n            scrollToTab($('.J_menuTab.active'));\n        }\n        return false;\n    }\n\n    $('.J_menuItem').on('click', menuItem);\n\n    // 关闭选项卡菜单\n    function closeTab() {\n        var closeTabId = $(this).parents('.J_menuTab').data('id');\n        var currentWidth = $(this).parents('.J_menuTab').width();\n\n        // 当前元素处于活动状态\n        if ($(this).parents('.J_menuTab').hasClass('active')) {\n\n            // 当前元素后面有同辈元素，使后面的一个元素处于活动状态\n            if ($(this).parents('.J_menuTab').next('.J_menuTab').size()) {\n\n                var activeId = $(this).parents('.J_menuTab').next('.J_menuTab:eq(0)').data('id');\n                $(this).parents('.J_menuTab').next('.J_menuTab:eq(0)').addClass('active');\n\n                $('.J_mainContent .J_iframe').each(function () {\n                    if ($(this).data('id') == activeId) {\n                        $(this).show().siblings('.J_iframe').hide();\n                        return false;\n                    }\n                });\n\n                var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left'));\n                if (marginLeftVal < 0) {\n                    $('.page-tabs-content').animate({\n                        marginLeft: (marginLeftVal + currentWidth) + 'px'\n                    }, \"fast\");\n                }\n\n                //  移除当前选项卡\n                $(this).parents('.J_menuTab').remove();\n\n                // 移除tab对应的内容区\n                $('.J_mainContent .J_iframe').each(function () {\n                    if ($(this).data('id') == closeTabId) {\n                        $(this).remove();\n                        return false;\n                    }\n                });\n            }\n\n            // 当前元素后面没有同辈元素，使当前元素的上一个元素处于活动状态\n            if ($(this).parents('.J_menuTab').prev('.J_menuTab').size()) {\n                var activeId = $(this).parents('.J_menuTab').prev('.J_menuTab:last').data('id');\n                $(this).parents('.J_menuTab').prev('.J_menuTab:last').addClass('active');\n                $('.J_mainContent .J_iframe').each(function () {\n                    if ($(this).data('id') == activeId) {\n                        $(this).show().siblings('.J_iframe').hide();\n                        return false;\n                    }\n                });\n\n                //  移除当前选项卡\n                $(this).parents('.J_menuTab').remove();\n\n                // 移除tab对应的内容区\n                $('.J_mainContent .J_iframe').each(function () {\n                    if ($(this).data('id') == closeTabId) {\n                        $(this).remove();\n                        return false;\n                    }\n                });\n            }\n        }\n        // 当前元素不处于活动状态\n        else {\n            //  移除当前选项卡\n            $(this).parents('.J_menuTab').remove();\n\n            // 移除相应tab对应的内容区\n            $('.J_mainContent .J_iframe').each(function () {\n                if ($(this).data('id') == closeTabId) {\n                    $(this).remove();\n                    return false;\n                }\n            });\n            scrollToTab($('.J_menuTab.active'));\n        }\n        return false;\n    }\n\n    $('.J_menuTabs').on('click', '.J_menuTab i', closeTab);\n\n    //关闭其他选项卡\n    function closeOtherTabs(){\n        $('.page-tabs-content').children(\"[data-id]\").not(\":first\").not(\".active\").each(function () {\n            $('.J_iframe[data-id=\"' + $(this).data('id') + '\"]').remove();\n            $(this).remove();\n        });\n        $('.page-tabs-content').css(\"margin-left\", \"0\");\n    }\n    $('.J_tabCloseOther').on('click', closeOtherTabs);\n\n    //滚动到已激活的选项卡\n    function showActiveTab(){\n        scrollToTab($('.J_menuTab.active'));\n    }\n    $('.J_tabShowActive').on('click', showActiveTab);\n\n\n    // 点击选项卡菜单\n    function activeTab() {\n        if (!$(this).hasClass('active')) {\n            var currentId = $(this).data('id');\n            // 显示tab对应的内容区\n            $('.J_mainContent .J_iframe').each(function () {\n                if ($(this).data('id') == currentId) {\n                    $(this).show().siblings('.J_iframe').hide();\n                    return false;\n                }\n            });\n            $(this).addClass('active').siblings('.J_menuTab').removeClass('active');\n            scrollToTab(this);\n        }\n    }\n\n    $('.J_menuTabs').on('click', '.J_menuTab', activeTab);\n\n    //刷新iframe\n    function refreshTab() {\n        var target = $('.J_iframe[data-id=\"' + $(this).data('id') + '\"]');\n        var url = target.attr('src');\n//        //显示loading提示\n//        var loading = layer.load();\n//        target.attr('src', url).load(function () {\n//            //关闭loading提示\n//            layer.close(loading);\n//        });\n    }\n\n    $('.J_menuTabs').on('dblclick', '.J_menuTab', refreshTab);\n\n    // 左移按扭\n    $('.J_tabLeft').on('click', scrollTabLeft);\n\n    // 右移按扭\n    $('.J_tabRight').on('click', scrollTabRight);\n\n    // 关闭全部\n    $('.J_tabCloseAll').on('click', function () {\n        $('.page-tabs-content').children(\"[data-id]\").not(\":first\").each(function () {\n            $('.J_iframe[data-id=\"' + $(this).data('id') + '\"]').remove();\n            $(this).remove();\n        });\n        $('.page-tabs-content').children(\"[data-id]:first\").each(function () {\n            $('.J_iframe[data-id=\"' + $(this).data('id') + '\"]').show();\n            $(this).addClass(\"active\");\n        });\n        $('.page-tabs-content').css(\"margin-left\", \"0\");\n    });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/content.js",
    "content": "var $parentNode = window.parent.document;\n\nfunction $childNode(name) {\n    return window.frames[name]\n}\n\n// tooltips\n$('.tooltip-demo').tooltip({\n    selector: \"[data-toggle=tooltip]\",\n    container: \"body\"\n});\n\n// 使用animation.css修改Bootstrap Modal\n$('.modal').appendTo(\"body\");\n\n$(\"[data-toggle=popover]\").popover();\n\n//折叠ibox\n$('.collapse-link').click(function () {\n    var ibox = $(this).closest('div.ibox');\n    var button = $(this).find('i');\n    var content = ibox.find('div.ibox-content');\n    content.slideToggle(200);\n    button.toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');\n    ibox.toggleClass('').toggleClass('border-bottom');\n    setTimeout(function () {\n        ibox.resize();\n        ibox.find('[id^=map-]').resize();\n    }, 50);\n});\n\n//关闭ibox\n$('.close-link').click(function () {\n    var content = $(this).closest('div.ibox');\n    content.remove();\n});\n\n//判断当前页面是否在iframe中\n//if (top == this) {\n//    var gohome = '<div class=\"gohome\"><a class=\"animated bounceInUp\" href=\"index.html?v=4.0\" title=\"返回首页\"><i class=\"fa fa-home\"></i></a></div>';\n//    $('body').append(gohome);\n//}\n\n//animation.css\nfunction animationHover(element, animation) {\n    element = $(element);\n    element.hover(\n        function () {\n            element.addClass('animated ' + animation);\n        },\n        function () {\n            //动画完成之前移除class\n            window.setTimeout(function () {\n                element.removeClass('animated ' + animation);\n            }, 2000);\n        });\n}\n\n//拖动面板\nfunction WinMove() {\n    var element = \"[class*=col]\";\n    var handle = \".ibox-title\";\n    var connect = \"[class*=col]\";\n    $(element).sortable({\n            handle: handle,\n            connectWith: connect,\n            tolerance: 'pointer',\n            forcePlaceholderSize: true,\n            opacity: 0.8,\n        })\n        .disableSelection();\n};\n\n\n//编辑器新增的ajax上传图片函数\nfunction sendFile(files, editor, $editable) {\n    var size = files[0].size;\n    if((size / 1024 / 1024) > 2) {\n        alert(\"图片大小不能超过2M...\");\n        return false;\n    }\n    console.log(\"size=\"+size);\n    var formData = new FormData();\n    formData.append(\"file\", files[0]);\n    $.ajax({\n        data : formData,\n        type : \"POST\",\n        url : \"/common/sysFile/upload\",    // 图片上传出来的url，返回的是图片上传后的路径，http格式\n        cache : false,\n        contentType : false,\n        processData : false,\n        dataType : \"json\",\n        success: function(data) {//data是返回的hash,key之类的值，key是定义的文件名\n            $('.summernote').summernote('insertImage',data.fileName);\n        },\n        error:function(){\n            alert(\"上传失败\");\n        }\n    });\n}\n"
  },
  {
    "path": "src/main/resources/static/js/demo/bootstrap-table-demo.js",
    "content": "/*!\n * Remark (http://getbootstrapadmin.com/remark)\n * Copyright 2015 amazingsurge\n * Licensed under the Themeforest Standard Licenses\n */\nfunction cellStyle(value, row, index) {\n  var classes = ['active', 'success', 'info', 'warning', 'danger'];\n\n  if (index % 2 === 0 && index / 2 < classes.length) {\n    return {\n      classes: classes[index / 2]\n    };\n  }\n  return {};\n}\n\nfunction rowStyle(row, index) {\n  var classes = ['active', 'success', 'info', 'warning', 'danger'];\n\n  if (index % 2 === 0 && index / 2 < classes.length) {\n    return {\n      classes: classes[index / 2]\n    };\n  }\n  return {};\n}\n\nfunction scoreSorter(a, b) {\n  if (a > b) return 1;\n  if (a < b) return -1;\n  return 0;\n}\n\nfunction nameFormatter(value) {\n  return value + '<i class=\"icon wb-book\" aria-hidden=\"true\"></i> ';\n}\n\nfunction starsFormatter(value) {\n  return '<i class=\"icon wb-star\" aria-hidden=\"true\"></i> ' + value;\n}\n\nfunction queryParams() {\n  return {\n    type: 'owner',\n    sort: 'updated',\n    direction: 'desc',\n    per_page: 100,\n    page: 1\n  };\n}\n\nfunction buildTable($el, cells, rows) {\n  var i, j, row,\n    columns = [],\n    data = [];\n\n  for (i = 0; i < cells; i++) {\n    columns.push({\n      field: '字段' + i,\n      title: '单元' + i\n    });\n  }\n  for (i = 0; i < rows; i++) {\n    row = {};\n    for (j = 0; j < cells; j++) {\n      row['字段' + j] = 'Row-' + i + '-' + j;\n    }\n    data.push(row);\n  }\n  $el.bootstrapTable('destroy').bootstrapTable({\n    columns: columns,\n    data: data,\n    iconSize: 'outline',\n    icons: {\n      columns: 'glyphicon-list'\n    }\n  });\n}\n\n(function(document, window, $) {\n  'use strict';\n\n  // Example Bootstrap Table From Data\n  // ---------------------------------\n  (function() {\n    var bt_data = [{\n      \"Tid\": \"1\",\n      \"First\": \"奔波儿灞\",\n      \"sex\": \"男\",\n      \"Score\": \"50\"\n    }, {\n      \"Tid\": \"2\",\n      \"First\": \"灞波儿奔\",\n      \"sex\": \"男\",\n      \"Score\": \"94\"\n    }, {\n      \"Tid\": \"3\",\n      \"First\": \"作家崔成浩\",\n      \"sex\": \"男\",\n      \"Score\": \"80\"\n    }, {\n      \"Tid\": \"4\",\n      \"First\": \"韩寒\",\n      \"sex\": \"男\",\n      \"Score\": \"67\"\n    }, {\n      \"Tid\": \"5\",\n      \"First\": \"郭敬明\",\n      \"sex\": \"男\",\n      \"Score\": \"100\"\n    }, {\n      \"Tid\": \"6\",\n      \"First\": \"马云\",\n      \"sex\": \"男\",\n      \"Score\": \"77\"\n    }, {\n      \"Tid\": \"7\",\n      \"First\": \"范爷\",\n      \"sex\": \"女\",\n      \"Score\": \"87\"\n    }];\n\n\n    $('#exampleTableFromData').bootstrapTable({\n      data: bt_data,\n      // mobileResponsive: true,\n      height: \"250\"\n    });\n  })();\n\n  // Example Bootstrap Table Columns\n  // -------------------------------\n  (function() {\n    $('#exampleTableColumns').bootstrapTable({\n      url: \"/sys/user/list\",\n      height: \"400\",\n      iconSize: 'outline',\n      showColumns: true,\n      icons: {\n        refresh: 'glyphicon-repeat',\n        toggle: 'glyphicon-list-alt',\n        columns: 'glyphicon-list'\n      }\n    });\n  })();\n  //\n\n\n  // Example Bootstrap Table Large Columns\n  // -------------------------------------\n  buildTable($('#exampleTableLargeColumns'), 50, 50);\n\n\n  // Example Bootstrap Table Toolbar\n  // -------------------------------\n  (function() {\n    $('#exampleTableToolbar').bootstrapTable({\n      url: \"js/demo/bootstrap_table_test2.json\",\n      search: true,\n      showRefresh: true,\n      showToggle: true,\n      showColumns: true,\n      toolbar: '#exampleToolbar',\n      iconSize: 'outline',\n      icons: {\n        refresh: 'glyphicon-repeat',\n        toggle: 'glyphicon-list-alt',\n        columns: 'glyphicon-list'\n      }\n    });\n  })();\n\n\n  // Example Bootstrap Table Events\n  // ------------------------------\n  (function() {\n    $('#exampleTableEvents').bootstrapTable({\n      url: \"js/demo/bootstrap_table_test.json\",\n      search: true,\n      pagination: true,\n      showRefresh: true,\n      showToggle: true,\n      showColumns: true,\n      iconSize: 'outline',\n      toolbar: '#exampleTableEventsToolbar',\n      icons: {\n        refresh: 'glyphicon-repeat',\n        toggle: 'glyphicon-list-alt',\n        columns: 'glyphicon-list'\n      }\n    });\n\n    var $result = $('#examplebtTableEventsResult');\n\n    $('#exampleTableEvents').on('all.bs.table', function(e, name, args) {\n        console.log('Event:', name, ', data:', args);\n      })\n      .on('click-row.bs.table', function(e, row, $element) {\n        $result.text('Event: click-row.bs.table');\n      })\n      .on('dbl-click-row.bs.table', function(e, row, $element) {\n        $result.text('Event: dbl-click-row.bs.table');\n      })\n      .on('sort.bs.table', function(e, name, order) {\n        $result.text('Event: sort.bs.table');\n      })\n      .on('check.bs.table', function(e, row) {\n        $result.text('Event: check.bs.table');\n      })\n      .on('uncheck.bs.table', function(e, row) {\n        $result.text('Event: uncheck.bs.table');\n      })\n      .on('check-all.bs.table', function(e) {\n        $result.text('Event: check-all.bs.table');\n      })\n      .on('uncheck-all.bs.table', function(e) {\n        $result.text('Event: uncheck-all.bs.table');\n      })\n      .on('load-success.bs.table', function(e, data) {\n        $result.text('Event: load-success.bs.table');\n      })\n      .on('load-error.bs.table', function(e, status) {\n        $result.text('Event: load-error.bs.table');\n      })\n      .on('column-switch.bs.table', function(e, field, checked) {\n        $result.text('Event: column-switch.bs.table');\n      })\n      .on('page-change.bs.table', function(e, size, number) {\n        $result.text('Event: page-change.bs.table');\n      })\n      .on('search.bs.table', function(e, text) {\n        $result.text('Event: search.bs.table');\n      });\n  })();\n})(document, window, jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/demo/bootstrap_table_test.json",
    "content": "\n[\n    {\n        \"id\": 0,\n        \"name\": \"测试0\",\n        \"price\": \"&yen;0\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 1,\n        \"name\": \"测试1\",\n        \"price\": \"&yen;1\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 2,\n        \"name\": \"测试2\",\n        \"price\": \"&yen;2\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 3,\n        \"name\": \"测试3\",\n        \"price\": \"&yen;3\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 4,\n        \"name\": \"测试4\",\n        \"price\": \"&yen;4\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 5,\n        \"name\": \"测试5\",\n        \"price\": \"&yen;5\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 6,\n        \"name\": \"测试6\",\n        \"price\": \"&yen;6\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 7,\n        \"name\": \"测试7\",\n        \"price\": \"&yen;7\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 8,\n        \"name\": \"测试8\",\n        \"price\": \"&yen;8\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 9,\n        \"name\": \"测试9\",\n        \"price\": \"&yen;9\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 10,\n        \"name\": \"测试10\",\n        \"price\": \"&yen;10\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 11,\n        \"name\": \"测试11\",\n        \"price\": \"&yen;11\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 12,\n        \"name\": \"测试12\",\n        \"price\": \"&yen;12\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 13,\n        \"name\": \"测试13\",\n        \"price\": \"&yen;13\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 14,\n        \"name\": \"测试14\",\n        \"price\": \"&yen;14\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 15,\n        \"name\": \"测试15\",\n        \"price\": \"&yen;15\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 16,\n        \"name\": \"测试16\",\n        \"price\": \"&yen;16\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 17,\n        \"name\": \"测试17\",\n        \"price\": \"&yen;17\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 18,\n        \"name\": \"测试18\",\n        \"price\": \"&yen;18\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 19,\n        \"name\": \"测试19\",\n        \"price\": \"&yen;19\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    },\n    {\n        \"id\": 20,\n        \"name\": \"测试20\",\n        \"price\": \"&yen;20\",\n        \"column1\": \"c10\",\n        \"column2\": \"c20\",\n        \"column3\": \"c30\",\n        \"column4\": \"c40\"\n    }\n]\n"
  },
  {
    "path": "src/main/resources/static/js/demo/bootstrap_table_test2.json",
    "content": "\n[\n    {\n        \"name\": \"asSelect\",\n        \"star\": 777,\n        \"license\": \"MIT\",\n        \"description\": \"A jQuery plugin to select multiple elements with checkboxes and radio:)\",\n        \"url\": \"<a href='https://github.com/amazingSurger/jquery-asSelect'>https://github.com/amazingSurger/jquery-asSelect</a>\"\n    },\n    {\n        \"name\": \"Bootstrap Table\",\n        \"star\": 778,\n        \"license\": \"MIT & XXX\",\n        \"description\": \"Bootstrap table displays data in a tabular format and offers rich support to radio, checkbox, sort, pagination and so on. \",\n        \"url\": \"<a href='https://github.com/wenzhixin/bootstrap-table'>https://github.com/wenzhixin/bootstrap-table</a>\"\n    },\n    {\n        \"name\": \"asDatepicker\",\n        \"star\": 779,\n        \"license\": \"MIT\",\n        \"description\": \"A jQuery datepicker plugin for best .\",\n        \"url\": \"<a href='https://github.com/amazingSurger/jquery-asDatepicker'>https://github.com/amazingSurger/jquery-asDatepicker</a>\"\n    },\n    {\n        \"name\": \"asColorpicker\",\n        \"star\": 780,\n        \"license\": \"MIT\",\n        \"description\": \"A jQuery colorpicker for best .\",\n        \"url\": \"<a href='https://github.com/amazingSurger/jquery-asColorpicker'>https://github.com/amazingSurger/jquery-asColorpicker</a>\"\n    }\n]\n"
  },
  {
    "path": "src/main/resources/static/js/demo/echarts-demo.js",
    "content": "$(function () {\n\n    // var lineoption = {\n    //     title : {\n    //         text: '未来一周气温变化'\n    //     },\n    //     tooltip : {\n    //         trigger: 'axis'\n    //     },\n    //     legend: {\n    //         data:['最高气温','最低气温']\n    //     },\n    //     grid:{\n    //         x:40,\n    //         x2:40,\n    //         y2:24\n    //     },\n    //     calculable : true,\n    //     xAxis : [\n    //         {\n    //             type : 'category',\n    //             boundaryGap : false,\n    //             data : ['周一','周二','周三','周四','周五','周六','周日']\n    //         }\n    //     ],\n    //     yAxis : [\n    //         {\n    //             type : 'value',\n    //             axisLabel : {\n    //                 formatter: '{value} °C'\n    //             }\n    //         }\n    //     ],\n    //     series : [\n    //         {\n    //             name:'最高气温',\n    //             type:'line',\n    //             data:[11, 11, 15, 13, 12, 13, 10],\n    //             markPoint : {\n    //                 data : [\n    //                     {type : 'max', name: '最大值'},\n    //                     {type : 'min', name: '最小值'}\n    //                 ]\n    //             },\n    //             markLine : {\n    //                 data : [\n    //                     {type : 'average', name: '平均值'}\n    //                 ]\n    //             }\n    //         },\n    //         {\n    //             name:'最低气温',\n    //             type:'line',\n    //             data:[1, -2, 2, 5, 3, 2, 0],\n    //             markPoint : {\n    //                 data : [\n    //                     {name : '周最低', value : -2, xAxis: 1, yAxis: -1.5}\n    //                 ]\n    //             },\n    //             markLine : {\n    //                 data : [\n    //                     {type : 'average', name : '平均值'}\n    //                 ]\n    //             }\n    //         }\n    //     ]\n    // };\n    $.getJSON('/echarts/pie',function(lineoption){\n        // lineoption = {\n        //     title: {\n        //         text: 'ECharts 入门示例'\n        //     },\n        //     tooltip : {\n        //         trigger: 'axis'\n        //     },\n        //     legend: {\n        //         data:['销量']\n        //     },\n        //     calculable : true,\n        //     xAxis: {\n        //         data: [\"衬衫\",\"羊毛衫\",\"雪纺衫\",\"裤子\",\"高跟鞋\",\"袜子\"]\n        //     },\n        //     yAxis: {data:null},\n        //     series: [{\n        //         name: '销量',\n        //         type: 'pie',\n        //         data: [5, 20, 36, 10, 10, 20]\n        //     }]\n        // };\n        var lineChart = echarts.init(document.getElementById(\"echarts-line-chart\"));\n        lineChart.setOption(lineoption);\n        $(window).resize(lineChart.resize);\n    })\n\n\n    var barChart = echarts.init(document.getElementById(\"echarts-bar-chart\"));\n    var baroption = {\n        title : {\n            text: '某地区蒸发量和降水量'\n        },\n        tooltip : {\n            trigger: 'axis'\n        },\n        legend: {\n            data:['蒸发量','降水量']\n        },\n        grid:{\n            x:30,\n            x2:40,\n            y2:24\n        },\n        calculable : true,\n        xAxis : [\n            {\n                type : 'category',\n                data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']\n            }\n        ],\n        yAxis : [\n            {\n                type : 'value'\n            }\n        ],\n        series : [\n            {\n                name:'蒸发量',\n                type:'bar',\n                data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],\n                markPoint : {\n                    data : [\n                        {type : 'max', name: '最大值'},\n                        {type : 'min', name: '最小值'}\n                    ]\n                },\n                markLine : {\n                    data : [\n                        {type : 'average', name: '平均值'}\n                    ]\n                }\n            },\n            {\n                name:'降水量',\n                type:'bar',\n                data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],\n                markPoint : {\n                    data : [\n                        {name : '年最高', value : 182.2, xAxis: 7, yAxis: 183, symbolSize:18},\n                        {name : '年最低', value : 2.3, xAxis: 11, yAxis: 3}\n                    ]\n                },\n                markLine : {\n                    data : [\n                        {type : 'average', name : '平均值'}\n                    ]\n                }\n            }\n        ]\n    };\n    barChart.setOption(baroption);\n\n    window.onresize = barChart.resize;\n\n    var scatterChart = echarts.init(document.getElementById(\"echarts-scatter-chart\"));\n    var scatteroption = {\n        title : {\n            text: '男性女性身高体重分布',\n            subtext: '抽样调查来自: Heinz  2003'\n        },\n        tooltip : {\n            trigger: 'axis',\n            showDelay : 0,\n            axisPointer:{\n                type : 'cross',\n                lineStyle: {\n                    type : 'dashed',\n                    width : 1\n                }\n            }\n        },\n        legend: {\n            data:['女性','男性']\n        },\n        grid:{\n            x:45,\n            x2:40,\n            y2:24\n        },\n        xAxis : [\n            {\n                type : 'value',\n                scale:true,\n                axisLabel : {\n                    formatter: '{value} cm'\n                }\n            }\n        ],\n        yAxis : [\n            {\n                type : 'value',\n                scale:true,\n                axisLabel : {\n                    formatter: '{value} kg'\n                }\n            }\n        ],\n        series : [\n            {\n                name:'女性',\n                type:'scatter',\n                tooltip : {\n                    trigger: 'item',\n                    formatter : function (params) {\n                        if (params.value.length > 1) {\n                            return params.seriesName + ' :<br/>'\n                               + params.value[0] + 'cm '\n                               + params.value[1] + 'kg ';\n                        }\n                        else {\n                            return params.seriesName + ' :<br/>'\n                               + params.name + ' : '\n                               + params.value + 'kg ';\n                        }\n                    }\n                },\n                data: [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],\n                    [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],\n                    [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],\n                    [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],\n                    [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],\n                    [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],\n                    [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],\n                    [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],\n                    [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],\n                    [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],\n                    [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],\n                    [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],\n                    [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],\n                    [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],\n                    [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],\n                    [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],\n                    [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],\n                    [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],\n                    [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],\n                    [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],\n                    [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],\n                    [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],\n                    [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],\n                    [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],\n                    [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],\n                    [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],\n                    [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],\n                    [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],\n                    [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],\n                    [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],\n                    [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],\n                    [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],\n                    [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],\n                    [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],\n                    [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],\n                    [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],\n                    [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],\n                    [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],\n                    [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],\n                    [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],\n                    [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],\n                    [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],\n                    [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],\n                    [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],\n                    [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],\n                    [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],\n                    [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],\n                    [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],\n                    [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],\n                    [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],\n                    [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],\n                    [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]\n                ],\n                markPoint : {\n                    data : [\n                        {type : 'max', name: '最大值'},\n                        {type : 'min', name: '最小值'}\n                    ]\n                },\n                markLine : {\n                    data : [\n                        {type : 'average', name: '平均值'}\n                    ]\n                }\n            },\n            {\n                name:'男性',\n                type:'scatter',\n                tooltip : {\n                    trigger: 'item',\n                    formatter : function (params) {\n                        if (params.value.length > 1) {\n                            return params.seriesName + ' :<br/>'\n                               + params.value[0] + 'cm '\n                               + params.value[1] + 'kg ';\n                        }\n                        else {\n                            return params.seriesName + ' :<br/>'\n                               + params.name + ' : '\n                               + params.value + 'kg ';\n                        }\n                    }\n                },\n                data: [[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],\n                    [181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],\n                    [180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],\n                    [184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],\n                    [176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],\n                    [178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],\n                    [183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],\n                    [170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],\n                    [186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],\n                    [182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],\n                    [169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],\n                    [163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],\n                    [177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],\n                    [167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],\n                    [171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],\n                    [174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],\n                    [180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],\n                    [180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],\n                    [175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],\n                    [176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],\n                    [184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],\n                    [157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],\n                    [165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],\n                    [185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],\n                    [177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],\n                    [188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],\n                    [166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],\n                    [185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],\n                    [190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],\n                    [176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],\n                    [172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],\n                    [167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],\n                    [172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],\n                    [193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],\n                    [167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],\n                    [188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],\n                    [171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],\n                    [182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],\n                    [188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],\n                    [175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],\n                    [177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],\n                    [174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],\n                    [167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],\n                    [175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],\n                    [177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],\n                    [174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],\n                    [174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],\n                    [180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],\n                    [170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],\n                    [180.3, 83.2], [180.3, 83.2]\n                ],\n                markPoint : {\n                    data : [\n                        {type : 'max', name: '最大值'},\n                        {type : 'min', name: '最小值'}\n                    ]\n                },\n                markLine : {\n                    data : [\n                        {type : 'average', name: '平均值'}\n                    ]\n                }\n            }\n        ]\n    };\n    scatterChart.setOption(scatteroption);\n    $(window).resize(scatterChart.resize);\n\n\n    var kChart = echarts.init(document.getElementById(\"echarts-k-chart\"));\n    var koption = {\n        title : {\n            text: '2013年上半年上证指数'\n        },\n        tooltip : {\n            trigger: 'axis',\n            formatter: function (params) {\n                var res = params[0].seriesName + ' ' + params[0].name;\n                res += '<br/>  开盘 : ' + params[0].value[0] + '  最高 : ' + params[0].value[3];\n                res += '<br/>  收盘 : ' + params[0].value[1] + '  最低 : ' + params[0].value[2];\n                return res;\n            }\n        },\n        legend: {\n            data:['上证指数']\n        },\n        grid:{\n            x:40,\n            x2:2\n        },\n        dataZoom : {\n            show : true,\n            realtime: true,\n            start : 50,\n            end : 100\n        },\n        xAxis : [\n            {\n                type : 'category',\n                boundaryGap : true,\n                axisTick: {onGap:false},\n                splitLine: {show:false},\n                data : [\n                    \"2013/1/24\", \"2013/1/25\", \"2013/1/28\", \"2013/1/29\", \"2013/1/30\",\n                    \"2013/1/31\", \"2013/2/1\", \"2013/2/4\", \"2013/2/5\", \"2013/2/6\",\n                    \"2013/2/7\", \"2013/2/8\", \"2013/2/18\", \"2013/2/19\", \"2013/2/20\",\n                    \"2013/2/21\", \"2013/2/22\", \"2013/2/25\", \"2013/2/26\", \"2013/2/27\",\n                    \"2013/2/28\", \"2013/3/1\", \"2013/3/4\", \"2013/3/5\", \"2013/3/6\",\n                    \"2013/3/7\", \"2013/3/8\", \"2013/3/11\", \"2013/3/12\", \"2013/3/13\",\n                    \"2013/3/14\", \"2013/3/15\", \"2013/3/18\", \"2013/3/19\", \"2013/3/20\",\n                    \"2013/3/21\", \"2013/3/22\", \"2013/3/25\", \"2013/3/26\", \"2013/3/27\",\n                    \"2013/3/28\", \"2013/3/29\", \"2013/4/1\", \"2013/4/2\", \"2013/4/3\",\n                    \"2013/4/8\", \"2013/4/9\", \"2013/4/10\", \"2013/4/11\", \"2013/4/12\",\n                    \"2013/4/15\", \"2013/4/16\", \"2013/4/17\", \"2013/4/18\", \"2013/4/19\",\n                    \"2013/4/22\", \"2013/4/23\", \"2013/4/24\", \"2013/4/25\", \"2013/4/26\",\n                    \"2013/5/2\", \"2013/5/3\", \"2013/5/6\", \"2013/5/7\", \"2013/5/8\",\n                    \"2013/5/9\", \"2013/5/10\", \"2013/5/13\", \"2013/5/14\", \"2013/5/15\",\n                    \"2013/5/16\", \"2013/5/17\", \"2013/5/20\", \"2013/5/21\", \"2013/5/22\",\n                    \"2013/5/23\", \"2013/5/24\", \"2013/5/27\", \"2013/5/28\", \"2013/5/29\",\n                    \"2013/5/30\", \"2013/5/31\", \"2013/6/3\", \"2013/6/4\", \"2013/6/5\",\n                    \"2013/6/6\", \"2013/6/7\", \"2013/6/13\"\n                ]\n            }\n        ],\n        yAxis : [\n            {\n                type : 'value',\n                scale:true,\n                boundaryGap: [0.01, 0.01]\n            }\n        ],\n        series : [\n            {\n                name:'上证指数',\n                type:'k',\n                data:[ // 开盘，收盘，最低，最高\n                    [2320.26,2302.6,2287.3,2362.94],\n                    [2300,2291.3,2288.26,2308.38],\n                    [2295.35,2346.5,2295.35,2346.92],\n                    [2347.22,2358.98,2337.35,2363.8],\n                    [2360.75,2382.48,2347.89,2383.76],\n                    [2383.43,2385.42,2371.23,2391.82],\n                    [2377.41,2419.02,2369.57,2421.15],\n                    [2425.92,2428.15,2417.58,2440.38],\n                    [2411,2433.13,2403.3,2437.42],\n                    [2432.68,2434.48,2427.7,2441.73],\n                    [2430.69,2418.53,2394.22,2433.89],\n                    [2416.62,2432.4,2414.4,2443.03],\n                    [2441.91,2421.56,2415.43,2444.8],\n                    [2420.26,2382.91,2373.53,2427.07],\n                    [2383.49,2397.18,2370.61,2397.94],\n                    [2378.82,2325.95,2309.17,2378.82],\n                    [2322.94,2314.16,2308.76,2330.88],\n                    [2320.62,2325.82,2315.01,2338.78],\n                    [2313.74,2293.34,2289.89,2340.71],\n                    [2297.77,2313.22,2292.03,2324.63],\n                    [2322.32,2365.59,2308.92,2366.16],\n                    [2364.54,2359.51,2330.86,2369.65],\n                    [2332.08,2273.4,2259.25,2333.54],\n                    [2274.81,2326.31,2270.1,2328.14],\n                    [2333.61,2347.18,2321.6,2351.44],\n                    [2340.44,2324.29,2304.27,2352.02],\n                    [2326.42,2318.61,2314.59,2333.67],\n                    [2314.68,2310.59,2296.58,2320.96],\n                    [2309.16,2286.6,2264.83,2333.29],\n                    [2282.17,2263.97,2253.25,2286.33],\n                    [2255.77,2270.28,2253.31,2276.22],\n                    [2269.31,2278.4,2250,2312.08],\n                    [2267.29,2240.02,2239.21,2276.05],\n                    [2244.26,2257.43,2232.02,2261.31],\n                    [2257.74,2317.37,2257.42,2317.86],\n                    [2318.21,2324.24,2311.6,2330.81],\n                    [2321.4,2328.28,2314.97,2332],\n                    [2334.74,2326.72,2319.91,2344.89],\n                    [2318.58,2297.67,2281.12,2319.99],\n                    [2299.38,2301.26,2289,2323.48],\n                    [2273.55,2236.3,2232.91,2273.55],\n                    [2238.49,2236.62,2228.81,2246.87],\n                    [2229.46,2234.4,2227.31,2243.95],\n                    [2234.9,2227.74,2220.44,2253.42],\n                    [2232.69,2225.29,2217.25,2241.34],\n                    [2196.24,2211.59,2180.67,2212.59],\n                    [2215.47,2225.77,2215.47,2234.73],\n                    [2224.93,2226.13,2212.56,2233.04],\n                    [2236.98,2219.55,2217.26,2242.48],\n                    [2218.09,2206.78,2204.44,2226.26],\n                    [2199.91,2181.94,2177.39,2204.99],\n                    [2169.63,2194.85,2165.78,2196.43],\n                    [2195.03,2193.8,2178.47,2197.51],\n                    [2181.82,2197.6,2175.44,2206.03],\n                    [2201.12,2244.64,2200.58,2250.11],\n                    [2236.4,2242.17,2232.26,2245.12],\n                    [2242.62,2184.54,2182.81,2242.62],\n                    [2187.35,2218.32,2184.11,2226.12],\n                    [2213.19,2199.31,2191.85,2224.63],\n                    [2203.89,2177.91,2173.86,2210.58],\n                    [2170.78,2174.12,2161.14,2179.65],\n                    [2179.05,2205.5,2179.05,2222.81],\n                    [2212.5,2231.17,2212.5,2236.07],\n                    [2227.86,2235.57,2219.44,2240.26],\n                    [2242.39,2246.3,2235.42,2255.21],\n                    [2246.96,2232.97,2221.38,2247.86],\n                    [2228.82,2246.83,2225.81,2247.67],\n                    [2247.68,2241.92,2231.36,2250.85],\n                    [2238.9,2217.01,2205.87,2239.93],\n                    [2217.09,2224.8,2213.58,2225.19],\n                    [2221.34,2251.81,2210.77,2252.87],\n                    [2249.81,2282.87,2248.41,2288.09],\n                    [2286.33,2299.99,2281.9,2309.39],\n                    [2297.11,2305.11,2290.12,2305.3],\n                    [2303.75,2302.4,2292.43,2314.18],\n                    [2293.81,2275.67,2274.1,2304.95],\n                    [2281.45,2288.53,2270.25,2292.59],\n                    [2286.66,2293.08,2283.94,2301.7],\n                    [2293.4,2321.32,2281.47,2322.1],\n                    [2323.54,2324.02,2321.17,2334.33],\n                    [2316.25,2317.75,2310.49,2325.72],\n                    [2320.74,2300.59,2299.37,2325.53],\n                    [2300.21,2299.25,2294.11,2313.43],\n                    [2297.1,2272.42,2264.76,2297.1],\n                    [2270.71,2270.93,2260.87,2276.86],\n                    [2264.43,2242.11,2240.07,2266.69],\n                    [2242.26,2210.9,2205.07,2250.63],\n                    [2190.1,2148.35,2126.22,2190.1]\n                ]\n            }\n        ]\n    };\n    kChart.setOption(koption);\n    $(window).resize(kChart.resize);\n\n    var pieChart = echarts.init(document.getElementById(\"echarts-pie-chart\"));\n    var pieoption = {\n        title : {\n            text: '某站点用户访问来源',\n            subtext: '纯属虚构',\n            x:'center'\n        },\n        tooltip : {\n            trigger: 'item',\n            formatter: \"{a} <br/>{b} : {c} ({d}%)\"\n        },\n        legend: {\n            orient : 'vertical',\n            x : 'left',\n            data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']\n        },\n        calculable : true,\n        series : [\n            {\n                name:'访问来源',\n                type:'pie',\n                radius : '55%',\n                center: ['50%', '60%'],\n                data:[\n                    {value:335, name:'直接访问'},\n                    {value:310, name:'邮件营销'},\n                    {value:234, name:'联盟广告'},\n                    {value:135, name:'视频广告'},\n                    {value:1548, name:'搜索引擎'}\n                ]\n            }\n        ]\n    };\n    pieChart.setOption(pieoption);\n    $(window).resize(pieChart.resize);\n\n    var radarChart = echarts.init(document.getElementById(\"echarts-radar-chart\"));\n    var radaroption = {\n        title : {\n            text: '预算 vs 开销',\n            subtext: '纯属虚构'\n        },\n        tooltip : {\n            trigger: 'axis'\n        },\n        legend: {\n            orient : 'vertical',\n            x : 'right',\n            y : 'bottom',\n            data:['预算分配','实际开销']\n        },\n        polar : [\n           {\n               indicator : [\n                   { text: '销售', max: 6000},\n                   { text: '管理', max: 16000},\n                   { text: '信息技术', max: 30000},\n                   { text: '客服', max: 38000},\n                   { text: '研发', max: 52000},\n                   { text: '市场', max: 25000}\n                ]\n            }\n        ],\n        calculable : true,\n        series : [\n            {\n                name: '预算 vs 开销',\n                type: 'radar',\n                data : [\n                    {\n                        value : [4300, 10000, 28000, 35000, 50000, 19000],\n                        name : '预算分配'\n                    },\n                     {\n                        value : [5000, 14000, 28000, 31000, 42000, 21000],\n                        name : '实际开销'\n                    }\n                ]\n            }\n        ]\n    };\n\n    radarChart.setOption(radaroption);\n    $(window).resize(radarChart.resize);\n\n    var mapChart = echarts.init(document.getElementById(\"echarts-map-chart\"));\n    var mapoption = {\n        title : {\n            text: 'iphone销量',\n            subtext: '纯属虚构',\n            x:'center'\n        },\n        tooltip : {\n            trigger: 'item'\n        },\n        legend: {\n            orient: 'vertical',\n            x:'left',\n            data:['iphone3','iphone4','iphone5']\n        },\n        dataRange: {\n            min: 0,\n            max: 2500,\n            x: 'left',\n            y: 'bottom',\n            text:['高','低'],           // 文本，默认为数值文本\n            calculable : true\n        },\n        toolbox: {\n            show: true,\n            orient : 'vertical',\n            x: 'right',\n            y: 'center',\n            feature : {\n                mark : {show: true},\n                dataView : {show: true, readOnly: false},\n                restore : {show: true},\n                saveAsImage : {show: true}\n            }\n        },\n        roamController: {\n            show: true,\n            x: 'right',\n            mapTypeControl: {\n                'china': true\n            }\n        },\n        series : [\n            {\n                name: 'iphone3',\n                type: 'map',\n                mapType: 'china',\n                roam: false,\n                itemStyle:{\n                    normal:{label:{show:true}},\n                    emphasis:{label:{show:true}}\n                },\n                data:[\n                    {name: '北京',value: Math.round(Math.random()*1000)},\n                    {name: '天津',value: Math.round(Math.random()*1000)},\n                    {name: '上海',value: Math.round(Math.random()*1000)},\n                    {name: '重庆',value: Math.round(Math.random()*1000)},\n                    {name: '河北',value: Math.round(Math.random()*1000)},\n                    {name: '河南',value: Math.round(Math.random()*1000)},\n                    {name: '云南',value: Math.round(Math.random()*1000)},\n                    {name: '辽宁',value: Math.round(Math.random()*1000)},\n                    {name: '黑龙江',value: Math.round(Math.random()*1000)},\n                    {name: '湖南',value: Math.round(Math.random()*1000)},\n                    {name: '安徽',value: Math.round(Math.random()*1000)},\n                    {name: '山东',value: Math.round(Math.random()*1000)},\n                    {name: '新疆',value: Math.round(Math.random()*1000)},\n                    {name: '江苏',value: Math.round(Math.random()*1000)},\n                    {name: '浙江',value: Math.round(Math.random()*1000)},\n                    {name: '江西',value: Math.round(Math.random()*1000)},\n                    {name: '湖北',value: Math.round(Math.random()*1000)},\n                    {name: '广西',value: Math.round(Math.random()*1000)},\n                    {name: '甘肃',value: Math.round(Math.random()*1000)},\n                    {name: '山西',value: Math.round(Math.random()*1000)},\n                    {name: '内蒙古',value: Math.round(Math.random()*1000)},\n                    {name: '陕西',value: Math.round(Math.random()*1000)},\n                    {name: '吉林',value: Math.round(Math.random()*1000)},\n                    {name: '福建',value: Math.round(Math.random()*1000)},\n                    {name: '贵州',value: Math.round(Math.random()*1000)},\n                    {name: '广东',value: Math.round(Math.random()*1000)},\n                    {name: '青海',value: Math.round(Math.random()*1000)},\n                    {name: '西藏',value: Math.round(Math.random()*1000)},\n                    {name: '四川',value: Math.round(Math.random()*1000)},\n                    {name: '宁夏',value: Math.round(Math.random()*1000)},\n                    {name: '海南',value: Math.round(Math.random()*1000)},\n                    {name: '台湾',value: Math.round(Math.random()*1000)},\n                    {name: '香港',value: Math.round(Math.random()*1000)},\n                    {name: '澳门',value: Math.round(Math.random()*1000)}\n                ]\n            },\n            {\n                name: 'iphone4',\n                type: 'map',\n                mapType: 'china',\n                itemStyle:{\n                    normal:{label:{show:true}},\n                    emphasis:{label:{show:true}}\n                },\n                data:[\n                    {name: '北京',value: Math.round(Math.random()*1000)},\n                    {name: '天津',value: Math.round(Math.random()*1000)},\n                    {name: '上海',value: Math.round(Math.random()*1000)},\n                    {name: '重庆',value: Math.round(Math.random()*1000)},\n                    {name: '河北',value: Math.round(Math.random()*1000)},\n                    {name: '安徽',value: Math.round(Math.random()*1000)},\n                    {name: '新疆',value: Math.round(Math.random()*1000)},\n                    {name: '浙江',value: Math.round(Math.random()*1000)},\n                    {name: '江西',value: Math.round(Math.random()*1000)},\n                    {name: '山西',value: Math.round(Math.random()*1000)},\n                    {name: '内蒙古',value: Math.round(Math.random()*1000)},\n                    {name: '吉林',value: Math.round(Math.random()*1000)},\n                    {name: '福建',value: Math.round(Math.random()*1000)},\n                    {name: '广东',value: Math.round(Math.random()*1000)},\n                    {name: '西藏',value: Math.round(Math.random()*1000)},\n                    {name: '四川',value: Math.round(Math.random()*1000)},\n                    {name: '宁夏',value: Math.round(Math.random()*1000)},\n                    {name: '香港',value: Math.round(Math.random()*1000)},\n                    {name: '澳门',value: Math.round(Math.random()*1000)}\n                ]\n            },\n            {\n                name: 'iphone5',\n                type: 'map',\n                mapType: 'china',\n                itemStyle:{\n                    normal:{label:{show:true}},\n                    emphasis:{label:{show:true}}\n                },\n                data:[\n                    {name: '北京',value: Math.round(Math.random()*1000)},\n                    {name: '天津',value: Math.round(Math.random()*1000)},\n                    {name: '上海',value: Math.round(Math.random()*1000)},\n                    {name: '广东',value: Math.round(Math.random()*1000)},\n                    {name: '台湾',value: Math.round(Math.random()*1000)},\n                    {name: '香港',value: Math.round(Math.random()*1000)},\n                    {name: '澳门',value: Math.round(Math.random()*1000)}\n                ]\n            }\n        ]\n    };\n    mapChart.setOption(mapoption);\n    $(window).resize(mapChart.resize);\n\n    var chordChart = echarts.init(document.getElementById(\"echarts-chord-chart\"));\n    var chordoption = {\n        title : {\n            text: '测试数据',\n            subtext: 'From d3.js',\n            x:'right',\n            y:'bottom'\n        },\n        tooltip : {\n            trigger: 'item',\n            formatter: function (params) {\n                if (params.indicator2) { // is edge\n                    return params.value.weight;\n                } else {// is node\n                    return params.name\n                }\n            }\n        },\n        toolbox: {\n            show : true,\n            feature : {\n                restore : {show: true},\n                magicType: {show: true, type: ['force', 'chord']},\n                saveAsImage : {show: true}\n            }\n        },\n        legend: {\n            x: 'left',\n            data:['group1','group2', 'group3', 'group4']\n        },\n        series : [\n            {\n                type:'chord',\n                sort : 'ascending',\n                sortSub : 'descending',\n                showScale : true,\n                showScaleText : true,\n                data : [\n                    {name : 'group1'},\n                    {name : 'group2'},\n                    {name : 'group3'},\n                    {name : 'group4'}\n                ],\n                itemStyle : {\n                    normal : {\n                        label : {\n                            show : false\n                        }\n                    }\n                },\n                matrix : [\n                    [11975,  5871, 8916, 2868],\n                    [ 1951, 10048, 2060, 6171],\n                    [ 8010, 16145, 8090, 8045],\n                    [ 1013,   990,  940, 6907]\n                ]\n            }\n        ]\n    };\n\n    chordChart.setOption(chordoption);\n    $(window).resize(chordChart.resize);\n\n    var forceChart = echarts.init(document.getElementById(\"echarts-force-chart\"));\n    var forceoption ={\n        title : {\n            text: '人物关系：乔布斯',\n            subtext: '数据来自人立方',\n            x:'right',\n            y:'bottom'\n        },\n        tooltip : {\n            trigger: 'item',\n            formatter: '{a} : {b}'\n        },\n        toolbox: {\n            show : true,\n            feature : {\n                restore : {show: true},\n                magicType: {show: true, type: ['force', 'chord']},\n                saveAsImage : {show: true}\n            }\n        },\n        legend: {\n            x: 'left',\n            data:['家人','朋友']\n        },\n        series : [\n            {\n                type:'force',\n                name : \"人物关系\",\n                ribbonType: false,\n                categories : [\n                    {\n                        name: '人物'\n                    },\n                    {\n                        name: '家人'\n                    },\n                    {\n                        name:'朋友'\n                    }\n                ],\n                itemStyle: {\n                    normal: {\n                        label: {\n                            show: true,\n                            textStyle: {\n                                color: '#333'\n                            }\n                        },\n                        nodeStyle : {\n                            brushType : 'both',\n                            borderColor : 'rgba(255,215,0,0.4)',\n                            borderWidth : 1\n                        },\n                        linkStyle: {\n                            type: 'curve'\n                        }\n                    },\n                    emphasis: {\n                        label: {\n                            show: false\n                            // textStyle: null      // 默认使用全局文本样式，详见TEXTSTYLE\n                        },\n                        nodeStyle : {\n                            //r: 30\n                        },\n                        linkStyle : {}\n                    }\n                },\n                useWorker: false,\n                minRadius : 15,\n                maxRadius : 25,\n                gravity: 1.1,\n                scaling: 1.1,\n                roam: 'move',\n                nodes:[\n                    {category:0, name: '乔布斯', value : 10},\n                    {category:1, name: '丽萨-乔布斯',value : 2},\n                    {category:1, name: '保罗-乔布斯',value : 3},\n                    {category:1, name: '克拉拉-乔布斯',value : 3},\n                    {category:1, name: '劳伦-鲍威尔',value : 7},\n                    {category:2, name: '史蒂夫-沃兹尼艾克',value : 5},\n                    {category:2, name: '奥巴马',value : 8},\n                    {category:2, name: '比尔-盖茨',value : 9},\n                    {category:2, name: '乔纳森-艾夫',value : 4},\n                    {category:2, name: '蒂姆-库克',value : 4},\n                    {category:2, name: '龙-韦恩',value : 1},\n                ],\n                links : [\n                    {source : '丽萨-乔布斯', target : '乔布斯', weight : 1, name: '女儿'},\n                    {source : '保罗-乔布斯', target : '乔布斯', weight : 2, name: '父亲'},\n                    {source : '克拉拉-乔布斯', target : '乔布斯', weight : 1, name: '母亲'},\n                    {source : '劳伦-鲍威尔', target : '乔布斯', weight : 2},\n                    {source : '史蒂夫-沃兹尼艾克', target : '乔布斯', weight : 3, name: '合伙人'},\n                    {source : '奥巴马', target : '乔布斯', weight : 1},\n                    {source : '比尔-盖茨', target : '乔布斯', weight : 6, name: '竞争对手'},\n                    {source : '乔纳森-艾夫', target : '乔布斯', weight : 1, name: '爱将'},\n                    {source : '蒂姆-库克', target : '乔布斯', weight : 1},\n                    {source : '龙-韦恩', target : '乔布斯', weight : 1},\n                    {source : '克拉拉-乔布斯', target : '保罗-乔布斯', weight : 1},\n                    {source : '奥巴马', target : '保罗-乔布斯', weight : 1},\n                    {source : '奥巴马', target : '克拉拉-乔布斯', weight : 1},\n                    {source : '奥巴马', target : '劳伦-鲍威尔', weight : 1},\n                    {source : '奥巴马', target : '史蒂夫-沃兹尼艾克', weight : 1},\n                    {source : '比尔-盖茨', target : '奥巴马', weight : 6},\n                    {source : '比尔-盖茨', target : '克拉拉-乔布斯', weight : 1},\n                    {source : '蒂姆-库克', target : '奥巴马', weight : 1}\n                ]\n            }\n        ]\n    };\n    forceChart.setOption(forceoption);\n    $(window).resize(forceChart.resize);\n\n    var gaugeChart = echarts.init(document.getElementById(\"echarts-gauge-chart\"));\n    var gaugeoption = {\n        tooltip : {\n            formatter: \"{a} <br/>{c} {b}\"\n        },\n        toolbox: {\n            show : true,\n            feature : {\n                mark : {show: true},\n                restore : {show: true},\n                saveAsImage : {show: true}\n            }\n        },\n        series : [\n            {\n                name:'速度',\n                type:'gauge',\n                min:0,\n                max:220,\n                splitNumber:11,\n                axisLine: {            // 坐标轴线\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        width: 10\n                    }\n                },\n                axisTick: {            // 坐标轴小标记\n                    length :15,        // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        color: 'auto'\n                    }\n                },\n                splitLine: {           // 分隔线\n                    length :20,         // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle（详见lineStyle）控制线条样式\n                        color: 'auto'\n                    }\n                },\n                title : {\n                    textStyle: {       // 其余属性默认使用全局文本样式，详见TEXTSTYLE\n                        fontWeight: 'bolder',\n                        fontSize: 20,\n                        fontStyle: 'italic'\n                    }\n                },\n                detail : {\n                    textStyle: {       // 其余属性默认使用全局文本样式，详见TEXTSTYLE\n                        fontWeight: 'bolder'\n                    }\n                },\n                data:[{value: 40, name: 'km/h'}]\n            },\n            {\n                name:'转速',\n                type:'gauge',\n                center : ['25%', '55%'],    // 默认全局居中\n                radius : '50%',\n                min:0,\n                max:7,\n                endAngle:45,\n                splitNumber:7,\n                axisLine: {            // 坐标轴线\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        width: 8\n                    }\n                },\n                axisTick: {            // 坐标轴小标记\n                    length :12,        // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        color: 'auto'\n                    }\n                },\n                splitLine: {           // 分隔线\n                    length :20,         // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle（详见lineStyle）控制线条样式\n                        color: 'auto'\n                    }\n                },\n                pointer: {\n                    width:5\n                },\n                title : {\n                    offsetCenter: [0, '-30%'],       // x, y，单位px\n                },\n                detail : {\n                    textStyle: {       // 其余属性默认使用全局文本样式，详见TEXTSTYLE\n                        fontWeight: 'bolder'\n                    }\n                },\n                data:[{value: 1.5, name: 'x1000 r/min'}]\n            },\n            {\n                name:'油表',\n                type:'gauge',\n                center : ['75%', '50%'],    // 默认全局居中\n                radius : '50%',\n                min:0,\n                max:2,\n                startAngle:135,\n                endAngle:45,\n                splitNumber:2,\n                axisLine: {            // 坐标轴线\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        color: [[0.2, '#ff4500'],[0.8, '#48b'],[1, '#228b22']],\n                        width: 8\n                    }\n                },\n                axisTick: {            // 坐标轴小标记\n                    splitNumber:5,\n                    length :10,        // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        color: 'auto'\n                    }\n                },\n                axisLabel: {\n                    formatter:function(v){\n                        switch (v + '') {\n                            case '0' : return 'E';\n                            case '1' : return 'Gas';\n                            case '2' : return 'F';\n                        }\n                    }\n                },\n                splitLine: {           // 分隔线\n                    length :15,         // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle（详见lineStyle）控制线条样式\n                        color: 'auto'\n                    }\n                },\n                pointer: {\n                    width:2\n                },\n                title : {\n                    show: false\n                },\n                detail : {\n                    show: false\n                },\n                data:[{value: 0.5, name: 'gas'}]\n            },\n            {\n                name:'水表',\n                type:'gauge',\n                center : ['75%', '50%'],    // 默认全局居中\n                radius : '50%',\n                min:0,\n                max:2,\n                startAngle:315,\n                endAngle:225,\n                splitNumber:2,\n                axisLine: {            // 坐标轴线\n                    lineStyle: {       // 属性lineStyle控制线条样式\n                        color: [[0.2, '#ff4500'],[0.8, '#48b'],[1, '#228b22']],\n                        width: 8\n                    }\n                },\n                axisTick: {            // 坐标轴小标记\n                    show: false\n                },\n                axisLabel: {\n                    formatter:function(v){\n                        switch (v + '') {\n                            case '0' : return 'H';\n                            case '1' : return 'Water';\n                            case '2' : return 'C';\n                        }\n                    }\n                },\n                splitLine: {           // 分隔线\n                    length :15,         // 属性length控制线长\n                    lineStyle: {       // 属性lineStyle（详见lineStyle）控制线条样式\n                        color: 'auto'\n                    }\n                },\n                pointer: {\n                    width:2\n                },\n                title : {\n                    show: false\n                },\n                detail : {\n                    show: false\n                },\n                data:[{value: 0.5, name: 'gas'}]\n            }\n        ]\n    };\n    gaugeChart.setOption(gaugeoption);\n    $(window).resize(gaugeChart.resize);\n\n    var funnelChart = echarts.init(document.getElementById(\"echarts-funnel-chart\"));\n    var funneloption = {\n        title : {\n            text: '漏斗图',\n            subtext: '纯属虚构'\n        },\n        tooltip : {\n            trigger: 'item',\n            formatter: \"{a} <br/>{b} : {c}%\"\n        },\n        legend: {\n            data : ['展现','点击','访问','咨询','订单']\n        },\n        calculable : true,\n        series : [\n            {\n                name:'漏斗图',\n                type:'funnel',\n                width: '40%',\n                data:[\n                    {value:60, name:'访问'},\n                    {value:40, name:'咨询'},\n                    {value:20, name:'订单'},\n                    {value:80, name:'点击'},\n                    {value:100, name:'展现'}\n                ]\n            },\n            {\n                name:'金字塔',\n                type:'funnel',\n                x : '50%',\n                sort : 'ascending',\n                itemStyle: {\n                    normal: {\n                        // color: 各异,\n                        label: {\n                            position: 'left'\n                        }\n                    }\n                },\n                data:[\n                    {value:60, name:'访问'},\n                    {value:40, name:'咨询'},\n                    {value:20, name:'订单'},\n                    {value:80, name:'点击'},\n                    {value:100, name:'展现'}\n                ]\n            }\n        ]\n    };\n\n    funnelChart.setOption(funneloption);\n    $(window).resize(funnelChart.resize);\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/flot-demo.js",
    "content": "//Flot Bar Chart\n$(function() {\n    var barOptions = {\n        series: {\n            bars: {\n                show: true,\n                barWidth: 0.6,\n                fill: true,\n                fillColor: {\n                    colors: [{\n                        opacity: 0.8\n                    }, {\n                        opacity: 0.8\n                    }]\n                }\n            }\n        },\n        xaxis: {\n            tickDecimals: 0\n        },\n        colors: [\"#1ab394\"],\n        grid: {\n            color: \"#999999\",\n            hoverable: true,\n            clickable: true,\n            tickColor: \"#D4D4D4\",\n            borderWidth:0\n        },\n        legend: {\n            show: false\n        },\n        tooltip: true,\n        tooltipOpts: {\n            content: \"x: %x, y: %y\"\n        }\n    };\n    var barData = {\n        label: \"bar\",\n        data: [\n            [1, 34],\n            [2, 25],\n            [3, 19],\n            [4, 34],\n            [5, 32],\n            [6, 44]\n        ]\n    };\n    $.plot($(\"#flot-bar-chart\"), [barData], barOptions);\n\n});\n\n$(function() {\n    var barOptions = {\n        series: {\n            lines: {\n                show: true,\n                lineWidth: 2,\n                fill: true,\n                fillColor: {\n                    colors: [{\n                        opacity: 0.0\n                    }, {\n                        opacity: 0.0\n                    }]\n                }\n            }\n        },\n        xaxis: {\n            tickDecimals: 0\n        },\n        colors: [\"#1ab394\"],\n        grid: {\n            color: \"#999999\",\n            hoverable: true,\n            clickable: true,\n            tickColor: \"#D4D4D4\",\n            borderWidth:0\n        },\n        legend: {\n            show: false\n        },\n        tooltip: true,\n        tooltipOpts: {\n            content: \"x: %x, y: %y\"\n        }\n    };\n    var barData = {\n        label: \"bar\",\n        data: [\n            [1, 34],\n            [2, 25],\n            [3, 19],\n            [4, 34],\n            [5, 32],\n            [6, 44]\n        ]\n    };\n    $.plot($(\"#flot-line-chart\"), [barData], barOptions);\n\n});\n//Flot Pie Chart\n$(function() {\n\n    var data = [{\n        label: \"数据 1\",\n        data: 21,\n        color: \"#d3d3d3\",\n    }, {\n        label: \"数据 2\",\n        data: 3,\n        color: \"#bababa\",\n    }, {\n        label: \"数据 3\",\n        data: 15,\n        color: \"#79d2c0\",\n    }, {\n        label: \"数据 4\",\n        data: 52,\n        color: \"#1ab394\",\n    }];\n\n    var plotObj = $.plot($(\"#flot-pie-chart\"), data, {\n        series: {\n            pie: {\n                show: true\n            }\n        },\n        grid: {\n            hoverable: true\n        },\n        tooltip: true,\n        tooltipOpts: {\n            content: \"%p.0%, %s\", // show percentages, rounding to 2 decimal places\n            shifts: {\n                x: 20,\n                y: 0\n            },\n            defaultTheme: false\n        }\n    });\n\n});\n\n$(function() {\n\n    var container = $(\"#flot-line-chart-moving\");\n\n    // Determine how many data points to keep based on the placeholder's initial size;\n    // this gives us a nice high-res plot while avoiding more than one point per pixel.\n\n    var maximum = container.outerWidth() / 2 || 300;\n\n    //\n\n    var data = [];\n\n    function getRandomData() {\n\n        if (data.length) {\n            data = data.slice(1);\n        }\n\n        while (data.length < maximum) {\n            var previous = data.length ? data[data.length - 1] : 50;\n            var y = previous + Math.random() * 10 - 5;\n            data.push(y < 0 ? 0 : y > 100 ? 100 : y);\n        }\n\n        // zip the generated y values with the x values\n\n        var res = [];\n        for (var i = 0; i < data.length; ++i) {\n            res.push([i, data[i]])\n        }\n\n        return res;\n    }\n\n    //\n\n    series = [{\n        data: getRandomData(),\n        lines: {\n            fill: true\n        }\n    }];\n\n    //\n\n    var plot = $.plot(container, series, {\n        grid: {\n\n            color: \"#999999\",\n            tickColor: \"#D4D4D4\",\n            borderWidth:0,\n            minBorderMargin: 20,\n            labelMargin: 10,\n            backgroundColor: {\n                colors: [\"#ffffff\", \"#ffffff\"]\n            },\n            margin: {\n                top: 8,\n                bottom: 20,\n                left: 20\n            },\n            markings: function(axes) {\n                var markings = [];\n                var xaxis = axes.xaxis;\n                for (var x = Math.floor(xaxis.min); x < xaxis.max; x += xaxis.tickSize * 2) {\n                    markings.push({\n                        xaxis: {\n                            from: x,\n                            to: x + xaxis.tickSize\n                        },\n                        color: \"#fff\"\n                    });\n                }\n                return markings;\n            }\n        },\n        colors: [\"#1ab394\"],\n        xaxis: {\n            tickFormatter: function() {\n                return \"\";\n            }\n        },\n        yaxis: {\n            min: 0,\n            max: 110\n        },\n        legend: {\n            show: true\n        }\n    });\n\n    // Update the random dataset at 25FPS for a smoothly-animating chart\n\n    setInterval(function updateRandom() {\n        series[0].data = getRandomData();\n        plot.setData(series);\n        plot.draw();\n    }, 40);\n\n});\n\n//Flot Multiple Axes Line Chart\n$(function() {\n    var oilprices = [\n        [1167692400000, 61.05],\n        [1167778800000, 58.32],\n        [1167865200000, 57.35],\n        [1167951600000, 56.31],\n        [1168210800000, 55.55],\n        [1168297200000, 55.64],\n        [1168383600000, 54.02],\n        [1168470000000, 51.88],\n        [1168556400000, 52.99],\n        [1168815600000, 52.99],\n        [1168902000000, 51.21],\n        [1168988400000, 52.24],\n        [1169074800000, 50.48],\n        [1169161200000, 51.99],\n        [1169420400000, 51.13],\n        [1169506800000, 55.04],\n        [1169593200000, 55.37],\n        [1169679600000, 54.23],\n        [1169766000000, 55.42],\n        [1170025200000, 54.01],\n        [1170111600000, 56.97],\n        [1170198000000, 58.14],\n        [1170284400000, 58.14],\n        [1170370800000, 59.02],\n        [1170630000000, 58.74],\n        [1170716400000, 58.88],\n        [1170802800000, 57.71],\n        [1170889200000, 59.71],\n        [1170975600000, 59.89],\n        [1171234800000, 57.81],\n        [1171321200000, 59.06],\n        [1171407600000, 58.00],\n        [1171494000000, 57.99],\n        [1171580400000, 59.39],\n        [1171839600000, 59.39],\n        [1171926000000, 58.07],\n        [1172012400000, 60.07],\n        [1172098800000, 61.14],\n        [1172444400000, 61.39],\n        [1172530800000, 61.46],\n        [1172617200000, 61.79],\n        [1172703600000, 62.00],\n        [1172790000000, 60.07],\n        [1173135600000, 60.69],\n        [1173222000000, 61.82],\n        [1173308400000, 60.05],\n        [1173654000000, 58.91],\n        [1173740400000, 57.93],\n        [1173826800000, 58.16],\n        [1173913200000, 57.55],\n        [1173999600000, 57.11],\n        [1174258800000, 56.59],\n        [1174345200000, 59.61],\n        [1174518000000, 61.69],\n        [1174604400000, 62.28],\n        [1174860000000, 62.91],\n        [1174946400000, 62.93],\n        [1175032800000, 64.03],\n        [1175119200000, 66.03],\n        [1175205600000, 65.87],\n        [1175464800000, 64.64],\n        [1175637600000, 64.38],\n        [1175724000000, 64.28],\n        [1175810400000, 64.28],\n        [1176069600000, 61.51],\n        [1176156000000, 61.89],\n        [1176242400000, 62.01],\n        [1176328800000, 63.85],\n        [1176415200000, 63.63],\n        [1176674400000, 63.61],\n        [1176760800000, 63.10],\n        [1176847200000, 63.13],\n        [1176933600000, 61.83],\n        [1177020000000, 63.38],\n        [1177279200000, 64.58],\n        [1177452000000, 65.84],\n        [1177538400000, 65.06],\n        [1177624800000, 66.46],\n        [1177884000000, 64.40],\n        [1178056800000, 63.68],\n        [1178143200000, 63.19],\n        [1178229600000, 61.93],\n        [1178488800000, 61.47],\n        [1178575200000, 61.55],\n        [1178748000000, 61.81],\n        [1178834400000, 62.37],\n        [1179093600000, 62.46],\n        [1179180000000, 63.17],\n        [1179266400000, 62.55],\n        [1179352800000, 64.94],\n        [1179698400000, 66.27],\n        [1179784800000, 65.50],\n        [1179871200000, 65.77],\n        [1179957600000, 64.18],\n        [1180044000000, 65.20],\n        [1180389600000, 63.15],\n        [1180476000000, 63.49],\n        [1180562400000, 65.08],\n        [1180908000000, 66.30],\n        [1180994400000, 65.96],\n        [1181167200000, 66.93],\n        [1181253600000, 65.98],\n        [1181599200000, 65.35],\n        [1181685600000, 66.26],\n        [1181858400000, 68.00],\n        [1182117600000, 69.09],\n        [1182204000000, 69.10],\n        [1182290400000, 68.19],\n        [1182376800000, 68.19],\n        [1182463200000, 69.14],\n        [1182722400000, 68.19],\n        [1182808800000, 67.77],\n        [1182895200000, 68.97],\n        [1182981600000, 69.57],\n        [1183068000000, 70.68],\n        [1183327200000, 71.09],\n        [1183413600000, 70.92],\n        [1183586400000, 71.81],\n        [1183672800000, 72.81],\n        [1183932000000, 72.19],\n        [1184018400000, 72.56],\n        [1184191200000, 72.50],\n        [1184277600000, 74.15],\n        [1184623200000, 75.05],\n        [1184796000000, 75.92],\n        [1184882400000, 75.57],\n        [1185141600000, 74.89],\n        [1185228000000, 73.56],\n        [1185314400000, 75.57],\n        [1185400800000, 74.95],\n        [1185487200000, 76.83],\n        [1185832800000, 78.21],\n        [1185919200000, 76.53],\n        [1186005600000, 76.86],\n        [1186092000000, 76.00],\n        [1186437600000, 71.59],\n        [1186696800000, 71.47],\n        [1186956000000, 71.62],\n        [1187042400000, 71.00],\n        [1187301600000, 71.98],\n        [1187560800000, 71.12],\n        [1187647200000, 69.47],\n        [1187733600000, 69.26],\n        [1187820000000, 69.83],\n        [1187906400000, 71.09],\n        [1188165600000, 71.73],\n        [1188338400000, 73.36],\n        [1188511200000, 74.04],\n        [1188856800000, 76.30],\n        [1189116000000, 77.49],\n        [1189461600000, 78.23],\n        [1189548000000, 79.91],\n        [1189634400000, 80.09],\n        [1189720800000, 79.10],\n        [1189980000000, 80.57],\n        [1190066400000, 81.93],\n        [1190239200000, 83.32],\n        [1190325600000, 81.62],\n        [1190584800000, 80.95],\n        [1190671200000, 79.53],\n        [1190757600000, 80.30],\n        [1190844000000, 82.88],\n        [1190930400000, 81.66],\n        [1191189600000, 80.24],\n        [1191276000000, 80.05],\n        [1191362400000, 79.94],\n        [1191448800000, 81.44],\n        [1191535200000, 81.22],\n        [1191794400000, 79.02],\n        [1191880800000, 80.26],\n        [1191967200000, 80.30],\n        [1192053600000, 83.08],\n        [1192140000000, 83.69],\n        [1192399200000, 86.13],\n        [1192485600000, 87.61],\n        [1192572000000, 87.40],\n        [1192658400000, 89.47],\n        [1192744800000, 88.60],\n        [1193004000000, 87.56],\n        [1193090400000, 87.56],\n        [1193176800000, 87.10],\n        [1193263200000, 91.86],\n        [1193612400000, 93.53],\n        [1193698800000, 94.53],\n        [1193871600000, 95.93],\n        [1194217200000, 93.98],\n        [1194303600000, 96.37],\n        [1194476400000, 95.46],\n        [1194562800000, 96.32],\n        [1195081200000, 93.43],\n        [1195167600000, 95.10],\n        [1195426800000, 94.64],\n        [1195513200000, 95.10],\n        [1196031600000, 97.70],\n        [1196118000000, 94.42],\n        [1196204400000, 90.62],\n        [1196290800000, 91.01],\n        [1196377200000, 88.71],\n        [1196636400000, 88.32],\n        [1196809200000, 90.23],\n        [1196982000000, 88.28],\n        [1197241200000, 87.86],\n        [1197327600000, 90.02],\n        [1197414000000, 92.25],\n        [1197586800000, 90.63],\n        [1197846000000, 90.63],\n        [1197932400000, 90.49],\n        [1198018800000, 91.24],\n        [1198105200000, 91.06],\n        [1198191600000, 90.49],\n        [1198710000000, 96.62],\n        [1198796400000, 96.00],\n        [1199142000000, 99.62],\n        [1199314800000, 99.18],\n        [1199401200000, 95.09],\n        [1199660400000, 96.33],\n        [1199833200000, 95.67],\n        [1200351600000, 91.90],\n        [1200438000000, 90.84],\n        [1200524400000, 90.13],\n        [1200610800000, 90.57],\n        [1200956400000, 89.21],\n        [1201042800000, 86.99],\n        [1201129200000, 89.85],\n        [1201474800000, 90.99],\n        [1201561200000, 91.64],\n        [1201647600000, 92.33],\n        [1201734000000, 91.75],\n        [1202079600000, 90.02],\n        [1202166000000, 88.41],\n        [1202252400000, 87.14],\n        [1202338800000, 88.11],\n        [1202425200000, 91.77],\n        [1202770800000, 92.78],\n        [1202857200000, 93.27],\n        [1202943600000, 95.46],\n        [1203030000000, 95.46],\n        [1203289200000, 101.74],\n        [1203462000000, 98.81],\n        [1203894000000, 100.88],\n        [1204066800000, 99.64],\n        [1204153200000, 102.59],\n        [1204239600000, 101.84],\n        [1204498800000, 99.52],\n        [1204585200000, 99.52],\n        [1204671600000, 104.52],\n        [1204758000000, 105.47],\n        [1204844400000, 105.15],\n        [1205103600000, 108.75],\n        [1205276400000, 109.92],\n        [1205362800000, 110.33],\n        [1205449200000, 110.21],\n        [1205708400000, 105.68],\n        [1205967600000, 101.84],\n        [1206313200000, 100.86],\n        [1206399600000, 101.22],\n        [1206486000000, 105.90],\n        [1206572400000, 107.58],\n        [1206658800000, 105.62],\n        [1206914400000, 101.58],\n        [1207000800000, 100.98],\n        [1207173600000, 103.83],\n        [1207260000000, 106.23],\n        [1207605600000, 108.50],\n        [1207778400000, 110.11],\n        [1207864800000, 110.14],\n        [1208210400000, 113.79],\n        [1208296800000, 114.93],\n        [1208383200000, 114.86],\n        [1208728800000, 117.48],\n        [1208815200000, 118.30],\n        [1208988000000, 116.06],\n        [1209074400000, 118.52],\n        [1209333600000, 118.75],\n        [1209420000000, 113.46],\n        [1209592800000, 112.52],\n        [1210024800000, 121.84],\n        [1210111200000, 123.53],\n        [1210197600000, 123.69],\n        [1210543200000, 124.23],\n        [1210629600000, 125.80],\n        [1210716000000, 126.29],\n        [1211148000000, 127.05],\n        [1211320800000, 129.07],\n        [1211493600000, 132.19],\n        [1211839200000, 128.85],\n        [1212357600000, 127.76],\n        [1212703200000, 138.54],\n        [1212962400000, 136.80],\n        [1213135200000, 136.38],\n        [1213308000000, 134.86],\n        [1213653600000, 134.01],\n        [1213740000000, 136.68],\n        [1213912800000, 135.65],\n        [1214172000000, 134.62],\n        [1214258400000, 134.62],\n        [1214344800000, 134.62],\n        [1214431200000, 139.64],\n        [1214517600000, 140.21],\n        [1214776800000, 140.00],\n        [1214863200000, 140.97],\n        [1214949600000, 143.57],\n        [1215036000000, 145.29],\n        [1215381600000, 141.37],\n        [1215468000000, 136.04],\n        [1215727200000, 146.40],\n        [1215986400000, 145.18],\n        [1216072800000, 138.74],\n        [1216159200000, 134.60],\n        [1216245600000, 129.29],\n        [1216332000000, 130.65],\n        [1216677600000, 127.95],\n        [1216850400000, 127.95],\n        [1217282400000, 122.19],\n        [1217455200000, 124.08],\n        [1217541600000, 125.10],\n        [1217800800000, 121.41],\n        [1217887200000, 119.17],\n        [1217973600000, 118.58],\n        [1218060000000, 120.02],\n        [1218405600000, 114.45],\n        [1218492000000, 113.01],\n        [1218578400000, 116.00],\n        [1218751200000, 113.77],\n        [1219010400000, 112.87],\n        [1219096800000, 114.53],\n        [1219269600000, 114.98],\n        [1219356000000, 114.98],\n        [1219701600000, 116.27],\n        [1219788000000, 118.15],\n        [1219874400000, 115.59],\n        [1219960800000, 115.46],\n        [1220306400000, 109.71],\n        [1220392800000, 109.35],\n        [1220565600000, 106.23],\n        [1220824800000, 106.34]\n    ];\n    var exchangerates = [\n        [1167606000000, 0.7580],\n        [1167692400000, 0.7580],\n        [1167778800000, 0.75470],\n        [1167865200000, 0.75490],\n        [1167951600000, 0.76130],\n        [1168038000000, 0.76550],\n        [1168124400000, 0.76930],\n        [1168210800000, 0.76940],\n        [1168297200000, 0.76880],\n        [1168383600000, 0.76780],\n        [1168470000000, 0.77080],\n        [1168556400000, 0.77270],\n        [1168642800000, 0.77490],\n        [1168729200000, 0.77410],\n        [1168815600000, 0.77410],\n        [1168902000000, 0.77320],\n        [1168988400000, 0.77270],\n        [1169074800000, 0.77370],\n        [1169161200000, 0.77240],\n        [1169247600000, 0.77120],\n        [1169334000000, 0.7720],\n        [1169420400000, 0.77210],\n        [1169506800000, 0.77170],\n        [1169593200000, 0.77040],\n        [1169679600000, 0.7690],\n        [1169766000000, 0.77110],\n        [1169852400000, 0.7740],\n        [1169938800000, 0.77450],\n        [1170025200000, 0.77450],\n        [1170111600000, 0.7740],\n        [1170198000000, 0.77160],\n        [1170284400000, 0.77130],\n        [1170370800000, 0.76780],\n        [1170457200000, 0.76880],\n        [1170543600000, 0.77180],\n        [1170630000000, 0.77180],\n        [1170716400000, 0.77280],\n        [1170802800000, 0.77290],\n        [1170889200000, 0.76980],\n        [1170975600000, 0.76850],\n        [1171062000000, 0.76810],\n        [1171148400000, 0.7690],\n        [1171234800000, 0.7690],\n        [1171321200000, 0.76980],\n        [1171407600000, 0.76990],\n        [1171494000000, 0.76510],\n        [1171580400000, 0.76130],\n        [1171666800000, 0.76160],\n        [1171753200000, 0.76140],\n        [1171839600000, 0.76140],\n        [1171926000000, 0.76070],\n        [1172012400000, 0.76020],\n        [1172098800000, 0.76110],\n        [1172185200000, 0.76220],\n        [1172271600000, 0.76150],\n        [1172358000000, 0.75980],\n        [1172444400000, 0.75980],\n        [1172530800000, 0.75920],\n        [1172617200000, 0.75730],\n        [1172703600000, 0.75660],\n        [1172790000000, 0.75670],\n        [1172876400000, 0.75910],\n        [1172962800000, 0.75820],\n        [1173049200000, 0.75850],\n        [1173135600000, 0.76130],\n        [1173222000000, 0.76310],\n        [1173308400000, 0.76150],\n        [1173394800000, 0.760],\n        [1173481200000, 0.76130],\n        [1173567600000, 0.76270],\n        [1173654000000, 0.76270],\n        [1173740400000, 0.76080],\n        [1173826800000, 0.75830],\n        [1173913200000, 0.75750],\n        [1173999600000, 0.75620],\n        [1174086000000, 0.7520],\n        [1174172400000, 0.75120],\n        [1174258800000, 0.75120],\n        [1174345200000, 0.75170],\n        [1174431600000, 0.7520],\n        [1174518000000, 0.75110],\n        [1174604400000, 0.7480],\n        [1174690800000, 0.75090],\n        [1174777200000, 0.75310],\n        [1174860000000, 0.75310],\n        [1174946400000, 0.75270],\n        [1175032800000, 0.74980],\n        [1175119200000, 0.74930],\n        [1175205600000, 0.75040],\n        [1175292000000, 0.750],\n        [1175378400000, 0.74910],\n        [1175464800000, 0.74910],\n        [1175551200000, 0.74850],\n        [1175637600000, 0.74840],\n        [1175724000000, 0.74920],\n        [1175810400000, 0.74710],\n        [1175896800000, 0.74590],\n        [1175983200000, 0.74770],\n        [1176069600000, 0.74770],\n        [1176156000000, 0.74830],\n        [1176242400000, 0.74580],\n        [1176328800000, 0.74480],\n        [1176415200000, 0.7430],\n        [1176501600000, 0.73990],\n        [1176588000000, 0.73950],\n        [1176674400000, 0.73950],\n        [1176760800000, 0.73780],\n        [1176847200000, 0.73820],\n        [1176933600000, 0.73620],\n        [1177020000000, 0.73550],\n        [1177106400000, 0.73480],\n        [1177192800000, 0.73610],\n        [1177279200000, 0.73610],\n        [1177365600000, 0.73650],\n        [1177452000000, 0.73620],\n        [1177538400000, 0.73310],\n        [1177624800000, 0.73390],\n        [1177711200000, 0.73440],\n        [1177797600000, 0.73270],\n        [1177884000000, 0.73270],\n        [1177970400000, 0.73360],\n        [1178056800000, 0.73330],\n        [1178143200000, 0.73590],\n        [1178229600000, 0.73590],\n        [1178316000000, 0.73720],\n        [1178402400000, 0.7360],\n        [1178488800000, 0.7360],\n        [1178575200000, 0.7350],\n        [1178661600000, 0.73650],\n        [1178748000000, 0.73840],\n        [1178834400000, 0.73950],\n        [1178920800000, 0.74130],\n        [1179007200000, 0.73970],\n        [1179093600000, 0.73960],\n        [1179180000000, 0.73850],\n        [1179266400000, 0.73780],\n        [1179352800000, 0.73660],\n        [1179439200000, 0.740],\n        [1179525600000, 0.74110],\n        [1179612000000, 0.74060],\n        [1179698400000, 0.74050],\n        [1179784800000, 0.74140],\n        [1179871200000, 0.74310],\n        [1179957600000, 0.74310],\n        [1180044000000, 0.74380],\n        [1180130400000, 0.74430],\n        [1180216800000, 0.74430],\n        [1180303200000, 0.74430],\n        [1180389600000, 0.74340],\n        [1180476000000, 0.74290],\n        [1180562400000, 0.74420],\n        [1180648800000, 0.7440],\n        [1180735200000, 0.74390],\n        [1180821600000, 0.74370],\n        [1180908000000, 0.74370],\n        [1180994400000, 0.74290],\n        [1181080800000, 0.74030],\n        [1181167200000, 0.73990],\n        [1181253600000, 0.74180],\n        [1181340000000, 0.74680],\n        [1181426400000, 0.7480],\n        [1181512800000, 0.7480],\n        [1181599200000, 0.7490],\n        [1181685600000, 0.74940],\n        [1181772000000, 0.75220],\n        [1181858400000, 0.75150],\n        [1181944800000, 0.75020],\n        [1182031200000, 0.74720],\n        [1182117600000, 0.74720],\n        [1182204000000, 0.74620],\n        [1182290400000, 0.74550],\n        [1182376800000, 0.74490],\n        [1182463200000, 0.74670],\n        [1182549600000, 0.74580],\n        [1182636000000, 0.74270],\n        [1182722400000, 0.74270],\n        [1182808800000, 0.7430],\n        [1182895200000, 0.74290],\n        [1182981600000, 0.7440],\n        [1183068000000, 0.7430],\n        [1183154400000, 0.74220],\n        [1183240800000, 0.73880],\n        [1183327200000, 0.73880],\n        [1183413600000, 0.73690],\n        [1183500000000, 0.73450],\n        [1183586400000, 0.73450],\n        [1183672800000, 0.73450],\n        [1183759200000, 0.73520],\n        [1183845600000, 0.73410],\n        [1183932000000, 0.73410],\n        [1184018400000, 0.7340],\n        [1184104800000, 0.73240],\n        [1184191200000, 0.72720],\n        [1184277600000, 0.72640],\n        [1184364000000, 0.72550],\n        [1184450400000, 0.72580],\n        [1184536800000, 0.72580],\n        [1184623200000, 0.72560],\n        [1184709600000, 0.72570],\n        [1184796000000, 0.72470],\n        [1184882400000, 0.72430],\n        [1184968800000, 0.72440],\n        [1185055200000, 0.72350],\n        [1185141600000, 0.72350],\n        [1185228000000, 0.72350],\n        [1185314400000, 0.72350],\n        [1185400800000, 0.72620],\n        [1185487200000, 0.72880],\n        [1185573600000, 0.73010],\n        [1185660000000, 0.73370],\n        [1185746400000, 0.73370],\n        [1185832800000, 0.73240],\n        [1185919200000, 0.72970],\n        [1186005600000, 0.73170],\n        [1186092000000, 0.73150],\n        [1186178400000, 0.72880],\n        [1186264800000, 0.72630],\n        [1186351200000, 0.72630],\n        [1186437600000, 0.72420],\n        [1186524000000, 0.72530],\n        [1186610400000, 0.72640],\n        [1186696800000, 0.7270],\n        [1186783200000, 0.73120],\n        [1186869600000, 0.73050],\n        [1186956000000, 0.73050],\n        [1187042400000, 0.73180],\n        [1187128800000, 0.73580],\n        [1187215200000, 0.74090],\n        [1187301600000, 0.74540],\n        [1187388000000, 0.74370],\n        [1187474400000, 0.74240],\n        [1187560800000, 0.74240],\n        [1187647200000, 0.74150],\n        [1187733600000, 0.74190],\n        [1187820000000, 0.74140],\n        [1187906400000, 0.73770],\n        [1187992800000, 0.73550],\n        [1188079200000, 0.73150],\n        [1188165600000, 0.73150],\n        [1188252000000, 0.7320],\n        [1188338400000, 0.73320],\n        [1188424800000, 0.73460],\n        [1188511200000, 0.73280],\n        [1188597600000, 0.73230],\n        [1188684000000, 0.7340],\n        [1188770400000, 0.7340],\n        [1188856800000, 0.73360],\n        [1188943200000, 0.73510],\n        [1189029600000, 0.73460],\n        [1189116000000, 0.73210],\n        [1189202400000, 0.72940],\n        [1189288800000, 0.72660],\n        [1189375200000, 0.72660],\n        [1189461600000, 0.72540],\n        [1189548000000, 0.72420],\n        [1189634400000, 0.72130],\n        [1189720800000, 0.71970],\n        [1189807200000, 0.72090],\n        [1189893600000, 0.7210],\n        [1189980000000, 0.7210],\n        [1190066400000, 0.7210],\n        [1190152800000, 0.72090],\n        [1190239200000, 0.71590],\n        [1190325600000, 0.71330],\n        [1190412000000, 0.71050],\n        [1190498400000, 0.70990],\n        [1190584800000, 0.70990],\n        [1190671200000, 0.70930],\n        [1190757600000, 0.70930],\n        [1190844000000, 0.70760],\n        [1190930400000, 0.7070],\n        [1191016800000, 0.70490],\n        [1191103200000, 0.70120],\n        [1191189600000, 0.70110],\n        [1191276000000, 0.70190],\n        [1191362400000, 0.70460],\n        [1191448800000, 0.70630],\n        [1191535200000, 0.70890],\n        [1191621600000, 0.70770],\n        [1191708000000, 0.70770],\n        [1191794400000, 0.70770],\n        [1191880800000, 0.70910],\n        [1191967200000, 0.71180],\n        [1192053600000, 0.70790],\n        [1192140000000, 0.70530],\n        [1192226400000, 0.7050],\n        [1192312800000, 0.70550],\n        [1192399200000, 0.70550],\n        [1192485600000, 0.70450],\n        [1192572000000, 0.70510],\n        [1192658400000, 0.70510],\n        [1192744800000, 0.70170],\n        [1192831200000, 0.70],\n        [1192917600000, 0.69950],\n        [1193004000000, 0.69940],\n        [1193090400000, 0.70140],\n        [1193176800000, 0.70360],\n        [1193263200000, 0.70210],\n        [1193349600000, 0.70020],\n        [1193436000000, 0.69670],\n        [1193522400000, 0.6950],\n        [1193612400000, 0.6950],\n        [1193698800000, 0.69390],\n        [1193785200000, 0.6940],\n        [1193871600000, 0.69220],\n        [1193958000000, 0.69190],\n        [1194044400000, 0.69140],\n        [1194130800000, 0.68940],\n        [1194217200000, 0.68910],\n        [1194303600000, 0.69040],\n        [1194390000000, 0.6890],\n        [1194476400000, 0.68340],\n        [1194562800000, 0.68230],\n        [1194649200000, 0.68070],\n        [1194735600000, 0.68150],\n        [1194822000000, 0.68150],\n        [1194908400000, 0.68470],\n        [1194994800000, 0.68590],\n        [1195081200000, 0.68220],\n        [1195167600000, 0.68270],\n        [1195254000000, 0.68370],\n        [1195340400000, 0.68230],\n        [1195426800000, 0.68220],\n        [1195513200000, 0.68220],\n        [1195599600000, 0.67920],\n        [1195686000000, 0.67460],\n        [1195772400000, 0.67350],\n        [1195858800000, 0.67310],\n        [1195945200000, 0.67420],\n        [1196031600000, 0.67440],\n        [1196118000000, 0.67390],\n        [1196204400000, 0.67310],\n        [1196290800000, 0.67610],\n        [1196377200000, 0.67610],\n        [1196463600000, 0.67850],\n        [1196550000000, 0.68180],\n        [1196636400000, 0.68360],\n        [1196722800000, 0.68230],\n        [1196809200000, 0.68050],\n        [1196895600000, 0.67930],\n        [1196982000000, 0.68490],\n        [1197068400000, 0.68330],\n        [1197154800000, 0.68250],\n        [1197241200000, 0.68250],\n        [1197327600000, 0.68160],\n        [1197414000000, 0.67990],\n        [1197500400000, 0.68130],\n        [1197586800000, 0.68090],\n        [1197673200000, 0.68680],\n        [1197759600000, 0.69330],\n        [1197846000000, 0.69330],\n        [1197932400000, 0.69450],\n        [1198018800000, 0.69440],\n        [1198105200000, 0.69460],\n        [1198191600000, 0.69640],\n        [1198278000000, 0.69650],\n        [1198364400000, 0.69560],\n        [1198450800000, 0.69560],\n        [1198537200000, 0.6950],\n        [1198623600000, 0.69480],\n        [1198710000000, 0.69280],\n        [1198796400000, 0.68870],\n        [1198882800000, 0.68240],\n        [1198969200000, 0.67940],\n        [1199055600000, 0.67940],\n        [1199142000000, 0.68030],\n        [1199228400000, 0.68550],\n        [1199314800000, 0.68240],\n        [1199401200000, 0.67910],\n        [1199487600000, 0.67830],\n        [1199574000000, 0.67850],\n        [1199660400000, 0.67850],\n        [1199746800000, 0.67970],\n        [1199833200000, 0.680],\n        [1199919600000, 0.68030],\n        [1200006000000, 0.68050],\n        [1200092400000, 0.6760],\n        [1200178800000, 0.6770],\n        [1200265200000, 0.6770],\n        [1200351600000, 0.67360],\n        [1200438000000, 0.67260],\n        [1200524400000, 0.67640],\n        [1200610800000, 0.68210],\n        [1200697200000, 0.68310],\n        [1200783600000, 0.68420],\n        [1200870000000, 0.68420],\n        [1200956400000, 0.68870],\n        [1201042800000, 0.69030],\n        [1201129200000, 0.68480],\n        [1201215600000, 0.68240],\n        [1201302000000, 0.67880],\n        [1201388400000, 0.68140],\n        [1201474800000, 0.68140],\n        [1201561200000, 0.67970],\n        [1201647600000, 0.67690],\n        [1201734000000, 0.67650],\n        [1201820400000, 0.67330],\n        [1201906800000, 0.67290],\n        [1201993200000, 0.67580],\n        [1202079600000, 0.67580],\n        [1202166000000, 0.6750],\n        [1202252400000, 0.6780],\n        [1202338800000, 0.68330],\n        [1202425200000, 0.68560],\n        [1202511600000, 0.69030],\n        [1202598000000, 0.68960],\n        [1202684400000, 0.68960],\n        [1202770800000, 0.68820],\n        [1202857200000, 0.68790],\n        [1202943600000, 0.68620],\n        [1203030000000, 0.68520],\n        [1203116400000, 0.68230],\n        [1203202800000, 0.68130],\n        [1203289200000, 0.68130],\n        [1203375600000, 0.68220],\n        [1203462000000, 0.68020],\n        [1203548400000, 0.68020],\n        [1203634800000, 0.67840],\n        [1203721200000, 0.67480],\n        [1203807600000, 0.67470],\n        [1203894000000, 0.67470],\n        [1203980400000, 0.67480],\n        [1204066800000, 0.67330],\n        [1204153200000, 0.6650],\n        [1204239600000, 0.66110],\n        [1204326000000, 0.65830],\n        [1204412400000, 0.6590],\n        [1204498800000, 0.6590],\n        [1204585200000, 0.65810],\n        [1204671600000, 0.65780],\n        [1204758000000, 0.65740],\n        [1204844400000, 0.65320],\n        [1204930800000, 0.65020],\n        [1205017200000, 0.65140],\n        [1205103600000, 0.65140],\n        [1205190000000, 0.65070],\n        [1205276400000, 0.6510],\n        [1205362800000, 0.64890],\n        [1205449200000, 0.64240],\n        [1205535600000, 0.64060],\n        [1205622000000, 0.63820],\n        [1205708400000, 0.63820],\n        [1205794800000, 0.63410],\n        [1205881200000, 0.63440],\n        [1205967600000, 0.63780],\n        [1206054000000, 0.64390],\n        [1206140400000, 0.64780],\n        [1206226800000, 0.64810],\n        [1206313200000, 0.64810],\n        [1206399600000, 0.64940],\n        [1206486000000, 0.64380],\n        [1206572400000, 0.63770],\n        [1206658800000, 0.63290],\n        [1206745200000, 0.63360],\n        [1206831600000, 0.63330],\n        [1206914400000, 0.63330],\n        [1207000800000, 0.6330],\n        [1207087200000, 0.63710],\n        [1207173600000, 0.64030],\n        [1207260000000, 0.63960],\n        [1207346400000, 0.63640],\n        [1207432800000, 0.63560],\n        [1207519200000, 0.63560],\n        [1207605600000, 0.63680],\n        [1207692000000, 0.63570],\n        [1207778400000, 0.63540],\n        [1207864800000, 0.6320],\n        [1207951200000, 0.63320],\n        [1208037600000, 0.63280],\n        [1208124000000, 0.63310],\n        [1208210400000, 0.63420],\n        [1208296800000, 0.63210],\n        [1208383200000, 0.63020],\n        [1208469600000, 0.62780],\n        [1208556000000, 0.63080],\n        [1208642400000, 0.63240],\n        [1208728800000, 0.63240],\n        [1208815200000, 0.63070],\n        [1208901600000, 0.62770],\n        [1208988000000, 0.62690],\n        [1209074400000, 0.63350],\n        [1209160800000, 0.63920],\n        [1209247200000, 0.640],\n        [1209333600000, 0.64010],\n        [1209420000000, 0.63960],\n        [1209506400000, 0.64070],\n        [1209592800000, 0.64230],\n        [1209679200000, 0.64290],\n        [1209765600000, 0.64720],\n        [1209852000000, 0.64850],\n        [1209938400000, 0.64860],\n        [1210024800000, 0.64670],\n        [1210111200000, 0.64440],\n        [1210197600000, 0.64670],\n        [1210284000000, 0.65090],\n        [1210370400000, 0.64780],\n        [1210456800000, 0.64610],\n        [1210543200000, 0.64610],\n        [1210629600000, 0.64680],\n        [1210716000000, 0.64490],\n        [1210802400000, 0.6470],\n        [1210888800000, 0.64610],\n        [1210975200000, 0.64520],\n        [1211061600000, 0.64220],\n        [1211148000000, 0.64220],\n        [1211234400000, 0.64250],\n        [1211320800000, 0.64140],\n        [1211407200000, 0.63660],\n        [1211493600000, 0.63460],\n        [1211580000000, 0.6350],\n        [1211666400000, 0.63460],\n        [1211752800000, 0.63460],\n        [1211839200000, 0.63430],\n        [1211925600000, 0.63460],\n        [1212012000000, 0.63790],\n        [1212098400000, 0.64160],\n        [1212184800000, 0.64420],\n        [1212271200000, 0.64310],\n        [1212357600000, 0.64310],\n        [1212444000000, 0.64350],\n        [1212530400000, 0.6440],\n        [1212616800000, 0.64730],\n        [1212703200000, 0.64690],\n        [1212789600000, 0.63860],\n        [1212876000000, 0.63560],\n        [1212962400000, 0.6340],\n        [1213048800000, 0.63460],\n        [1213135200000, 0.6430],\n        [1213221600000, 0.64520],\n        [1213308000000, 0.64670],\n        [1213394400000, 0.65060],\n        [1213480800000, 0.65040],\n        [1213567200000, 0.65030],\n        [1213653600000, 0.64810],\n        [1213740000000, 0.64510],\n        [1213826400000, 0.6450],\n        [1213912800000, 0.64410],\n        [1213999200000, 0.64140],\n        [1214085600000, 0.64090],\n        [1214172000000, 0.64090],\n        [1214258400000, 0.64280],\n        [1214344800000, 0.64310],\n        [1214431200000, 0.64180],\n        [1214517600000, 0.63710],\n        [1214604000000, 0.63490],\n        [1214690400000, 0.63330],\n        [1214776800000, 0.63340],\n        [1214863200000, 0.63380],\n        [1214949600000, 0.63420],\n        [1215036000000, 0.6320],\n        [1215122400000, 0.63180],\n        [1215208800000, 0.6370],\n        [1215295200000, 0.63680],\n        [1215381600000, 0.63680],\n        [1215468000000, 0.63830],\n        [1215554400000, 0.63710],\n        [1215640800000, 0.63710],\n        [1215727200000, 0.63550],\n        [1215813600000, 0.6320],\n        [1215900000000, 0.62770],\n        [1215986400000, 0.62760],\n        [1216072800000, 0.62910],\n        [1216159200000, 0.62740],\n        [1216245600000, 0.62930],\n        [1216332000000, 0.63110],\n        [1216418400000, 0.6310],\n        [1216504800000, 0.63120],\n        [1216591200000, 0.63120],\n        [1216677600000, 0.63040],\n        [1216764000000, 0.62940],\n        [1216850400000, 0.63480],\n        [1216936800000, 0.63780],\n        [1217023200000, 0.63680],\n        [1217109600000, 0.63680],\n        [1217196000000, 0.63680],\n        [1217282400000, 0.6360],\n        [1217368800000, 0.6370],\n        [1217455200000, 0.64180],\n        [1217541600000, 0.64110],\n        [1217628000000, 0.64350],\n        [1217714400000, 0.64270],\n        [1217800800000, 0.64270],\n        [1217887200000, 0.64190],\n        [1217973600000, 0.64460],\n        [1218060000000, 0.64680],\n        [1218146400000, 0.64870],\n        [1218232800000, 0.65940],\n        [1218319200000, 0.66660],\n        [1218405600000, 0.66660],\n        [1218492000000, 0.66780],\n        [1218578400000, 0.67120],\n        [1218664800000, 0.67050],\n        [1218751200000, 0.67180],\n        [1218837600000, 0.67840],\n        [1218924000000, 0.68110],\n        [1219010400000, 0.68110],\n        [1219096800000, 0.67940],\n        [1219183200000, 0.68040],\n        [1219269600000, 0.67810],\n        [1219356000000, 0.67560],\n        [1219442400000, 0.67350],\n        [1219528800000, 0.67630],\n        [1219615200000, 0.67620],\n        [1219701600000, 0.67770],\n        [1219788000000, 0.68150],\n        [1219874400000, 0.68020],\n        [1219960800000, 0.6780],\n        [1220047200000, 0.67960],\n        [1220133600000, 0.68170],\n        [1220220000000, 0.68170],\n        [1220306400000, 0.68320],\n        [1220392800000, 0.68770],\n        [1220479200000, 0.69120],\n        [1220565600000, 0.69140],\n        [1220652000000, 0.70090],\n        [1220738400000, 0.70120],\n        [1220824800000, 0.7010],\n        [1220911200000, 0.70050]\n    ];\n\n    function euroFormatter(v, axis) {\n        return \"&yen;\"+v.toFixed(axis.tickDecimals);\n    }\n\n    function doPlot(position) {\n        $.plot($(\"#flot-line-chart-multi\"), [{\n            data: oilprices,\n            label: \"油价 (&yen;)\"\n        }, {\n            data: exchangerates,\n            label: \"美元/人民币汇率\",\n            yaxis: 2\n        }], {\n            xaxes: [{\n                mode: 'time'\n            }],\n            yaxes: [{\n                min: 0\n            }, {\n                // align if we are to the right\n                alignTicksWithAxis: position == \"right\" ? 1 : null,\n                position: position,\n                tickFormatter: euroFormatter\n            }],\n            legend: {\n                position: 'sw'\n            },\n            colors: [\"#1ab394\"],\n            grid: {\n                color: \"#999999\",\n                hoverable: true,\n                clickable: true,\n                tickColor: \"#D4D4D4\",\n                borderWidth:0,\n                hoverable: true //IMPORTANT! this is needed for tooltip to work,\n\n            },\n            tooltip: true,\n            tooltipOpts: {\n                content: \"%s %x 为 %y\",\n                xDateFormat: \"%y-%0m-%0d\",\n\n                onHover: function(flotItem, $tooltipEl) {\n                    // console.log(flotItem, $tooltipEl);\n                }\n            }\n\n        });\n    }\n\n    doPlot(\"right\");\n\n    $(\"button\").click(function() {\n        doPlot($(this).text());\n    });\n});\n\n\n\n\n"
  },
  {
    "path": "src/main/resources/static/js/demo/form-advanced-demo.js",
    "content": "$(document).ready(function () {\n\n            var $image = $(\".image-crop > img\")\n            $($image).cropper({\n                aspectRatio: 1.618,\n                preview: \".img-preview\",\n                done: function (data) {\n                    // 输出结果\n                }\n            });\n\n            var $inputImage = $(\"#inputImage\");\n            if (window.FileReader) {\n                $inputImage.change(function () {\n                    var fileReader = new FileReader(),\n                        files = this.files,\n                        file;\n\n                    if (!files.length) {\n                        return;\n                    }\n\n                    file = files[0];\n\n                    if (/^image\\/\\w+$/.test(file.type)) {\n                        fileReader.readAsDataURL(file);\n                        fileReader.onload = function () {\n                            $inputImage.val(\"\");\n                            $image.cropper(\"reset\", true).cropper(\"replace\", this.result);\n                        };\n                    } else {\n                        showMessage(\"请选择图片文件\");\n                    }\n                });\n            } else {\n                $inputImage.addClass(\"hide\");\n            }\n\n            $(\"#download\").click(function () {\n                window.open($image.cropper(\"getDataURL\"));\n            });\n\n            $(\"#zoomIn\").click(function () {\n                $image.cropper(\"zoom\", 0.1);\n            });\n\n            $(\"#zoomOut\").click(function () {\n                $image.cropper(\"zoom\", -0.1);\n            });\n\n            $(\"#rotateLeft\").click(function () {\n                $image.cropper(\"rotate\", 45);\n            });\n\n            $(\"#rotateRight\").click(function () {\n                $image.cropper(\"rotate\", -45);\n            });\n\n            $(\"#setDrag\").click(function () {\n                $image.cropper(\"setDragMode\", \"crop\");\n            });\n\n            $('#data_1 .input-group.date').datepicker({\n                todayBtn: \"linked\",\n                keyboardNavigation: false,\n                forceParse: false,\n                calendarWeeks: true,\n                autoclose: true\n            });\n\n            $('#data_2 .input-group.date').datepicker({\n                startView: 1,\n                todayBtn: \"linked\",\n                keyboardNavigation: false,\n                forceParse: false,\n                autoclose: true,\n                format: \"yyyy-mm-dd\"\n            });\n\n            $('#data_3 .input-group.date').datepicker({\n                startView: 2,\n                todayBtn: \"linked\",\n                keyboardNavigation: false,\n                forceParse: false,\n                autoclose: true\n            });\n\n            $('#data_4 .input-group.date').datepicker({\n                minViewMode: 1,\n                keyboardNavigation: false,\n                forceParse: false,\n                autoclose: true,\n                todayHighlight: true\n            });\n\n            $('#data_5 .input-daterange').datepicker({\n                keyboardNavigation: false,\n                forceParse: false,\n                autoclose: true\n            });\n\n            var elem = document.querySelector('.js-switch');\n            var switchery = new Switchery(elem, {\n                color: '#1AB394'\n            });\n\n            var elem_2 = document.querySelector('.js-switch_2');\n            var switchery_2 = new Switchery(elem_2, {\n                color: '#ED5565'\n            });\n\n            var elem_3 = document.querySelector('.js-switch_3');\n            var switchery_3 = new Switchery(elem_3, {\n                color: '#1AB394'\n            });\n\n            $('.i-checks').iCheck({\n                checkboxClass: 'icheckbox_square-green',\n                radioClass: 'iradio_square-green'\n            });\n\n            $('.colorpicker-demo1').colorpicker();\n\n            $('.colorpicker-demo2').colorpicker();\n\n            $('.colorpicker-demo3').colorpicker();\n\n            // Code for demos\n            function createColorpickers() {\n                // Api demo\n                var bodyStyle = $('body')[0].style;\n                $('#demo_apidemo').colorpicker({\n                    color: bodyStyle.backgroundColor\n                }).on('changeColor', function (ev) {\n                    bodyStyle.backgroundColor = ev.color.toHex();\n                });\n\n                // Horizontal mode\n                $('#demo_forceformat').colorpicker({\n                    format: 'rgba', // force this format\n                    horizontal: true\n                });\n\n                $('.demo-auto').colorpicker();\n\n                // Disabled / enabled triggers\n                $(\".disable-button\").click(function (e) {\n                    e.preventDefault();\n                    $(\"#demo_endis\").colorpicker('disable');\n                });\n\n                $(\".enable-button\").click(function (e) {\n                    e.preventDefault();\n                    $(\"#demo_endis\").colorpicker('enable');\n                });\n            }\n\n            createColorpickers();\n\n            // Create / destroy instances\n            $('.demo-destroy').click(function (e) {\n                e.preventDefault();\n                $('.demo').colorpicker('destroy');\n                $(\".disable-button, .enable-button\").off('click');\n            });\n\n            $('.demo-create').click(function (e) {\n                e.preventDefault();\n                createColorpickers();\n            });\n\n            var divStyle = $('.back-change')[0].style;\n            $('#demo_apidemo').colorpicker({\n                color: divStyle.backgroundColor\n            }).on('changeColor', function (ev) {\n                divStyle.backgroundColor = ev.color.toHex();\n            });\n\n            $('.clockpicker').clockpicker();\n\n            $( '#file-pretty input[type=\"file\"]' ).prettyFile();\n\n        });\n        var config = {\n            '.chosen-select': {},\n            '.chosen-select-deselect': {\n                allow_single_deselect: true\n            },\n            '.chosen-select-no-single': {\n                disable_search_threshold: 10\n            },\n            '.chosen-select-no-results': {\n                no_results_text: 'Oops, nothing found!'\n            },\n            '.chosen-select-width': {\n                width: \"95%\"\n            }\n        }\n        for (var selector in config) {\n            $(selector).chosen(config[selector]);\n        }\n\n        $(\"#ionrange_1\").ionRangeSlider({\n            min: 0,\n            max: 5000,\n            type: 'double',\n            prefix: \"&yen;\",\n            maxPostfix: \"+\",\n            prettify: false,\n            hasGrid: true\n        });\n\n        $(\"#ionrange_2\").ionRangeSlider({\n            min: 0,\n            max: 10,\n            type: 'single',\n            step: 0.1,\n            postfix: \" 克\",\n            prettify: false,\n            hasGrid: true\n        });\n\n        $(\"#ionrange_3\").ionRangeSlider({\n            min: -50,\n            max: 50,\n            from: 0,\n            postfix: \"°\",\n            prettify: false,\n            hasGrid: true\n        });\n\n        $(\"#ionrange_4\").ionRangeSlider({\n            values: [\n                \"一月\", \"二月\", \"三月\",\n                \"四月\", \"五月\", \"六月\",\n                \"七月\", \"八月\", \"九月\",\n                \"十月\", \"十一月\", \"十二月\"\n            ],\n            type: 'single',\n            hasGrid: true\n        });\n\n        $(\"#ionrange_5\").ionRangeSlider({\n            min: 10000,\n            max: 100000,\n            step: 100,\n            postfix: \" km\",\n            from: 55000,\n            hideMinMax: true,\n            hideFromTo: false\n        });\n\n        $(\".dial\").knob();\n\n        $(\"#basic_slider\").noUiSlider({\n            start: 40,\n            behaviour: 'tap',\n            connect: 'upper',\n            range: {\n                'min': 20,\n                'max': 80\n            }\n        });\n\n        $(\"#range_slider\").noUiSlider({\n            start: [40, 60],\n            behaviour: 'drag',\n            connect: true,\n            range: {\n                'min': 20,\n                'max': 80\n            }\n        });\n\n        $(\"#drag-fixed\").noUiSlider({\n            start: [40, 60],\n            behaviour: 'drag-fixed',\n            connect: true,\n            range: {\n                'min': 20,\n                'max': 80\n            }\n        });\n"
  },
  {
    "path": "src/main/resources/static/js/demo/form-validate-demo.js",
    "content": "//以下为修改jQuery Validation插件兼容Bootstrap的方法，没有直接写在插件中是为了便于插件升级\n        $.validator.setDefaults({\n            highlight: function (element) {\n                $(element).closest('.form-group').removeClass('has-success').addClass('has-error');\n            },\n            success: function (element) {\n                element.closest('.form-group').removeClass('has-error').addClass('has-success');\n            },\n            errorElement: \"span\",\n            errorPlacement: function (error, element) {\n                if (element.is(\":radio\") || element.is(\":checkbox\")) {\n                    error.appendTo(element.parent().parent().parent());\n                } else {\n                    error.appendTo(element.parent());\n                }\n            },\n            errorClass: \"help-block m-b-none\",\n            validClass: \"help-block m-b-none\"\n\n\n        });\n\n        //以下为官方示例\n      /*  $().ready(function () {\n            // validate the comment form when it is submitted\n            $(\"#commentForm\").validate();\n\n            // validate signup form on keyup and submit\n            var icon = \"<i class='fa fa-times-circle'></i> \";\n            $(\"#signupForm\").validate({\n                rules: {\n                    firstname: \"required\",\n                    lastname: \"required\",\n                    username: {\n                        required: true,\n                        minlength: 2\n                    },\n                    password: {\n                        required: true,\n                        minlength: 5\n                    },\n                    confirm_password: {\n                        required: true,\n                        minlength: 5,\n                        equalTo: \"#password\"\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    topic: {\n                        required: \"#newsletter:checked\",\n                        minlength: 2\n                    },\n                    agree: \"required\"\n                },\n                messages: {\n                    firstname: icon + \"请输入你的姓\",\n                    lastname: icon + \"请输入您的名字\",\n                    username: {\n                        required: icon + \"请输入您的用户名\",\n                        minlength: icon + \"用户名必须两个字符以上\"\n                    },\n                    password: {\n                        required: icon + \"请输入您的密码\",\n                        minlength: icon + \"密码必须5个字符以上\"\n                    },\n                    confirm_password: {\n                        required: icon + \"请再次输入密码\",\n                        minlength: icon + \"密码必须5个字符以上\",\n                        equalTo: icon + \"两次输入的密码不一致\"\n                    },\n                    email: icon + \"请输入您的E-mail\",\n                    agree: {\n                        required: icon + \"必须同意协议后才能注册\",\n                        element: '#agree-error'\n                    }\n                }\n            });\n\n            // propose username by combining first- and lastname\n            $(\"#username\").focus(function () {\n                var firstname = $(\"#firstname\").val();\n                var lastname = $(\"#lastname\").val();\n                if (firstname && lastname && !this.value) {\n                    this.value = firstname + \".\" + lastname;\n                }\n            });\n        });*/\n"
  },
  {
    "path": "src/main/resources/static/js/demo/layer-demo.js",
    "content": "/*! layer demo */ ;\n! function () {\n    var gather = {\n        htdy: $('html, body')\n    };\n\n    //一睹为快\n    gather.demo1 = $('#demo1');\n    $('#chutiyan>a').on('click', function () {\n        var othis = $(this),\n            index = othis.index();\n        var p = gather.demo1.children('p').eq(index);\n        var top = p.position().top;\n        gather.demo1.animate({\n            scrollTop: gather.demo1.scrollTop() + top\n        }, 0);\n        switch (index) {\n        case 0:\n            var icon = -1;\n            (function changeIcon() {\n                var index = parent.layer.alert('点击确认更换图标', {\n                    icon: icon,\n                    shadeClose: true,\n                    title: icon === -1 ? '初体验' : 'icon：' + icon\n                }, changeIcon);\n                if (8 === ++icon) layer.close(index);\n            }());\n            break;\n        case 1:\n            var icon = 0;\n            (function changeIcon1() {\n                var index = parent.layer.alert('点击确认更换图标', {\n                    icon: icon,\n                    shadeClose: true,\n                    skin: 'layer-ext-moon',\n                    shift: 5,\n                    title: icon === -1 ? '第三方扩展皮肤' : 'icon：' + icon\n                }, changeIcon1);\n                if (9 === ++icon) {\n                    parent.layer.confirm('怎么样，是否很喜欢该皮肤，去下载？', {\n                        skin: 'layer-ext-moon'\n                    }, function (index, layero) {\n                        layero.find('.layui-layer-btn0').attr({\n                            href: 'http://layer.layui.com/skin.html',\n                            target: '_blank'\n                        });\n                        parent.layer.close(index);\n                    });\n                };\n            }());\n            break;\n        case 6:\n            parent.layer.open({\n                type: 1,\n                area: ['420px', '240px'],\n                skin: 'layui-layer-rim', //加上边框\n                content: '<div style=\"padding:20px;\">即直接给content传入html字符<br>当内容宽高超过定义宽高，会自动出现滚动条。<br><br><br><br><br><br><br><br><br><br><br>很高兴在下面遇见你</div>'\n            });\n            break;\n        case 7:\n            parent.layer.open({\n                type: 1,\n                skin: 'layui-layer-demo',\n                closeBtn: false,\n                area: '350px',\n                shift: 2,\n                shadeClose: true,\n                content: '<div style=\"padding:20px;\">即传入skin:\"样式名\"，然后你就可以为所欲为了。<br>你怎么样给她整容都行<br><br><br>我是华丽的酱油==。</div>'\n            });\n            break;\n        case 8:\n            layer.tips('Hi，我是tips', this);\n            break;\n        case 11:\n            var ii = parent.layer.load(0, {\n                shade: false\n            });\n            setTimeout(function () {\n                parent.layer.close(ii)\n            }, 5000);\n            break;\n        case 12:\n            var iii = parent.layer.load(1, {\n                shade: [0.1, '#fff']\n            });\n            setTimeout(function () {\n                parent.layer.close(iii)\n            }, 3000);\n            break;\n        case 13:\n            layer.tips('我是另外一个tips，只不过我长得跟之前那位稍有些不一样。', this, {\n                tips: [1, '#3595CC'],\n                time: 4000\n            });\n            break;\n        case 14:\n            parent.layer.prompt({\n                title: '输入任何口令，并确认',\n                formType: 1\n            }, function (pass) {\n                parent.layer.prompt({\n                    title: '随便写点啥，并确认',\n                    formType: 2\n                }, function (text) {\n                    parent.layer.msg('演示完毕！您的口令：' + pass + '<br>您最后写下了：' + text);\n                });\n            });\n            break;\n        case 15:\n            parent.layer.tab({\n                area: ['600px', '300px'],\n                tab: [{\n                    title: '无题',\n                    content: '<div style=\"padding:20px; line-height:30px; text-align:center\">欢迎体验layer.tab<br>此时此刻不禁让人吟诗一首：<br>一入前端深似海<br>从此妹纸是浮云<br>以下省略七个字<br>。。。。。。。<br>——贤心</div>'\n                }, {\n                    title: 'TAB2',\n                    content: '<div style=\"padding:20px;\">TAB2该说些啥</div>'\n                }, {\n                    title: 'TAB3',\n                    content: '<div style=\"padding:20px;\">有一种坚持叫：layer</div>'\n                }]\n            });\n            break;\n        case 16:\n            if (gather.photoJSON) {\n                layer.photos({\n                    photos: gather.photoJSON\n                });\n            } else {\n                $.getJSON('js/demo/photos.json?v=', function (json) {\n                    gather.photoJSON = json;\n                    layer.photos({\n                        photos: json\n                    });\n                });\n            }\n            break;\n        default:\n            new Function(p.text())();\n            break;\n        }\n    });\n}();\n"
  },
  {
    "path": "src/main/resources/static/js/demo/morris-demo.js",
    "content": "$(function() {\n\n    Morris.Line({\n        element: 'morris-one-line-chart',\n            data: [\n                { year: '2008', value: 5 },\n                { year: '2009', value: 10 },\n                { year: '2010', value: 8 },\n                { year: '2011', value: 22 },\n                { year: '2012', value: 8 },\n                { year: '2014', value: 10 },\n                { year: '2015', value: 5 }\n            ],\n        xkey: 'year',\n        ykeys: ['value'],\n        resize: true,\n        lineWidth:4,\n        labels: ['Value'],\n        lineColors: ['#1ab394'],\n        pointSize:5,\n    });\n\n    Morris.Area({\n        element: 'morris-area-chart',\n        data: [{\n            period: '2010 Q1',\n            iphone: 2666,\n            ipad: null,\n            itouch: 2647\n        }, {\n            period: '2010 Q2',\n            iphone: 2778,\n            ipad: 2294,\n            itouch: 2441\n        }, {\n            period: '2010 Q3',\n            iphone: 4912,\n            ipad: 1969,\n            itouch: 2501\n        }, {\n            period: '2010 Q4',\n            iphone: 3767,\n            ipad: 3597,\n            itouch: 5689\n        }, {\n            period: '2011 Q1',\n            iphone: 6810,\n            ipad: 1914,\n            itouch: 2293\n        }, {\n            period: '2011 Q2',\n            iphone: 5670,\n            ipad: 4293,\n            itouch: 1881\n        }, {\n            period: '2011 Q3',\n            iphone: 4820,\n            ipad: 3795,\n            itouch: 1588\n        }, {\n            period: '2011 Q4',\n            iphone: 15073,\n            ipad: 5967,\n            itouch: 5175\n        }, {\n            period: '2012 Q1',\n            iphone: 10687,\n            ipad: 4460,\n            itouch: 2028\n        }, {\n            period: '2012 Q2',\n            iphone: 8432,\n            ipad: 5713,\n            itouch: 1791\n        }],\n        xkey: 'period',\n        ykeys: ['iphone', 'ipad', 'itouch'],\n        labels: ['iPhone', 'iPad', 'iPod Touch'],\n        pointSize: 2,\n        hideHover: 'auto',\n        resize: true,\n        lineColors: ['#87d6c6', '#54cdb4','#1ab394'],\n        lineWidth:2,\n        pointSize:1,\n    });\n\n    Morris.Donut({\n        element: 'morris-donut-chart',\n        data: [{\n            label: \"A系列\",\n            value: 12\n        }, {\n            label: \"B系列\",\n            value: 30\n        }, {\n            label: \"C系列\",\n            value: 20\n        }],\n        resize: true,\n        colors: ['#87d6c6', '#54cdb4','#1ab394'],\n    });\n\n    Morris.Bar({\n        element: 'morris-bar-chart',\n        data: [{\n            y: '2006',\n            a: 60,\n            b: 50\n        }, {\n            y: '2007',\n            a: 75,\n            b: 65\n        }, {\n            y: '2008',\n            a: 50,\n            b: 40\n        }, {\n            y: '2009',\n            a: 75,\n            b: 65\n        }, {\n            y: '2010',\n            a: 50,\n            b: 40\n        }, {\n            y: '2011',\n            a: 75,\n            b: 65\n        }, {\n            y: '2012',\n            a: 100,\n            b: 90\n        }],\n        xkey: 'y',\n        ykeys: ['a', 'b'],\n        labels: ['A系列', 'B系列'],\n        hideHover: 'auto',\n        resize: true,\n        barColors: ['#1ab394', '#cacaca'],\n    });\n\n    Morris.Line({\n        element: 'morris-line-chart',\n        data: [{\n            y: '2006',\n            a: 100,\n            b: 90\n        }, {\n            y: '2007',\n            a: 75,\n            b: 65\n        }, {\n            y: '2008',\n            a: 50,\n            b: 40\n        }, {\n            y: '2009',\n            a: 75,\n            b: 65\n        }, {\n            y: '2010',\n            a: 50,\n            b: 40\n        }, {\n            y: '2011',\n            a: 75,\n            b: 65\n        }, {\n            y: '2012',\n            a: 100,\n            b: 90\n        }],\n        xkey: 'y',\n        ykeys: ['a', 'b'],\n        labels: ['A系列', 'B系列'],\n        hideHover: 'auto',\n        resize: true,\n        lineColors: ['#54cdb4','#1ab394'],\n    });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/peity-demo.js",
    "content": "$(function() {\n    $(\"span.pie\").peity(\"pie\", {\n        fill: ['#1ab394', '#d7d7d7', '#ffffff']\n    })\n\n    $(\".line\").peity(\"line\",{\n        fill: '#1ab394',\n        stroke:'#169c81',\n    })\n\n    $(\".bar\").peity(\"bar\", {\n        fill: [\"#1ab394\", \"#d7d7d7\"]\n    })\n\n    $(\".bar_dashboard\").peity(\"bar\", {\n        fill: [\"#1ab394\", \"#d7d7d7\"],\n        width:100\n    })\n\n    var updatingChart = $(\".updating-chart\").peity(\"line\", { fill: '#1ab394',stroke:'#169c81', width: 64 })\n\n    setInterval(function() {\n        var random = Math.round(Math.random() * 10)\n        var values = updatingChart.text().split(\",\")\n        values.shift()\n        values.push(random)\n\n        updatingChart\n            .text(values.join(\",\"))\n            .change()\n    }, 1000);\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/photos.json",
    "content": "{\n    \"status\": 1,\n    \"msg\": \"\",\n    \"title\": \"JSON请求的相册\",\n    \"id\": 8,\n    \"start\": 0,\n    \"data\": [\n        {\n            \"name\": \"越来越喜欢观察微小的事物\",\n            \"pid\": 109,\n            \"src\": \"http://f8.topitme.com/8/99/b0/1100251118d0cb0998l.jpg\",\n            \"thumb\": \"http://f8.topitme.com/8/99/b0/1100251118d0cb0998l.jpg\",\n            \"area\": [\n                510,\n                287\n            ]\n        },\n        {\n            \"name\": \"决定，意味着对与错的并存\",\n            \"pid\": 110,\n            \"src\": \"http://t.williamgates.net/image-9A50_54058FA3.jpg\",\n            \"thumb\": \"http://t.williamgates.net/image-9A50_54058FA3.jpg\",\n            \"area\": [\n                690,\n                431\n            ]\n        },\n        {\n            \"name\": \"给人姐姐般温暖的的邻家女孩\",\n            \"pid\": 111,\n            \"src\": \"http://t.williamgates.net/image-E9BF_54058FA3.jpg\",\n            \"thumb\": \"http://t.williamgates.net/image-E9BF_54058FA3.jpg\",\n            \"area\": [\n                690,\n                431\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": "src/main/resources/static/js/demo/rickshaw-demo.js",
    "content": "$(function() {\n    var graph = new Rickshaw.Graph( {\n        element: document.querySelector(\"#chart\"),\n        series: [{\n            color: '#1ab394',\n            data: [\n                { x: 0, y: 40 },\n                { x: 1, y: 49 },\n                { x: 2, y: 38 },\n                { x: 3, y: 30 },\n                { x: 4, y: 32 } ]\n        }]\n    });\n    graph.render();\n\n    var graph2 = new Rickshaw.Graph( {\n        element: document.querySelector(\"#rickshaw_multi\"),\n        renderer: 'area',\n        stroke: true,\n        series: [ {\n            data: [ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 20 }, { x: 4, y: 16 } ],\n            color: '#1ab394',\n            stroke: '#17997f'\n        }, {\n            data: [ { x: 0, y: 22 }, { x: 1, y: 25 }, { x: 2, y: 38 }, { x: 3, y: 44 }, { x: 4, y: 46 } ],\n            color: '#eeeeee',\n            stroke: '#d7d7d7'\n        } ]\n    } );\n    graph2.renderer.unstack = true;\n    graph2.render();\n\n    var graph3 = new Rickshaw.Graph({\n        element: document.querySelector(\"#rickshaw_line\"),\n        renderer: 'line',\n        series: [ {\n            data: [ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ],\n            color: '#1ab394'\n        } ]\n    } );\n    graph3.render();\n\n    var graph4 = new Rickshaw.Graph({\n        element: document.querySelector(\"#rickshaw_multi_line\"),\n        renderer: 'line',\n        series: [{\n            data: [ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ],\n            color: '#1ab394'\n        }, {\n            data: [ { x: 0, y: 20 }, { x: 1, y: 24 }, { x: 2, y: 19 }, { x: 3, y: 15 }, { x: 4, y: 16 } ],\n            color: '#d7d7d7'\n        }]\n    });\n    graph4.render();\n\n    var graph5 = new Rickshaw.Graph( {\n        element: document.querySelector(\"#rickshaw_bars\"),\n        renderer: 'bar',\n        series: [ {\n            data: [ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ],\n            color: '#1ab394'\n        } ]\n    } );\n    graph5.render();\n\n    var graph6 = new Rickshaw.Graph( {\n        element: document.querySelector(\"#rickshaw_bars_stacked\"),\n        renderer: 'bar',\n        series: [\n            {\n                data: [ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ],\n                color: '#1ab394'\n            }, {\n                data: [ { x: 0, y: 20 }, { x: 1, y: 24 }, { x: 2, y: 19 }, { x: 3, y: 15 }, { x: 4, y: 16 } ],\n                color: '#d7d7d7'\n            } ]\n    } );\n    graph6.render();\n\n    var graph7 = new Rickshaw.Graph( {\n        element: document.querySelector(\"#rickshaw_scatterplot\"),\n        renderer: 'scatterplot',\n        stroke: true,\n        padding: { top: 0.05, left: 0.05, right: 0.05 },\n        series: [ {\n            data: [ { x: 0, y: 15 },\n                { x: 1, y: 18 },\n                { x: 2, y: 10 },\n                { x: 3, y: 12 },\n                { x: 4, y: 15 },\n                { x: 5, y: 24 },\n                { x: 6, y: 28 },\n                { x: 7, y: 31 },\n                { x: 8, y: 22 },\n                { x: 9, y: 18 },\n                { x: 10, y: 16 }\n            ],\n            color: '#1ab394'\n        } ]\n    } );\n    graph7.render();\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/sparkline-demo.js",
    "content": "$(function () {\n    $(\"#sparkline1\").sparkline([34, 43, 43, 35, 44, 32, 44, 52, 25], {\n        type: 'line',\n        lineColor: '#17997f',\n        fillColor: '#1ab394',\n    });\n    $(\"#sparkline2\").sparkline([5, 6, 7, 2, 0, -4, -2, 4], {\n        type: 'bar',\n        barColor: '#1ab394',\n        negBarColor: '#c6c6c6'});\n\n    $(\"#sparkline3\").sparkline([1, 1, 2], {\n        type: 'pie',\n        sliceColors: ['#1ab394', '#b3b3b3', '#e4f0fb']});\n\n    $(\"#sparkline4\").sparkline([34, 43, 43, 35, 44, 32, 15, 22, 46, 33, 86, 54, 73, 53, 12, 53, 23, 65, 23, 63, 53, 42, 34, 56, 76, 15, 54, 23, 44], {\n        type: 'line',\n        lineColor: '#17997f',\n        fillColor: '#ffffff',\n    });\n\n    $(\"#sparkline5\").sparkline([1, 1, 0, 1, -1, -1, 1, -1, 0, 0, 1, 1], {\n        type: 'tristate',\n        posBarColor: '#1ab394',\n        negBarColor: '#bfbfbf'});\n\n\n    $(\"#sparkline6\").sparkline([4, 6, 7, 7, 4, 3, 2, 1, 4, 4, 5, 6, 3, 4, 5, 8, 7, 6, 9, 3, 2, 4, 1, 5, 6, 4, 3, 7, ], {\n        type: 'discrete',\n        lineColor: '#1ab394'});\n\n    $(\"#sparkline7\").sparkline([52, 12, 44], {\n        type: 'pie',\n        height: '150px',\n        sliceColors: ['#1ab394', '#b3b3b3', '#e4f0fb']});\n\n    $(\"#sparkline8\").sparkline([5, 6, 7, 2, 0, 4, 2, 4, 5, 7, 2, 4, 12, 14, 4, 2, 14, 12, 7], {\n        type: 'bar',\n        barWidth: 8,\n        height: '150px',\n        barColor: '#1ab394',\n        negBarColor: '#c6c6c6'});\n\n    $(\"#sparkline9\").sparkline([34, 43, 43, 35, 44, 32, 15, 22, 46, 33, 86, 54, 73, 53, 12, 53, 23, 65, 23, 63, 53, 42, 34, 56, 76, 15, 54, 23, 44], {\n        type: 'line',\n        lineWidth: 1,\n        height: '150px',\n        lineColor: '#17997f',\n        fillColor: '#ffffff',\n    });\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/table_base.json",
    "content": "[{\n      \"Tid\": \"1\",\n      \"First\": \"奔波儿灞\",\n      \"sex\": \"男\",\n      \"Score\": \"50\"\n    }, {\n      \"Tid\": \"2\",\n      \"First\": \"灞波儿奔\",\n      \"sex\": \"男\",\n      \"Score\": \"94\"\n    }, {\n      \"Tid\": \"3\",\n      \"First\": \"作家崔成浩\",\n      \"sex\": \"男\",\n      \"Score\": \"80\"\n    }, {\n      \"Tid\": \"4\",\n      \"First\": \"韩寒\",\n      \"sex\": \"男\",\n      \"Score\": \"67\"\n    }, {\n      \"Tid\": \"5\",\n      \"First\": \"郭敬明\",\n      \"sex\": \"男\",\n      \"Score\": \"100\"\n    }, {\n      \"Tid\": \"6\",\n      \"First\": \"马云\",\n      \"sex\": \"男\",\n      \"Score\": \"77\"\n    }, {\n      \"Tid\": \"7\",\n      \"First\": \"范爷\",\n      \"sex\": \"女\",\n      \"Score\": \"87\"\n    }]\n"
  },
  {
    "path": "src/main/resources/static/js/demo/treeview-demo.js",
    "content": "$(function () {\n\n    var defaultData = [\n        {\n            text: '父节点 1',\n            href: '#parent1',\n            tags: ['4'],\n            nodes: [\n                {\n                    text: '子节点 1',\n                    href: '#child1',\n                    tags: ['2'],\n                    nodes: [\n                        {\n                            text: '孙子节点 1',\n                            href: '#grandchild1',\n                            tags: ['0']\n                  },\n                        {\n                            text: '孙子节点 2',\n                            href: '#grandchild2',\n                            tags: ['0']\n                  }\n                ]\n              },\n                {\n                    text: '子节点 2',\n                    href: '#child2',\n                    tags: ['0']\n              }\n            ]\n          },\n        {\n            text: '父节点 2',\n            href: '#parent2',\n            tags: ['0']\n          },\n        {\n            text: '父节点 3',\n            href: '#parent3',\n            tags: ['0']\n          },\n        {\n            text: '父节点 4',\n            href: '#parent4',\n            tags: ['0']\n          },\n        {\n            text: '父节点 5',\n            href: '#parent5',\n            tags: ['0']\n          }\n        ];\n\n    var alternateData = [\n        {\n            text: '父节点 1',\n            tags: ['2'],\n            nodes: [\n                {\n                    text: '子节点 1',\n                    tags: ['3'],\n                    nodes: [\n                        {\n                            text: '孙子节点 1',\n                            tags: ['6']\n                  },\n                        {\n                            text: '孙子节点 2',\n                            tags: ['3']\n                  }\n                ]\n              },\n                {\n                    text: '子节点 2',\n                    tags: ['3']\n              }\n            ]\n          },\n        {\n            text: '父节点 2',\n            tags: ['7']\n          },\n        {\n            text: '父节点 3',\n            icon: 'glyphicon glyphicon-earphone',\n            href: '#demo',\n            tags: ['11']\n          },\n        {\n            text: '父节点 4',\n            icon: 'glyphicon glyphicon-cloud-download',\n            href: '/demo.html',\n            tags: ['19'],\n            selected: true\n          },\n        {\n            text: '父节点 5',\n            icon: 'glyphicon glyphicon-certificate',\n            color: 'pink',\n            backColor: 'red',\n            href: 'http://www.tesco.com',\n            tags: ['available', '0']\n          }\n        ];\n\n    var json = '[' +\n        '{' +\n        '\"text\": \"父节点 1\",' +\n        '\"nodes\": [' +\n        '{' +\n        '\"text\": \"子节点 1\",' +\n        '\"nodes\": [' +\n        '{' +\n        '\"text\": \"孙子节点 1\"' +\n        '},' +\n        '{' +\n        '\"text\": \"孙子节点 2\"' +\n        '}' +\n        ']' +\n        '},' +\n        '{' +\n        '\"text\": \"子节点 2\"' +\n        '}' +\n        ']' +\n        '},' +\n        '{' +\n        '\"text\": \"父节点 2\"' +\n        '},' +\n        '{' +\n        '\"text\": \"父节点 3\"' +\n        '},' +\n        '{' +\n        '\"text\": \"父节点 4\"' +\n        '},' +\n        '{' +\n        '\"text\": \"父节点 5\"' +\n        '}' +\n        ']';\n\n\n    $('#treeview1').treeview({\n        data: defaultData\n    });\n\n    $('#treeview2').treeview({\n        levels: 1,\n        data: defaultData\n    });\n\n    $('#treeview3').treeview({\n        levels: 99,\n        data: defaultData\n    });\n\n    $('#treeview4').treeview({\n\n        color: \"#428bca\",\n        data: defaultData\n    });\n\n    $('#treeview5').treeview({\n        color: \"#428bca\",\n        expandIcon: 'glyphicon glyphicon-chevron-right',\n        collapseIcon: 'glyphicon glyphicon-chevron-down',\n        nodeIcon: 'glyphicon glyphicon-bookmark',\n        data: defaultData\n    });\n\n    $('#treeview6').treeview({\n        color: \"#428bca\",\n        expandIcon: \"glyphicon glyphicon-stop\",\n        collapseIcon: \"glyphicon glyphicon-unchecked\",\n        nodeIcon: \"glyphicon glyphicon-user\",\n        showTags: true,\n        data: defaultData\n    });\n\n    $('#treeview7').treeview({\n        color: \"#428bca\",\n        showBorder: false,\n        data: defaultData\n    });\n\n    $('#treeview8').treeview({\n        expandIcon: \"glyphicon glyphicon-stop\",\n        collapseIcon: \"glyphicon glyphicon-unchecked\",\n        nodeIcon: \"glyphicon glyphicon-user\",\n        color: \"yellow\",\n        backColor: \"purple\",\n        onhoverColor: \"orange\",\n        borderColor: \"red\",\n        showBorder: false,\n        showTags: true,\n        highlightSelected: true,\n        selectedColor: \"yellow\",\n        selectedBackColor: \"darkorange\",\n        data: defaultData\n    });\n\n    $('#treeview9').treeview({\n        expandIcon: \"glyphicon glyphicon-stop\",\n        collapseIcon: \"glyphicon glyphicon-unchecked\",\n        nodeIcon: \"glyphicon glyphicon-user\",\n        color: \"yellow\",\n        backColor: \"purple\",\n        onhoverColor: \"orange\",\n        borderColor: \"red\",\n        showBorder: false,\n        showTags: true,\n        highlightSelected: true,\n        selectedColor: \"yellow\",\n        selectedBackColor: \"darkorange\",\n        data: alternateData\n    });\n\n    $('#treeview10').treeview({\n        color: \"#428bca\",\n        enableLinks: true,\n        data: defaultData\n    });\n\n    $('#treeview11').treeview({\n        color: \"#428bca\",\n        data: defaultData,\n        onNodeSelected: function (event, node) {\n            $('#event_output').prepend('<p>您单击了 ' + node.text + '</p>');\n        }\n    });\n\n    // $('#treeview11').on('nodeSelected', function (event, node) {\n    //   $('#event_output').prepend('<p>您单击了 ' + node.text + '</p>');\n    // });\n\n\n    $('#treeview12').treeview({\n        data: json\n    });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/demo/webuploader-demo.js",
    "content": "jQuery(function() {\n    var $ = jQuery,    // just in case. Make sure it's not an other libaray.\n\n        $wrap = $('#uploader'),\n\n        // 图片容器\n        $queue = $('<ul class=\"filelist\"></ul>')\n            .appendTo( $wrap.find('.queueList') ),\n\n        // 状态栏，包括进度和控制按钮\n        $statusBar = $wrap.find('.statusBar'),\n\n        // 文件总体选择信息。\n        $info = $statusBar.find('.info'),\n\n        // 上传按钮\n        $upload = $wrap.find('.uploadBtn'),\n\n        // 没选择文件之前的内容。\n        $placeHolder = $wrap.find('.placeholder'),\n\n        // 总体进度条\n        $progress = $statusBar.find('.progress').hide(),\n\n        // 添加的文件数量\n        fileCount = 0,\n\n        // 添加的文件总大小\n        fileSize = 0,\n\n        // 优化retina, 在retina下这个值是2\n        ratio = window.devicePixelRatio || 1,\n\n        // 缩略图大小\n        thumbnailWidth = 110 * ratio,\n        thumbnailHeight = 110 * ratio,\n\n        // 可能有pedding, ready, uploading, confirm, done.\n        state = 'pedding',\n\n        // 所有文件的进度信息，key为file id\n        percentages = {},\n\n        supportTransition = (function(){\n            var s = document.createElement('p').style,\n                r = 'transition' in s ||\n                      'WebkitTransition' in s ||\n                      'MozTransition' in s ||\n                      'msTransition' in s ||\n                      'OTransition' in s;\n            s = null;\n            return r;\n        })(),\n\n        // WebUploader实例\n        uploader;\n\n    if ( !WebUploader.Uploader.support() ) {\n        alert( 'Web Uploader 不支持您的浏览器！如果你使用的是IE浏览器，请尝试升级 flash 播放器');\n        throw new Error( 'WebUploader does not support the browser you are using.' );\n    }\n\n    // 实例化\n    uploader = WebUploader.create({\n        pick: {\n            id: '#filePicker',\n            label: '点击选择图片'\n        },\n        dnd: '#uploader .queueList',\n        paste: document.body,\n\n        accept: {\n            title: 'Images',\n            extensions: 'gif,jpg,jpeg,bmp,png',\n            mimeTypes: 'image/*'\n        },\n\n        // swf文件路径\n        swf: BASE_URL + '/Uploader.swf',\n\n        disableGlobalDnd: true,\n\n        chunked: true,\n        // server: 'http://webuploader.duapp.com/server/fileupload.php',\n        server: 'http://2betop.net/fileupload.php',\n        fileNumLimit: 300,\n        fileSizeLimit: 5 * 1024 * 1024,    // 200 M\n        fileSingleSizeLimit: 1 * 1024 * 1024    // 50 M\n    });\n\n    // 添加“添加文件”的按钮，\n    uploader.addButton({\n        id: '#filePicker2',\n        label: '继续添加'\n    });\n\n    // 当有文件添加进来时执行，负责view的创建\n    function addFile( file ) {\n        var $li = $( '<li id=\"' + file.id + '\">' +\n                '<p class=\"title\">' + file.name + '</p>' +\n                '<p class=\"imgWrap\"></p>'+\n                '<p class=\"progress\"><span></span></p>' +\n                '</li>' ),\n\n            $btns = $('<div class=\"file-panel\">' +\n                '<span class=\"cancel\">删除</span>' +\n                '<span class=\"rotateRight\">向右旋转</span>' +\n                '<span class=\"rotateLeft\">向左旋转</span></div>').appendTo( $li ),\n            $prgress = $li.find('p.progress span'),\n            $wrap = $li.find( 'p.imgWrap' ),\n            $info = $('<p class=\"error\"></p>'),\n\n            showError = function( code ) {\n                switch( code ) {\n                    case 'exceed_size':\n                        text = '文件大小超出';\n                        break;\n\n                    case 'interrupt':\n                        text = '上传暂停';\n                        break;\n\n                    default:\n                        text = '上传失败，请重试';\n                        break;\n                }\n\n                $info.text( text ).appendTo( $li );\n            };\n\n        if ( file.getStatus() === 'invalid' ) {\n            showError( file.statusText );\n        } else {\n            // @todo lazyload\n            $wrap.text( '预览中' );\n            uploader.makeThumb( file, function( error, src ) {\n                if ( error ) {\n                    $wrap.text( '不能预览' );\n                    return;\n                }\n\n                var img = $('<img src=\"'+src+'\">');\n                $wrap.empty().append( img );\n            }, thumbnailWidth, thumbnailHeight );\n\n            percentages[ file.id ] = [ file.size, 0 ];\n            file.rotation = 0;\n        }\n\n        file.on('statuschange', function( cur, prev ) {\n            if ( prev === 'progress' ) {\n                $prgress.hide().width(0);\n            } else if ( prev === 'queued' ) {\n                $li.off( 'mouseenter mouseleave' );\n                $btns.remove();\n            }\n\n            // 成功\n            if ( cur === 'error' || cur === 'invalid' ) {\n                console.log( file.statusText );\n                showError( file.statusText );\n                percentages[ file.id ][ 1 ] = 1;\n            } else if ( cur === 'interrupt' ) {\n                showError( 'interrupt' );\n            } else if ( cur === 'queued' ) {\n                percentages[ file.id ][ 1 ] = 0;\n            } else if ( cur === 'progress' ) {\n                $info.remove();\n                $prgress.css('display', 'block');\n            } else if ( cur === 'complete' ) {\n                $li.append( '<span class=\"success\"></span>' );\n            }\n\n            $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );\n        });\n\n        $li.on( 'mouseenter', function() {\n            $btns.stop().animate({height: 30});\n        });\n\n        $li.on( 'mouseleave', function() {\n            $btns.stop().animate({height: 0});\n        });\n\n        $btns.on( 'click', 'span', function() {\n            var index = $(this).index(),\n                deg;\n\n            switch ( index ) {\n                case 0:\n                    uploader.removeFile( file );\n                    return;\n\n                case 1:\n                    file.rotation += 90;\n                    break;\n\n                case 2:\n                    file.rotation -= 90;\n                    break;\n            }\n\n            if ( supportTransition ) {\n                deg = 'rotate(' + file.rotation + 'deg)';\n                $wrap.css({\n                    '-webkit-transform': deg,\n                    '-mos-transform': deg,\n                    '-o-transform': deg,\n                    'transform': deg\n                });\n            } else {\n                $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');\n                // use jquery animate to rotation\n                // $({\n                //     rotation: rotation\n                // }).animate({\n                //     rotation: file.rotation\n                // }, {\n                //     easing: 'linear',\n                //     step: function( now ) {\n                //         now = now * Math.PI / 180;\n\n                //         var cos = Math.cos( now ),\n                //             sin = Math.sin( now );\n\n                //         $wrap.css( 'filter', \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + cos + \",M12=\" + (-sin) + \",M21=\" + sin + \",M22=\" + cos + \",SizingMethod='auto expand')\");\n                //     }\n                // });\n            }\n\n\n        });\n\n        $li.appendTo( $queue );\n    }\n\n    // 负责view的销毁\n    function removeFile( file ) {\n        var $li = $('#'+file.id);\n\n        delete percentages[ file.id ];\n        updateTotalProgress();\n        $li.off().find('.file-panel').off().end().remove();\n    }\n\n    function updateTotalProgress() {\n        var loaded = 0,\n            total = 0,\n            spans = $progress.children(),\n            percent;\n\n        $.each( percentages, function( k, v ) {\n            total += v[ 0 ];\n            loaded += v[ 0 ] * v[ 1 ];\n        } );\n\n        percent = total ? loaded / total : 0;\n\n        spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );\n        spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );\n        updateStatus();\n    }\n\n    function updateStatus() {\n        var text = '', stats;\n\n        if ( state === 'ready' ) {\n            text = '选中' + fileCount + '张图片，共' +\n                    WebUploader.formatSize( fileSize ) + '。';\n        } else if ( state === 'confirm' ) {\n            stats = uploader.getStats();\n            if ( stats.uploadFailNum ) {\n                text = '已成功上传' + stats.successNum+ '张照片至XX相册，'+\n                    stats.uploadFailNum + '张照片上传失败，<a class=\"retry\" href=\"#\">重新上传</a>失败图片或<a class=\"ignore\" href=\"#\">忽略</a>'\n            }\n\n        } else {\n            stats = uploader.getStats();\n            text = '共' + fileCount + '张（' +\n                    WebUploader.formatSize( fileSize )  +\n                    '），已上传' + stats.successNum + '张';\n\n            if ( stats.uploadFailNum ) {\n                text += '，失败' + stats.uploadFailNum + '张';\n            }\n        }\n\n        $info.html( text );\n    }\n\n    function setState( val ) {\n        var file, stats;\n\n        if ( val === state ) {\n            return;\n        }\n\n        $upload.removeClass( 'state-' + state );\n        $upload.addClass( 'state-' + val );\n        state = val;\n\n        switch ( state ) {\n            case 'pedding':\n                $placeHolder.removeClass( 'element-invisible' );\n                $queue.parent().removeClass('filled');\n                $queue.hide();\n                $statusBar.addClass( 'element-invisible' );\n                uploader.refresh();\n                break;\n\n            case 'ready':\n                $placeHolder.addClass( 'element-invisible' );\n                $( '#filePicker2' ).removeClass( 'element-invisible');\n                $queue.parent().addClass('filled');\n                $queue.show();\n                $statusBar.removeClass('element-invisible');\n                uploader.refresh();\n                break;\n\n            case 'uploading':\n                $( '#filePicker2' ).addClass( 'element-invisible' );\n                $progress.show();\n                $upload.text( '暂停上传' );\n                break;\n\n            case 'paused':\n                $progress.show();\n                $upload.text( '继续上传' );\n                break;\n\n            case 'confirm':\n                $progress.hide();\n                $upload.text( '开始上传' ).addClass( 'disabled' );\n\n                stats = uploader.getStats();\n                if ( stats.successNum && !stats.uploadFailNum ) {\n                    setState( 'finish' );\n                    return;\n                }\n                break;\n            case 'finish':\n                stats = uploader.getStats();\n                if ( stats.successNum ) {\n                    alert( '上传成功' );\n                } else {\n                    // 没有成功的图片，重设\n                    state = 'done';\n                    location.reload();\n                }\n                break;\n        }\n\n        updateStatus();\n    }\n\n    uploader.onUploadProgress = function( file, percentage ) {\n        var $li = $('#'+file.id),\n            $percent = $li.find('.progress span');\n\n        $percent.css( 'width', percentage * 100 + '%' );\n        percentages[ file.id ][ 1 ] = percentage;\n        updateTotalProgress();\n    };\n\n    uploader.onFileQueued = function( file ) {\n        fileCount++;\n        fileSize += file.size;\n\n        if ( fileCount === 1 ) {\n            $placeHolder.addClass( 'element-invisible' );\n            $statusBar.show();\n        }\n\n        addFile( file );\n        setState( 'ready' );\n        updateTotalProgress();\n    };\n\n    uploader.onFileDequeued = function( file ) {\n        fileCount--;\n        fileSize -= file.size;\n\n        if ( !fileCount ) {\n            setState( 'pedding' );\n        }\n\n        removeFile( file );\n        updateTotalProgress();\n\n    };\n\n    uploader.on( 'all', function( type ) {\n        var stats;\n        switch( type ) {\n            case 'uploadFinished':\n                setState( 'confirm' );\n                break;\n\n            case 'startUpload':\n                setState( 'uploading' );\n                break;\n\n            case 'stopUpload':\n                setState( 'paused' );\n                break;\n\n        }\n    });\n\n    uploader.onError = function( code ) {\n        alert( 'Eroor: ' + code );\n    };\n\n    $upload.on('click', function() {\n        if ( $(this).hasClass( 'disabled' ) ) {\n            return false;\n        }\n\n        if ( state === 'ready' ) {\n            uploader.upload();\n        } else if ( state === 'paused' ) {\n            uploader.upload();\n        } else if ( state === 'uploading' ) {\n            uploader.stop();\n        }\n    });\n\n    $info.on( 'click', '.retry', function() {\n        uploader.retry();\n    } );\n\n    $info.on( 'click', '.ignore', function() {\n        alert( 'todo' );\n    } );\n\n    $upload.addClass( 'state-' + state );\n    updateTotalProgress();\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/all-mobile.js",
    "content": "﻿/**\n\n @Name：用于打包移动完整版\n @author 郑保乐\n @License：LGPL\n    \n */\n \nlayui.define(function(exports){\n  exports('layui.mobile', layui.v);\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/all.js",
    "content": "﻿/**\n\n @Name：用于打包PC完整版，即包含layui.js和所有模块的完整合并（该文件不会存在于构建后的目录）\n @author 郑保乐\n @License：LGPL\n    \n */\n \nlayui.define(function(exports){\n  var cache = layui.cache;\n  layui.config({\n    dir: cache.dir.replace(/lay\\/dest\\/$/, '')\n  });\n  exports('layui.all', layui.v);\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/carousel.js",
    "content": "/**\n\n @Name：layui.carousel 轮播模块\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,hint = layui.hint()\n  ,device = layui.device()\n\n  //外部接口\n  ,carousel = {\n    config: {} //全局配置项\n\n    //设置全局项\n    ,set: function(options){\n      var that = this;\n      that.config = $.extend({}, that.config, options);\n      return that;\n    }\n    \n    //事件监听\n    ,on: function(events, callback){\n      return layui.onevent.call(this, MOD_NAME, events, callback);\n    }\n  }\n  \n  //字符常量\n  ,MOD_NAME = 'carousel', ELEM = '.layui-carousel', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'\n  \n  ,ELEM_ITEM = '>*[carousel-item]>*', ELEM_LEFT = 'layui-carousel-left', ELEM_RIGHT = 'layui-carousel-right', ELEM_PREV = 'layui-carousel-prev', ELEM_NEXT = 'layui-carousel-next', ELEM_ARROW = 'layui-carousel-arrow', ELEM_IND = 'layui-carousel-ind'\n  \n  //构造器\n  ,Class = function(options){\n    var that = this;\n    that.config = $.extend({}, that.config, carousel.config, options);\n    that.render();\n  };\n  \n  //默认配置\n  Class.prototype.config = {\n    width: '600px'\n    ,height: '280px'\n    ,full: false //是否全屏\n    ,arrow: 'hover' //切换箭头默认显示状态：hover/always/none\n    ,indicator: 'inside' //指示器位置：inside/outside/none\n    ,autoplay: true //是否自动切换\n    ,interval: 3000 //自动切换的时间间隔，不能低于800ms\n    ,anim: '' //动画类型：default/updown/fade\n    ,trigger: 'click' //指示器的触发方式：click/hover\n    ,index: 0 //初始开始的索引\n  };\n  \n  //轮播渲染\n  Class.prototype.render = function(){\n    var that = this\n    ,options = that.config;\n\n    options.elem = $(options.elem);\n    if(!options.elem[0]) return;\n    that.elemItem = options.elem.find(ELEM_ITEM);\n    \n    if(options.index < 0) options.index = 0;\n    if(options.index >= that.elemItem.length) options.index = that.elemItem.length - 1;\n    if(options.interval < 800) options.interval = 800;\n\n    //是否全屏模式\n    if(options.full){\n      options.elem.css({\n        position: 'fixed'\n        ,width: '100%'\n        ,height: '100%'\n        ,zIndex: 9999\n      });\n    } else {\n      options.elem.css({\n        width: options.width\n        ,height: options.height\n      });\n    }\n    \n    options.elem.attr('lay-anim', options.anim);\n    \n    //初始焦点状态\n    that.elemItem.eq(options.index).addClass(THIS);\n    \n    //指示器等动作\n    that.indicator();\n    if(that.elemItem.length <= 1) return;\n    that.arrow();\n    that.autoplay();\n    that.events();\n  };\n  \n  //重置轮播\n  Class.prototype.reload = function(options){\n    var that = this;\n    clearInterval(that.timer);\n    that.config = $.extend({}, that.config, options);\n    that.render();\n  };\n  \n  //获取上一个等待条目的索引\n  Class.prototype.prevIndex = function(){\n    var that = this\n    ,options = that.config;\n    \n    var prevIndex = options.index - 1;\n    if(prevIndex < 0){\n      prevIndex = that.elemItem.length - 1;\n    }\n    return prevIndex;\n  };\n  \n  //获取下一个等待条目的索引\n  Class.prototype.nextIndex = function(){\n    var that = this\n    ,options = that.config;\n    \n    var nextIndex = options.index + 1;\n    if(nextIndex >= that.elemItem.length){\n      nextIndex = 0;\n    }\n    return nextIndex;\n  };\n  \n  //索引递增\n  Class.prototype.addIndex = function(num){\n    var that = this\n    ,options = that.config;\n    \n    num = num || 1;\n    options.index = options.index + num;\n      \n    //index不能超过轮播总数量\n    if(options.index >= that.elemItem.length){\n      options.index = 0;\n    }\n  };\n  \n  //索引递减\n  Class.prototype.subIndex = function(num){\n    var that = this\n    ,options = that.config;\n    \n    num = num || 1;\n    options.index = options.index - num;\n      \n    //index不能超过轮播总数量\n    if(options.index < 0){\n      options.index = that.elemItem.length - 1;\n    }\n  };\n  \n  //自动轮播\n  Class.prototype.autoplay = function(){\n    var that = this\n    ,options = that.config;\n    \n    if(!options.autoplay) return;\n    \n    that.timer = setInterval(function(){\n      that.slide();\n    }, options.interval);\n  };\n  \n  //箭头\n  Class.prototype.arrow = function(){\n    var that = this\n    ,options = that.config;\n    \n    //模板\n    var tplArrow = $([\n      '<button class=\"layui-icon '+ ELEM_ARROW +'\" lay-type=\"sub\">'+ (options.anim === 'updown' ? '&#xe619;' : '&#xe603;') +'</button>'\n      ,'<button class=\"layui-icon '+ ELEM_ARROW +'\" lay-type=\"add\">'+ (options.anim === 'updown' ? '&#xe61a;' : '&#xe602;') +'</button>'\n    ].join(''));\n    \n    //预设基础属性\n    options.elem.attr('lay-arrow', options.arrow);\n    \n    //避免重复插入\n    if(options.elem.find('.'+ELEM_ARROW)[0]){\n      options.elem.find('.'+ELEM_ARROW).remove();\n    };\n    options.elem.append(tplArrow);\n    \n    //事件\n    tplArrow.on('click', function(){\n      var othis = $(this)\n      ,type = othis.attr('lay-type')\n      that.slide(type);\n    });\n  };\n  \n  //指示器\n  Class.prototype.indicator = function(){\n    var that = this\n    ,options = that.config;\n    \n    //模板\n    var tplInd = that.elemInd = $(['<div class=\"'+ ELEM_IND +'\"><ul>'\n      ,function(){\n        var li = [];\n        layui.each(that.elemItem, function(index){\n          li.push('<li'+ (options.index === index ? ' class=\"layui-this\"' : '') +'></li>');\n        });\n        return li.join('');\n      }()\n    ,'</ul></div>'].join(''));\n    \n    //预设基础属性\n    options.elem.attr('lay-indicator', options.indicator);\n    \n    //避免重复插入\n    if(options.elem.find('.'+ELEM_IND)[0]){\n      options.elem.find('.'+ELEM_IND).remove();\n    };\n    options.elem.append(tplInd);\n    \n    if(options.anim === 'updown'){\n      tplInd.css('margin-top', -(tplInd.height()/2));\n    }\n    \n    //事件\n    tplInd.find('li').on(options.trigger === 'hover' ? 'mouseover' : options.trigger, function(){\n      var othis = $(this)\n      ,index = othis.index();\n      if(index > options.index){\n        that.slide('add', index - options.index);\n      } else if(index < options.index){\n        that.slide('sub', options.index - index);\n      }\n    });\n  };\n  \n  //滑动切换\n  Class.prototype.slide = function(type, num){\n    var that = this\n    ,elemItem = that.elemItem\n    ,options = that.config\n    ,thisIndex = options.index\n    ,filter = options.elem.attr('lay-filter');\n    \n    if(that.haveSlide) return;\n    \n    //滑动方向\n    if(type === 'sub'){\n      that.subIndex(num);\n      elemItem.eq(options.index).addClass(ELEM_PREV);\n      setTimeout(function(){\n        elemItem.eq(thisIndex).addClass(ELEM_RIGHT);\n        elemItem.eq(options.index).addClass(ELEM_RIGHT);\n      }, 50);\n    } else { //默认递增滑\n      that.addIndex(num);\n      elemItem.eq(options.index).addClass(ELEM_NEXT);\n      setTimeout(function(){\n        elemItem.eq(thisIndex).addClass(ELEM_LEFT);\n        elemItem.eq(options.index).addClass(ELEM_LEFT);\n      }, 50);  \n    };\n    \n    //移除过度类\n    setTimeout(function(){\n      elemItem.removeClass(THIS + ' ' + ELEM_PREV + ' ' + ELEM_NEXT + ' ' + ELEM_LEFT + ' ' + ELEM_RIGHT);\n      elemItem.eq(options.index).addClass(THIS);\n      that.haveSlide = false; //解锁\n    }, 300);\n    \n    //指示器焦点\n    that.elemInd.find('li').eq(options.index).addClass(THIS)\n    .siblings().removeClass(THIS);\n    \n    that.haveSlide = true;\n    \n    layui.event.call(this, MOD_NAME, 'change('+ filter +')', {\n      index: options.index\n      ,prevIndex: thisIndex\n      ,item: elemItem.eq(options.index)\n    });\n  };\n  \n  //事件处理\n  Class.prototype.events = function(){\n    var that = this\n    ,options = that.config;\n    \n    if(options.elem.data('haveEvents')) return;\n    \n    //移入移出容器\n    options.elem.on('mouseenter', function(){\n      clearInterval(that.timer);\n    }).on('mouseleave', function(){\n      that.autoplay();\n    });\n    \n    options.elem.data('haveEvents', true);\n  };\n  \n  //核心入口\n  carousel.render = function(options){\n    var inst = new Class(options);\n    return inst;\n  };\n  \n  exports(MOD_NAME, carousel);\n});\n\n \n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/code.js",
    "content": "/**\n\n @Name：layui.code 代码修饰器\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$;\n  var about = 'http://www.layui.com/doc/modules/code.html'; //关于信息\n  \n  exports('code', function(options){\n    var elems = [];\n    options = options || {};\n    options.elem = $(options.elem||'.layui-code');\n    options.about = 'about' in options ? options.about : true;\n    \n    options.elem.each(function(){\n      elems.push(this);\n    });\n    \n    layui.each(elems.reverse(), function(index, item){\n      var othis = $(item), html = othis.html();\n      \n      //转义HTML标签\n      if(othis.attr('lay-encode') || options.encode){\n        html = html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')\n        .replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/\"/g, '&quot;')\n      }\n      \n      othis.html('<ol class=\"layui-code-ol\"><li>' + html.replace(/[\\r\\t\\n]+/g, '</li><li>') + '</li></ol>')\n      \n      if(!othis.find('>.layui-code-h3')[0]){\n        othis.prepend('<h3 class=\"layui-code-h3\">'+ (othis.attr('lay-title')||options.title||'code') + (options.about ? '<a href=\"'+ about +'\" target=\"_blank\">layui.code</a>' : '') + '</h3>');\n      }\n      \n      var ol = othis.find('>.layui-code-ol');\n      othis.addClass('layui-box layui-code-view');\n      \n      //识别皮肤\n      if(othis.attr('lay-skin') || options.skin){\n        othis.addClass('layui-code-' +(othis.attr('lay-skin') || options.skin));\n      }\n      \n      //按行数适配左边距\n      if((ol.find('li').length/100|0) > 0){\n        ol.css('margin-left', (ol.find('li').length/100|0) + 'px');\n      }\n      \n      //设置最大高度\n      if(othis.attr('lay-height') || options.height){\n        ol.css('max-height', othis.attr('lay-height') || options.height);\n      }\n\n    });\n    \n  });\n}).addcss('modules/code.css', 'skincodecss');"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/element.js",
    "content": "/**\n\n @Name：layui.element 常用元素操作\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,hint = layui.hint()\n  ,device = layui.device()\n  \n  ,MOD_NAME = 'element', THIS = 'layui-this', SHOW = 'layui-show'\n  \n  ,Element = function(){\n    this.config = {};\n  };\n  \n  //全局设置\n  Element.prototype.set = function(options){\n    var that = this;\n    $.extend(true, that.config, options);\n    return that;\n  };\n  \n  //表单事件监听\n  Element.prototype.on = function(events, callback){\n    return layui.onevent.call(this, MOD_NAME, events, callback);\n  };\n  \n  //外部Tab新增\n  Element.prototype.tabAdd = function(filter, options){\n    var TITLE = '.layui-tab-title'\n    ,tabElem = $('.layui-tab[lay-filter='+ filter +']')\n    ,titElem = tabElem.children(TITLE)\n    ,barElem = titElem.children('.layui-tab-bar')\n    ,contElem = tabElem.children('.layui-tab-content')\n    ,li = '<li lay-id=\"'+ (options.id||'') +'\">'+ (options.title||'unnaming') +'</li>';\n    barElem[0] ? barElem.before(li) : titElem.append(li);\n    contElem.append('<div class=\"layui-tab-item\">'+ (options.content||'') +'</div>');\n    call.hideTabMore(true);\n    call.tabAuto();\n    return this;\n  };\n  \n  //外部Tab删除\n  Element.prototype.tabDelete = function(filter, layid){\n    var TITLE = '.layui-tab-title'\n    ,tabElem = $('.layui-tab[lay-filter='+ filter +']')\n    ,titElem = tabElem.children(TITLE)\n    ,liElem = titElem.find('>li[lay-id=\"'+ layid +'\"]');\n    call.tabDelete(null, liElem);\n    return this;\n  };\n  \n  //外部Tab切换\n  Element.prototype.tabChange = function(filter, layid){\n    var TITLE = '.layui-tab-title'\n    ,tabElem = $('.layui-tab[lay-filter='+ filter +']')\n    ,titElem = tabElem.children(TITLE)\n    ,liElem = titElem.find('>li[lay-id=\"'+ layid +'\"]');\n    call.tabClick(null, null, liElem);\n    return this;\n  };\n  \n  //动态改变进度条\n  Element.prototype.progress = function(filter, percent){\n    var ELEM = 'layui-progress'\n    ,elem = $('.'+ ELEM +'[lay-filter='+ filter +']')\n    ,elemBar = elem.find('.'+ ELEM +'-bar')\n    ,text = elemBar.find('.'+ ELEM +'-text');\n    elemBar.css('width', percent);\n    text.text(percent);\n    return this;\n  };\n  \n  var NAV_ELEM = '.layui-nav', NAV_ITEM = 'layui-nav-item', NAV_BAR = 'layui-nav-bar'\n  ,NAV_TREE = 'layui-nav-tree', NAV_CHILD = 'layui-nav-child', NAV_MORE = 'layui-nav-more'\n  ,NAV_ANIM = 'layui-anim layui-anim-upbit'\n  \n  //基础事件体\n  ,call = {\n    //Tab点击\n    tabClick: function(e, index, liElem){\n      var othis = liElem || $(this)\n      ,index = index || othis.parent().children('li').index(othis)\n      ,parents = othis.parents('.layui-tab').eq(0)\n      ,item = parents.children('.layui-tab-content').children('.layui-tab-item')\n      ,elemA = othis.find('a')\n      ,filter = parents.attr('lay-filter');\n      \n      if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank')){\n        othis.addClass(THIS).siblings().removeClass(THIS);\n        item.eq(index).addClass(SHOW).siblings().removeClass(SHOW);\n      }\n      \n      layui.event.call(this, MOD_NAME, 'tab('+ filter +')', {\n        elem: parents\n        ,index: index\n      });\n    }\n    \n    //Tab删除\n    ,tabDelete: function(e, othis){\n      var li = othis || $(this).parent(), index = li.index();\n      var parents = li.parents('.layui-tab').eq(0);\n      var item = parents.children('.layui-tab-content').children('.layui-tab-item')\n      \n      if(li.hasClass(THIS)){\n        if(li.next()[0]){\n          call.tabClick.call(li.next()[0], null, index + 1);\n        } else if(li.prev()[0]){\n          call.tabClick.call(li.prev()[0], null, index - 1);\n        }\n      }\n      \n      li.remove();\n      item.eq(index).remove();\n      setTimeout(function(){\n        call.tabAuto();\n      }, 50);\n    }\n    \n    //Tab自适应\n    ,tabAuto: function(){\n      var SCROLL = 'layui-tab-scroll', MORE = 'layui-tab-more', BAR = 'layui-tab-bar'\n      ,CLOSE = 'layui-tab-close', that = this;\n      \n      $('.layui-tab').each(function(){\n        var othis = $(this)\n        ,title = othis.children('.layui-tab-title')\n        ,item = othis.children('.layui-tab-content').children('.layui-tab-item')\n        ,STOPE = 'lay-stope=\"tabmore\"'\n        ,span = $('<span class=\"layui-unselect layui-tab-bar\" '+ STOPE +'><i '+ STOPE +' class=\"layui-icon\">&#xe61a;</i></span>');\n        \n        if(that === window && device.ie != 8){\n          call.hideTabMore(true)\n        }\n        \n        //允许关闭\n        if(othis.attr('lay-allowClose')){\n          title.find('li').each(function(){\n            var li = $(this);\n            if(!li.find('.'+CLOSE)[0]){\n              var close = $('<i class=\"layui-icon layui-unselect '+ CLOSE +'\">&#x1006;</i>');\n              close.on('click', call.tabDelete);\n              li.append(close);\n            }\n          });\n        }\n        \n        //响应式\n        if(title.prop('scrollWidth') > title.outerWidth()+1){\n          if(title.find('.'+BAR)[0]) return;\n          title.append(span);\n          othis.attr('overflow', '');\n          span.on('click', function(e){\n            title[this.title ? 'removeClass' : 'addClass'](MORE);\n            this.title = this.title ? '' : '收缩';\n          });\n        } else {\n          title.find('.'+BAR).remove();\n          othis.removeAttr('overflow');\n        }\n      });\n    }\n    //隐藏更多Tab\n    ,hideTabMore: function(e){\n      var tsbTitle = $('.layui-tab-title');\n      if(e === true || $(e.target).attr('lay-stope') !== 'tabmore'){\n        tsbTitle.removeClass('layui-tab-more');\n        tsbTitle.find('.layui-tab-bar').attr('title','');\n      }\n    }\n    \n    //点击选中\n    ,clickThis: function(){\n      var othis = $(this), parents = othis.parents(NAV_ELEM)\n      ,filter = parents.attr('lay-filter')\n      ,elemA = othis.find('a');\n\n      if(othis.find('.'+NAV_CHILD)[0]) return;\n      \n      if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank')){\n        parents.find('.'+THIS).removeClass(THIS);\n        othis.addClass(THIS);\n      }\n      \n      layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis);\n    }\n    //点击子菜单选中\n    ,clickChild: function(){\n      var othis = $(this), parents = othis.parents(NAV_ELEM)\n      ,filter = parents.attr('lay-filter');\n      parents.find('.'+THIS).removeClass(THIS);\n      othis.addClass(THIS);\n      layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis);\n    }\n    //展开二级菜单\n    ,showChild: function(){\n      var othis = $(this), parents = othis.parents(NAV_ELEM);\n      var parent = othis.parent(), child = othis.siblings('.'+NAV_CHILD);\n      if(parents.hasClass(NAV_TREE)){\n        child.removeClass(NAV_ANIM);\n        parent[child.css('display') === 'none' ? 'addClass': 'removeClass'](NAV_ITEM+'ed');\n      }\n    }\n    \n    //折叠面板\n    ,collapse: function(){\n      var othis = $(this), icon = othis.find('.layui-colla-icon')\n      ,elemCont = othis.siblings('.layui-colla-content')\n      ,parents = othis.parents('.layui-collapse').eq(0)\n      ,filter = parents.attr('lay-filter')\n      ,isNone = elemCont.css('display') === 'none';\n      //是否手风琴\n      if(typeof parents.attr('lay-accordion') === 'string'){\n        var show = parents.children('.layui-colla-item').children('.'+SHOW);\n        show.siblings('.layui-colla-title').children('.layui-colla-icon').html('&#xe602;');\n        show.removeClass(SHOW);\n      }\n      elemCont[isNone ? 'addClass' : 'removeClass'](SHOW);\n      icon.html(isNone ? '&#xe61a;' : '&#xe602;');\n      \n      layui.event.call(this, MOD_NAME, 'collapse('+ filter +')', {\n        title: othis\n        ,content: elemCont\n        ,show: isNone\n      });\n    }\n  };\n  \n  //初始化元素操作\n  Element.prototype.init = function(type){\n    var that = this, items = {\n      \n      //Tab选项卡\n      tab: function(){\n        call.tabAuto.call({});\n      }\n      \n      //导航菜单\n      ,nav: function(){\n        var TIME = 200, timer = {}, timerMore = {}, timeEnd = {}, follow = function(bar, nav, index){\n          var othis = $(this), child = othis.find('.'+NAV_CHILD);\n          \n          if(nav.hasClass(NAV_TREE)){\n            bar.css({\n              top: othis.position().top\n              ,height: othis.children('a').height()\n              ,opacity: 1\n            });\n          } else {\n            child.addClass(NAV_ANIM);\n            bar.css({\n              left: othis.position().left + parseFloat(othis.css('marginLeft'))\n              ,top: othis.position().top + othis.height() - 5\n            });\n            \n            timer[index] = setTimeout(function(){\n              bar.css({\n                width: othis.width()\n                ,opacity: 1\n              });\n            }, device.ie && device.ie < 10 ? 0 : TIME);\n            \n            clearTimeout(timeEnd[index]);\n            if(child.css('display') === 'block'){\n              clearTimeout(timerMore[index]);\n            }\n            timerMore[index] = setTimeout(function(){\n              child.addClass(SHOW)\n              othis.find('.'+NAV_MORE).addClass(NAV_MORE+'d');\n            }, 300);\n          }\n        }\n        \n        $(NAV_ELEM).each(function(index){\n          var othis = $(this)\n          ,bar = $('<span class=\"'+ NAV_BAR +'\"></span>')\n          ,itemElem = othis.find('.'+NAV_ITEM);\n          \n          //Hover滑动效果\n          if(!othis.find('.'+NAV_BAR)[0]){\n            othis.append(bar);\n            itemElem.on('mouseenter', function(){\n              follow.call(this, bar, othis, index);\n            }).on('mouseleave', function(){\n              if(!othis.hasClass(NAV_TREE)){\n                clearTimeout(timerMore[index]);\n                timerMore[index] = setTimeout(function(){\n                  othis.find('.'+NAV_CHILD).removeClass(SHOW);\n                  othis.find('.'+NAV_MORE).removeClass(NAV_MORE+'d');\n                }, 300);\n              }\n            });\n            othis.on('mouseleave', function(){\n              clearTimeout(timer[index])\n              timeEnd[index] = setTimeout(function(){\n                if(othis.hasClass(NAV_TREE)){\n                  bar.css({\n                    height: 0\n                    ,top: bar.position().top + bar.height()/2\n                    ,opacity: 0\n                  });\n                } else {\n                  bar.css({\n                    width: 0\n                    ,left: bar.position().left + bar.width()/2\n                    ,opacity: 0\n                  });\n                }\n              }, TIME);\n            });\n          }\n          \n          itemElem.each(function(){\n            var oitem = $(this), child = oitem.find('.'+NAV_CHILD);\n            \n            //二级菜单\n            if(child[0] && !oitem.find('.'+NAV_MORE)[0]){\n              var one = oitem.children('a');\n              one.append('<span class=\"'+ NAV_MORE +'\"></span>');\n            }\n            \n            oitem.off('click', call.clickThis).on('click', call.clickThis); //点击选中\n            oitem.children('a').off('click', call.showChild).on('click', call.showChild); //展开二级菜单\n            child.children('dd').off('click', call.clickChild).on('click', call.clickChild); //点击子菜单选中\n          });\n        });\n      }\n      \n      //面包屑\n      ,breadcrumb: function(){\n        var ELEM = '.layui-breadcrumb';\n        \n        $(ELEM).each(function(){\n          var othis = $(this)\n          ,separator = othis.attr('lay-separator') || '>'\n          ,aNode = othis.find('a');\n          if(aNode.find('.layui-box')[0]) return;\n          aNode.each(function(index){\n            if(index === aNode.length - 1) return;\n            $(this).append('<span class=\"layui-box\">'+ separator +'</span>');\n          });\n          othis.css('visibility', 'visible');\n        });\n      }\n      \n      //进度条\n      ,progress: function(){\n        var ELEM = 'layui-progress';\n        \n        $('.'+ELEM).each(function(){\n          var othis = $(this)\n          ,elemBar = othis.find('.layui-progress-bar')\n          ,width = elemBar.attr('lay-percent');\n          elemBar.css('width', width);\n          if(othis.attr('lay-showPercent')){\n            setTimeout(function(){\n              var percent = Math.round(elemBar.width()/othis.width()*100);\n              if(percent > 100) percent = 100;\n              elemBar.html('<span class=\"'+ ELEM +'-text\">'+ percent +'%</span>');\n            },350);\n          }\n        });\n      }\n      \n      //折叠面板\n      ,collapse: function(){\n        var ELEM = 'layui-collapse';\n        \n        $('.'+ELEM).each(function(){\n          var elemItem = $(this).find('.layui-colla-item')\n          elemItem.each(function(){\n            var othis = $(this)\n            ,elemTitle = othis.find('.layui-colla-title')\n            ,elemCont = othis.find('.layui-colla-content')\n            ,isNone = elemCont.css('display') === 'none';\n            \n            //初始状态\n            elemTitle.find('.layui-colla-icon').remove();\n            elemTitle.append('<i class=\"layui-icon layui-colla-icon\">'+ (isNone ? '&#xe602;' : '&#xe61a;') +'</i>');\n\n            //点击标题\n            elemTitle.off('click', call.collapse).on('click', call.collapse);\n          });     \n         \n        });\n      }\n    };\n\n    return layui.each(items, function(index, item){\n      item();\n    });\n  };\n\n  var element = new Element(), dom = $(document);\n  element.init();\n  \n  var TITLE = '.layui-tab-title li';\n  dom.on('click', TITLE, call.tabClick); //Tab切换\n  dom.on('click', call.hideTabMore); //隐藏展开的Tab\n  $(window).on('resize', call.tabAuto); //自适应\n  \n  exports(MOD_NAME, element);\n});\n\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/flow.js",
    "content": "/**\n\n @Name：layui.flow 流加载\n @author 郑保乐\n @License：MIT\n    \n */\n \n \nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$, Flow = function(options){}\n  ,ELEM_MORE = 'layui-flow-more'\n  ,ELEM_LOAD = '<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';\n\n  //主方法\n  Flow.prototype.load = function(options){\n    var that = this, page = 0, lock, isOver, lazyimg, timer;\n    options = options || {};\n    \n    var elem = $(options.elem); if(!elem[0]) return;\n    var scrollElem = $(options.scrollElem || document); //滚动条所在元素\n    var mb = options.mb || 50; //与底部的临界距离\n    var isAuto = 'isAuto' in options ? options.isAuto : true; //是否自动滚动加载\n    var end = options.end || '没有更多了'; //“末页”显示文案\n    \n    //滚动条所在元素是否为document\n    var notDocment = options.scrollElem && options.scrollElem !== document;\n    \n    //加载更多\n    var ELEM_TEXT = '<cite>加载更多</cite>'\n    ,more = $('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+ ELEM_TEXT +'</a></div>');\n    \n    if(!elem.find('.layui-flow-more')[0]){\n      elem.append(more);\n    }\n    \n    //加载下一个元素\n    var next = function(html, over){ \n      html = $(html);\n      more.before(html);\n      over = over == 0 ? true : null;\n      over ? more.html(end) : more.find('a').html(ELEM_TEXT);\n      isOver = over;\n      lock = null;\n      lazyimg && lazyimg();\n    };\n    \n    //触发请求\n    var done = function(){\n      lock = true;\n      more.find('a').html(ELEM_LOAD);\n      typeof options.done === 'function' && options.done(++page, next);\n    };\n    \n    done();\n    \n    //不自动滚动加载\n    more.find('a').on('click', function(){\n      var othis = $(this);\n      if(isOver) return;\n      lock || done();\n    });\n    \n    //如果允许图片懒加载\n    if(options.isLazyimg){\n      var lazyimg = that.lazyimg({\n        elem: options.elem + ' img'\n        ,scrollElem: options.scrollElem\n      });\n    }\n    \n    if(!isAuto) return that;\n    \n    scrollElem.on('scroll', function(){\n      var othis = $(this), top = othis.scrollTop();\n      \n      if(timer) clearTimeout(timer);\n      if(isOver) return;\n      \n      timer = setTimeout(function(){\n        //计算滚动所在容器的可视高度\n        var height = notDocment ? othis.height() : $(window).height();\n        \n        //计算滚动所在容器的实际高度\n        var scrollHeight = notDocment\n          ? othis.prop('scrollHeight')\n        : document.documentElement.scrollHeight;\n\n        //临界点\n        if(scrollHeight - top - height <= mb){\n          lock || done();\n        }\n      }, 100);\n    });\n    return that;\n  };\n  \n  //图片懒加载\n  Flow.prototype.lazyimg = function(options){\n    var that = this, index = 0, haveScroll;\n    options = options || {};\n    \n    var scrollElem = $(options.scrollElem || document); //滚动条所在元素\n    var elem = options.elem || 'img';\n    \n    //滚动条所在元素是否为document\n    var notDocment = options.scrollElem && options.scrollElem !== document;\n    \n    //显示图片\n    var show = function(item, height){\n      var start = scrollElem.scrollTop(), end = start + height;\n      var elemTop = notDocment ? function(){\n        return item.offset().top - scrollElem.offset().top + start;\n      }() : item.offset().top;\n\n      /* 始终只加载在当前屏范围内的图片 */\n      if(elemTop >= start && elemTop <= end){\n        if(!item.attr('src')){\n          var src = item.attr('lay-src');\n          layui.img(src, function(){\n            var next = that.lazyimg.elem.eq(index);\n            item.attr('src', src).removeAttr('lay-src');\n            \n            /* 当前图片加载就绪后，检测下一个图片是否在当前屏 */\n            next[0] && render(next);\n            index++;\n          });\n        }\n      }\n    }, render = function(othis, scroll){\n      \n      //计算滚动所在容器的可视高度\n      var height = notDocment ? (scroll||scrollElem).height() : $(window).height();\n      var start = scrollElem.scrollTop(), end = start + height;\n\n      that.lazyimg.elem = $(elem);\n\n      if(othis){\n        show(othis, height);\n      } else {\n        //计算未加载过的图片\n        for(var i = 0; i < that.lazyimg.elem.length; i++){\n          var item = that.lazyimg.elem.eq(i), elemTop = notDocment ? function(){\n            return item.offset().top - scrollElem.offset().top + start;\n          }() : item.offset().top;\n          \n          show(item, height);\n          index = i;\n          \n          //如果图片的top坐标，超出了当前屏，则终止后续图片的遍历\n          if(elemTop > end) break;\n        }\n      }\n    };\n    \n    render();\n    \n    if(!haveScroll){\n      var timer;\n      scrollElem.on('scroll', function(){\n        var othis = $(this);\n        if(timer) clearTimeout(timer)\n        timer = setTimeout(function(){\n          render(null, othis);\n        }, 50);\n      }); \n      haveScroll = true;\n    }\n    return render;\n  };\n  \n  //暴露接口\n  exports('flow', new Flow());\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/form.js",
    "content": "/**\n\n @Name：layui.form 表单组件\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define('layer', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,layer = layui.layer\n  ,hint = layui.hint()\n  ,device = layui.device()\n  \n  ,MOD_NAME = 'form', ELEM = '.layui-form', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'\n  \n  ,Form = function(){\n    this.config = {\n      verify: {\n        required: [\n          /[\\S]+/\n          ,'必填项不能为空'\n        ]\n        ,phone: [\n          /^1\\d{10}$/\n          ,'请输入正确的手机号'\n        ]\n        ,email: [\n          /^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/\n          ,'邮箱格式不正确'\n        ]\n        ,url: [\n          /(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/\n          ,'链接格式不正确'\n        ]\n        ,number: function(value){\n          if(!value || isNaN(value)) return '只能填写数字'\n        }\n        ,date: [\n          /^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/\n          ,'日期格式不正确'\n        ]\n        ,identity: [\n          /(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/\n          ,'请输入正确的身份证号'\n        ]\n      }\n    };\n  };\n  \n  //全局设置\n  Form.prototype.set = function(options){\n    var that = this;\n    $.extend(true, that.config, options);\n    return that;\n  };\n  \n  //验证规则设定\n  Form.prototype.verify = function(settings){\n    var that = this;\n    $.extend(true, that.config.verify, settings);\n    return that;\n  };\n  \n  //表单事件监听\n  Form.prototype.on = function(events, callback){\n    return layui.onevent.call(this, MOD_NAME, events, callback);\n  };\n  \n  //表单控件渲染\n  Form.prototype.render = function(type, filter){\n    var that = this\n    ,elemForm = $(ELEM + function(){\n      return filter ? ('[lay-filter=\"' + filter +'\"]') : '';\n    }())\n    ,items = {\n      \n      //下拉选择框\n      select: function(){\n        var TIPS = '请选择', CLASS = 'layui-form-select', TITLE = 'layui-select-title'\n        ,NONE = 'layui-select-none', initValue = '', thatInput\n        \n        ,selects = elemForm.find('select'), 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        \n        ,events = function(reElem, disabled, isSearch){\n          var select = $(this)\n          ,title = reElem.find('.' + TITLE)\n          ,input = title.find('input')\n          ,dl = reElem.find('dl')\n          ,dds = dl.children('dd')\n          \n          \n          if(disabled) return;\n          \n          //展开下拉\n          var showDown = function(){\n            var top = reElem.offset().top + reElem.outerHeight() + 5 - win.scrollTop()\n            ,dlHeight = dl.outerHeight();\n            reElem.addClass(CLASS+'ed');\n            dds.removeClass(HIDE);\n            \n            //上下定位识别\n            if(top + dlHeight > win.height() && top >= dlHeight){\n              reElem.addClass(CLASS + 'up');\n            }\n          }, hideDown = function(choose){\n            reElem.removeClass(CLASS+'ed ' + CLASS+'up');\n            input.blur();\n            \n            if(choose) return;\n            \n            notOption(input.val(), function(none){\n              if(none){\n                initValue = dl.find('.'+THIS).html();\n                input && input.val(initValue);\n              }\n            });\n          };\n          \n          //点击标题区域\n          title.on('click', function(e){\n            reElem.hasClass(CLASS+'ed') ? (\n              hideDown()\n            ) : (\n              hide(e, true), \n              showDown()\n            );\n            dl.find('.'+NONE).remove();\n          }); \n          \n          //点击箭头获取焦点\n          title.find('.layui-edge').on('click', function(){\n            input.focus();\n          });\n          \n          //键盘事件\n          input.on('keyup', function(e){\n            var keyCode = e.keyCode;\n            //Tab键\n            if(keyCode === 9){\n              showDown();\n            }\n          }).on('keydown', 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          \n          //检测值是否不属于select项\n          var notOption = function(value, callback, origin){\n            var num = 0;\n            layui.each(dds, function(){\n              var othis = $(this)\n              ,text = othis.text()\n              ,not = text.indexOf(value) === -1;\n              if(value === '' || (origin === 'blur') ? value !== text : not) num++;\n              origin === 'keyup' && othis[not ? 'addClass' : 'removeClass'](HIDE);\n            });\n            var none = num === dds.length;\n            return callback(none), none;\n          };\n          \n          //搜索匹配\n          var search = function(e){\n            var value = this.value, keyCode = e.keyCode;\n            \n            if(keyCode === 9 || keyCode === 13 \n              || keyCode === 37 || keyCode === 38 \n              || keyCode === 39 || keyCode === 40\n            ){\n              return false;\n            }\n            \n            notOption(value, function(none){\n              if(none){\n                dl.find('.'+NONE)[0] || dl.append('<p class=\"'+ NONE +'\">无匹配项</p>');\n              } else {\n                dl.find('.'+NONE).remove();\n              }\n            }, 'keyup');\n            \n            if(value === ''){\n              dl.find('.'+NONE).remove();\n            }\n          };\n          if(isSearch){\n            input.on('keyup', search).on('blur', function(e){\n              thatInput = input;\n              initValue = dl.find('.'+THIS).html();\n              setTimeout(function(){\n                notOption(input.val(), function(none){\n                  if(none && !initValue){\n                    input.val('');\n                  }\n                }, 'blur');\n              }, 200);\n            });\n          }\n\n          //选择\n          dds.on('click', function(){\n            var othis = $(this), value = othis.attr('lay-value');\n            var filter = select.attr('lay-filter'); //获取过滤器\n\n            if(othis.hasClass(DISABLED)) return false;\n            \n            if(othis.hasClass('layui-select-tips')){\n              input.val('');\n            } else {\n              input.val(othis.text());\n              othis.addClass(THIS);\n            }\n            \n            othis.siblings().removeClass(THIS);\n            select.val(value).removeClass('layui-form-danger')\n            layui.event.call(this, MOD_NAME, 'select('+ filter +')', {\n              elem: select[0]\n              ,value: value\n              ,othis: reElem\n            });\n\n            hideDown(true);\n            return false;\n          });\n          \n          reElem.find('dl>dt').on('click', function(e){\n            return false;\n          });\n          \n          //关闭下拉\n          $(document).off('click', hide).on('click', hide);\n        }\n        \n        selects.each(function(index, select){\n          var othis = $(this)\n          ,hasRender = othis.next('.'+CLASS)\n          ,disabled = this.disabled\n          ,value = select.value\n          ,selected = $(select.options[select.selectedIndex]) //获取当前选中项\n          ,optionsFirst = select.options[0];\n          \n          if(typeof othis.attr('lay-ignore') === 'string') return othis.show();\n          \n          var isSearch = typeof othis.attr('lay-search') === 'string'\n          ,placeholder = optionsFirst ? (\n            optionsFirst.value ? TIPS : (optionsFirst.innerHTML || TIPS)\n          ) : TIPS;\n\n          //替代元素\n          var reElem = $(['<div class=\"'+ (isSearch ? '' : 'layui-unselect ') + CLASS + (disabled ? ' layui-select-disabled' : '') +'\">'\n            ,'<div class=\"'+ TITLE +'\"><input type=\"text\" placeholder=\"'+ placeholder +'\" value=\"'+ (value ? selected.html() : '') +'\" '+ (isSearch ? '' : 'readonly') +' class=\"layui-input'+ (isSearch ? '' : ' layui-unselect') + (disabled ? (' ' + DISABLED) : '') +'\">'\n            ,'<i class=\"layui-edge\"></i></div>'\n            ,'<dl class=\"layui-anim layui-anim-upbit'+ (othis.find('optgroup')[0] ? ' layui-select-group' : '') +'\">'+ function(options){\n              var arr = [];\n              layui.each(options, function(index, item){\n                if(index === 0 && !item.value){\n                  arr.push('<dd lay-value=\"\" class=\"layui-select-tips\">'+ (item.innerHTML || TIPS) +'</dd>');\n                } else if(item.tagName.toLowerCase() === 'optgroup'){\n                  arr.push('<dt>'+ item.label +'</dt>'); \n                } else {\n                  arr.push('<dd lay-value=\"'+ item.value +'\" class=\"'+ (value === item.value ?  THIS : '') + (item.disabled ? (' '+DISABLED) : '') +'\">'+ item.innerHTML +'</dd>');\n                }\n              });\n              arr.length === 0 && arr.push('<dd lay-value=\"\" class=\"'+ DISABLED +'\">没有选项</dd>');\n              return arr.join('');\n            }(othis.find('*')) +'</dl>'\n          ,'</div>'].join(''));\n          \n          hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender\n          othis.after(reElem);          \n          events.call(this, reElem, disabled, isSearch);\n        });\n      }\n      //复选框/开关\n      ,checkbox: function(){\n        var CLASS = {\n          checkbox: ['layui-form-checkbox', 'layui-form-checked', 'checkbox']\n          ,_switch: ['layui-form-switch', 'layui-form-onswitch', 'switch']\n        }\n        ,checks = elemForm.find('input[type=checkbox]')\n        \n        ,events = function(reElem, RE_CLASS){\n          var check = $(this);\n          \n          //勾选\n          reElem.on('click', function(){\n            var filter = check.attr('lay-filter') //获取过滤器\n            ,text = (check.attr('lay-text')||'').split('|');\n\n            if(check[0].disabled) return;\n            \n            check[0].checked ? (\n              check[0].checked = false\n              ,reElem.removeClass(RE_CLASS[1]).find('em').text(text[1])\n            ) : (\n              check[0].checked = true\n              ,reElem.addClass(RE_CLASS[1]).find('em').text(text[0])\n            );\n            \n            layui.event.call(check[0], MOD_NAME, RE_CLASS[2]+'('+ filter +')', {\n              elem: check[0]\n              ,value: check[0].value\n              ,othis: reElem\n            });\n          });\n        }\n        \n        checks.each(function(index, check){\n          var othis = $(this), skin = othis.attr('lay-skin')\n          ,text = (othis.attr('lay-text')||'').split('|'), disabled = this.disabled;\n          if(skin === 'switch') skin = '_'+skin;\n          var RE_CLASS = CLASS[skin] || CLASS.checkbox;\n          \n          if(typeof othis.attr('lay-ignore') === 'string') return othis.show();\n          \n          //替代元素\n          var hasRender = othis.next('.' + RE_CLASS[0]);\n          var reElem = $(['<div class=\"layui-unselect '+ RE_CLASS[0] + (\n            check.checked ? (' '+RE_CLASS[1]) : '') + (disabled ? ' layui-checkbox-disbaled '+DISABLED : '') +'\" lay-skin=\"'+ (skin||'') +'\">'\n          ,{\n            _switch: '<em>'+ ((check.checked ? text[0] : text[1])||'') +'</em><i></i>'\n          }[skin] || ((check.title.replace(/\\s/g, '') ? ('<span>'+ check.title +'</span>') : '') +'<i class=\"layui-icon\">'+ (skin ? '&#xe605;' : '&#xe618;') +'</i>')\n          ,'</div>'].join(''));\n\n          hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender\n          othis.after(reElem);\n          events.call(this, reElem, RE_CLASS);\n        });\n      }\n      //单选框\n      ,radio: function(){\n        var CLASS = 'layui-form-radio', ICON = ['&#xe643;', '&#xe63f;']\n        ,radios = elemForm.find('input[type=radio]')\n        \n        ,events = function(reElem){\n          var radio = $(this), ANIM = 'layui-anim-scaleSpring';\n          \n          reElem.on('click', function(){\n            var name = radio[0].name, forms = radio.parents(ELEM);\n            var filter = radio.attr('lay-filter'); //获取过滤器\n            var sameRadio = forms.find('input[name='+ name.replace(/(\\.|#|\\[|\\])/g, '\\\\$1') +']'); //找到相同name的兄弟\n            \n            if(radio[0].disabled) return;\n            \n            layui.each(sameRadio, function(){\n              var next = $(this).next('.'+CLASS);\n              this.checked = false;\n              next.removeClass(CLASS+'ed');\n              next.find('.layui-icon').removeClass(ANIM).html(ICON[1]);\n            });\n            \n            radio[0].checked = true;\n            reElem.addClass(CLASS+'ed');\n            reElem.find('.layui-icon').addClass(ANIM).html(ICON[0]);\n            \n            layui.event.call(radio[0], MOD_NAME, 'radio('+ filter +')', {\n              elem: radio[0]\n              ,value: radio[0].value\n              ,othis: reElem\n            });\n          });\n        };\n        \n        radios.each(function(index, radio){\n          var othis = $(this), hasRender = othis.next('.' + CLASS), disabled = this.disabled;\n          \n          if(typeof othis.attr('lay-ignore') === 'string') return othis.show();\n          \n          //替代元素\n          var reElem = $(['<div class=\"layui-unselect '+ CLASS + (radio.checked ? (' '+CLASS+'ed') : '') + (disabled ? ' layui-radio-disbaled '+DISABLED : '') +'\">'\n          ,'<i class=\"layui-anim layui-icon\">'+ ICON[radio.checked ? 0 : 1] +'</i>'\n          ,'<span>'+ (radio.title||'未命名') +'</span>'\n          ,'</div>'].join(''));\n          \n          hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender\n          othis.after(reElem);\n          events.call(this, reElem);\n        });\n      }\n    };\n    type ? (\n      items[type] ? items[type]() : hint.error('不支持的'+ type + '表单渲染')\n    ) : layui.each(items, function(index, item){\n      item();\n    });\n    return that;\n  };\n  \n  //表单提交校验\n  var submit = function(){\n    var button = $(this), verify = form.config.verify, stop = null\n    ,DANGER = 'layui-form-danger', field = {} ,elem = button.parents(ELEM)\n    \n    ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素\n    ,formElem = button.parents('form')[0] //获取当前所在的form元素，如果存在的话\n    ,fieldElem = elem.find('input,select,textarea') //获取所有表单域\n    ,filter = button.attr('lay-filter'); //获取过滤器\n \n    //开始校验\n    layui.each(verifyElem, function(_, item){\n      var othis = $(this), ver = othis.attr('lay-verify').split('|');\n      var tips = '', value = othis.val();\n      othis.removeClass(DANGER);\n      layui.each(ver, function(_, thisVer){\n        var isFn = typeof verify[thisVer] === 'function';\n        if(verify[thisVer] && (isFn ? tips = verify[thisVer](value, item) : !verify[thisVer][0].test(value)) ){\n          layer.msg(tips || verify[thisVer][1], {\n            icon: 5\n            ,shift: 6\n          });\n          //非移动设备自动定位焦点\n          if(!device.android && !device.ios){\n            item.focus();\n          }\n          othis.addClass(DANGER);\n          return stop = true;\n        }\n      });\n      if(stop) return stop;\n    });\n    \n    if(stop) return false;\n    \n    layui.each(fieldElem, function(_, item){\n      if(!item.name) return;\n      if(/^checkbox|radio$/.test(item.type) && !item.checked) return;\n      field[item.name] = item.value;\n    });\n \n    //获取字段\n    return layui.event.call(this, MOD_NAME, 'submit('+ filter +')', {\n      elem: this\n      ,form: formElem\n      ,field: field\n    });\n  };\n\n  //自动完成渲染\n  var form = new Form()\n  ,dom = $(document), win = $(window);\n  \n  form.render();\n  \n  //表单reset重置渲染\n  dom.on('reset', ELEM, function(){\n    var filter = $(this).attr('lay-filter');\n    setTimeout(function(){\n      form.render(null, filter);\n    }, 50);\n  });\n  \n  //表单提交事件\n  dom.on('submit', ELEM, submit)\n  .on('click', '*[lay-submit]', submit);\n  \n  exports(MOD_NAME, form);\n});\n\n \n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.12.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://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-04-05T19:16Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\"use strict\";\nvar deletedIds = [];\n\nvar document = window.document;\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 support = {};\n\n\n\nvar\n\tversion = \"1.12.3\",\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.1, IE<9\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\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: 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\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 = jQuery.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 && 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\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\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\tvar realStringObj = obj && obj.toString();\n\t\treturn !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 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\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\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.ownFirst ) {\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// 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\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 ); // jscs:ignore requireDotNotation\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\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.1, IE<9\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\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\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 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 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// JSHint would error on this code due to the Symbol not being defined in ES5.\n// Defining this global in .jshintrc would create a danger of using the global\n// unguarded in another place, it seems safer to just disable JSHint for these\n// three lines.\n/* jshint ignore: start */\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ];\n}\n/* jshint ignore: end */\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: iOS 8.2 (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!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.2.1\n * http://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2015-10-17\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// 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-]|[^\\\\x00-\\\\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\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, nidselect, 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( rescape, \"\\\\$&\" );\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\tnidselect = ridentifier.test( nid ) ? \"#\" + nid : \"[id='\" + nid + \"']\";\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = nidselect + \" \" + 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 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 = 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\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// 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 ( (parent = document.defaultView) && parent.top !== parent ) {\n\t\t// Support: IE 11\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.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( 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( document.createComment(\"\") );\n\t\treturn !div.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 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 !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\treturn m ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\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\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 http://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( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\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// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully 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.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\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, 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 ( (oldCache = uniqueCache[ 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\tuniqueCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || 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\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\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( 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.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\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\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 ) > -1 ) !== 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// 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, 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// 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.charAt( 0 ) === \"<\" &&\n\t\t\t\tselector.charAt( 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// 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\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\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 || 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.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 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\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\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 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\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.uniqueSort( 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\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.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\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 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\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\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.uniqueSort( 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// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\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\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 = 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 = true;\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\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\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\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\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.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 === promise ? newDefer.promise() : this,\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\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\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 ||\n\t\t\t\t( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred.\n\t\t\t// 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.progress( updateFunc( i, progressContexts, progressValues ) )\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} 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\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\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// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n} );\n\n/**\n * Clean-up method for dom ready events\n */\nfunction detach() {\n\tif ( document.addEventListener ) {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\t\twindow.removeEventListener( \"load\", completed );\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\n\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\tif ( document.addEventListener ||\n\t\twindow.event.type === \"load\" ||\n\t\tdocument.readyState === \"complete\" ) {\n\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\n\t\t// after the browser event has already occurred.\n\t\t// Support: IE6-10\n\t\t// Older IE sometimes signals \"interactive\" too soon\n\t\tif ( document.readyState === \"complete\" ||\n\t\t\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\twindow.setTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed );\n\n\t\t// If IE event model is used\n\t\t} else {\n\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\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 window.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// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\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.ownFirst = 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\n// Execute ASAP in case we need to set body.style.zoom\njQuery( function() {\n\n\t// Minified: var a,b,c,d\n\tvar val, div, body, container;\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\tif ( !body || !body.style ) {\n\n\t\t// Return for frameset docs that don't have a body\n\t\treturn;\n\t}\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\tbody.appendChild( container ).appendChild( div );\n\n\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\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 = \"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\";\n\n\t\tsupport.inlineBlockNeedsLayout = val = div.offsetWidth === 3;\n\t\tif ( val ) {\n\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\n\n( function() {\n\tvar div = document.createElement( \"div\" );\n\n\t// Support: IE<9\n\tsupport.deleteExpando = true;\n\ttry {\n\t\tdelete div.test;\n\t} catch ( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n} )();\nvar 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\n\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\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\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\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 ( !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 ) ) &&\n\t\tdata === undefined && typeof name === \"string\" ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\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\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 ( !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\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, undefined\n\t} else {\n\t\tcache[ id ] = undefined;\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\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\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\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,\n\t// 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\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} );\n\n\n( function() {\n\tvar shrinkWrapBlocksVal;\n\n\tsupport.shrinkWrapBlocks = function() {\n\t\tif ( shrinkWrapBlocksVal != null ) {\n\t\t\treturn shrinkWrapBlocksVal;\n\t\t}\n\n\t\t// Will be changed later if needed.\n\t\tshrinkWrapBlocksVal = false;\n\n\t\t// Minified: var b,c,d\n\t\tvar div, body, container;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE6\n\t\t// Check if elements with layout shrink-wrap their children\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border\n\t\t\tdiv.style.cssText =\n\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;\" +\n\t\t\t\t\"padding:1px;width:1px;zoom:1\";\n\t\t\tdiv.appendChild( document.createElement( \"div\" ) ).style.width = \"5px\";\n\t\t\tshrinkWrapBlocksVal = div.offsetWidth !== 3;\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\treturn shrinkWrapBlocksVal;\n\t};\n\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 isHidden = function( elem, el ) {\n\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\" ||\n\t\t\t!jQuery.contains( elem.ownerDocument, elem );\n\t};\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() { return tween.cur(); } :\n\t\t\tfunction() { return jQuery.css( elem, prop, \"\" ); },\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\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\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\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 < length; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ],\n\t\t\t\t\tkey,\n\t\t\t\t\traw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\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\nvar rtagName = ( /<([\\w:-]+)/ );\n\nvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\nvar rleadingWhitespace = ( /^\\s+/ );\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|\" +\n\t\t\"details|dialog|figcaption|figure|footer|header|hgroup|main|\" +\n\t\t\"mark|meter|nav|output|picture|progress|section|summary|template|time|video\";\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\n\n( function() {\n\tvar div = document.createElement( \"div\" ),\n\t\tfragment = document.createDocumentFragment(),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\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\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput = document.createElement( \"input\" );\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari 5.1, 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// Cloned elements keep attachEvent handlers, we use addEventListener on IE9+\n\tsupport.noCloneEvent = !!div.addEventListener;\n\n\t// Support: IE<9\n\t// Since attributes and properties are the same in IE,\n\t// cleanData must set properties to undefined rather than use removeAttribute\n\tdiv[ jQuery.expando ] = 1;\n\tsupport.attributes = !div.getAttribute( jQuery.expando );\n} )();\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\tarea: [ 1, \"<map>\", \"</map>\" ],\n\n\t// Support: IE8\n\tparam: [ 1, \"<object>\", \"</object>\" ],\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t// unless wrapped in a div with non-breaking characters in front of it.\n\t_default: support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\" ]\n};\n\n// Support: IE8-IE9\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\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== \"undefined\" ?\n\t\t\t\tcontext.querySelectorAll( tag || \"*\" ) :\n\t\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context;\n\t\t\t( elem = elems[ i ] ) != null;\n\t\t\ti++\n\t\t) {\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\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(\n\t\t\telem,\n\t\t\t\"globalEval\",\n\t\t\t!refElements || jQuery._data( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/,\n\trtbody = /<tbody/i;\n\nfunction fixDefaultChecked( elem ) {\n\tif ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar j, elem, contains,\n\t\ttmp, tag, tbody, wrap,\n\t\tl = elems.length,\n\n\t\t// Ensure a safe fragment\n\t\tsafe = createSafeFragment( context ),\n\n\t\tnodes = [],\n\t\ti = 0;\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\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 || safe.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\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// Manually add leading whitespace removed by IE\n\t\t\t\tif ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) );\n\t\t\t\t}\n\n\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\tif ( !support.tbody ) {\n\n\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\twrap[ 1 ] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t0;\n\n\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\tif ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), \"tbody\" ) &&\n\t\t\t\t\t\t\t!tbody.childNodes.length ) {\n\n\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t}\n\n\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\ttmp = safe.lastChild;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fix #11356: Clear elements from fragment\n\tif ( tmp ) {\n\t\tsafe.removeChild( tmp );\n\t}\n\n\t// Reset defaultChecked for any radios and checkboxes\n\t// about to be appended to the DOM in IE 6/7 (#8060)\n\tif ( !support.appendChecked ) {\n\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t}\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\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( safe.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\ttmp = null;\n\n\treturn safe;\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 (lack focus(in | out) events)\n\tfor ( i in { submit: true, change: true, focusin: true } ) {\n\t\teventName = \"on\" + i;\n\n\t\tif ( !( support[ i ] = eventName in window ) ) {\n\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 ] = 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|pointer|contextmenu|drag|drop)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE9\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\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\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\" &&\n\t\t\t\t\t( !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\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak\n\t\t\t// 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 ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\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 ] &&\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 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( \".\" ) > -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 = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tjQuery._data( cur, \"handle\" );\n\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 (\n\t\t\t\t( !special._default ||\n\t\t\t\t special._default.apply( eventPath.pop(), data ) === false\n\t\t\t\t) && acceptData( elem )\n\t\t\t) {\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\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, j, ret, matched, handleObj,\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++ ] ) &&\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, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Support (at least): Chrome, IE9\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t//\n\t\t// Support: Firefox<=42+\n\t\t// Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)\n\t\tif ( delegateCount && cur.nodeType &&\n\t\t\t( event.type !== \"click\" || isNaN( event.button ) || event.button < 1 ) ) {\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 ) > -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 ( 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: Safari 6-8+\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 detail eventPhase \" +\n\t\t\"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 \" +\n\t\t\t\"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 +\n\t\t\t\t\t( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -\n\t\t\t\t\t( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY +\n\t\t\t\t\t( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) -\n\t\t\t\t\t( 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 ?\n\t\t\t\t\toriginal.toElement :\n\t\t\t\t\tfromElement;\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\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\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\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\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// 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\t// Piggyback on a donor event to simulate a different one\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\n\t\t\t\t// Previously, `originalEvent: {}` was set here, so stopPropagation call\n\t\t\t\t// would not be triggered on donor event, since in our own\n\t\t\t\t// jQuery.event.stopPropagation function we had a check for existence of\n\t\t\t\t// originalEvent.stopPropagation method, so, consequently it would be a noop.\n\t\t\t\t//\n\t\t\t\t// Guard for simulated events was moved to jQuery.event.stopPropagation function\n\t\t\t\t// since `originalEvent` should point to the original event for the\n\t\t\t\t// constancy with other events and for more focused logic\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\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\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\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,\n\t\t\t// to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === \"undefined\" ) {\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\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: IE < 9, Android < 4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\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\n\t\tif ( !e || this.isSimulated ) {\n\t\t\treturn;\n\t\t}\n\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\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// 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://code.google.com/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\n// IE submit delegation\nif ( !support.submit ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\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\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\" ) ?\n\n\t\t\t\t\t\t// Support: IE <=8\n\t\t\t\t\t\t// We use jQuery.prop instead of elem.form\n\t\t\t\t\t\t// to allow fixing the IE8 delegated submit issue (gh-2332)\n\t\t\t\t\t\t// by 3rd party polyfills/workarounds.\n\t\t\t\t\t\tjQuery.prop( elem, \"form\" ) :\n\t\t\t\t\t\tundefined;\n\n\t\t\t\tif ( form && !jQuery._data( form, \"submit\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submitBubble = true;\n\t\t\t\t\t} );\n\t\t\t\t\tjQuery._data( form, \"submit\", true );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submitBubble ) {\n\t\t\t\tdelete event._submitBubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\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.change ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\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._justChanged = 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._justChanged && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._justChanged = false;\n\t\t\t\t\t\t}\n\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 );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\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, \"change\" ) ) {\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 );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t\tjQuery._data( elem, \"change\", 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 ||\n\t\t\t\t( elem.type !== \"radio\" && elem.type !== \"checkbox\" ) ) {\n\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// Support: Firefox\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, Safari\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://code.google.com/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 = 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 ) {\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\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp( \"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\" ),\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,\n\n\t// Support: IE 10-11, Edge 10240+\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\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement( \"div\" ) );\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\nfunction cloneCopyEvent( src, dest ) {\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\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\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar first, node, hasScripts,\n\t\tscripts, doc, fragment,\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.1, PhantomJS<2\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!jQuery._data( 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\tjQuery.globalEval(\n\t\t\t\t\t\t\t\t( node.text || node.textContent || node.innerHTML || \"\" )\n\t\t\t\t\t\t\t\t\t.replace( rcleanScript, \"\" )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\tfragment = first = null;\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\telems = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = elems[ i ] ) != null; i++ ) {\n\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 destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( support.html5Clone || jQuery.isXMLDoc( elem ) ||\n\t\t\t!rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\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\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\tcleanData: function( elems, /* internal */ forceAcceptData ) {\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\tattributes = support.attributes,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\tif ( forceAcceptData || 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// Support: IE<9\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// IE creates expando attributes along with the property\n\t\t\t\t\t\t// IE does not have a removeAttribute function on Document nodes\n\t\t\t\t\t\tif ( !attributes && typeof elem.removeAttribute !== \"undefined\" ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t\t\t\t// https://code.google.com/p/chromium/issues/detail?id=378607\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = undefined;\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\n\t// Keep domManip exposed until 3.0 (gh-2225)\n\tdomManip: domManip,\n\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().append(\n\t\t\t\t\t( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value )\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\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 = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\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 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\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\t\t// Support: Firefox\n\t\t// We have to pre-define these values for FF (#10227)\n\t\tHTML: \"block\",\n\t\tBODY: \"block\"\n\t};\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\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\tdisplay = 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'/>\" ) )\n\t\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\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\nvar rmargin = ( /^margin/ );\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar 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 documentElement = document.documentElement;\n\n\n\n( function() {\n\tvar pixelPositionVal, pixelMarginRightVal, boxSizingReliableVal,\n\t\treliableHiddenOffsetsVal, reliableMarginRightVal, 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\tdiv.style.cssText = \"float:left;opacity:.5\";\n\n\t// Support: IE<9\n\t// Make sure that element opacity exists (as opposed to filter)\n\tsupport.opacity = div.style.opacity === \"0.5\";\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!div.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\tcontainer = document.createElement( \"div\" );\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\tdiv.innerHTML = \"\";\n\tcontainer.appendChild( div );\n\n\t// Support: Firefox<29, Android 2.3\n\t// Vendor-prefix box-sizing\n\tsupport.boxSizing = div.style.boxSizing === \"\" || div.style.MozBoxSizing === \"\" ||\n\t\tdiv.style.WebkitBoxSizing === \"\";\n\n\tjQuery.extend( support, {\n\t\treliableHiddenOffsets: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableHiddenOffsetsVal;\n\t\t},\n\n\t\tboxSizingReliable: function() {\n\n\t\t\t// We're checking for pixelPositionVal here instead of boxSizingReliableVal\n\t\t\t// since that compresses better and they're computed together anyway.\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\n\t\tpixelMarginRight: function() {\n\n\t\t\t// Support: Android 4.0-4.3\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelMarginRightVal;\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\n\t\t\t// Support: Android 2.3\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginRightVal;\n\t\t},\n\n\t\treliableMarginLeft: function() {\n\n\t\t\t// Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginLeftVal;\n\t\t}\n\t} );\n\n\tfunction computeStyleTests() {\n\t\tvar contents, divStyle,\n\t\t\tdocumentElement = document.documentElement;\n\n\t\t// Setup\n\t\tdocumentElement.appendChild( container );\n\n\t\tdiv.style.cssText =\n\n\t\t\t// Support: Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;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\n\t\t// Support: IE<9\n\t\t// Assume reasonable values in the absence of getComputedStyle\n\t\tpixelPositionVal = boxSizingReliableVal = reliableMarginLeftVal = false;\n\t\tpixelMarginRightVal = reliableMarginRightVal = true;\n\n\t\t// Check for getComputedStyle so that this code is not run in IE<9.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdivStyle = window.getComputedStyle( div );\n\t\t\tpixelPositionVal = ( divStyle || {} ).top !== \"1%\";\n\t\t\treliableMarginLeftVal = ( divStyle || {} ).marginLeft === \"2px\";\n\t\t\tboxSizingReliableVal = ( divStyle || { width: \"4px\" } ).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\" } ).marginRight === \"4px\";\n\n\t\t\t// Support: Android 2.3 only\n\t\t\t// 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// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tcontents = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\tcontents.style.cssText = div.style.cssText =\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\tcontents.style.marginRight = contents.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\treliableMarginRightVal =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( contents ) || {} ).marginRight );\n\n\t\t\tdiv.removeChild( contents );\n\t\t}\n\n\t\t// Support: IE6-8\n\t\t// First check that getClientRects works as expected\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.style.display = \"none\";\n\t\treliableHiddenOffsetsVal = div.getClientRects().length === 0;\n\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\tdiv.style.display = \"\";\n\t\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\t\tcontents = div.getElementsByTagName( \"td\" );\n\t\t\tcontents[ 0 ].style.cssText = \"margin:0;border:0;padding:0;display:none\";\n\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\t\tcontents[ 0 ].style.display = \"\";\n\t\t\t\tcontents[ 1 ].style.display = \"none\";\n\t\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t\t}\n\t\t}\n\n\t\t// Teardown\n\t\tdocumentElement.removeChild( container );\n\t}\n\n} )();\n\n\nvar getStyles, curCSS,\n\trposition = /^(top|right|bottom|left)$/;\n\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\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\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\t// Support: Opera 12.1x only\n\t\t// Fall back to style even without computed\n\t\t// computed is undefined for elems on document fragments\n\t\tif ( ( ret === \"\" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\tif ( computed ) {\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\"\n\t\t\t// 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,\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// http://dev.w3.org/csswg/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\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 ( 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\n\t\t// proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it\n\t\t// 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\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\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/i,\n\n\t// swappable if display is none or starts with table except\n\t// \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values:\n\t// https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = 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\temptyStyle = document.createElement( \"div\" ).style;\n\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.charAt( 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\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\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 ] =\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay( elem.nodeName ) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\tjQuery._data(\n\t\t\t\t\telem,\n\t\t\t\t\t\"olddisplay\",\n\t\t\t\t\thidden ? 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\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\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\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\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 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 &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Support: IE11 only\n\t// In IE 11 fullscreen elements inside of an iframe have\n\t// 100x too small dimensions (gh-1764).\n\tif ( document.msFullscreenElement && window.top !== window ) {\n\n\t\t// Support: IE11 only\n\t\t// Running getBoundingClientRect on a disconnected node\n\t\t// in IE throws an error.\n\t\tif ( elem.getClientRects().length ) {\n\t\t\tval = Math.round( elem.getBoundingClientRect()[ name ] * 100 );\n\t\t}\n\t}\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\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 &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\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\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\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 ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || 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 \"+=\" 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. 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 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// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight\n\t\t\t// (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 ) ||\n\t\t\t\t( 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\tstyle[ name ] = value;\n\t\t\t\t} catch ( e ) {}\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 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 ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || 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 || isFinite( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\t\t\t\t\telem.offsetWidth === 0 ?\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 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 &&\n\t\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n} );\n\nif ( !support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( ( computed && elem.currentStyle ?\n\t\t\t\telem.currentStyle.filter :\n\t\t\t\telem.style.filter ) || \"\" ) ?\n\t\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\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 -\n\t\t\t// 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\n\t\t\t\t// 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\treturn swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\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 (\n\t\t\t\tparseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\n\t\t\t\t// Support: IE<=11+\n\t\t\t\t// Running getBoundingClientRect on a disconnected node in IE throws an error\n\t\t\t\t// Support: IE8 only\n\t\t\t\t// getClientRects() errors on disconnected elems\n\t\t\t\t( jQuery.contains( elem.ownerDocument, elem ) ?\n\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\t0\n\t\t\t\t)\n\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 ( 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 || jQuery.easing._default;\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\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && 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\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\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.nodeType === 1 &&\n\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\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\t_default: \"swing\"\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\trrun = /queueHooks$/;\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( 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 = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// we're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = 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\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\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\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tjQuery._data( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.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 || defaultDisplay( elem.nodeName ) === \"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\n\t\t\t\t// and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = 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\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( ( display === \"none\" ? defaultDisplay( elem.nodeName ) : display ) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this 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 = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\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\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, 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\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.notifyWith( elem, [ animation, 1, 0 ] );\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 = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( jQuery.isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tjQuery.proxy( result.stop, result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\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.match( rnotwhite );\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\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.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 ?\n\t\t\tjQuery.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\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 &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\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\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 = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\twindow.clearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://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 a,\n\t\tinput = document.createElement( \"input\" ),\n\t\tdiv = document.createElement( \"div\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\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// Support: Windows Web Apps (WWA)\n\t// `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"checkbox\" );\n\tdiv.appendChild( input );\n\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// First batch of tests.\n\ta.style.cssText = \"top:1px\";\n\n\t// Test setAttribute on camelCase class.\n\t// 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\n\nvar rreturn = /\\r/g,\n\trspaces = /[\\x20\\t\\r\\n\\f]+/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 (\n\t\t\t\t\thooks &&\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\treturn typeof ret === \"string\" ?\n\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace( rreturn, \"\" ) :\n\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\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\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\tjQuery.trim( jQuery.text( elem ) ).replace( rspaces, \" \" );\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\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 ?\n\t\t\t\t\t\t\t\t!option.disabled :\n\t\t\t\t\t\t\t\toption.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!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 ) > -1 ) {\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 ) > -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\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 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// 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\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\tjQuery.nodeName( elem, \"input\" ) ) {\n\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE8-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\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\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\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\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 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\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} else {\n\n\t\t\t// Support: IE<9\n\t\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\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\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\t\tvar ret, handle;\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[ 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} else {\n\t\tattrHandle[ name ] = function( 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\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\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\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\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\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 sensitivity 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\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\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// 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// 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 ) ||\n\t\t\t\t\t\trclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t\t0 :\n\t\t\t\t\t\t\t-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// 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\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// 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\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\tset: function( elem ) {\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// 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\nfunction getClass( elem ) {\n\treturn jQuery.attr( elem, \"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( rnotwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 &&\n\t\t\t\t\t( \" \" + curValue + \" \" ).replace( rclass, \" \" );\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 ( curValue !== finalValue ) {\n\t\t\t\t\t\tjQuery.attr( elem, \"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( rnotwhite ) || [];\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 &&\n\t\t\t\t\t( \" \" + curValue + \" \" ).replace( rclass, \" \" );\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 = jQuery.trim( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\tjQuery.attr( elem, \"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( rnotwhite ) || [];\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\tjQuery._data( 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\tjQuery.attr( this, \"class\",\n\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\"\" :\n\t\t\t\t\tjQuery._data( this, \"__className__\" ) || \"\"\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( \" \" + getClass( elem ) + \" \" ).replace( rclass, \" \" )\n\t\t\t\t\t.indexOf( className ) > -1\n\t\t\t) {\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( \" \" ),\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\nvar location = window.location;\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\n\t// Attempt to parse using the native JSON parser first\n\tif ( window.JSON && window.JSON.parse ) {\n\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 window.DOMParser();\n\t\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new window.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\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\n\t// IE leaves an \\r character at EOL\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\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\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\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\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\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\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\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\" ] ) { // jscs:ignore requireDotNotation\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 {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\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\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: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\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\n\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\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\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\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 &&\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// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\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\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\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 ) + \"\" )\n\t\t\t.replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\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 ] ] +\n\t\t\t\t\t( 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 &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\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\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.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\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\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\twindow.clearTimeout( 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\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\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\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\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\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}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\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\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\nfunction getDisplay( elem ) {\n\treturn elem.style && elem.style.display || jQuery.css( elem, \"display\" );\n}\n\nfunction filterHidden( elem ) {\n\twhile ( elem && elem.nodeType === 1 ) {\n\t\tif ( getDisplay( elem ) === \"none\" || elem.type === \"hidden\" ) {\n\t\t\treturn true;\n\t\t}\n\t\telem = elem.parentNode;\n\t}\n\treturn false;\n}\n\njQuery.expr.filters.hidden = function( elem ) {\n\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn support.reliableHiddenOffsets() ?\n\t\t( elem.offsetWidth <= 0 && elem.offsetHeight <= 0 &&\n\t\t\t!elem.getClientRects().length ) :\n\t\t\tfilterHidden( elem );\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\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, value ) {\n\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\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( \"&\" ).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\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t} ) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?\n\n\t// Support: IE6-IE8\n\tfunction() {\n\n\t\t// XHR cannot access local files, always use ActiveX for that case\n\t\tif ( this.isLocal ) {\n\t\t\treturn createActiveXHR();\n\t\t}\n\n\t\t// Support: IE 9-11\n\t\t// IE seems to error on cross-domain PATCH requests when ActiveX XHR\n\t\t// is used. In IE 9+ always use the native XHR.\n\t\t// Note: this condition won't catch Edge as it doesn't define\n\t\t// document.documentMode but it also doesn't support ActiveX so it won't\n\t\t// reach this code.\n\t\tif ( document.documentMode > 8 ) {\n\t\t\treturn createStandardXHR();\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// oldIE XHR does not support non-RFC2616 methods (#13240)\n\t\t// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx\n\t\t// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9\n\t\t// Although this check for six methods instead of eight\n\t\t// since IE also does not support \"trace\" and \"connect\"\n\t\treturn /^(get|post|head|put|delete|options)$/i.test( this.type ) &&\n\t\t\tcreateStandardXHR() || createActiveXHR();\n\t} :\n\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)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 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\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(\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\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\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\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\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\t// Do send the request\n\t\t\t\t\t// `xhr.send` may raise an exception, but it will be\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\tif ( !options.async ) {\n\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\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\twindow.setTimeout( callback );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Register the callback, but delay it in case `xhr.send` throws\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, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\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\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.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\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\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,\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 ( !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 = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = jQuery.trim( 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\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\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// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\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\n\t\t// 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\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\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 !== \"undefined\" ) {\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},\n\t\t// because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\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\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;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\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 = /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// Support: Safari<7-8+, Chrome<37-44+\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\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\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// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only,\n\t\t\t\t\t// 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\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\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\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\n\n//将jQuery对象局部暴露给layui\nlayui.define(function(exports){\n  layui.$ = jQuery;\n  exports('jquery', jQuery);\n});\n\nreturn jQuery;\n}));"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/laydate.js",
    "content": "/**\n \n @Name : layDate 5.0.7 日期时间控件\n @author 郑保乐\n @Site：http://www.layui.com/laydate/\n @License：MIT\n \n */\n\n;!function(){\n  \"use strict\";\n\n  var isLayui = window.layui && layui.define, ready = {\n    getPath: function(){\n      var js = document.scripts, script = js[js.length - 1], jsPath = script.src;\n      if(script.getAttribute('merge')) return;\n      return jsPath.substring(0, jsPath.lastIndexOf('/') + 1);\n    }()\n    \n    //获取节点的style属性值\n    ,getStyle: function(node, name){\n      var style = node.currentStyle ? node.currentStyle : window.getComputedStyle(node, null);\n      return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name);\n    }\n    \n    //载入CSS配件\n    ,link: function(href, fn, cssname){\n      \n      //未设置路径，则不主动加载css\n      if(!laydate.path) return;\n      \n      var head = document.getElementsByTagName(\"head\")[0], link = document.createElement('link');\n      if(typeof fn === 'string') cssname = fn;\n      var app = (cssname || href).replace(/\\.|\\//g, '');\n      var id = 'layuicss-'+ app, timeout = 0;\n      \n      link.rel = 'stylesheet';\n      link.href = laydate.path + href;\n      link.id = id;\n      \n      if(!document.getElementById(id)){\n        head.appendChild(link);\n      }\n      \n      if(typeof fn !== 'function') return;\n      \n      //轮询css是否加载完毕\n      (function poll() { \n        if(++timeout > 8 * 1000 / 100){\n          return window.console && console.error('laydate.css: Invalid');\n        };\n        parseInt(ready.getStyle(document.getElementById(id), 'width')) === 1989 ? fn() : setTimeout(poll, 100);\n      }());\n    }\n  }\n\n  ,laydate = {\n    v: '5.0.7'\n    ,config: {} //全局配置项\n    ,index: (window.laydate && window.laydate.v) ? 100000 : 0\n    ,path: ready.getPath\n    \n    //设置全局项\n    ,set: function(options){\n      var that = this;\n      that.config = ready.extend({}, that.config, options);\n      return that;\n    }\n    \n    //主体CSS等待事件\n    ,ready: function(fn){\n      var cssname = 'laydate', ver = ''\n      ,path = (isLayui ? 'modules/laydate/' : 'theme/') + 'default/laydate.css?v='+ laydate.v + ver;\n      isLayui ? layui.addcss(path, fn, cssname) : ready.link(path, fn, cssname);\n      return this;\n    }\n  }\n  \n  //操作当前实例\n  ,thisDate = function(){\n    var that = this;\n    return {\n      //提示框\n      hint: function(content){\n        that.hint.call(that, content);\n      }\n      ,config: that.config\n    };\n  }\n\n  //字符常量\n  ,MOD_NAME = 'laydate', ELEM = '.layui-laydate', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'laydate-disabled', TIPS_OUT = '开始日期超出了结束日期<br>建议重新选择', LIMIT_YEAR = [100, 200000]\n  \n  ,ELEM_STATIC = 'layui-laydate-static', ELEM_LIST = 'layui-laydate-list', ELEM_SELECTED = 'laydate-selected', ELEM_HINT = 'layui-laydate-hint', ELEM_PREV = 'laydate-day-prev', ELEM_NEXT = 'laydate-day-next', ELEM_FOOTER = 'layui-laydate-footer', ELEM_CONFIRM = '.laydate-btns-confirm', ELEM_TIME_TEXT = 'laydate-time-text', ELEM_TIME_BTN = '.laydate-btns-time'\n  \n  //组件构造器\n  ,Class = function(options){\n    var that = this;\n    that.index = ++laydate.index;\n    that.config = lay.extend({}, that.config, laydate.config, options);\n    laydate.ready(function(){\n      that.init();\n    });\n  }\n  \n  //DOM查找\n  ,lay = function(selector){   \n    return new LAY(selector);\n  }\n  \n  //DOM构造器\n  ,LAY = function(selector){\n    var index = 0\n    ,nativeDOM = typeof selector === 'object' ? [selector] : (\n      this.selector = selector\n      ,document.querySelectorAll(selector || null)\n    );\n    for(; index < nativeDOM.length; index++){\n      this.push(nativeDOM[index]);\n    }\n  };\n  \n  \n  /*\n    lay对象操作\n  */\n  \n  LAY.prototype = [];\n  LAY.prototype.constructor = LAY;\n  \n  //普通对象深度扩展\n  lay.extend = function(){\n    var ai = 1, args = arguments\n    ,clone = function(target, obj){\n      target = target || (obj.constructor === Array ? [] : {}); \n      for(var i in obj){\n        //如果值为对象，则进入递归，继续深度合并\n        target[i] = (obj[i] && (obj[i].constructor === Object))\n          ? clone(target[i], obj[i])\n        : obj[i];\n      }\n      return target;\n    }\n\n    args[0] = typeof args[0] === 'object' ? args[0] : {};\n\n    for(; ai < args.length; ai++){\n      if(typeof args[ai] === 'object'){\n        clone(args[0], args[ai])\n      }\n    }\n    return args[0];\n  };\n  \n  //ie版本\n  lay.ie = function(){\n    var agent = navigator.userAgent.toLowerCase();\n    return (!!window.ActiveXObject || \"ActiveXObject\" in window) ? (\n      (agent.match(/msie\\s(\\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识\n    ) : false;\n  }();\n  \n  //中止冒泡\n  lay.stope = function(e){\n    e = e || window.event;\n    e.stopPropagation \n      ? e.stopPropagation() \n    : e.cancelBubble = true;\n  };\n  \n  //对象遍历\n  lay.each = function(obj, fn){\n    var key\n    ,that = this;\n    if(typeof fn !== 'function') return that;\n    obj = obj || [];\n    if(obj.constructor === Object){\n      for(key in obj){\n        if(fn.call(obj[key], key, obj[key])) break;\n      }\n    } else {\n      for(key = 0; key < obj.length; key++){\n        if(fn.call(obj[key], key, obj[key])) break;\n      }\n    }\n    return that;\n  };\n  \n  //数字前置补零\n  lay.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  //创建元素\n  lay.elem = function(elemName, attr){\n    var elem = document.createElement(elemName);\n    lay.each(attr || {}, function(key, value){\n      elem.setAttribute(key, value);\n    });\n    return elem;\n  };\n  \n  //追加字符\n  LAY.addStr = function(str, new_str){\n    str = str.replace(/\\s+/, ' ');\n    new_str = new_str.replace(/\\s+/, ' ').split(' ');\n    lay.each(new_str, function(ii, item){\n      if(!new RegExp('\\\\b'+ item + '\\\\b').test(str)){\n        str = str + ' ' + item;\n      }\n    });\n    return str.replace(/^\\s|\\s$/, '');\n  };\n  \n  //移除值\n  LAY.removeStr = function(str, new_str){\n    str = str.replace(/\\s+/, ' ');\n    new_str = new_str.replace(/\\s+/, ' ').split(' ');\n    lay.each(new_str, function(ii, item){\n      var exp = new RegExp('\\\\b'+ item + '\\\\b')\n      if(exp.test(str)){\n        str = str.replace(exp, '');\n      }\n    });\n    return str.replace(/\\s+/, ' ').replace(/^\\s|\\s$/, '');\n  };\n  \n  //查找子元素\n  LAY.prototype.find = function(selector){\n    var that = this;\n    var index = 0, arr = []\n    ,isObject = typeof selector === 'object';\n    \n    this.each(function(i, item){\n      var nativeDOM = isObject ? [selector] : item.querySelectorAll(selector || null);\n      for(; index < nativeDOM.length; index++){\n        arr.push(nativeDOM[index]);\n      }\n      that.shift();\n    });\n    \n    if(!isObject){\n      that.selector =  (that.selector ? that.selector + ' ' : '') + selector\n    }\n    \n    lay.each(arr, function(i, item){\n      that.push(item);\n    });\n    \n    return that;\n  };\n  \n  //DOM遍历\n  LAY.prototype.each = function(fn){\n    return lay.each.call(this, this, fn);\n  };\n  \n  //添加css类\n  LAY.prototype.addClass = function(className, type){\n    return this.each(function(index, item){\n      item.className = LAY[type ? 'removeStr' : 'addStr'](item.className, className)\n    });\n  };\n  \n  //移除css类\n  LAY.prototype.removeClass = function(className){\n    return this.addClass(className, true);\n  };\n  \n  //是否包含css类\n  LAY.prototype.hasClass = function(className){\n    var has = false;\n    this.each(function(index, item){\n      if(new RegExp('\\\\b'+ className +'\\\\b').test(item.className)){\n        has = true;\n      }\n    });\n    return has;\n  };\n  \n  //添加或获取属性\n  LAY.prototype.attr = function(key, value){\n    var that = this;\n    return value === undefined ? function(){\n      if(that.length > 0) return that[0].getAttribute(key);\n    }() : that.each(function(index, item){\n      item.setAttribute(key, value);\n    });   \n  };\n  \n  //移除属性\n  LAY.prototype.removeAttr = function(key){\n    return this.each(function(index, item){\n      item.removeAttribute(key);\n    });\n  };\n  \n  //设置HTML内容\n  LAY.prototype.html = function(html){\n    return this.each(function(index, item){\n      item.innerHTML = html;\n    });\n  };\n  \n  //设置值\n  LAY.prototype.val = function(value){\n    return this.each(function(index, item){\n      item.value = value;\n    });\n  };\n  \n  //追加内容\n  LAY.prototype.append = function(elem){\n    return this.each(function(index, item){\n      typeof elem === 'object' \n        ? item.appendChild(elem)\n      :  item.innerHTML = item.innerHTML + elem;\n    });\n  };\n  \n  //移除内容\n  LAY.prototype.remove = function(elem){\n    return this.each(function(index, item){\n      elem ? item.removeChild(elem) : item.parentNode.removeChild(item);\n    });\n  };\n  \n  //事件绑定\n  LAY.prototype.on = function(eventName, fn){\n    return this.each(function(index, item){\n      item.attachEvent ? item.attachEvent('on' + eventName, function(e){\n        e.target = e.srcElement;\n        fn.call(item, e);\n      }) : item.addEventListener(eventName, fn, false);\n    });\n  };\n  \n  //解除事件\n  LAY.prototype.off = function(eventName, fn){\n    return this.each(function(index, item){\n      item.detachEvent \n        ? item.detachEvent('on'+ eventName, fn)  \n      : item.removeEventListener(eventName, fn, false);\n    });\n  };\n  \n  \n  /*\n    组件操作\n  */\n  \n  \n  //是否闰年\n  Class.isLeapYear = function(year){\n    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n  };\n  \n  //默认配置\n  Class.prototype.config = {\n    type: 'date' //控件类型，支持：year/month/date/time/datetime\n    ,range: false //是否开启范围选择，即双控件\n    ,format: 'yyyy-MM-dd' //默认日期格式\n    ,value: null //默认日期，支持传入new Date()，或者符合format参数设定的日期格式字符\n    ,min: '1900-1-1' //有效最小日期，年月日必须用“-”分割，时分秒必须用“:”分割。注意：它并不是遵循 format 设定的格式。\n    ,max: '2099-12-31' //有效最大日期，同上\n    ,trigger: 'focus' //呼出控件的事件\n    ,show: false //是否直接显示，如果设置true，则默认直接显示控件\n    ,showBottom: true //是否显示底部栏\n    ,btns: ['clear', 'now', 'confirm'] //右下角显示的按钮，会按照数组顺序排列\n    ,lang: 'cn' //语言，只支持cn/en，即中文和英文\n    ,theme: 'default' //主题\n    ,position: null //控件定位方式定位, 默认absolute，支持：fixed/absolute/static\n    ,calendar: false //是否开启公历重要节日，仅支持中文版\n    ,mark: {} //日期备注，如重要事件或活动标记\n    ,zIndex: null //控件层叠顺序\n    ,done: null //控件选择完毕后的回调，点击清空/现在/确定也均会触发\n    ,change: null //日期时间改变后的回调\n  };\n  \n  //多语言\n  Class.prototype.lang = function(){\n    var that = this\n    ,options = that.config\n    ,text = {\n      cn: {\n        weeks: ['日', '一', '二', '三', '四', '五', '六']\n        ,time: ['时', '分', '秒']\n        ,timeTips: '选择时间'\n        ,startTime: '开始时间'\n        ,endTime: '结束时间'\n        ,dateTips: '返回日期'\n        ,month: ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']\n        ,tools: {\n          confirm: '确定'\n          ,clear: '清空'\n          ,now: '现在'\n        }\n      }\n      ,en: {\n        weeks: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n        ,time: ['Hours', 'Minutes', 'Seconds']\n        ,timeTips: 'Select Time'\n        ,startTime: 'Start Time'\n        ,endTime: 'End Time'\n        ,dateTips: 'Select Date'\n        ,month: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n        ,tools: {\n          confirm: 'Confirm'\n          ,clear: 'Clear'\n          ,now: 'Now'\n        }\n      }\n    };\n    return text[options.lang] || text['cn'];\n  };\n  \n  //初始准备\n  Class.prototype.init = function(){\n    var that = this\n    ,options = that.config\n    ,dateType = 'yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s'\n    ,isStatic = options.position === 'static'\n    ,format = {\n      year: 'yyyy'\n      ,month: 'yyyy-MM'\n      ,date: 'yyyy-MM-dd'\n      ,time: 'HH:mm:ss'\n      ,datetime: 'yyyy-MM-dd HH:mm:ss'\n    };\n    \n    options.elem = lay(options.elem);\n    options.eventElem = lay(options.eventElem);\n    \n    if(!options.elem[0]) return;\n    \n    //日期范围分隔符\n    if(options.range === true) options.range = '-';\n    \n    //根据不同type，初始化默认format\n    if(options.format === format.date){\n      options.format = format[options.type];\n    }\n    \n    //将日期格式转化成数组\n    that.format = options.format.match(new RegExp(dateType + '|.', 'g')) || [];\n    \n    //生成正则表达式\n    that.EXP_IF = ''; \n    that.EXP_SPLIT = ''; \n    lay.each(that.format, function(i, item){\n      var EXP =  new RegExp(dateType).test(item) \n        ? '\\\\d{'+ function(){\n          if(new RegExp(dateType).test(that.format[i === 0 ? i + 1 : i - 1]||'')){\n            if(/^yyyy|y$/.test(item)) return 4;\n            return item.length;\n          }\n          if(/^yyyy$/.test(item)) return '1,4';\n          if(/^y$/.test(item)) return '1,308';\n          return '1,2';\n        }() +'}' \n      : '\\\\' + item;\n      that.EXP_IF = that.EXP_IF + EXP;\n      that.EXP_SPLIT = that.EXP_SPLIT + '(' + EXP + ')';\n    });\n    that.EXP_IF = new RegExp('^'+ (\n      options.range ? \n        that.EXP_IF + '\\\\s\\\\'+ options.range + '\\\\s' + that.EXP_IF\n      : that.EXP_IF\n    ) +'$');\n    that.EXP_SPLIT = new RegExp('^'+ that.EXP_SPLIT +'$', '');\n    \n    //如果不是input|textarea元素，则默认采用click事件\n    if(!that.isInput(options.elem[0])){\n      if(options.trigger === 'focus'){\n        options.trigger = 'click';\n      }\n    }\n    \n    //设置唯一KEY\n    if(!options.elem.attr('lay-key')){\n      options.elem.attr('lay-key', that.index);\n      options.eventElem.attr('lay-key', that.index);\n    }\n    \n    //记录重要日期\n    options.mark = lay.extend({}, (options.calendar && options.lang === 'cn') ? {\n      '0-1-1': '元旦'\n      ,'0-2-14': '情人'\n      ,'0-3-8': '妇女'\n      ,'0-3-12': '植树'\n      ,'0-4-1': '愚人'\n      ,'0-5-1': '劳动'\n      ,'0-5-4': '青年'\n      ,'0-6-1': '儿童'\n      ,'0-9-10': '教师'\n      ,'0-9-18': '国耻'\n      ,'0-10-1': '国庆'\n      ,'0-12-25': '圣诞'\n    } : {}, options.mark);\n    \n    //获取限制内日期\n    lay.each(['min', 'max'], function(i, item){\n      var ymd = [], hms = [];\n      if(typeof options[item] === 'number'){ //如果为数字\n        var day = options[item]\n        ,time = new Date().getTime()\n        ,STAMP = 86400000 //代表一天的时间戳\n        ,thisDate = new Date(\n          day ? (\n            day < STAMP ? time + day*STAMP : day //如果数字小于一天的时间戳，则数字为天数，否则为时间戳\n          ) : time\n        );\n        ymd = [thisDate.getFullYear(), thisDate.getMonth() + 1, thisDate.getDate()];\n        day < STAMP || (hms = [thisDate.getHours(), thisDate.getMinutes(), thisDate.getSeconds()]);\n      } else {\n        ymd = (options[item].match(/\\d+-\\d+-\\d+/) || [''])[0].split('-');\n        hms = (options[item].match(/\\d+:\\d+:\\d+/) || [''])[0].split(':');\n      }\n      options[item] = {\n        year: ymd[0] | 0 || new Date().getFullYear()\n        ,month: ymd[1] ? (ymd[1] | 0) - 1 : new Date().getMonth()\n        ,date: ymd[2] | 0 || new Date().getDate()\n        ,hours: hms[0] | 0\n        ,minutes: hms[1] | 0\n        ,seconds: hms[2] | 0\n      };\n    });\n    \n    that.elemID = 'layui-laydate'+ options.elem.attr('lay-key');\n    \n    if(options.show || isStatic) that.render();\n    isStatic || that.events();\n    \n    //默认赋值\n    if(options.value){\n      if(options.value.constructor === Date){\n        that.setValue(that.parse(0, that.systemDate(options.value))); \n      } else {\n        that.setValue(options.value); \n      }\n    }\n  };\n  \n  //控件主体渲染\n  Class.prototype.render = function(){\n    var that = this\n    ,options = that.config\n    ,lang = that.lang()\n    ,isStatic = options.position === 'static'\n    \n    //主面板\n    ,elem = that.elem = lay.elem('div', {\n      id: that.elemID\n      ,'class': [\n        'layui-laydate'\n        ,options.range ? ' layui-laydate-range' : ''\n        ,isStatic ? (' '+ ELEM_STATIC) : ''\n        ,options.theme && options.theme !== 'default' && !/^#/.test(options.theme) ? (' laydate-theme-' + options.theme) : ''\n      ].join('')\n    })\n    \n    //主区域\n    ,elemMain = that.elemMain = []\n    ,elemHeader = that.elemHeader = []\n    ,elemCont = that.elemCont = []\n    ,elemTable = that.table = []\n\n    //底部区域\n    ,divFooter = that.footer = lay.elem('div', {\n      'class': ELEM_FOOTER\n    });\n    \n    if(options.zIndex) elem.style.zIndex = options.zIndex;\n    \n    //单双日历区域\n    lay.each(new Array(2), function(i){\n      if(!options.range && i > 0){\n        return true;\n      }\n\n      //头部区域\n      var divHeader = lay.elem('div', {\n        'class': 'layui-laydate-header'\n      })\n      \n      //左右切换\n      ,headerChild = [function(){ //上一年\n        var elem = lay.elem('i', {\n          'class': 'layui-icon laydate-icon laydate-prev-y'\n        });\n        elem.innerHTML = '&#xe65a;';\n        return elem;\n      }(), function(){ //上一月\n        var elem = lay.elem('i', {\n          'class': 'layui-icon laydate-icon laydate-prev-m'\n        });\n        elem.innerHTML = '&#xe603;';\n        return elem;\n      }(), function(){ //年月选择\n        var elem = lay.elem('div', {\n          'class': 'laydate-set-ym'\n        }), spanY = lay.elem('span'), spanM = lay.elem('span');\n        elem.appendChild(spanY);\n        elem.appendChild(spanM);\n        return elem;\n      }(), function(){ //下一月\n        var elem = lay.elem('i', {\n          'class': 'layui-icon laydate-icon laydate-next-m'\n        });\n        elem.innerHTML = '&#xe602;';\n        return elem;\n      }(), function(){ //下一年\n        var elem = lay.elem('i', {\n          'class': 'layui-icon laydate-icon laydate-next-y'\n        });\n        elem.innerHTML = '&#xe65b;';\n        return elem;\n      }()]\n      \n      //日历内容区域\n      ,divContent = lay.elem('div', {\n        'class': 'layui-laydate-content'\n      })\n      ,table = lay.elem('table')\n      ,thead = lay.elem('thead'), theadTr = lay.elem('tr');\n      \n      //生成年月选择\n      lay.each(headerChild, function(i, item){\n        divHeader.appendChild(item);\n      });\n      \n       //生成表格\n      thead.appendChild(theadTr);\n      lay.each(new Array(6), function(i){ //表体\n        var tr = table.insertRow(0);\n        lay.each(new Array(7), function(j){\n          if(i === 0){\n            var th = lay.elem('th');\n            th.innerHTML = lang.weeks[j];\n            theadTr.appendChild(th);\n          }\n          tr.insertCell(j);\n        });\n      });\n      table.insertBefore(thead, table.children[0]); //表头\n      divContent.appendChild(table);\n      \n      elemMain[i] = lay.elem('div', {\n        'class': 'layui-laydate-main laydate-main-list-'+ i\n      });\n      \n      elemMain[i].appendChild(divHeader);\n      elemMain[i].appendChild(divContent);\n      \n      elemHeader.push(headerChild);\n      elemCont.push(divContent);\n      elemTable.push(table);\n    });\n    \n    //生成底部栏\n    lay(divFooter).html(function(){\n      var html = [], btns = [];\n      if(options.type === 'datetime'){\n        html.push('<span lay-type=\"datetime\" class=\"laydate-btns-time\">'+ lang.timeTips +'</span>');\n      }\n      lay.each(options.btns, function(i, item){\n        var title = lang.tools[item] || 'btn';\n        if(options.range && item === 'now') return;\n        if(isStatic && item === 'clear') title = options.lang === 'cn' ? '重置' : 'Reset';\n        btns.push('<span lay-type=\"'+ item +'\" class=\"laydate-btns-'+ item +'\">'+ title +'</span>');\n      });\n      html.push('<div class=\"laydate-footer-btns\">'+ btns.join('') +'</div>');\n      return html.join('');\n    }());\n    \n    //插入到主区域\n    lay.each(elemMain, function(i, main){\n      elem.appendChild(main);\n    });\n    options.showBottom && elem.appendChild(divFooter);\n    \n    //生成自定义主题\n    if(/^#/.test(options.theme)){\n      var style = lay.elem('style')\n      ,styleText = [\n        '#{{id}} .layui-laydate-header{background-color:{{theme}};}'\n        ,'#{{id}} .layui-this{background-color:{{theme}} !important;}'\n      ].join('').replace(/{{id}}/g, that.elemID).replace(/{{theme}}/g, options.theme);\n      \n      if('styleSheet' in style){\n        style.setAttribute('type', 'text/css');\n        style.styleSheet.cssText = styleText;\n      } else {\n        style.innerHTML = styleText;\n      }\n      \n      lay(elem).addClass('laydate-theme-molv');\n      elem.appendChild(style);\n    }\n    \n    //移除上一个控件\n    that.remove(Class.thisElem); \n    \n    //如果是静态定位，则插入到指定的容器中，否则，插入到body\n    isStatic ? options.elem.append(elem) : (\n      document.body.appendChild(elem)\n      ,that.position() //定位\n    );\n    \n    that.checkDate().calendar(); //初始校验\n    that.changeEvent(); //日期切换\n    \n    Class.thisElem = that.elemID;\n    \n    typeof options.ready === 'function' && options.ready(lay.extend({}, options.dateTime, {\n      month: options.dateTime.month + 1\n    }));\n  };\n  \n  //控件移除\n  Class.prototype.remove = function(prev){\n    var that = this\n    ,options = that.config\n    ,elem = lay('#'+ (prev || that.elemID));\n    if(elem[0] && !elem.hasClass(ELEM_STATIC)){\n      that.checkDate(function(){\n        elem.remove();\n      });\n    }\n    return that;\n  };\n  \n  //定位算法\n  Class.prototype.position = function(){\n    var that = this\n    ,options = that.config\n    ,elem = that.bindElem || options.elem[0]\n    ,rect = elem.getBoundingClientRect() //绑定元素的坐标\n    ,elemWidth = that.elem.offsetWidth //控件的宽度\n    ,elemHeight = that.elem.offsetHeight //控件的高度\n    \n    //滚动条高度\n    ,scrollArea = function(type){\n      type = type ? 'scrollLeft' : 'scrollTop';\n      return document.body[type] | document.documentElement[type];\n    }\n    ,winArea = function(type){\n      return document.documentElement[type ? 'clientWidth' : 'clientHeight']\n    }, margin = 5, left = rect.left, top = rect.bottom;\n    \n    //如果右侧超出边界\n    if(left + elemWidth + margin > winArea('width')){\n      left = winArea('width') - elemWidth - margin;\n    }\n    \n    //如果底部超出边界\n    if(top + elemHeight + margin > winArea()){\n      top = rect.top > elemHeight //顶部是否有足够区域显示完全\n        ? rect.top - elemHeight \n      : winArea() - elemHeight;\n      top = top - margin*2;\n    }\n    \n    if(options.position){\n      that.elem.style.position = options.position;\n    }\n    that.elem.style.left = left + (options.position === 'fixed' ? 0 : scrollArea(1)) + 'px';\n    that.elem.style.top = top + (options.position === 'fixed' ? 0 : scrollArea()) + 'px';\n  };\n  \n  //提示\n  Class.prototype.hint = function(content){\n    var that = this\n    ,options = that.config\n    ,div = lay.elem('div', {\n      'class': ELEM_HINT\n    });\n    \n    div.innerHTML = content || '';\n    lay(that.elem).find('.'+ ELEM_HINT).remove();\n    that.elem.appendChild(div);\n\n    clearTimeout(that.hinTimer);\n    that.hinTimer = setTimeout(function(){\n      lay(that.elem).find('.'+ ELEM_HINT).remove();\n    }, 3000);\n  };\n  \n  //获取递增/减后的年月\n  Class.prototype.getAsYM = function(Y, M, type){\n    type ? M-- : M++;\n    if(M < 0){\n      M = 11;\n      Y--;\n    }\n    if(M > 11){\n      M = 0;\n      Y++;\n    }\n    return [Y, M];\n  };\n  \n  //系统消息\n  Class.prototype.systemDate = function(newDate){\n    var thisDate = newDate || new Date();\n    return {\n      year: thisDate.getFullYear() //年\n      ,month: thisDate.getMonth() //月\n      ,date: thisDate.getDate() //日\n      ,hours: newDate ? newDate.getHours() : 0 //时\n      ,minutes: newDate ? newDate.getMinutes() : 0 //分\n      ,seconds: newDate ? newDate.getSeconds() : 0 //秒\n    }\n  };\n  \n  //日期校验\n  Class.prototype.checkDate = function(fn){\n    var that = this\n    ,thisDate = new Date()\n    ,options = that.config\n    ,dateTime = options.dateTime = options.dateTime || that.systemDate()\n    ,thisMaxDate, error\n    \n    ,elem = that.bindElem || options.elem[0]\n    ,valType = that.isInput(elem) ? 'val' : 'html'\n    ,value = that.isInput(elem) ? elem.value : (options.position === 'static' ? '' : elem.innerHTML)\n    \n    //校验日期有效数字\n    ,checkValid = function(dateTime){\n      if(dateTime.year > LIMIT_YEAR[1]) dateTime.year = LIMIT_YEAR[1], error = true; //不能超过20万年\n      if(dateTime.month > 11) dateTime.month = 11, error = true;\n      if(dateTime.hours > 23) dateTime.hours = 0, error = true;\n      if(dateTime.minutes > 59) dateTime.minutes = 0, dateTime.hours++, error = true;\n      if(dateTime.seconds > 59) dateTime.seconds = 0, dateTime.minutes++, error = true;\n      \n      //计算当前月的最后一天\n      thisMaxDate = laydate.getEndDate(dateTime.month + 1, dateTime.year);\n      if(dateTime.date > thisMaxDate) dateTime.date = thisMaxDate, error = true;\n    }\n    \n    //获得初始化日期值\n    ,initDate = function(dateTime, value, index){\n      var startEnd = ['startTime', 'endTime'];\n      value = (value.match(that.EXP_SPLIT) || []).slice(1);\n      index = index || 0;\n      if(options.range){\n        that[startEnd[index]] = that[startEnd[index]] || {};\n      }\n      lay.each(that.format, function(i, item){\n        var thisv = parseFloat(value[i]);\n        if(value[i].length < item.length) error = true;\n        if(/yyyy|y/.test(item)){ //年\n          if(thisv < LIMIT_YEAR[0]) thisv = LIMIT_YEAR[0], error = true; //年不能低于100年\n          dateTime.year = thisv;\n        } else if(/MM|M/.test(item)){ //月\n          if(thisv < 1) thisv = 1, error = true;\n          dateTime.month = thisv - 1;\n        } else if(/dd|d/.test(item)){ //日\n          if(thisv < 1) thisv = 1, error = true;\n          dateTime.date = thisv;\n        } else if(/HH|H/.test(item)){ //时\n          if(thisv < 1) thisv = 0, error = true;\n          dateTime.hours = thisv;\n          options.range && (that[startEnd[index]].hours = thisv);\n        } else if(/mm|m/.test(item)){ //分\n          if(thisv < 1) thisv = 0, error = true;\n          dateTime.minutes = thisv;\n          options.range && (that[startEnd[index]].minutes = thisv);\n        } else if(/ss|s/.test(item)){ //秒\n          if(thisv < 1) thisv = 0, error = true;\n          dateTime.seconds = thisv;\n          options.range && (that[startEnd[index]].seconds = thisv);\n        }\n      });\n      checkValid(dateTime)\n    };\n    \n    if(fn === 'limit') return checkValid(dateTime), that;\n    \n    value = value || options.value;\n    if(typeof value === 'string'){\n      value = value.replace(/\\s+/g, ' ').replace(/^\\s|\\s$/g, '');\n    }\n    \n    //如果点击了开始，单未选择结束就关闭，则重新选择开始\n    if(that.startState && !that.endState){\n      delete that.startState;\n      that.endState = true;\n    };\n\n    if(typeof value === 'string' && value){\n      if(that.EXP_IF.test(value)){ //校验日期格式\n        if(options.range){\n          value = value.split(' '+ options.range +' ');\n          that.startDate = that.startDate || that.systemDate();\n          that.endDate = that.endDate || that.systemDate();\n          options.dateTime = lay.extend({}, that.startDate);\n          lay.each([that.startDate, that.endDate], function(i, item){\n            initDate(item, value[i], i);\n          });\n        } else {\n          initDate(dateTime, value)\n        }\n      } else {\n        that.hint('日期格式不合法<br>必须遵循下述格式：<br>'+ (\n          options.range ? (options.format + ' '+ options.range +' ' + options.format) : options.format\n        ) + '<br>已为你重置');\n        error = true;\n      }\n    } else if(value && value.constructor === Date){ //如果值为日期对象时\n      options.dateTime = that.systemDate(value);\n    } else {\n      options.dateTime = that.systemDate();\n      delete that.startState;\n      delete that.endState;\n      delete that.startDate;\n      delete that.endDate;\n      delete that.startTime;\n      delete that.endTime;\n    }\n\n    checkValid(dateTime);\n\n    if(error && value){\n      that.setValue(\n        options.range ? (that.endDate ? that.parse() : '') : that.parse()\n      );\n    }\n    fn && fn();\n    return that;\n  };\n  \n  //公历重要日期与自定义备注\n  Class.prototype.mark = function(td, YMD){\n    var that = this\n    ,mark, options = that.config;\n    lay.each(options.mark, function(key, title){\n      var keys = key.split('-');\n      if((keys[0] == YMD[0] || keys[0] == 0) //每年的每月\n      && (keys[1] == YMD[1] || keys[1] == 0) //每月的每日\n      && keys[2] == YMD[2]){ //特定日\n        mark = title || YMD[2];\n      }\n    });\n    mark && td.html('<span class=\"laydate-day-mark\">'+ mark +'</span>');\n    \n    return that;\n  };\n  \n  //无效日期范围的标记\n  Class.prototype.limit = function(elem, date, index, time){\n    var that = this\n    ,options = that.config, timestrap = {}\n    ,dateTime = options[index > 41 ? 'endDate' : 'dateTime']\n    ,isOut, thisDateTime = lay.extend({}, dateTime, date || {});\n    lay.each({\n      now: thisDateTime\n      ,min: options.min\n      ,max: options.max\n    }, function(key, item){\n      timestrap[key] = that.newDate(lay.extend({\n        year: item.year\n        ,month: item.month\n        ,date: item.date\n      }, function(){\n        var hms = {};\n        lay.each(time, function(i, keys){\n          hms[keys] = item[keys];\n        });\n        return hms;\n      }())).getTime();  //time：是否比较时分秒\n    });\n    \n    isOut = timestrap.now < timestrap.min || timestrap.now > timestrap.max;\n    elem && elem[isOut ? 'addClass' : 'removeClass'](DISABLED);\n    return isOut;\n  };\n  \n  //日历表\n  Class.prototype.calendar = function(value){\n    var that = this\n    ,options = that.config\n    ,dateTime = value || options.dateTime\n    ,thisDate = new Date(), startWeek, prevMaxDate, thisMaxDate\n    ,lang = that.lang()\n    \n    ,isAlone = options.type !== 'date' && options.type !== 'datetime'\n    ,index = value ? 1 : 0\n    ,tds = lay(that.table[index]).find('td')\n    ,elemYM = lay(that.elemHeader[index][2]).find('span');\n    \n    if(dateTime.year < LIMIT_YEAR[0]) dateTime.year = LIMIT_YEAR[0], that.hint('最低只能支持到公元'+ LIMIT_YEAR[0] +'年');\n    if(dateTime.year > LIMIT_YEAR[1]) dateTime.year = LIMIT_YEAR[1], that.hint('最高只能支持到公元'+ LIMIT_YEAR[1] +'年');\n    \n    //记录初始值\n    if(!that.firstDate){\n      that.firstDate = lay.extend({}, dateTime);\n    }\n    \n    //计算当前月第一天的星期\n    thisDate.setFullYear(dateTime.year, dateTime.month, 1);\n    startWeek = thisDate.getDay();\n\n    prevMaxDate = laydate.getEndDate(dateTime.month, dateTime.year); //计算上个月的最后一天\n    thisMaxDate = laydate.getEndDate(dateTime.month + 1, dateTime.year); //计算当前月的最后一天\n    \n    //赋值日\n    lay.each(tds, function(index, item){\n      var YMD = [dateTime.year, dateTime.month], st = 0;\n      item = lay(item);\n      item.removeAttr('class');\n      if(index < startWeek){\n        st = prevMaxDate - startWeek + index;\n        item.addClass('laydate-day-prev');\n        YMD = that.getAsYM(dateTime.year, dateTime.month, 'sub');\n      } else if(index >= startWeek && index < thisMaxDate + startWeek){\n        st = index - startWeek;\n        if(!options.range){\n          st + 1 === dateTime.date && item.addClass(THIS);\n        }\n      } else {\n        st = index - thisMaxDate - startWeek;\n        item.addClass('laydate-day-next');\n        YMD = that.getAsYM(dateTime.year, dateTime.month);\n      }\n      YMD[1]++;\n      YMD[2] = st + 1;\n      item.attr('lay-ymd', YMD.join('-')).html(YMD[2]);\n      that.mark(item, YMD).limit(item, {\n        year: YMD[0]\n        ,month: YMD[1] - 1\n        ,date: YMD[2]\n      }, index);\n    });  \n    \n    //同步头部年月\n    lay(elemYM[0]).attr('lay-ym', dateTime.year + '-' + (dateTime.month + 1));\n    lay(elemYM[1]).attr('lay-ym', dateTime.year + '-' + (dateTime.month + 1));\n    \n    if(options.lang === 'cn'){\n      lay(elemYM[0]).attr('lay-type', 'year').html(dateTime.year + '年')\n      lay(elemYM[1]).attr('lay-type', 'month').html((dateTime.month + 1) + '月');\n    } else {\n      lay(elemYM[0]).attr('lay-type', 'month').html(lang.month[dateTime.month]);\n      lay(elemYM[1]).attr('lay-type', 'year').html(dateTime.year);\n    }\n\n    //初始默认选择器\n    if(isAlone){\n      if(options.range){\n        value ? that.endDate = (that.endDate || {\n          year: dateTime.year + (options.type === 'year' ? 1 : 0)\n          ,month: dateTime.month + (options.type === 'month' ? 0 : -1)\n        }) : (that.startDate = that.startDate || {\n          year: dateTime.year\n          ,month: dateTime.month\n        });\n        if(value){\n          that.listYM = [\n            [that.startDate.year, that.startDate.month + 1]\n            ,[that.endDate.year, that.endDate.month + 1]\n          ];  \n          that.list(options.type, 0).list(options.type, 1);\n          //同步按钮可点状态\n          options.type === 'time' ? that.setBtnStatus('时间'\n            ,lay.extend({}, that.systemDate(), that.startTime)\n            ,lay.extend({}, that.systemDate(), that.endTime)\n          ) : that.setBtnStatus(true);\n        }        \n      }\n      if(!options.range){\n        that.listYM = [[dateTime.year, dateTime.month + 1]];\n        that.list(options.type, 0);\n      }\n    }\n    \n    //赋值双日历\n    if(options.range && !value){\n      var EYM = that.getAsYM(dateTime.year, dateTime.month)\n      that.calendar(lay.extend({}, dateTime, {\n        year: EYM[0]\n        ,month: EYM[1]\n      }));\n    }\n    \n    //通过检测当前有效日期，来设定确定按钮是否可点\n    if(!options.range) that.limit(lay(that.footer).find(ELEM_CONFIRM), null, 0, ['hours', 'minutes', 'seconds']);\n    \n    //标记选择范围\n    if(options.range && value && !isAlone) that.stampRange();\n    return that;\n  };\n\n  //生成年月时分秒列表\n  Class.prototype.list = function(type, index){\n    var that = this\n    ,options = that.config\n    ,dateTime = options.dateTime\n    ,lang = that.lang()\n    ,isAlone = options.range && options.type !== 'date' && options.type !== 'datetime' //独立范围选择器\n    \n    ,ul = lay.elem('ul', {\n      'class': ELEM_LIST + ' ' + ({\n        year: 'laydate-year-list'\n        ,month: 'laydate-month-list'\n        ,time: 'laydate-time-list'\n      })[type]\n    })\n    ,elemHeader = that.elemHeader[index]\n    ,elemYM = lay(elemHeader[2]).find('span')\n    ,elemCont = that.elemCont[index || 0]\n    ,haveList = lay(elemCont).find('.'+ ELEM_LIST)[0]\n    ,isCN = options.lang === 'cn'\n    ,text = isCN ? '年' : ''\n   \n    ,listYM = that.listYM[index] || {}\n    ,hms = ['hours', 'minutes', 'seconds']\n    ,startEnd = ['startTime', 'endTime'][index];\n\n    if(listYM[0] < 1) listYM[0] = 1;\n    \n    if(type === 'year'){ //年列表\n      var yearNum, startY = yearNum = listYM[0] - 7;\n      if(startY < 1) startY = yearNum = 1;\n      lay.each(new Array(15), function(i){\n        var li = lay.elem('li', {\n          'lay-ym': yearNum\n        }), ymd = {year: yearNum};\n        yearNum == listYM[0] && lay(li).addClass(THIS);\n        li.innerHTML = yearNum + text;\n        ul.appendChild(li);\n        if(yearNum < that.firstDate.year){\n          ymd.month = options.min.month;\n          ymd.date = options.min.date;\n        } else if(yearNum >= that.firstDate.year){\n          ymd.month = options.max.month;\n          ymd.date = options.max.date;\n        }\n        that.limit(lay(li), ymd, index);\n        yearNum++;\n      });\n      lay(elemYM[isCN ? 0 : 1]).attr('lay-ym', (yearNum - 8) + '-' + listYM[1])\n      .html((startY + text) + ' - ' + (yearNum - 1 + text));\n    } else if(type === 'month'){ //月列表\n      lay.each(new Array(12), function(i){\n        var li = lay.elem('li', {\n          'lay-ym': i\n        }), ymd = {year: listYM[0], month: i};\n        i + 1 == listYM[1] && lay(li).addClass(THIS);\n        li.innerHTML = lang.month[i] + (isCN ? '月' : '');\n        ul.appendChild(li);\n        if(listYM[0] < that.firstDate.year){\n          ymd.date = options.min.date;\n        } else if(listYM[0] >= that.firstDate.year){\n          ymd.date = options.max.date;\n        }\n        that.limit(lay(li), ymd, index);\n      });\n      lay(elemYM[isCN ? 0 : 1]).attr('lay-ym', listYM[0] + '-' + listYM[1])\n      .html(listYM[0] + text);\n    } else if(type === 'time'){ //时间列表\n      //检测时分秒状态是否在有效日期时间范围内\n      var setTimeStatus = function(){\n        lay(ul).find('ol').each(function(i, ol){\n          lay(ol).find('li').each(function(ii, li){\n            that.limit(lay(li), [{\n              hours: ii\n            }, {\n              hours: that[startEnd].hours\n              ,minutes: ii\n            }, {\n              hours: that[startEnd].hours\n              ,minutes: that[startEnd].minutes\n              ,seconds: ii\n            }][i], index, [['hours'], ['hours', 'minutes'], ['hours', 'minutes', 'seconds']][i]);\n          });\n        });\n        if(!options.range) that.limit(lay(that.footer).find(ELEM_CONFIRM), that[startEnd], 0, ['hours', 'minutes', 'seconds']);\n      };\n      if(options.range){\n        if(!that[startEnd]) that[startEnd] = {\n          hours: 0\n          ,minutes: 0\n          ,seconds: 0\n        };\n      } else {\n        that[startEnd] = dateTime;\n      }\n      lay.each([24, 60, 60], function(i, item){\n        var li = lay.elem('li'), childUL = ['<p>'+ lang.time[i] +'</p><ol>'];\n        lay.each(new Array(item), function(ii){\n          childUL.push('<li'+ (that[startEnd][hms[i]] === ii ? ' class=\"'+ THIS +'\"' : '') +'>'+ lay.digit(ii, 2) +'</li>');\n        });\n        li.innerHTML = childUL.join('') + '</ol>';\n        ul.appendChild(li);\n      });\n      setTimeStatus();\n    }\n    \n    //插入容器\n    if(haveList) elemCont.removeChild(haveList);\n    elemCont.appendChild(ul);\n    \n    //年月\n    if(type === 'year' || type === 'month'){      \n      //显示切换箭头\n      lay(that.elemMain[index]).addClass('laydate-ym-show');\n      \n      //选中\n      lay(ul).find('li').on('click', function(){\n        var ym = lay(this).attr('lay-ym') | 0;\n        if(lay(this).hasClass(DISABLED)) return;\n        \n        if(index === 0){\n          dateTime[type] = ym;\n          if(isAlone) that.startDate[type] = ym;\n          that.limit(lay(that.footer).find(ELEM_CONFIRM), null, 0);\n        } else { //范围选择\n          if(isAlone){ //非date/datetime类型\n            that.endDate[type] = ym;\n          } else { //date/datetime类型\n            var YM = type === 'year' \n              ? that.getAsYM(ym, listYM[1] - 1, 'sub') \n            : that.getAsYM(listYM[0], ym, 'sub');\n            lay.extend(dateTime, {\n              year: YM[0]\n              ,month: YM[1]\n            });\n          }\n        }\n        \n        if(options.type === 'year' || options.type === 'month'){\n          lay(ul).find('.'+ THIS).removeClass(THIS);\n          lay(this).addClass(THIS);\n          \n          //如果为年月选择器，点击了年列表，则切换到月选择器\n          if(options.type === 'month' && type === 'year'){\n            that.listYM[index][0] = ym;\n            isAlone && (that[['startDate', 'endDate'][index]].year = ym);\n            that.list('month', index);\n          }\n        } else {\n          that.checkDate('limit').calendar();\n          that.closeList();\n        }\n\n        that.setBtnStatus(); //同步按钮可点状态\n        options.range || that.done(null, 'change');\n        lay(that.footer).find(ELEM_TIME_BTN).removeClass(DISABLED);\n      });\n    } else {\n      var span = lay.elem('span', {\n        'class': ELEM_TIME_TEXT\n      }), scroll = function(){ //滚动条定位\n        lay(ul).find('ol').each(function(i){\n          var ol = this\n          ,li = lay(ol).find('li')\n          ol.scrollTop = 30*(that[startEnd][hms[i]] - 2);\n          if(ol.scrollTop <= 0){\n            li.each(function(ii, item){\n              if(!lay(this).hasClass(DISABLED)){\n                ol.scrollTop = 30*(ii - 2);\n                return true;\n              }\n            });\n          }\n        });\n      }, haveSpan = lay(elemHeader[2]).find('.'+ ELEM_TIME_TEXT);\n      scroll()\n      span.innerHTML = options.range ? [lang.startTime,lang.endTime][index] : lang.timeTips\n      lay(that.elemMain[index]).addClass('laydate-time-show');\n      if(haveSpan[0]) haveSpan.remove();\n      elemHeader[2].appendChild(span);\n\n      lay(ul).find('ol').each(function(i){\n        var ol = this;\n        //选择时分秒\n        lay(ol).find('li').on('click', function(){\n          var value = this.innerHTML | 0;\n          if(lay(this).hasClass(DISABLED)) return;\n          if(options.range){\n            that[startEnd][hms[i]]  = value;\n          } else {\n            dateTime[hms[i]] = value;\n          }\n          lay(ol).find('.'+ THIS).removeClass(THIS);\n          lay(this).addClass(THIS);\n\n          setTimeStatus();\n          scroll();\n          (that.endDate || options.type === 'time') && that.done(null, 'change');\n          \n          //同步按钮可点状态\n          that.setBtnStatus();\n        });\n      });\n    }\n    \n    return that;\n  };\n  \n  //记录列表切换后的年月\n  Class.prototype.listYM = [];\n  \n  //关闭列表\n  Class.prototype.closeList = function(){\n    var that = this\n    ,options = that.config;\n    \n    lay.each(that.elemCont, function(index, item){\n      lay(this).find('.'+ ELEM_LIST).remove();\n      lay(that.elemMain[index]).removeClass('laydate-ym-show laydate-time-show');\n    });\n    lay(that.elem).find('.'+ ELEM_TIME_TEXT).remove();\n  };\n  \n  //检测结束日期是否超出开始日期\n  Class.prototype.setBtnStatus = function(tips, start, end){\n    var that = this\n    ,options = that.config\n    ,isOut, elemBtn = lay(that.footer).find(ELEM_CONFIRM)\n    ,isAlone = options.range && options.type !== 'date' && options.type !== 'time';\n    if(isAlone){\n      start = start || that.startDate;\n      end = end || that.endDate;\n      isOut = that.newDate(start).getTime() > that.newDate(end).getTime();\n      \n      //如果不在有效日期内，直接禁用按钮，否则比较开始和结束日期\n      (that.limit(null, start) || that.limit(null, end)) \n        ? elemBtn.addClass(DISABLED)\n      : elemBtn[isOut ? 'addClass' : 'removeClass'](DISABLED);\n      \n      //是否异常提示\n      if(tips && isOut) that.hint(\n        typeof tips === 'string' ? TIPS_OUT.replace(/日期/g, tips) : TIPS_OUT\n      );\n    }\n  };\n  \n  //转义为规定格式的日期字符\n  Class.prototype.parse = function(state, date){\n    var that = this\n    ,options = that.config\n    ,dateTime = date || (state \n      ? lay.extend({}, that.endDate, that.endTime)\n    : (options.range ? lay.extend({}, that.startDate, that.startTime) : options.dateTime))\n    ,format = that.format.concat();\n\n    //转义为规定格式\n    lay.each(format, function(i, item){\n      if(/yyyy|y/.test(item)){ //年\n        format[i] = lay.digit(dateTime.year, item.length);\n      } else if(/MM|M/.test(item)){ //月\n        format[i] = lay.digit(dateTime.month + 1, item.length);\n      } else if(/dd|d/.test(item)){ //日\n        format[i] = lay.digit(dateTime.date, item.length);\n      } else if(/HH|H/.test(item)){ //时\n        format[i] = lay.digit(dateTime.hours, item.length);\n      } else if(/mm|m/.test(item)){ //分\n        format[i] = lay.digit(dateTime.minutes, item.length);\n      } else if(/ss|s/.test(item)){ //秒\n        format[i] = lay.digit(dateTime.seconds, item.length);\n      }\n    });\n    \n    //返回日期范围字符\n    if(options.range && !state){\n      return format.join('') + ' '+ options.range +' ' + that.parse(1);\n    }\n    \n    return format.join('');\n  };\n  \n  //创建指定日期时间对象\n  Class.prototype.newDate = function(dateTime){\n    return new Date(\n      dateTime.year || 1\n      ,dateTime.month || 0\n      ,dateTime.date || 1\n      ,dateTime.hours || 0\n      ,dateTime.minutes || 0\n      ,dateTime.seconds || 0\n    );\n  };\n  \n  //赋值\n  Class.prototype.setValue = function(value){\n    var that = this\n    ,options = that.config\n    ,elem = that.bindElem || options.elem[0]\n    ,valType = that.isInput(elem) ? 'val' : 'html'\n    \n    options.position === 'static' || lay(elem)[valType](value || '');\n    return this;\n  };\n  \n  //标记范围内的日期\n  Class.prototype.stampRange = function(){\n    var that = this\n    ,options = that.config\n    ,startTime, endTime\n    ,tds = lay(that.elem).find('td');\n    \n    if(options.range && !that.endDate) lay(that.footer).find(ELEM_CONFIRM).addClass(DISABLED);\n    if(!that.endDate) return;\n\n    startTime = that.newDate({\n      year: that.startDate.year\n      ,month: that.startDate.month\n      ,date: that.startDate.date\n    }).getTime();\n    \n    endTime = that.newDate({\n      year: that.endDate.year\n      ,month: that.endDate.month\n      ,date: that.endDate.date\n    }).getTime();\n    \n    if(startTime > endTime) return that.hint(TIPS_OUT);\n    \n    lay.each(tds, function(i, item){\n      var ymd = lay(item).attr('lay-ymd').split('-')\n      ,thisTime = that.newDate({\n        year: ymd[0]\n        ,month: ymd[1] - 1\n        ,date: ymd[2]\n      }).getTime();\n      lay(item).removeClass(ELEM_SELECTED + ' ' + THIS);\n      if(thisTime === startTime || thisTime === endTime){\n        lay(item).addClass(\n          lay(item).hasClass(ELEM_PREV) || lay(item).hasClass(ELEM_NEXT)\n            ? ELEM_SELECTED\n          : THIS\n        );\n      }\n      if(thisTime > startTime && thisTime < endTime){\n        lay(item).addClass(ELEM_SELECTED);\n      }\n    });\n  };\n  \n  //执行done/change回调\n  Class.prototype.done = function(param, type){\n    var that = this\n    ,options = that.config\n    ,start = lay.extend({}, that.startDate ? lay.extend(that.startDate, that.startTime) : options.dateTime)\n    ,end = lay.extend({}, lay.extend(that.endDate, that.endTime))\n    \n    lay.each([start, end], function(i, item){\n      if(!('month' in item)) return;\n      lay.extend(item, {\n        month: item.month + 1\n      });\n    });\n    \n    param = param || [that.parse(), start, end];\n    typeof options[type || 'done'] === 'function' && options[type || 'done'].apply(options, param);\n    \n    return that;\n  };\n  \n  //选择日期\n  Class.prototype.choose = function(td){\n    var that = this\n    ,options = that.config\n    ,dateTime = options.dateTime\n\n    ,tds = lay(that.elem).find('td')\n    ,YMD = td.attr('lay-ymd').split('-')\n    \n    ,setDateTime = function(one){\n      var thisDate = new Date();\n      \n      //同步dateTime\n      one && lay.extend(dateTime, YMD);\n      \n      //记录开始日期\n      if(options.range){\n        that.startDate ? lay.extend(that.startDate, YMD) : (\n          that.startDate = lay.extend({}, YMD, that.startTime)\n        );\n        that.startYMD = YMD;\n      }\n    };\n    \n    YMD = {\n      year: YMD[0] | 0\n      ,month: (YMD[1] | 0) - 1\n      ,date: YMD[2] | 0\n    };\n    \n    if(td.hasClass(DISABLED)) return;\n\n    //范围选择\n    if(options.range){\n      \n      lay.each(['startTime', 'endTime'], function(i, item){\n        that[item] = that[item] || {\n          hours: 0\n          ,minutes: 0\n          ,seconds: 0\n        };\n      });\n      \n      if(that.endState){ //重新选择\n        setDateTime();\n        delete that.endState;\n        delete that.endDate;\n        that.startState = true;\n        tds.removeClass(THIS + ' ' + ELEM_SELECTED);\n        td.addClass(THIS);\n      } else if(that.startState){ //选中截止\n        td.addClass(THIS);\n        \n        that.endDate ? lay.extend(that.endDate, YMD) : (\n          that.endDate = lay.extend({}, YMD, that.endTime)\n        );\n        \n        //判断是否顺时或逆时选择\n        if(that.newDate(YMD).getTime() < that.newDate(that.startYMD).getTime()){\n          var startDate = lay.extend({}, that.endDate, {\n            hours: that.startDate.hours\n            ,minutes: that.startDate.minutes\n            ,seconds: that.startDate.seconds\n          });\n          lay.extend(that.endDate, that.startDate, {\n            hours: that.endDate.hours\n            ,minutes: that.endDate.minutes\n            ,seconds: that.endDate.seconds\n          });\n          that.startDate = startDate;\n        }\n        \n        options.showBottom || that.done();\n        that.stampRange(); //标记范围内的日期\n        that.endState = true;\n        that.done(null, 'change');\n      } else { //选中开始\n        td.addClass(THIS);\n        setDateTime(); \n        that.startState = true;\n      }\n      lay(that.footer).find(ELEM_CONFIRM)[that.endDate ? 'removeClass' : 'addClass'](DISABLED);\n    } else if(options.position === 'static'){ //直接嵌套的选中\n      setDateTime(true);\n      that.calendar().done().done(null, 'change');\n    } else if(options.type === 'date'){\n      setDateTime(true);\n      that.setValue(that.parse()).remove().done();\n    } else if(options.type === 'datetime'){\n      setDateTime(true);\n      that.calendar().done(null, 'change');\n    }\n  };\n  \n  //底部按钮\n  Class.prototype.tool = function(btn, type){\n    var that = this\n    ,options = that.config\n    ,dateTime = options.dateTime\n    ,isStatic = options.position === 'static'\n    ,active = {\n      //选择时间\n      datetime: function(){\n        if(lay(btn).hasClass(DISABLED)) return;\n        that.list('time', 0);\n        options.range && that.list('time', 1);\n        lay(btn).attr('lay-type', 'date').html(that.lang().dateTips);\n      }\n      \n      //选择日期\n      ,date: function(){\n        that.closeList();\n        lay(btn).attr('lay-type', 'datetime').html(that.lang().timeTips);\n      }\n      \n      //清空、重置\n      ,clear: function(){\n        that.setValue('').remove();\n        isStatic && (\n          lay.extend(dateTime, that.firstDate)\n          ,that.calendar()\n        )\n        options.range && (\n          delete that.startState\n          ,delete that.endState\n          ,delete that.endDate\n          ,delete that.startTime\n          ,delete that.endTime\n        );\n        that.done(['', {}, {}]);\n      }\n      \n      //现在\n      ,now: function(){\n        var thisDate = new Date();\n        lay.extend(dateTime, that.systemDate(), {\n          hours: thisDate.getHours()\n          ,minutes: thisDate.getMinutes()\n          ,seconds: thisDate.getSeconds()\n        });\n        that.setValue(that.parse()).remove();\n        isStatic && that.calendar();\n        that.done();\n      }\n      \n      //确定\n      ,confirm: function(){\n        if(options.range){\n          if(!that.endDate) return that.hint('请先选择日期范围');\n          if(lay(btn).hasClass(DISABLED)) return that.hint(\n            options.type === 'time' ? TIPS_OUT.replace(/日期/g, '时间') : TIPS_OUT\n          );\n        } else {\n          if(lay(btn).hasClass(DISABLED)) return that.hint('不在有效日期或时间范围内');\n        }\n        that.done();\n        that.setValue(that.parse()).remove()\n      }\n    };\n    active[type] && active[type]();\n  };\n  \n  //统一切换处理\n  Class.prototype.change = function(index){\n    var that = this\n    ,options = that.config\n    ,dateTime = options.dateTime\n    ,isAlone = options.range && (options.type === 'year' || options.type === 'month')\n    \n    ,elemCont = that.elemCont[index || 0]\n    ,listYM = that.listYM[index]\n    ,addSubYeay = function(type){\n      var startEnd = ['startDate', 'endDate'][index]\n      ,isYear = lay(elemCont).find('.laydate-year-list')[0]\n      ,isMonth = lay(elemCont).find('.laydate-month-list')[0];\n      \n      //切换年列表\n      if(isYear){\n        listYM[0] = type ? listYM[0] - 15 : listYM[0] + 15;\n        that.list('year', index);\n      }\n      \n      if(isMonth){ //切换月面板中的年\n        type ? listYM[0]-- : listYM[0]++;\n        that.list('month', index);\n      }\n      \n      if(isYear || isMonth){\n        lay.extend(dateTime, {\n          year: listYM[0]\n        });\n        if(isAlone) that[startEnd].year = listYM[0];\n        options.range || that.done(null, 'change');\n        that.setBtnStatus();      \n        options.range || that.limit(lay(that.footer).find(ELEM_CONFIRM), {\n          year: listYM[0]\n        });\n      }\n      return isYear || isMonth;\n    };\n    \n    return {\n      prevYear: function(){\n        if(addSubYeay('sub')) return;\n        dateTime.year--;\n        that.checkDate('limit').calendar();\n        options.range || that.done(null, 'change');\n      }\n      ,prevMonth: function(){\n        var YM = that.getAsYM(dateTime.year, dateTime.month, 'sub');\n        lay.extend(dateTime, {\n          year: YM[0]\n          ,month: YM[1]\n        });\n        that.checkDate('limit').calendar();\n        options.range || that.done(null, 'change');\n      }\n      ,nextMonth: function(){\n        var YM = that.getAsYM(dateTime.year, dateTime.month);\n        lay.extend(dateTime, {\n          year: YM[0]\n          ,month: YM[1]\n        });\n        that.checkDate('limit').calendar();\n        options.range || that.done(null, 'change');\n      }\n      ,nextYear: function(){\n        if(addSubYeay()) return;\n        dateTime.year++\n        that.checkDate('limit').calendar();\n        options.range || that.done(null, 'change');\n      }\n    };\n  };\n  \n  //日期切换事件\n  Class.prototype.changeEvent = function(){\n    var that = this\n    ,options = that.config;\n\n    //日期选择事件\n    lay(that.elem).on('click', function(e){\n      lay.stope(e);\n    });\n    \n    //年月切换\n    lay.each(that.elemHeader, function(i, header){\n      //上一年\n      lay(header[0]).on('click', function(e){\n        that.change(i).prevYear();\n      });\n      \n      //上一月\n      lay(header[1]).on('click', function(e){\n        that.change(i).prevMonth();\n      });\n      \n      //选择年月\n      lay(header[2]).find('span').on('click', function(e){\n        var othis = lay(this)\n        ,layYM = othis.attr('lay-ym')\n        ,layType = othis.attr('lay-type');\n        \n        if(!layYM) return;\n        \n        layYM = layYM.split('-');\n\n        that.listYM[i] = [layYM[0] | 0, layYM[1] | 0];\n        that.list(layType, i);\n        lay(that.footer).find(ELEM_TIME_BTN).addClass(DISABLED);\n      });\n\n      //下一月\n      lay(header[3]).on('click', function(e){\n        that.change(i).nextMonth();\n      });\n      \n      //下一年\n      lay(header[4]).on('click', function(e){\n        that.change(i).nextYear();\n      });\n    });\n    \n    //点击日期\n    lay.each(that.table, function(i, table){\n      var tds = lay(table).find('td');\n      tds.on('click', function(){\n        that.choose(lay(this));\n      });\n    });\n    \n    //点击底部按钮\n    lay(that.footer).find('span').on('click', function(){\n      var type = lay(this).attr('lay-type');\n      that.tool(this, type);\n    });\n  };\n  \n  //是否输入框\n  Class.prototype.isInput = function(elem){\n    return /input|textarea/.test(elem.tagName.toLocaleLowerCase());\n  };\n\n  //绑定的元素事件处理\n  Class.prototype.events = function(){\n    var that = this\n    ,options = that.config\n\n    //绑定呼出控件事件\n    ,showEvent = function(elem, bind){\n      elem.on(options.trigger, function(){\n        bind && (that.bindElem = this);\n        that.render();\n      });\n    };\n    \n    if(!options.elem[0] || options.elem[0].eventHandler) return;\n    \n    showEvent(options.elem, 'bind');\n    showEvent(options.eventElem);\n    \n    //绑定关闭控件事件\n    lay(document).on('click', function(e){\n      if(e.target === options.elem[0] \n      || e.target === options.eventElem[0]\n      || e.target === lay(options.closeStop)[0]){\n        return;\n      }\n      that.remove();\n    }).on('keydown', function(e){\n      if(e.keyCode === 13){\n        if(lay('#'+ that.elemID)[0] && that.elemID === Class.thisElem){\n          e.preventDefault();\n          lay(that.footer).find(ELEM_CONFIRM)[0].click();\n        }\n      }\n    });\n    \n    //自适应定位\n    lay(window).on('resize', function(){\n      if(!that.elem || !lay(ELEM)[0]){\n        return false;\n      }\n      that.position();\n    });\n    \n    options.elem[0].eventHandler = true;\n  };\n\n  \n  //核心接口\n  laydate.render = function(options){\n    var inst = new Class(options);\n    return thisDate.call(inst);\n  };\n  \n  //得到某月的最后一天\n  laydate.getEndDate = function(month, year){\n    var thisDate = new Date();\n    //设置日期为下个月的第一天\n    thisDate.setFullYear(\n      year || thisDate.getFullYear()\n      ,month || (thisDate.getMonth() + 1)\n    ,1);\n    //减去一天，得到当前月最后一天\n    return new Date(thisDate.getTime() - 1000*60*60*24).getDate();\n  };\n  \n  //暴露lay\n  window.lay = window.lay || lay;\n  \n  //加载方式\n  isLayui ? (\n    laydate.ready()\n    ,layui.define(function(exports){ //layui加载\n      laydate.path = layui.cache.dir;\n      exports(MOD_NAME, laydate);\n    })\n  ) : (\n    (typeof define === 'function' && define.amd) ? define(function(){ //requirejs加载\n      return laydate;\n    }) : function(){ //普通script标签加载\n      laydate.ready();\n      window.laydate = laydate\n    }()\n  );\n\n}();"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/layedit.js",
    "content": "/**\n\n @Name：layui.layedit 富文本编辑器\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define(['layer', 'form'], function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,layer = layui.layer\n  ,form = layui.form\n  ,hint = layui.hint()\n  ,device = layui.device()\n  \n  ,MOD_NAME = 'layedit', THIS = 'layui-this', SHOW = 'layui-show', ABLED = 'layui-disabled'\n  \n  ,Edit = function(){\n    var that = this;\n    that.index = 0;\n    \n    //全局配置\n    that.config = {\n      //默认工具bar\n      tool: [\n        'strong', 'italic', 'underline', 'del'\n        ,'|'\n        ,'left', 'center', 'right'\n        ,'|'\n        ,'link', 'unlink', 'face', 'image'\n      ]\n      ,hideTool: []\n      ,height: 280 //默认高\n    };\n  };\n  \n  //全局设置\n  Edit.prototype.set = function(options){\n    var that = this;\n    $.extend(true, that.config, options);\n    return that;\n  };\n  \n  //事件监听\n  Edit.prototype.on = function(events, callback){\n    return layui.onevent(MOD_NAME, events, callback);\n  };\n  \n  //建立编辑器\n  Edit.prototype.build = function(id, settings){\n    settings = settings || {};\n    \n    var that = this\n    ,config = that.config\n    ,ELEM = 'layui-layedit', textArea = $('#'+id)\n    ,name =  'LAY_layedit_'+ (++that.index)\n    ,haveBuild = textArea.next('.'+ELEM)\n    \n    ,set = $.extend({}, config, settings)\n    \n    ,tool = function(){\n      var node = [], hideTools = {};\n      layui.each(set.hideTool, function(_, item){\n        hideTools[item] = true;\n      });\n      layui.each(set.tool, function(_, item){\n        if(tools[item] && !hideTools[item]){\n          node.push(tools[item]);\n        }\n      });\n      return node.join('');\n    }()\n \n    \n    ,editor = $(['<div class=\"'+ ELEM +'\">'\n      ,'<div class=\"layui-unselect layui-layedit-tool\">'+ tool +'</div>'\n      ,'<div class=\"layui-layedit-iframe\">'\n        ,'<iframe id=\"'+ name +'\" name=\"'+ name +'\" textarea=\"'+ id +'\" frameborder=\"0\"></iframe>'\n      ,'</div>'\n    ,'</div>'].join(''))\n    \n    //编辑器不兼容ie8以下\n    if(device.ie && device.ie < 8){\n      return textArea.removeClass('layui-hide').addClass(SHOW);\n    }\n\n    haveBuild[0] && (haveBuild.remove());\n\n    setIframe.call(that, editor, textArea[0], set)\n    textArea.addClass('layui-hide').after(editor);\n\n    return that.index;\n  };\n  \n  //获得编辑器中内容\n  Edit.prototype.getContent = function(index){\n    var iframeWin = getWin(index);\n    if(!iframeWin[0]) return;\n    return toLower(iframeWin[0].document.body.innerHTML);\n  };\n  \n  //获得编辑器中纯文本内容\n  Edit.prototype.getText = function(index){\n    var iframeWin = getWin(index);\n    if(!iframeWin[0]) return;\n    return $(iframeWin[0].document.body).text();\n  };\n  /**\n   * 设置编辑器内容\n   * @param {[type]} index   编辑器索引\n   * @param {[type]} content 要设置的内容\n   * @param {[type]} flag    是否追加模式\n   */\n  Edit.prototype.setContent = function(index, content, flag){\n    var iframeWin = getWin(index);\n    if(!iframeWin[0]) return;\n    if(flag){\n      $(iframeWin[0].document.body).append(content)\n    }else{\n      $(iframeWin[0].document.body).html(content)\n    };\n    layedit.sync(index)\n  };\n  //将编辑器内容同步到textarea（一般用于异步提交时）\n  Edit.prototype.sync = function(index){\n    var iframeWin = getWin(index);\n    if(!iframeWin[0]) return;\n    var textarea = $('#'+iframeWin[1].attr('textarea'));\n    textarea.val(toLower(iframeWin[0].document.body.innerHTML));\n  };\n  \n  //获取编辑器选中内容\n  Edit.prototype.getSelection = function(index){\n    var iframeWin = getWin(index);\n    if(!iframeWin[0]) return;\n    var range = Range(iframeWin[0].document);\n    return document.selection ? range.text : range.toString();\n  };\n\n  //iframe初始化\n  var setIframe = function(editor, textArea, set){\n    var that = this, iframe = editor.find('iframe');\n\n    iframe.css({\n      height: set.height\n    }).on('load', function(){\n      var conts = iframe.contents()\n      ,iframeWin = iframe.prop('contentWindow')\n      ,head = conts.find('head')\n      ,style = $(['<style>'\n        ,'*{margin: 0; padding: 0;}'\n        ,'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;}'\n        ,'a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}'\n        ,'p{margin-bottom: 10px;}'\n        ,'img{display: inline-block; border: none; vertical-align: middle;}'\n        ,'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;}'\n      ,'</style>'].join(''))\n      ,body = conts.find('body');\n      \n      head.append(style);\n      body.attr('contenteditable', 'true').css({\n        'min-height': set.height\n      }).html(textArea.value||'');\n\n      hotkey.apply(that, [iframeWin, iframe, textArea, set]); //快捷键处理\n      toolActive.call(that, iframeWin, editor, set); //触发工具\n\n    });\n  }\n  \n  //获得iframe窗口对象\n  ,getWin = function(index){\n    var iframe = $('#LAY_layedit_'+ index)\n    ,iframeWin = iframe.prop('contentWindow');\n    return [iframeWin, iframe];\n  }\n  \n  //IE8下将标签处理成小写\n  ,toLower = function(html){\n    if(device.ie == 8){\n      html = html.replace(/<.+>/g, function(str){\n        return str.toLowerCase();\n      });\n    }\n    return html;\n  }\n  \n  //快捷键处理\n  ,hotkey = function(iframeWin, iframe, textArea, set){\n    var iframeDOM = iframeWin.document, body = $(iframeDOM.body);\n    body.on('keydown', function(e){\n      var keycode = e.keyCode;\n      //处理回车\n      if(keycode === 13){\n        var range = Range(iframeDOM);\n        var container = getContainer(range)\n        ,parentNode = container.parentNode;\n        \n        if(parentNode.tagName.toLowerCase() === 'pre'){\n          if(e.shiftKey) return\n          layer.msg('请暂时用shift+enter');\n          return false;\n        }\n        iframeDOM.execCommand('formatBlock', false, '<p>');\n      }\n    });\n    \n    //给textarea同步内容\n    $(textArea).parents('form').on('submit', function(){\n      var html = body.html();\n      //IE8下将标签处理成小写\n      if(device.ie == 8){\n        html = html.replace(/<.+>/g, function(str){\n          return str.toLowerCase();\n        });\n      }\n      textArea.value = html;\n    });\n    \n    //处理粘贴\n    body.on('paste', function(e){\n      iframeDOM.execCommand('formatBlock', false, '<p>');\n      setTimeout(function(){\n        filter.call(iframeWin, body);\n        textArea.value = body.html();\n      }, 100); \n    });\n  }\n  \n  //标签过滤\n  ,filter = function(body){\n    var iframeWin = this\n    ,iframeDOM = iframeWin.document;\n    \n    //清除影响版面的css属性\n    body.find('*[style]').each(function(){\n      var textAlign = this.style.textAlign;\n      this.removeAttribute('style');\n      $(this).css({\n        'text-align': textAlign || ''\n      })\n    });\n    \n    //修饰表格\n    body.find('table').addClass('layui-table');\n    \n    //移除不安全的标签\n    body.find('script,link').remove();\n  }\n  \n  //Range对象兼容性处理\n  ,Range = function(iframeDOM){\n    return iframeDOM.selection \n      ? iframeDOM.selection.createRange()\n    : iframeDOM.getSelection().getRangeAt(0);\n  }\n  \n  //当前Range对象的endContainer兼容性处理\n  ,getContainer = function(range){\n    return range.endContainer || range.parentElement().childNodes[0]\n  }\n  \n  //在选区插入内联元素\n  ,insertInline = function(tagName, attr, range){\n    var iframeDOM = this.document\n    ,elem = document.createElement(tagName)\n    for(var key in attr){\n      elem.setAttribute(key, attr[key]);\n    }\n    elem.removeAttribute('text');\n\n    if(iframeDOM.selection){ //IE\n      var text = range.text || attr.text;\n      if(tagName === 'a' && !text) return;\n      if(text){\n        elem.innerHTML = text;\n      }\n      range.pasteHTML($(elem).prop('outerHTML')); \n      range.select();\n    } else { //非IE\n      var text = range.toString() || attr.text;\n      if(tagName === 'a' && !text) return;\n      if(text){\n        elem.innerHTML = text;\n      }\n      range.deleteContents();\n      range.insertNode(elem);\n    }\n  }\n  \n  //工具选中\n  ,toolCheck = function(tools, othis){\n    var iframeDOM = this.document\n    ,CHECK = 'layedit-tool-active'\n    ,container = getContainer(Range(iframeDOM))\n    ,item = function(type){\n      return tools.find('.layedit-tool-'+type)\n    }\n\n    if(othis){\n      othis[othis.hasClass(CHECK) ? 'removeClass' : 'addClass'](CHECK);\n    }\n    \n    tools.find('>i').removeClass(CHECK);\n    item('unlink').addClass(ABLED);\n\n    $(container).parents().each(function(){\n      var tagName = this.tagName.toLowerCase()\n      ,textAlign = this.style.textAlign;\n\n      //文字\n      if(tagName === 'b' || tagName === 'strong'){\n        item('b').addClass(CHECK)\n      }\n      if(tagName === 'i' || tagName === 'em'){\n        item('i').addClass(CHECK)\n      }\n      if(tagName === 'u'){\n        item('u').addClass(CHECK)\n      }\n      if(tagName === 'strike'){\n        item('d').addClass(CHECK)\n      }\n      \n      //对齐\n      if(tagName === 'p'){\n        if(textAlign === 'center'){\n          item('center').addClass(CHECK);\n        } else if(textAlign === 'right'){\n          item('right').addClass(CHECK);\n        } else {\n          item('left').addClass(CHECK);\n        }\n      }\n      \n      //超链接\n      if(tagName === 'a'){\n        item('link').addClass(CHECK);\n        item('unlink').removeClass(ABLED);\n      }\n    });\n  }\n\n  //触发工具\n  ,toolActive = function(iframeWin, editor, set){\n    var iframeDOM = iframeWin.document\n    ,body = $(iframeDOM.body)\n    ,toolEvent = {\n      //超链接\n      link: function(range){\n        var container = getContainer(range)\n        ,parentNode = $(container).parent();\n        \n        link.call(body, {\n          href: parentNode.attr('href')\n          ,target: parentNode.attr('target')\n        }, function(field){\n          var parent = parentNode[0];\n          if(parent.tagName === 'A'){\n            parent.href = field.url;\n          } else {\n            insertInline.call(iframeWin, 'a', {\n              target: field.target\n              ,href: field.url\n              ,text: field.url\n            }, range);\n          }\n        });\n      }\n      //清除超链接\n      ,unlink: function(range){\n        iframeDOM.execCommand('unlink');\n      }\n      //表情\n      ,face: function(range){\n        face.call(this, function(img){\n          insertInline.call(iframeWin, 'img', {\n            src: img.src\n            ,alt: img.alt\n          }, range);\n        });\n      }\n      //图片\n      ,image: function(range){\n        var that = this;\n        layui.use('upload', function(upload){\n          var uploadImage = set.uploadImage || {};\n          upload.render({\n            url: uploadImage.url\n            ,method: uploadImage.type\n            ,elem: $(that).find('input')[0]\n            ,done: function(res){\n              if(res.code == 0){\n                res.data = res.data || {};\n                insertInline.call(iframeWin, 'img', {\n                  src: res.data.src\n                  ,alt: res.data.title\n                }, range);\n              } else {\n                layer.msg(res.msg||'上传失败');\n              }\n            }\n          });\n        });\n      }\n      //插入代码\n      ,code: function(range){\n        code.call(body, function(pre){\n          insertInline.call(iframeWin, 'pre', {\n            text: pre.code\n            ,'lay-lang': pre.lang\n          }, range);\n        });\n      }\n      //帮助\n      ,help: function(){\n        layer.open({\n          type: 2\n          ,title: '帮助'\n          ,area: ['600px', '380px']\n          ,shadeClose: true\n          ,shade: 0.1\n          ,skin: 'layui-layer-msg'\n          ,content: ['http://www.layui.com/about/layedit/help.html', 'no']\n        });\n      }\n    }\n    ,tools = editor.find('.layui-layedit-tool')\n    \n    ,click = function(){\n      var othis = $(this)\n      ,events = othis.attr('layedit-event')\n      ,command = othis.attr('lay-command');\n      \n      if(othis.hasClass(ABLED)) return;\n\n      body.focus();\n      \n      var range = Range(iframeDOM)\n      ,container = range.commonAncestorContainer\n      \n      if(command){\n        iframeDOM.execCommand(command);\n        if(/justifyLeft|justifyCenter|justifyRight/.test(command)){\n          iframeDOM.execCommand('formatBlock', false, '<p>');\n        }\n        setTimeout(function(){\n          body.focus();\n        }, 10);\n      } else {\n        toolEvent[events] && toolEvent[events].call(this, range);\n      }\n      toolCheck.call(iframeWin, tools, othis);\n    }\n    \n    ,isClick = /image/\n\n    tools.find('>i').on('mousedown', function(){\n      var othis = $(this)\n      ,events = othis.attr('layedit-event');\n      if(isClick.test(events)) return;\n      click.call(this)\n    }).on('click', function(){\n      var othis = $(this)\n      ,events = othis.attr('layedit-event');\n      if(!isClick.test(events)) return;\n      click.call(this)\n    });\n    \n    //触发内容区域\n    body.on('click', function(){\n      toolCheck.call(iframeWin, tools);\n      layer.close(face.index);\n    });\n  }\n  \n  //超链接面板\n  ,link = function(options, callback){\n    var body = this, index = layer.open({\n      type: 1\n      ,id: 'LAY_layedit_link'\n      ,area: '350px'\n      ,shade: 0.05\n      ,shadeClose: true\n      ,moveType: 1\n      ,title: '超链接'\n      ,skin: 'layui-layer-msg'\n      ,content: ['<ul class=\"layui-form\" style=\"margin: 15px;\">'\n        ,'<li class=\"layui-form-item\">'\n          ,'<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>'\n          ,'<div class=\"layui-input-block\" style=\"margin-left: 90px\">'\n            ,'<input name=\"url\" lay-verify=\"url\" value=\"'+ (options.href||'') +'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">'\n            ,'</div>'\n        ,'</li>'\n        ,'<li class=\"layui-form-item\">'\n          ,'<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>'\n          ,'<div class=\"layui-input-block\" style=\"margin-left: 90px\">'\n            ,'<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'\n            + ((options.target==='_self' || !options.target) ? 'checked' : '') +'>'\n            ,'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '\n            + (options.target==='_blank' ? 'checked' : '') +'>'\n          ,'</div>'\n        ,'</li>'\n        ,'<li class=\"layui-form-item\" style=\"text-align: center;\">'\n          ,'<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>'\n          ,'<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>'\n        ,'</li>'\n      ,'</ul>'].join('')\n      ,success: function(layero, index){\n        var eventFilter = 'submit(layedit-link-yes)';\n        form.render('radio');  \n        layero.find('.layui-btn-primary').on('click', function(){\n          layer.close(index);\n          body.focus();\n        });\n        form.on(eventFilter, function(data){\n          layer.close(link.index);\n          callback && callback(data.field);\n        });\n      }\n    });\n    link.index = index;\n  }\n  \n  //表情面板\n  ,face = function(callback){\n    //表情库\n    var faces = function(){\n      var alt = [\"[微笑]\", \"[嘻嘻]\", \"[哈哈]\", \"[可爱]\", \"[可怜]\", \"[挖鼻]\", \"[吃惊]\", \"[害羞]\", \"[挤眼]\", \"[闭嘴]\", \"[鄙视]\", \"[爱你]\", \"[泪]\", \"[偷笑]\", \"[亲亲]\", \"[生病]\", \"[太开心]\", \"[白眼]\", \"[右哼哼]\", \"[左哼哼]\", \"[嘘]\", \"[衰]\", \"[委屈]\", \"[吐]\", \"[哈欠]\", \"[抱抱]\", \"[怒]\", \"[疑问]\", \"[馋嘴]\", \"[拜拜]\", \"[思考]\", \"[汗]\", \"[困]\", \"[睡]\", \"[钱]\", \"[失望]\", \"[酷]\", \"[色]\", \"[哼]\", \"[鼓掌]\", \"[晕]\", \"[悲伤]\", \"[抓狂]\", \"[黑线]\", \"[阴险]\", \"[怒骂]\", \"[互粉]\", \"[心]\", \"[伤心]\", \"[猪头]\", \"[熊猫]\", \"[兔子]\", \"[ok]\", \"[耶]\", \"[good]\", \"[NO]\", \"[赞]\", \"[来]\", \"[弱]\", \"[草泥马]\", \"[神马]\", \"[囧]\", \"[浮云]\", \"[给力]\", \"[围观]\", \"[威武]\", \"[奥特曼]\", \"[礼物]\", \"[钟]\", \"[话筒]\", \"[蜡烛]\", \"[蛋糕]\"], arr = {};\n      layui.each(alt, function(index, item){\n        arr[item] = layui.cache.dir + 'images/face/'+ index + '.gif';\n      });\n      return arr;\n    }();\n    face.hide = face.hide || function(e){\n      if($(e.target).attr('layedit-event') !== 'face'){\n        layer.close(face.index);\n      }\n    }\n    return face.index = layer.tips(function(){\n      var content = [];\n      layui.each(faces, function(key, item){\n        content.push('<li title=\"'+ key +'\"><img src=\"'+ item +'\" alt=\"'+ key +'\"></li>');\n      });\n      return '<ul class=\"layui-clear\">' + content.join('') + '</ul>';\n    }(), this, {\n      tips: 1\n      ,time: 0\n      ,skin: 'layui-box layui-util-face'\n      ,maxWidth: 500\n      ,success: function(layero, index){\n        layero.css({\n          marginTop: -4\n          ,marginLeft: -10\n        }).find('.layui-clear>li').on('click', function(){\n          callback && callback({\n            src: faces[this.title]\n            ,alt: this.title\n          });\n          layer.close(index);\n        });\n        $(document).off('click', face.hide).on('click', face.hide);\n      }\n    });\n  }\n  \n  //插入代码面板\n  ,code = function(callback){\n    var body = this, index = layer.open({\n      type: 1\n      ,id: 'LAY_layedit_code'\n      ,area: '550px'\n      ,shade: 0.05\n      ,shadeClose: true\n      ,moveType: 1\n      ,title: '插入代码'\n      ,skin: 'layui-layer-msg'\n      ,content: ['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">'\n        ,'<li class=\"layui-form-item\">'\n          ,'<label class=\"layui-form-label\">请选择语言</label>'\n          ,'<div class=\"layui-input-block\">'\n            ,'<select name=\"lang\">'\n              ,'<option value=\"JavaScript\">JavaScript</option>'\n              ,'<option value=\"HTML\">HTML</option>'\n              ,'<option value=\"CSS\">CSS</option>'\n              ,'<option value=\"Java\">Java</option>'\n              ,'<option value=\"PHP\">PHP</option>'\n              ,'<option value=\"C#\">C#</option>'\n              ,'<option value=\"Python\">Python</option>'\n              ,'<option value=\"Ruby\">Ruby</option>'\n              ,'<option value=\"Go\">Go</option>'\n            ,'</select>'\n          ,'</div>'\n        ,'</li>'\n        ,'<li class=\"layui-form-item layui-form-text\">'\n          ,'<label class=\"layui-form-label\">代码</label>'\n          ,'<div class=\"layui-input-block\">'\n            ,'<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>'\n          ,'</div>'\n        ,'</li>'\n        ,'<li class=\"layui-form-item\" style=\"text-align: center;\">'\n          ,'<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>'\n          ,'<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>'\n        ,'</li>'\n      ,'</ul>'].join('')\n      ,success: function(layero, index){\n        var eventFilter = 'submit(layedit-code-yes)';\n        form.render('select');  \n        layero.find('.layui-btn-primary').on('click', function(){\n          layer.close(index);\n          body.focus();\n        });\n        form.on(eventFilter, function(data){\n          layer.close(code.index);\n          callback && callback(data.field);\n        });\n      }\n    });\n    code.index = index;\n  }\n  \n  //全部工具\n  ,tools = {\n    html: '<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>'\n    ,strong: '<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>'\n    ,italic: '<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>'\n    ,underline: '<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>'\n    ,del: '<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>'\n    \n    ,'|': '<span class=\"layedit-tool-mid\"></span>'\n    \n    ,left: '<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>'\n    ,center: '<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>'\n    ,right: '<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>'\n    ,link: '<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>'\n    ,unlink: '<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>'\n    ,face: '<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>'\n    ,image: '<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>'\n    ,code: '<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>'\n    \n    ,help: '<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'\n  }\n  \n  ,edit = new Edit();\n\n  exports(MOD_NAME, edit);\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/layer.js",
    "content": "﻿/**\n\n @Name：layer v3.1.0 Web弹层组件\n @author 郑保乐\n @Site：http://layer.layui.com\n @License：MIT\n    \n */\n\n;!function(window, undefined){\n\"use strict\";\n\nvar isLayui = window.layui && layui.define, $, win, ready = {\n  getPath: function(){\n    var js = document.scripts, script = js[js.length - 1], jsPath = script.src;\n    if(script.getAttribute('merge')) return;\n    return jsPath.substring(0, jsPath.lastIndexOf(\"/\") + 1);\n  }(),\n\n  config: {}, end: {}, minIndex: 0, minLeft: [],\n  btn: ['&#x786E;&#x5B9A;', '&#x53D6;&#x6D88;'],\n\n  //五种原始层模式\n  type: ['dialog', 'page', 'iframe', 'loading', 'tips'],\n  \n  //获取节点的style属性值\n  getStyle: function(node, name){\n    var style = node.currentStyle ? node.currentStyle : window.getComputedStyle(node, null);\n    return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name);\n  },\n  \n  //载入CSS配件\n  link: function(href, fn, cssname){\n    \n    //未设置路径，则不主动加载css\n    if(!layer.path) return;\n    \n    var head = document.getElementsByTagName(\"head\")[0], link = document.createElement('link');\n    if(typeof fn === 'string') cssname = fn;\n    var app = (cssname || href).replace(/\\.|\\//g, '');\n    var id = 'layuicss-'+ app, timeout = 0;\n    \n    link.rel = 'stylesheet';\n    link.href = layer.path + href;\n    link.id = id;\n    \n    if(!document.getElementById(id)){\n      head.appendChild(link);\n    }\n    \n    if(typeof fn !== 'function') return;\n    \n    //轮询css是否加载完毕\n    (function poll() {\n      if(++timeout > 8 * 1000 / 100){\n        return window.console && console.error('layer.css: Invalid');\n      };\n      parseInt(ready.getStyle(document.getElementById(id), 'width')) === 1989 ? fn() : setTimeout(poll, 100);\n    }());\n  }\n};\n\n//默认内置方法。\nvar layer = {\n  v: '3.1.0',\n  ie: function(){ //ie版本\n    var agent = navigator.userAgent.toLowerCase();\n    return (!!window.ActiveXObject || \"ActiveXObject\" in window) ? (\n      (agent.match(/msie\\s(\\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识\n    ) : false;\n  }(),\n  index: (window.layer && window.layer.v) ? 100000 : 0,\n  path: ready.getPath,\n  config: function(options, fn){\n    options = options || {};\n    layer.cache = ready.config = $.extend({}, ready.config, options);\n    layer.path = ready.config.path || layer.path;\n    typeof options.extend === 'string' && (options.extend = [options.extend]);\n    \n    if(ready.config.path) layer.ready();\n    \n    if(!options.extend) return this;\n    \n    isLayui \n      ? layui.addcss('modules/layer/' + options.extend)\n    : ready.link('theme/' + options.extend);\n    \n    return this;\n  },\n\n  //主体CSS等待事件\n  ready: function(callback){\n    var cssname = 'layer', ver = ''\n    ,path = (isLayui ? 'modules/layer/' : 'theme/') + 'default/layer.css?v='+ layer.v + ver;\n    isLayui ? layui.addcss(path, callback, cssname) : ready.link(path, callback, cssname);\n    return this;\n  },\n  \n  //各种快捷引用\n  alert: function(content, options, yes){\n    var type = typeof options === 'function';\n    if(type) yes = options;\n    return layer.open($.extend({\n      content: content,\n      yes: yes\n    }, type ? {} : options));\n  }, \n  \n  confirm: function(content, options, yes, cancel){ \n    var type = typeof options === 'function';\n    if(type){\n      cancel = yes;\n      yes = options;\n    }\n    return layer.open($.extend({\n      content: content,\n      btn: ready.btn,\n      yes: yes,\n      btn2: cancel\n    }, type ? {} : options));\n  },\n  \n  msg: function(content, options, end){ //最常用提示层\n    var type = typeof options === 'function', rskin = ready.config.skin;\n    var skin = (rskin ? rskin + ' ' + rskin + '-msg' : '')||'layui-layer-msg';\n    var anim = doms.anim.length - 1;\n    if(type) end = options;\n    return layer.open($.extend({\n      content: content,\n      time: 3000,\n      shade: false,\n      skin: skin,\n      title: false,\n      closeBtn: false,\n      btn: false,\n      resize: false,\n      end: end\n    }, (type && !ready.config.skin) ? {\n      skin: skin + ' layui-layer-hui',\n      anim: anim\n    } : function(){\n       options = options || {};\n       if(options.icon === -1 || options.icon === undefined && !ready.config.skin){\n         options.skin = skin + ' ' + (options.skin||'layui-layer-hui');\n       }\n       return options;\n    }()));  \n  },\n  \n  load: function(icon, options){\n    return layer.open($.extend({\n      type: 3,\n      icon: icon || 0,\n      resize: false,\n      shade: 0.01\n    }, options));\n  }, \n  \n  tips: function(content, follow, options){\n    return layer.open($.extend({\n      type: 4,\n      content: [content, follow],\n      closeBtn: false,\n      time: 3000,\n      shade: false,\n      resize: false,\n      fixed: false,\n      maxWidth: 210\n    }, options));\n  }\n};\n\nvar Class = function(setings){  \n  var that = this;\n  that.index = ++layer.index;\n  that.config = $.extend({}, that.config, ready.config, setings);\n  document.body ? that.creat() : setTimeout(function(){\n    that.creat();\n  }, 30);\n};\n\nClass.pt = Class.prototype;\n\n//缓存常用字符\nvar doms = ['layui-layer', '.layui-layer-title', '.layui-layer-main', '.layui-layer-dialog', 'layui-layer-iframe', 'layui-layer-content', 'layui-layer-btn', 'layui-layer-close'];\ndoms.anim = ['layer-anim-00', 'layer-anim-01', 'layer-anim-02', 'layer-anim-03', 'layer-anim-04', 'layer-anim-05', 'layer-anim-06'];\n\n//默认配置\nClass.pt.config = {\n  type: 0,\n  shade: 0.3,\n  fixed: true,\n  move: doms[1],\n  title: '&#x4FE1;&#x606F;',\n  offset: 'auto',\n  area: 'auto',\n  closeBtn: 1,\n  time: 0, //0表示不自动关闭\n  zIndex: 19891014, \n  maxWidth: 360,\n  anim: 0,\n  isOutAnim: true,\n  icon: -1,\n  moveType: 1,\n  resize: true,\n  scrollbar: true, //是否允许浏览器滚动条\n  tips: 2\n};\n\n//容器\nClass.pt.vessel = function(conType, callback){\n  var that = this, times = that.index, config = that.config;\n  var zIndex = config.zIndex + times, titype = typeof config.title === 'object';\n  var ismax = config.maxmin && (config.type === 1 || config.type === 2);\n  var titleHTML = (config.title ? '<div class=\"layui-layer-title\" style=\"'+ (titype ? config.title[1] : '') +'\">' \n    + (titype ? config.title[0] : config.title) \n  + '</div>' : '');\n  \n  config.zIndex = zIndex;\n  callback([\n    //遮罩\n    config.shade ? ('<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+ times +'\" times=\"'+ times +'\" style=\"'+ ('z-index:'+ (zIndex-1) +'; ') +'\"></div>') : '',\n    \n    //主体\n    '<div class=\"'+ doms[0] + (' layui-layer-'+ready.type[config.type]) + (((config.type == 0 || config.type == 2) && !config.shade) ? ' layui-layer-border' : '') + ' ' + (config.skin||'') +'\" id=\"'+ doms[0] + times +'\" type=\"'+ ready.type[config.type] +'\" times=\"'+ times +'\" showtime=\"'+ config.time +'\" conType=\"'+ (conType ? 'object' : 'string') +'\" style=\"z-index: '+ zIndex +'; width:'+ config.area[0] + ';height:' + config.area[1] + (config.fixed ? '' : ';position:absolute;') +'\">'\n      + (conType && config.type != 2 ? '' : titleHTML)\n      + '<div id=\"'+ (config.id||'') +'\" class=\"layui-layer-content'+ ((config.type == 0 && config.icon !== -1) ? ' layui-layer-padding' :'') + (config.type == 3 ? ' layui-layer-loading'+config.icon : '') +'\">'\n        + (config.type == 0 && config.icon !== -1 ? '<i class=\"layui-layer-ico layui-layer-ico'+ config.icon +'\"></i>' : '')\n        + (config.type == 1 && conType ? '' : (config.content||''))\n      + '</div>'\n      + '<span class=\"layui-layer-setwin\">'+ function(){\n        var closebtn = ismax ? '<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>' : '';\n        config.closeBtn && (closebtn += '<a class=\"layui-layer-ico '+ doms[7] +' '+ doms[7] + (config.title ? config.closeBtn : (config.type == 4 ? '1' : '2')) +'\" href=\"javascript:;\"></a>');\n        return closebtn;\n      }() + '</span>'\n      + (config.btn ? function(){\n        var button = '';\n        typeof config.btn === 'string' && (config.btn = [config.btn]);\n        for(var i = 0, len = config.btn.length; i < len; i++){\n          button += '<a class=\"'+ doms[6] +''+ i +'\">'+ config.btn[i] +'</a>'\n        }\n        return '<div class=\"'+ doms[6] +' layui-layer-btn-'+ (config.btnAlign||'') +'\">'+ button +'</div>'\n      }() : '')\n      + (config.resize ? '<span class=\"layui-layer-resize\"></span>' : '')\n    + '</div>'\n  ], titleHTML, $('<div class=\"layui-layer-move\"></div>'));\n  return that;\n};\n\n//创建骨架\nClass.pt.creat = function(){\n  var that = this\n  ,config = that.config\n  ,times = that.index, nodeIndex\n  ,content = config.content\n  ,conType = typeof content === 'object'\n  ,body = $('body');\n  \n  if(config.id && $('#'+config.id)[0])  return;\n\n  if(typeof config.area === 'string'){\n    config.area = config.area === 'auto' ? ['', ''] : [config.area, ''];\n  }\n  \n  //anim兼容旧版shift\n  if(config.shift){\n    config.anim = config.shift;\n  }\n  \n  if(layer.ie == 6){\n    config.fixed = false;\n  }\n  \n  switch(config.type){\n    case 0:\n      config.btn = ('btn' in config) ? config.btn : ready.btn[0];\n      layer.closeAll('dialog');\n    break;\n    case 2:\n      var content = config.content = conType ? config.content : [config.content||'http://layer.layui.com', 'auto'];\n      config.content = '<iframe scrolling=\"'+ (config.content[1]||'auto') +'\" allowtransparency=\"true\" id=\"'+ doms[4] +''+ times +'\" name=\"'+ doms[4] +''+ times +'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"' + config.content[0] + '\"></iframe>';\n    break;\n    case 3:\n      delete config.title;\n      delete config.closeBtn;\n      config.icon === -1 && (config.icon === 0);\n      layer.closeAll('loading');\n    break;\n    case 4:\n      conType || (config.content = [config.content, 'body']);\n      config.follow = config.content[1];\n      config.content = config.content[0] + '<i class=\"layui-layer-TipsG\"></i>';\n      delete config.title;\n      config.tips = typeof config.tips === 'object' ? config.tips : [config.tips, true];\n      config.tipsMore || layer.closeAll('tips');\n    break;\n  }\n  \n  //建立容器\n  that.vessel(conType, function(html, titleHTML, moveElem){\n    body.append(html[0]);\n    conType ? function(){\n      (config.type == 2 || config.type == 4) ? function(){\n        $('body').append(html[1]);\n      }() : function(){\n        if(!content.parents('.'+doms[0])[0]){\n          content.data('display', content.css('display')).show().addClass('layui-layer-wrap').wrap(html[1]);\n          $('#'+ doms[0] + times).find('.'+doms[5]).before(titleHTML);\n        }\n      }();\n    }() : body.append(html[1]);\n    $('.layui-layer-move')[0] || body.append(ready.moveElem = moveElem);\n    that.layero = $('#'+ doms[0] + times);\n    config.scrollbar || doms.html.css('overflow', 'hidden').attr('layer-full', times);\n  }).auto(times);\n  \n  //遮罩\n  $('#layui-layer-shade'+ that.index).css({\n    'background-color': config.shade[1] || '#000'\n    ,'opacity': config.shade[0]||config.shade\n  });\n\n  config.type == 2 && layer.ie == 6 && that.layero.find('iframe').attr('src', content[0]);\n\n  //坐标自适应浏览器窗口尺寸\n  config.type == 4 ? that.tips() : that.offset();\n  if(config.fixed){\n    win.on('resize', function(){\n      that.offset();\n      (/^\\d+%$/.test(config.area[0]) || /^\\d+%$/.test(config.area[1])) && that.auto(times);\n      config.type == 4 && that.tips();\n    });\n  }\n  \n  config.time <= 0 || setTimeout(function(){\n    layer.close(that.index)\n  }, config.time);\n  that.move().callback();\n  \n  //为兼容jQuery3.0的css动画影响元素尺寸计算\n  if(doms.anim[config.anim]){\n    var animClass = 'layer-anim '+ doms.anim[config.anim];\n    that.layero.addClass(animClass).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){\n      $(this).removeClass(animClass);\n    });\n  };\n  \n  //记录关闭动画\n  if(config.isOutAnim){\n    that.layero.data('isOutAnim', true);\n  }\n};\n\n//自适应\nClass.pt.auto = function(index){\n  var that = this, config = that.config, layero = $('#'+ doms[0] + index);\n  \n  if(config.area[0] === '' && config.maxWidth > 0){\n    //为了修复IE7下一个让人难以理解的bug\n    if(layer.ie && layer.ie < 8 && config.btn){\n      layero.width(layero.innerWidth());\n    }\n    layero.outerWidth() > config.maxWidth && layero.width(config.maxWidth);\n  }\n  \n  var area = [layero.innerWidth(), layero.innerHeight()]\n  ,titHeight = layero.find(doms[1]).outerHeight() || 0\n  ,btnHeight = layero.find('.'+doms[6]).outerHeight() || 0\n  ,setHeight = function(elem){\n    elem = layero.find(elem);\n    elem.height(area[1] - titHeight - btnHeight - 2*(parseFloat(elem.css('padding-top'))|0));\n  };\n\n  switch(config.type){\n    case 2: \n      setHeight('iframe');\n    break;\n    default:\n      if(config.area[1] === ''){\n        if(config.maxHeight > 0 && layero.outerHeight() > config.maxHeight){\n          area[1] = config.maxHeight;\n          setHeight('.'+doms[5]);\n        } else if(config.fixed && area[1] >= win.height()){\n          area[1] = win.height();\n          setHeight('.'+doms[5]);\n        }\n      } else {\n        setHeight('.'+doms[5]);\n      }\n    break;\n  };\n  \n  return that;\n};\n\n//计算坐标\nClass.pt.offset = function(){\n  var that = this, config = that.config, layero = that.layero;\n  var area = [layero.outerWidth(), layero.outerHeight()];\n  var type = typeof config.offset === 'object';\n  that.offsetTop = (win.height() - area[1])/2;\n  that.offsetLeft = (win.width() - area[0])/2;\n  \n  if(type){\n    that.offsetTop = config.offset[0];\n    that.offsetLeft = config.offset[1]||that.offsetLeft;\n  } else if(config.offset !== 'auto'){\n    \n    if(config.offset === 't'){ //上\n      that.offsetTop = 0;\n    } else if(config.offset === 'r'){ //右\n      that.offsetLeft = win.width() - area[0];\n    } else if(config.offset === 'b'){ //下\n      that.offsetTop = win.height() - area[1];\n    } else if(config.offset === 'l'){ //左\n      that.offsetLeft = 0;\n    } else if(config.offset === 'lt'){ //左上角\n      that.offsetTop = 0;\n      that.offsetLeft = 0;\n    } else if(config.offset === 'lb'){ //左下角\n      that.offsetTop = win.height() - area[1];\n      that.offsetLeft = 0;\n    } else if(config.offset === 'rt'){ //右上角\n      that.offsetTop = 0;\n      that.offsetLeft = win.width() - area[0];\n    } else if(config.offset === 'rb'){ //右下角\n      that.offsetTop = win.height() - area[1];\n      that.offsetLeft = win.width() - area[0];\n    } else {\n      that.offsetTop = config.offset;\n    }\n    \n  }\n \n  if(!config.fixed){\n    that.offsetTop = /%$/.test(that.offsetTop) ? \n      win.height()*parseFloat(that.offsetTop)/100\n    : parseFloat(that.offsetTop);\n    that.offsetLeft = /%$/.test(that.offsetLeft) ? \n      win.width()*parseFloat(that.offsetLeft)/100\n    : parseFloat(that.offsetLeft);\n    that.offsetTop += win.scrollTop();\n    that.offsetLeft += win.scrollLeft();\n  }\n  \n  if(layero.attr('minLeft')){\n    that.offsetTop = win.height() - (layero.find(doms[1]).outerHeight() || 0);\n    that.offsetLeft = layero.css('left');\n  }\n\n  layero.css({top: that.offsetTop, left: that.offsetLeft});\n};\n\n//Tips\nClass.pt.tips = function(){\n  var that = this, config = that.config, layero = that.layero;\n  var layArea = [layero.outerWidth(), layero.outerHeight()], follow = $(config.follow);\n  if(!follow[0]) follow = $('body');\n  var goal = {\n    width: follow.outerWidth(),\n    height: follow.outerHeight(),\n    top: follow.offset().top,\n    left: follow.offset().left\n  }, tipsG = layero.find('.layui-layer-TipsG');\n  \n  var guide = config.tips[0];\n  config.tips[1] || tipsG.remove();\n  \n  goal.autoLeft = function(){\n    if(goal.left + layArea[0] - win.width() > 0){\n      goal.tipLeft = goal.left + goal.width - layArea[0];\n      tipsG.css({right: 12, left: 'auto'});\n    } else {\n      goal.tipLeft = goal.left;\n    };\n  };\n  \n  //辨别tips的方位\n  goal.where = [function(){ //上        \n    goal.autoLeft();\n    goal.tipTop = goal.top - layArea[1] - 10;\n    tipsG.removeClass('layui-layer-TipsB').addClass('layui-layer-TipsT').css('border-right-color', config.tips[1]);\n  }, function(){ //右\n    goal.tipLeft = goal.left + goal.width + 10;\n    goal.tipTop = goal.top;\n    tipsG.removeClass('layui-layer-TipsL').addClass('layui-layer-TipsR').css('border-bottom-color', config.tips[1]); \n  }, function(){ //下\n    goal.autoLeft();\n    goal.tipTop = goal.top + goal.height + 10;\n    tipsG.removeClass('layui-layer-TipsT').addClass('layui-layer-TipsB').css('border-right-color', config.tips[1]);\n  }, function(){ //左\n    goal.tipLeft = goal.left - layArea[0] - 10;\n    goal.tipTop = goal.top;\n    tipsG.removeClass('layui-layer-TipsR').addClass('layui-layer-TipsL').css('border-bottom-color', config.tips[1]);\n  }];\n  goal.where[guide-1]();\n  \n  /* 8*2为小三角形占据的空间 */\n  if(guide === 1){\n    goal.top - (win.scrollTop() + layArea[1] + 8*2) < 0 && goal.where[2]();\n  } else if(guide === 2){\n    win.width() - (goal.left + goal.width + layArea[0] + 8*2) > 0 || goal.where[3]()\n  } else if(guide === 3){\n    (goal.top - win.scrollTop() + goal.height + layArea[1] + 8*2) - win.height() > 0 && goal.where[0]();\n  } else if(guide === 4){\n     layArea[0] + 8*2 - goal.left > 0 && goal.where[1]()\n  }\n\n  layero.find('.'+doms[5]).css({\n    'background-color': config.tips[1], \n    'padding-right': (config.closeBtn ? '30px' : '')\n  });\n  layero.css({\n    left: goal.tipLeft - (config.fixed ? win.scrollLeft() : 0), \n    top: goal.tipTop  - (config.fixed ? win.scrollTop() : 0)\n  });\n}\n\n//拖拽层\nClass.pt.move = function(){\n  var that = this\n  ,config = that.config\n  ,_DOC = $(document)\n  ,layero = that.layero\n  ,moveElem = layero.find(config.move)\n  ,resizeElem = layero.find('.layui-layer-resize')\n  ,dict = {};\n  \n  if(config.move){\n    moveElem.css('cursor', 'move');\n  }\n\n  moveElem.on('mousedown', function(e){\n    e.preventDefault();\n    if(config.move){\n      dict.moveStart = true;\n      dict.offset = [\n        e.clientX - parseFloat(layero.css('left'))\n        ,e.clientY - parseFloat(layero.css('top'))\n      ];\n      ready.moveElem.css('cursor', 'move').show();\n    }\n  });\n  \n  resizeElem.on('mousedown', function(e){\n    e.preventDefault();\n    dict.resizeStart = true;\n    dict.offset = [e.clientX, e.clientY];\n    dict.area = [\n      layero.outerWidth()\n      ,layero.outerHeight()\n    ];\n    ready.moveElem.css('cursor', 'se-resize').show();\n  });\n  \n  _DOC.on('mousemove', function(e){\n\n    //拖拽移动\n    if(dict.moveStart){\n      var X = e.clientX - dict.offset[0]\n      ,Y = e.clientY - dict.offset[1]\n      ,fixed = layero.css('position') === 'fixed';\n      \n      e.preventDefault();\n      \n      dict.stX = fixed ? 0 : win.scrollLeft();\n      dict.stY = fixed ? 0 : win.scrollTop();\n\n      //控制元素不被拖出窗口外\n      if(!config.moveOut){\n        var setRig = win.width() - layero.outerWidth() + dict.stX\n        ,setBot = win.height() - layero.outerHeight() + dict.stY;  \n        X < dict.stX && (X = dict.stX);\n        X > setRig && (X = setRig); \n        Y < dict.stY && (Y = dict.stY);\n        Y > setBot && (Y = setBot);\n      }\n      \n      layero.css({\n        left: X\n        ,top: Y\n      });\n    }\n    \n    //Resize\n    if(config.resize && dict.resizeStart){\n      var X = e.clientX - dict.offset[0]\n      ,Y = e.clientY - dict.offset[1];\n      \n      e.preventDefault();\n      \n      layer.style(that.index, {\n        width: dict.area[0] + X\n        ,height: dict.area[1] + Y\n      })\n      dict.isResize = true;\n      config.resizing && config.resizing(layero);\n    }\n  }).on('mouseup', function(e){\n    if(dict.moveStart){\n      delete dict.moveStart;\n      ready.moveElem.hide();\n      config.moveEnd && config.moveEnd(layero);\n    }\n    if(dict.resizeStart){\n      delete dict.resizeStart;\n      ready.moveElem.hide();\n    }\n  });\n  \n  return that;\n};\n\nClass.pt.callback = function(){\n  var that = this, layero = that.layero, config = that.config;\n  that.openLayer();\n  if(config.success){\n    if(config.type == 2){\n      layero.find('iframe').on('load', function(){\n        config.success(layero, that.index);\n      });\n    } else {\n      config.success(layero, that.index);\n    }\n  }\n  layer.ie == 6 && that.IE6(layero);\n  \n  //按钮\n  layero.find('.'+ doms[6]).children('a').on('click', function(){\n    var index = $(this).index();\n    if(index === 0){\n      if(config.yes){\n        config.yes(that.index, layero)\n      } else if(config['btn1']){\n        config['btn1'](that.index, layero)\n      } else {\n        layer.close(that.index);\n      }\n    } else {\n      var close = config['btn'+(index+1)] && config['btn'+(index+1)](that.index, layero);\n      close === false || layer.close(that.index);\n    }\n  });\n  \n  //取消\n  function cancel(){\n    var close = config.cancel && config.cancel(that.index, layero);\n    close === false || layer.close(that.index);\n  }\n  \n  //右上角关闭回调\n  layero.find('.'+ doms[7]).on('click', cancel);\n  \n  //点遮罩关闭\n  if(config.shadeClose){\n    $('#layui-layer-shade'+ that.index).on('click', function(){\n      layer.close(that.index);\n    });\n  } \n  \n  //最小化\n  layero.find('.layui-layer-min').on('click', function(){\n    var min = config.min && config.min(layero);\n    min === false || layer.min(that.index, config); \n  });\n  \n  //全屏/还原\n  layero.find('.layui-layer-max').on('click', function(){\n    if($(this).hasClass('layui-layer-maxmin')){\n      layer.restore(that.index);\n      config.restore && config.restore(layero);\n    } else {\n      layer.full(that.index, config);\n      setTimeout(function(){\n        config.full && config.full(layero);\n      }, 100);\n    }\n  });\n\n  config.end && (ready.end[that.index] = config.end);\n};\n\n//for ie6 恢复select\nready.reselect = function(){\n  $.each($('select'), function(index , value){\n    var sthis = $(this);\n    if(!sthis.parents('.'+doms[0])[0]){\n      (sthis.attr('layer') == 1 && $('.'+doms[0]).length < 1) && sthis.removeAttr('layer').show(); \n    }\n    sthis = null;\n  });\n}; \n\nClass.pt.IE6 = function(layero){\n  //隐藏select\n  $('select').each(function(index , value){\n    var sthis = $(this);\n    if(!sthis.parents('.'+doms[0])[0]){\n      sthis.css('display') === 'none' || sthis.attr({'layer' : '1'}).hide();\n    }\n    sthis = null;\n  });\n};\n\n//需依赖原型的对外方法\nClass.pt.openLayer = function(){\n  var that = this;\n  \n  //置顶当前窗口\n  layer.zIndex = that.config.zIndex;\n  layer.setTop = function(layero){\n    var setZindex = function(){\n      layer.zIndex++;\n      layero.css('z-index', layer.zIndex + 1);\n    };\n    layer.zIndex = parseInt(layero[0].style.zIndex);\n    layero.on('mousedown', setZindex);\n    return layer.zIndex;\n  };\n};\n\nready.record = function(layero){\n  var area = [\n    layero.width(),\n    layero.height(),\n    layero.position().top, \n    layero.position().left + parseFloat(layero.css('margin-left'))\n  ];\n  layero.find('.layui-layer-max').addClass('layui-layer-maxmin');\n  layero.attr({area: area});\n};\n\nready.rescollbar = function(index){\n  if(doms.html.attr('layer-full') == index){\n    if(doms.html[0].style.removeProperty){\n      doms.html[0].style.removeProperty('overflow');\n    } else {\n      doms.html[0].style.removeAttribute('overflow');\n    }\n    doms.html.removeAttr('layer-full');\n  }\n};\n\n/** 内置成员 */\n\nwindow.layer = layer;\n\n//获取子iframe的DOM\nlayer.getChildFrame = function(selector, index){\n  index = index || $('.'+doms[4]).attr('times');\n  return $('#'+ doms[0] + index).find('iframe').contents().find(selector);  \n};\n\n//得到当前iframe层的索引，子iframe时使用\nlayer.getFrameIndex = function(name){\n  return $('#'+ name).parents('.'+doms[4]).attr('times');\n};\n\n//iframe层自适应宽高\nlayer.iframeAuto = function(index){\n  if(!index) return;\n  var heg = layer.getChildFrame('html', index).outerHeight();\n  var layero = $('#'+ doms[0] + index);\n  var titHeight = layero.find(doms[1]).outerHeight() || 0;\n  var btnHeight = layero.find('.'+doms[6]).outerHeight() || 0;\n  layero.css({height: heg + titHeight + btnHeight});\n  layero.find('iframe').css({height: heg});\n};\n\n//重置iframe url\nlayer.iframeSrc = function(index, url){\n  $('#'+ doms[0] + index).find('iframe').attr('src', url);\n};\n\n//设定层的样式\nlayer.style = function(index, options, limit){\n  var layero = $('#'+ doms[0] + index)\n  ,contElem = layero.find('.layui-layer-content')\n  ,type = layero.attr('type')\n  ,titHeight = layero.find(doms[1]).outerHeight() || 0\n  ,btnHeight = layero.find('.'+doms[6]).outerHeight() || 0\n  ,minLeft = layero.attr('minLeft');\n  \n  if(type === ready.type[3] || type === ready.type[4]){\n    return;\n  }\n  \n  if(!limit){\n    if(parseFloat(options.width) <= 260){\n      options.width = 260;\n    };\n    \n    if(parseFloat(options.height) - titHeight - btnHeight <= 64){\n      options.height = 64 + titHeight + btnHeight;\n    };\n  }\n  \n  layero.css(options);\n  btnHeight = layero.find('.'+doms[6]).outerHeight();\n  \n  if(type === ready.type[2]){\n    layero.find('iframe').css({\n      height: parseFloat(options.height) - titHeight - btnHeight\n    });\n  } else {\n    contElem.css({\n      height: parseFloat(options.height) - titHeight - btnHeight\n      - parseFloat(contElem.css('padding-top'))\n      - parseFloat(contElem.css('padding-bottom'))\n    })\n  }\n};\n\n//最小化\nlayer.min = function(index, options){\n  var layero = $('#'+ doms[0] + index)\n  ,titHeight = layero.find(doms[1]).outerHeight() || 0\n  ,left = layero.attr('minLeft') || (181*ready.minIndex)+'px'\n  ,position = layero.css('position');\n  \n  ready.record(layero);\n  \n  if(ready.minLeft[0]){\n    left = ready.minLeft[0];\n    ready.minLeft.shift();\n  }\n  \n  layero.attr('position', position);\n  \n  layer.style(index, {\n    width: 180\n    ,height: titHeight\n    ,left: left\n    ,top: win.height() - titHeight\n    ,position: 'fixed'\n    ,overflow: 'hidden'\n  }, true);\n\n  layero.find('.layui-layer-min').hide();\n  layero.attr('type') === 'page' && layero.find(doms[4]).hide();\n  ready.rescollbar(index);\n  \n  if(!layero.attr('minLeft')){\n    ready.minIndex++;\n  }\n  layero.attr('minLeft', left);\n};\n\n//还原\nlayer.restore = function(index){\n  var layero = $('#'+ doms[0] + index), area = layero.attr('area').split(',');\n  var type = layero.attr('type');\n  layer.style(index, {\n    width: parseFloat(area[0]), \n    height: parseFloat(area[1]), \n    top: parseFloat(area[2]), \n    left: parseFloat(area[3]),\n    position: layero.attr('position'),\n    overflow: 'visible'\n  }, true);\n  layero.find('.layui-layer-max').removeClass('layui-layer-maxmin');\n  layero.find('.layui-layer-min').show();\n  layero.attr('type') === 'page' && layero.find(doms[4]).show();\n  ready.rescollbar(index);\n};\n\n//全屏\nlayer.full = function(index){\n  var layero = $('#'+ doms[0] + index), timer;\n  ready.record(layero);\n  if(!doms.html.attr('layer-full')){\n    doms.html.css('overflow','hidden').attr('layer-full', index);\n  }\n  clearTimeout(timer);\n  timer = setTimeout(function(){\n    var isfix = layero.css('position') === 'fixed';\n    layer.style(index, {\n      top: isfix ? 0 : win.scrollTop(),\n      left: isfix ? 0 : win.scrollLeft(),\n      width: win.width(),\n      height: win.height()\n    }, true);\n    layero.find('.layui-layer-min').hide();\n  }, 100);\n};\n\n//改变title\nlayer.title = function(name, index){\n  var title = $('#'+ doms[0] + (index||layer.index)).find(doms[1]);\n  title.html(name);\n};\n\n//关闭layer总方法\nlayer.close = function(index){\n  var layero = $('#'+ doms[0] + index), type = layero.attr('type'), closeAnim = 'layer-anim-close';\n  if(!layero[0]) return;\n  var WRAP = 'layui-layer-wrap', remove = function(){\n    if(type === ready.type[1] && layero.attr('conType') === 'object'){\n      layero.children(':not(.'+ doms[5] +')').remove();\n      var wrap = layero.find('.'+WRAP);\n      for(var i = 0; i < 2; i++){\n        wrap.unwrap();\n      }\n      wrap.css('display', wrap.data('display')).removeClass(WRAP);\n    } else {\n      //低版本IE 回收 iframe\n      if(type === ready.type[2]){\n        try {\n          var iframe = $('#'+doms[4]+index)[0];\n          iframe.contentWindow.document.write('');\n          iframe.contentWindow.close();\n          layero.find('.'+doms[5])[0].removeChild(iframe);\n        } catch(e){}\n      }\n      layero[0].innerHTML = '';\n      layero.remove();\n    }\n    typeof ready.end[index] === 'function' && ready.end[index]();\n    delete ready.end[index];\n  };\n  \n  if(layero.data('isOutAnim')){\n    layero.addClass('layer-anim '+ closeAnim);\n  }\n  \n  $('#layui-layer-moves, #layui-layer-shade' + index).remove();\n  layer.ie == 6 && ready.reselect();\n  ready.rescollbar(index); \n  if(layero.attr('minLeft')){\n    ready.minIndex--;\n    ready.minLeft.push(layero.attr('minLeft'));\n  }\n  \n  if((layer.ie && layer.ie < 10) || !layero.data('isOutAnim')){\n    remove()\n  } else {\n    setTimeout(function(){\n      remove();\n    }, 200);\n  }\n};\n\n//关闭所有层\nlayer.closeAll = function(type){\n  $.each($('.'+doms[0]), function(){\n    var othis = $(this);\n    var is = type ? (othis.attr('type') === type) : 1;\n    is && layer.close(othis.attr('times'));\n    is = null;\n  });\n};\n\n/** \n\n  拓展模块，layui开始合并在一起\n\n */\n\nvar cache = layer.cache||{}, skin = function(type){\n  return (cache.skin ? (' ' + cache.skin + ' ' + cache.skin + '-'+type) : '');\n}; \n \n//仿系统prompt\nlayer.prompt = function(options, yes){\n  var style = '';\n  options = options || {};\n  \n  if(typeof options === 'function') yes = options;\n  \n  if(options.area){\n    var area = options.area;\n    style = 'style=\"width: '+ area[0] +'; height: '+ area[1] + ';\"';\n    delete options.area;\n  }\n  var prompt, content = options.formType == 2 ? '<textarea class=\"layui-layer-input\"' + style +'>' + (options.value||'') +'</textarea>' : function(){\n    return '<input type=\"'+ (options.formType == 1 ? 'password' : 'text') +'\" class=\"layui-layer-input\" value=\"'+ (options.value||'') +'\">';\n  }();\n  \n  var success = options.success;\n  delete options.success;\n  \n  return layer.open($.extend({\n    type: 1\n    ,btn: ['&#x786E;&#x5B9A;','&#x53D6;&#x6D88;']\n    ,content: content\n    ,skin: 'layui-layer-prompt' + skin('prompt')\n    ,maxWidth: win.width()\n    ,success: function(layero){\n      prompt = layero.find('.layui-layer-input');\n      prompt.focus();\n      typeof success === 'function' && success(layero);\n    }\n    ,resize: false\n    ,yes: function(index){\n      var value = prompt.val();\n      if(value === ''){\n        prompt.focus();\n      } else if(value.length > (options.maxlength||500)) {\n        layer.tips('&#x6700;&#x591A;&#x8F93;&#x5165;'+ (options.maxlength || 500) +'&#x4E2A;&#x5B57;&#x6570;', prompt, {tips: 1});\n      } else {\n        yes && yes(value, index, prompt);\n      }\n    }\n  }, options));\n};\n\n//tab层\nlayer.tab = function(options){\n  options = options || {};\n  \n  var tab = options.tab || {}\n  ,THIS = 'layui-this'\n  ,success = options.success;\n  \n  delete options.success;\n  \n  return layer.open($.extend({\n    type: 1,\n    skin: 'layui-layer-tab' + skin('tab'),\n    resize: false,\n    title: function(){\n      var len = tab.length, ii = 1, str = '';\n      if(len > 0){\n        str = '<span class=\"'+ THIS +'\">'+ tab[0].title +'</span>';\n        for(; ii < len; ii++){\n          str += '<span>'+ tab[ii].title +'</span>';\n        }\n      }\n      return str;\n    }(),\n    content: '<ul class=\"layui-layer-tabmain\">'+ function(){\n      var len = tab.length, ii = 1, str = '';\n      if(len > 0){\n        str = '<li class=\"layui-layer-tabli '+ THIS +'\">'+ (tab[0].content || 'no content') +'</li>';\n        for(; ii < len; ii++){\n          str += '<li class=\"layui-layer-tabli\">'+ (tab[ii].content || 'no  content') +'</li>';\n        }\n      }\n      return str;\n    }() +'</ul>',\n    success: function(layero){\n      var btn = layero.find('.layui-layer-title').children();\n      var main = layero.find('.layui-layer-tabmain').children();\n      btn.on('mousedown', function(e){\n        e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;\n        var othis = $(this), index = othis.index();\n        othis.addClass(THIS).siblings().removeClass(THIS);\n        main.eq(index).show().siblings().hide();\n        typeof options.change === 'function' && options.change(index);\n      });\n      typeof success === 'function' && success(layero);\n    }\n  }, options));\n};\n\n//相册层\nlayer.photos = function(options, loop, key){\n  var dict = {};\n  options = options || {};\n  if(!options.photos) return;\n  var type = options.photos.constructor === Object;\n  var photos = type ? options.photos : {}, data = photos.data || [];\n  var start = photos.start || 0;\n  dict.imgIndex = (start|0) + 1;\n  \n  options.img = options.img || 'img';\n  \n  var success = options.success;\n  delete options.success;\n\n  if(!type){ //页面直接获取\n    var parent = $(options.photos), pushData = function(){\n      data = [];\n      parent.find(options.img).each(function(index){\n        var othis = $(this);\n        othis.attr('layer-index', index);\n        data.push({\n          alt: othis.attr('alt'),\n          pid: othis.attr('layer-pid'),\n          src: othis.attr('layer-src') || othis.attr('src'),\n          thumb: othis.attr('src')\n        });\n      })\n    };\n    \n    pushData();\n    \n    if (data.length === 0) return;\n    \n    loop || parent.on('click', options.img, function(){\n      var othis = $(this), index = othis.attr('layer-index'); \n      layer.photos($.extend(options, {\n        photos: {\n          start: index,\n          data: data,\n          tab: options.tab\n        },\n        full: options.full\n      }), true);\n      pushData();\n    })\n    \n    //不直接弹出\n    if(!loop) return;\n    \n  } else if (data.length === 0){\n    return layer.msg('&#x6CA1;&#x6709;&#x56FE;&#x7247;');\n  }\n  \n  //上一张\n  dict.imgprev = function(key){\n    dict.imgIndex--;\n    if(dict.imgIndex < 1){\n      dict.imgIndex = data.length;\n    }\n    dict.tabimg(key);\n  };\n  \n  //下一张\n  dict.imgnext = function(key,errorMsg){\n    dict.imgIndex++;\n    if(dict.imgIndex > data.length){\n      dict.imgIndex = 1;\n      if (errorMsg) {return};\n    }\n    dict.tabimg(key)\n  };\n  \n  //方向键\n  dict.keyup = function(event){\n    if(!dict.end){\n      var code = event.keyCode;\n      event.preventDefault();\n      if(code === 37){\n        dict.imgprev(true);\n      } else if(code === 39) {\n        dict.imgnext(true);\n      } else if(code === 27) {\n        layer.close(dict.index);\n      }\n    }\n  }\n  \n  //切换\n  dict.tabimg = function(key){\n    if(data.length <= 1) return;\n    photos.start = dict.imgIndex - 1;\n    layer.close(dict.index);\n    return layer.photos(options, true, key);\n    setTimeout(function(){\n      layer.photos(options, true, key);\n    }, 200);\n  }\n  \n  //一些动作\n  dict.event = function(){\n    dict.bigimg.hover(function(){\n      dict.imgsee.show();\n    }, function(){\n      dict.imgsee.hide();\n    });\n    \n    dict.bigimg.find('.layui-layer-imgprev').on('click', function(event){\n      event.preventDefault();\n      dict.imgprev();\n    });  \n    \n    dict.bigimg.find('.layui-layer-imgnext').on('click', function(event){     \n      event.preventDefault();\n      dict.imgnext();\n    });\n    \n    $(document).on('keyup', dict.keyup);\n  };\n  \n  //图片预加载\n  function loadImage(url, callback, error) {   \n    var img = new Image();\n    img.src = url; \n    if(img.complete){\n      return callback(img);\n    }\n    img.onload = function(){\n      img.onload = null;\n      callback(img);\n    };\n    img.onerror = function(e){\n      img.onerror = null;\n      error(e);\n    };  \n  };\n  \n  dict.loadi = layer.load(1, {\n    shade: 'shade' in options ? false : 0.9,\n    scrollbar: false\n  });\n\n  loadImage(data[start].src, function(img){\n    layer.close(dict.loadi);\n    dict.index = layer.open($.extend({\n      type: 1,\n      id: 'layui-layer-photos',\n      area: function(){\n        var imgarea = [img.width, img.height];\n        var winarea = [$(window).width() - 100, $(window).height() - 100];\n        \n        //如果 实际图片的宽或者高比 屏幕大（那么进行缩放）\n        if(!options.full && (imgarea[0]>winarea[0]||imgarea[1]>winarea[1])){\n          var wh = [imgarea[0]/winarea[0],imgarea[1]/winarea[1]];//取宽度缩放比例、高度缩放比例\n          if(wh[0] > wh[1]){//取缩放比例最大的进行缩放\n            imgarea[0] = imgarea[0]/wh[0];\n            imgarea[1] = imgarea[1]/wh[0];\n          } else if(wh[0] < wh[1]){\n            imgarea[0] = imgarea[0]/wh[1];\n            imgarea[1] = imgarea[1]/wh[1];\n          }\n        }\n        \n        return [imgarea[0]+'px', imgarea[1]+'px']; \n      }(),\n      title: false,\n      shade: 0.9,\n      shadeClose: true,\n      closeBtn: false,\n      move: '.layui-layer-phimg img',\n      moveType: 1,\n      scrollbar: false,\n      moveOut: true,\n      //anim: Math.random()*5|0,\n      isOutAnim: false,\n      skin: 'layui-layer-photos' + skin('photos'),\n      content: '<div class=\"layui-layer-phimg\">'\n        +'<img src=\"'+ data[start].src +'\" alt=\"'+ (data[start].alt||'') +'\" layer-pid=\"'+ data[start].pid +'\">'\n        +'<div class=\"layui-layer-imgsee\">'\n          +(data.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>' : '')\n          +'<div class=\"layui-layer-imgbar\" style=\"display:'+ (key ? 'block' : '') +'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+ (data[start].alt||'') +'</a><em>'+ dict.imgIndex +'/'+ data.length +'</em></span></div>'\n        +'</div>'\n      +'</div>',\n      success: function(layero, index){\n        dict.bigimg = layero.find('.layui-layer-phimg');\n        dict.imgsee = layero.find('.layui-layer-imguide,.layui-layer-imgbar');\n        dict.event(layero);\n        options.tab && options.tab(data[start], layero);\n        typeof success === 'function' && success(layero);\n      }, end: function(){\n        dict.end = true;\n        $(document).off('keyup', dict.keyup);\n      }\n    }, options));\n  }, function(){\n    layer.close(dict.loadi);\n    layer.msg('&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;', {\n      time: 30000, \n      btn: ['&#x4E0B;&#x4E00;&#x5F20;', '&#x4E0D;&#x770B;&#x4E86;'], \n      yes: function(){\n        data.length > 1 && dict.imgnext(true,true);\n      }\n    });\n  });\n};\n\n//主入口\nready.run = function(_$){\n  $ = _$;\n  win = $(window);\n  doms.html = $('html');\n  layer.open = function(deliver){\n    var o = new Class(deliver);\n    return o.index;\n  };\n};\n\n//加载方式\nwindow.layui && layui.define ? (\n  layer.ready()\n  ,layui.define('jquery', function(exports){ //layui加载\n    layer.path = layui.cache.dir;\n    ready.run(layui.$);\n\n    //暴露模块\n    window.layer = layer;\n    exports('layer', layer);\n  })\n) : (\n  (typeof define === 'function' && define.amd) ? define(['jquery'], function(){ //requirejs加载\n    ready.run(window.jQuery);\n    return layer;\n  }) : function(){ //普通script标签加载\n    ready.run(window.jQuery);\n    layer.ready();\n  }()\n);\n\n}(window);\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/laypage.js",
    "content": "/**\n \n @Name : layui.laypage 分页组件\n @author 郑保乐\n @License：MIT\n \n */\n\nlayui.define(function(exports){\n  \"use strict\";\n  \n  var doc = document\n  ,id = 'getElementById'\n  ,tag = 'getElementsByTagName'\n  \n  //字符常量\n  ,MOD_NAME = 'laypage', DISABLED = 'layui-disabled'\n  \n  //构造器\n  ,Class = function(options){\n    var that = this;\n    that.config = options || {};\n    that.config.index = ++laypage.index;\n    that.render(true);\n  };\n\n  //判断传入的容器类型\n  Class.prototype.type = function(){\n    var config = this.config;\n    if(typeof config.elem === 'object'){\n      return config.elem.length === undefined ? 2 : 3;\n    }\n  };\n\n  //分页视图\n  Class.prototype.view = function(){\n    var that = this\n    ,config = that.config\n    ,groups = config.groups = 'groups' in config ? (config.groups|0) : 5; //连续页码个数\n    \n    //排版\n    config.layout = typeof config.layout === 'object' \n      ? config.layout \n    : ['prev', 'page', 'next'];\n    \n    config.count = config.count|0; //数据总数\n    config.curr = (config.curr|0) || 1; //当前页\n\n    //每页条数的选择项\n    config.limits = typeof config.limits === 'object'\n      ? config.limits\n    : [10, 20, 30, 40, 50];\n    config.limit = (config.limit|0) || 10; //默认条数\n    \n    //总页数\n    config.pages = Math.ceil(config.count/config.limit) || 1;\n    \n    //当前页不能超过总页数\n    if(config.curr > config.pages){\n      config.curr = config.pages;\n    }\n    \n    //连续分页个数不能低于0且不能大于总页数\n    if(groups < 0){\n      groups = 1;\n    } else if (groups > config.pages){\n      groups = config.pages;\n    }\n    \n    config.prev = 'prev' in config ? config.prev : '&#x4E0A;&#x4E00;&#x9875;'; //上一页文本\n    config.next = 'next' in config ? config.next : '&#x4E0B;&#x4E00;&#x9875;'; //下一页文本\n    \n    //计算当前组\n    var index = config.pages > groups \n      ? Math.ceil( (config.curr + (groups > 1 ? 1 : 0)) / (groups > 0 ? groups : 1) )\n    : 1\n    \n    //试图片段\n    ,views = {\n      //上一页\n      prev: function(){\n        return config.prev \n          ? '<a href=\"javascript:;\" class=\"layui-laypage-prev'+ (config.curr == 1 ? (' ' + DISABLED) : '') +'\" data-page=\"'+ (config.curr - 1) +'\">'+ config.prev +'</a>'\n        : '';\n      }()\n      \n      //页码\n      ,page: function(){\n        var pager = [];\n        \n        //数据量为0时，不输出页码\n        if(config.count < 1){\n          return '';\n        }\n        \n        //首页\n        if(index > 1 && config.first !== false && groups !== 0){\n          pager.push('<a href=\"javascript:;\" class=\"layui-laypage-first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+ (config.first || 1) +'</a>');\n        }\n\n        //计算当前页码组的起始页\n        var halve = Math.floor((groups-1)/2) //页码数等分\n        ,start = index > 1 ? config.curr - halve : 1\n        ,end = index > 1 ? (function(){\n          var max = config.curr + (groups - halve - 1);\n          return max > config.pages ? config.pages : max;\n        }()) : groups;\n        \n        //防止最后一组出现“不规定”的连续页码数\n        if(end - start < groups - 1){\n          start = end - groups + 1;\n        }\n\n        //输出左分割符\n        if(config.first !== false && start > 2){\n          pager.push('<span class=\"layui-laypage-spr\">&#x2026;</span>')\n        }\n        \n        //输出连续页码\n        for(; start <= end; start++){\n          if(start === config.curr){\n            //当前页\n            pager.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+ (/^#/.test(config.theme) ? 'style=\"background-color:'+ config.theme +';\"' : '') +'></em><em>'+ start +'</em></span>');\n          } else {\n            pager.push('<a href=\"javascript:;\" data-page=\"'+ start +'\">'+ start +'</a>');\n          }\n        }\n        \n        //输出输出右分隔符 & 末页\n        if(config.pages > groups && config.pages > end && config.last !== false){\n          if(end + 1 < config.pages){\n            pager.push('<span class=\"layui-laypage-spr\">&#x2026;</span>');\n          }\n          if(groups !== 0){\n            pager.push('<a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+ config.pages +'\">'+ (config.last || config.pages) +'</a>');\n          }\n        }\n\n        return pager.join('');\n      }()\n      \n      //下一页\n      ,next: function(){\n        return config.next \n          ? '<a href=\"javascript:;\" class=\"layui-laypage-next'+ (config.curr == config.pages ? (' ' + DISABLED) : '') +'\" data-page=\"'+ (config.curr + 1) +'\">'+ config.next +'</a>'\n        : '';\n      }()\n      \n      //数据总数\n      ,count: '<span class=\"layui-laypage-count\">共 '+ config.count +' 条</span>'\n      \n      //每页条数\n      ,limit: function(){\n        var options = ['<span class=\"layui-laypage-limits\"><select lay-ignore>'];\n        layui.each(config.limits, function(index, item){\n          options.push(\n            '<option value=\"'+ item +'\"'\n            +(item === config.limit ? 'selected' : '') \n            +'>'+ item +' 条/页</option>'\n          );\n        });\n        return options.join('') +'</select></span>';\n      }()\n      \n      //跳页区域\n      ,skip: function(){\n        return ['<span class=\"layui-laypage-skip\">&#x5230;&#x7B2C;'\n          ,'<input type=\"text\" min=\"1\" value=\"'+ config.curr +'\" class=\"layui-input\">'\n          ,'&#x9875;<button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button>'\n        ,'</span>'].join('');\n      }()\n    };\n\n    return ['<div class=\"layui-box layui-laypage layui-laypage-'+ (config.theme ? (\n      /^#/.test(config.theme) ? 'molv' : config.theme\n    ) : 'default') +'\" id=\"layui-laypage-'+ config.index +'\">'\n      ,function(){\n        var plate = [];\n        layui.each(config.layout, function(index, item){\n          if(views[item]){\n            plate.push(views[item])\n          }\n        });\n        return plate.join('');\n      }()\n    ,'</div>'].join('');\n  };\n\n  //跳页的回调\n  Class.prototype.jump = function(elem, isskip){\n    if(!elem) return;\n    var that = this\n    ,config = that.config\n    ,childs = elem.children\n    ,btn = elem[tag]('button')[0]\n    ,input = elem[tag]('input')[0]\n    ,select = elem[tag]('select')[0]\n    ,skip = function(){\n      var curr = input.value.replace(/\\s|\\D/g, '')|0;\n      if(curr){\n        config.curr = curr;\n        that.render();\n      }\n    };\n    \n    if(isskip) return skip();\n    \n    //页码\n    for(var i = 0, len = childs.length; i < len; i++){\n      if(childs[i].nodeName.toLowerCase() === 'a'){\n        laypage.on(childs[i], 'click', function(){\n          var curr = this.getAttribute('data-page')|0;\n          if(curr < 1 || curr > config.pages) return;\n          config.curr = curr;\n          that.render();\n        });\n      }\n    }\n    \n    //条数\n    if(select){\n      laypage.on(select, 'change', function(){\n        var value = this.value;\n        if(config.curr*value > config.count){\n          config.curr = Math.ceil(config.count/value);\n        }\n        config.limit = value;\n        that.render();\n      });\n    }\n    \n    //确定\n    if(btn){\n      laypage.on(btn, 'click', function(){\n        skip();\n      });\n    }\n  };\n  \n  //输入页数字控制\n  Class.prototype.skip = function(elem){\n    if(!elem) return;\n    var that = this, input = elem[tag]('input')[0];\n    if(!input) return;\n    laypage.on(input, 'keyup', function(e){\n      var value = this.value\n      ,keyCode = e.keyCode;\n      if(/^(37|38|39|40)$/.test(keyCode)) return;\n      if(/\\D/.test(value)){\n        this.value = value.replace(/\\D/, '');\n      }\n      if(keyCode === 13){\n        that.jump(elem, true)\n      }\n    });\n  };\n\n  //渲染分页\n  Class.prototype.render = function(load){\n    var that = this\n    ,config = that.config\n    ,type = that.type()\n    ,view = that.view();\n    \n    if(type === 2){\n      config.elem && (config.elem.innerHTML = view);\n    } else if(type === 3){\n      config.elem.html(view);\n    } else {\n      if(doc[id](config.elem)){\n        doc[id](config.elem).innerHTML = view;\n      }\n    }\n    \n    config.jump && config.jump(config, load);\n    \n    var elem = doc[id]('layui-laypage-' + config.index);\n    that.jump(elem);\n    \n    if(config.hash && !load){\n      location.hash = '!'+ config.hash +'='+ config.curr;\n    }\n    \n    that.skip(elem);\n  };\n  \n  //外部接口\n  var laypage = {\n    //分页渲染\n    render: function(options){\n      var o = new Class(options);\n      return o.index;\n    }\n    ,index: layui.laypage ? (layui.laypage.index + 10000) : 0\n    ,on: function(elem, even, fn){\n      elem.attachEvent ? elem.attachEvent('on'+ even, function(e){\n        fn.call(elem, e); //for ie\n      }) : elem.addEventListener(even, fn, false);\n      return this;\n    }\n  }\n\n  exports(MOD_NAME, laypage);\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/laytpl.js",
    "content": "﻿/**\n \n @Name : layui.laytpl 模板引擎\n @author 郑保乐\n @License：MIT\n \n */\n\nlayui.define(function(exports){\n\n  \"use strict\";\n\n  var config = {\n    open: '{{',\n    close: '}}'\n  };\n\n  var tool = {\n    exp: function(str){\n      return new RegExp(str, 'g');\n    },\n    //匹配满足规则内容\n    query: function(type, _, __){\n      var types = [\n        '#([\\\\s\\\\S])+?',   //js语句\n        '([^{#}])*?' //普通字段\n      ][type || 0];\n      return exp((_||'') + config.open + types + config.close + (__||''));\n    },   \n    escape: function(html){\n      return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')\n      .replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/\"/g, '&quot;');\n    },\n    error: function(e, tplog){\n      var error = 'Laytpl Error：';\n      typeof console === 'object' && console.error(error + e + '\\n'+ (tplog || ''));\n      return error + e;\n    }\n  };\n\n  var exp = tool.exp, Tpl = function(tpl){\n    this.tpl = tpl;\n  };\n\n  Tpl.pt = Tpl.prototype;\n\n  window.errors = 0;\n\n  //编译模版\n  Tpl.pt.parse = function(tpl, data){\n    var that = this, tplog = tpl;\n    var jss = exp('^'+config.open+'#', ''), jsse = exp(config.close+'$', '');\n    \n    tpl = tpl.replace(/\\s+|\\r|\\t|\\n/g, ' ').replace(exp(config.open+'#'), config.open+'# ')\n    \n    .replace(exp(config.close+'}'), '} '+config.close).replace(/\\\\/g, '\\\\\\\\')\n    \n    .replace(/(?=\"|')/g, '\\\\').replace(tool.query(), function(str){\n      str = str.replace(jss, '').replace(jsse, '');\n      return '\";' + str.replace(/\\\\/g, '') + ';view+=\"';\n    })\n    \n    .replace(tool.query(1), function(str){\n      var start = '\"+(';\n      if(str.replace(/\\s/g, '') === config.open+config.close){\n        return '';\n      }\n      str = str.replace(exp(config.open+'|'+config.close), '');\n      if(/^=/.test(str)){\n        str = str.replace(/^=/, '');\n        start = '\"+_escape_(';\n      }\n      return start + str.replace(/\\\\/g, '') + ')+\"';\n    });\n    \n    tpl = '\"use strict\";var view = \"' + tpl + '\";return view;';\n\n    try{\n      that.cache = tpl = new Function('d, _escape_', tpl);\n      return tpl(data, tool.escape);\n    } catch(e){\n      delete that.cache;\n      return tool.error(e, tplog);\n    }\n  };\n\n  Tpl.pt.render = function(data, callback){\n    var that = this, tpl;\n    if(!data) return tool.error('no data');\n    tpl = that.cache ? that.cache(data, tool.escape) : that.parse(that.tpl, data);\n    if(!callback) return tpl;\n    callback(tpl);\n  };\n\n  var laytpl = function(tpl){\n    if(typeof tpl !== 'string') return tool.error('Template not found');\n    return new Tpl(tpl);\n  };\n\n  laytpl.config = function(options){\n    options = options || {};\n    for(var i in options){\n      config[i] = options[i];\n    }\n  };\n\n  laytpl.v = '1.2.0';\n  \n  exports('laytpl', laytpl);\n\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/mobile/layer-mobile.js",
    "content": "/*!\n\n @Name：layer mobile v2.0.0 弹层组件移动版\n @author 郑保乐\n @Site：http://layer.layui.com/mobie/\n @License：MIT\n    \n */\n\nlayui.define(function(exports){\n  \n  \"use strict\";\n\n  var win = window, doc = document, query = 'querySelectorAll', claname = 'getElementsByClassName', S = function(s){\n    return doc[query](s);\n  };\n\n  //默认配置\n  var config = {\n    type: 0\n    ,shade: true\n    ,shadeClose: true\n    ,fixed: true\n    ,anim: 'scale' //默认动画类型\n  };\n\n  var ready = {\n    extend: function(obj){\n      var newobj = JSON.parse(JSON.stringify(config));\n      for(var i in obj){\n        newobj[i] = obj[i];\n      }\n      return newobj;\n    }, \n    timer: {}, end: {}\n  };\n\n  //点触事件\n  ready.touch = function(elem, fn){\n    elem.addEventListener('click', function(e){\n      fn.call(this, e);\n    }, false);\n  };\n\n  var index = 0, classs = ['layui-m-layer'], Layer = function(options){\n    var that = this;\n    that.config = ready.extend(options);\n    that.view();\n  };\n\n  Layer.prototype.view = function(){\n    var that = this, config = that.config, layerbox = doc.createElement('div');\n\n    that.id = layerbox.id = classs[0] + index;\n    layerbox.setAttribute('class', classs[0] + ' ' + classs[0]+(config.type || 0));\n    layerbox.setAttribute('index', index);\n    \n    //标题区域\n    var title = (function(){\n      var titype = typeof config.title === 'object';\n      return config.title\n      ? '<h3 style=\"'+ (titype ? config.title[1] : '') +'\">'+ (titype ? config.title[0] : config.title)  +'</h3>'\n      : '';\n    }());\n    \n    //按钮区域\n    var button = (function(){\n      typeof config.btn === 'string' && (config.btn = [config.btn]);\n      var btns = (config.btn || []).length, btndom;\n      if(btns === 0 || !config.btn){\n        return '';\n      }\n      btndom = '<span yes type=\"1\">'+ config.btn[0] +'</span>'\n      if(btns === 2){\n        btndom = '<span no type=\"0\">'+ config.btn[1] +'</span>' + btndom;\n      }\n      return '<div class=\"layui-m-layerbtn\">'+ btndom + '</div>';\n    }());\n    \n    if(!config.fixed){\n      config.top = config.hasOwnProperty('top') ?  config.top : 100;\n      config.style = config.style || '';\n      config.style += ' top:'+ ( doc.body.scrollTop + config.top) + 'px';\n    }\n    \n    if(config.type === 2){\n      config.content = '<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+ (config.content||'') +'</p>';\n    }\n    \n    if(config.skin) config.anim = 'up';\n    if(config.skin === 'msg') config.shade = false;\n    \n    layerbox.innerHTML = (config.shade ? '<div '+ (typeof config.shade === 'string' ? 'style=\"'+ config.shade +'\"' : '') +' class=\"layui-m-layershade\"></div>' : '')\n    +'<div class=\"layui-m-layermain\" '+ (!config.fixed ? 'style=\"position:static;\"' : '') +'>'\n      +'<div class=\"layui-m-layersection\">'\n        +'<div class=\"layui-m-layerchild '+ (config.skin ? 'layui-m-layer-' + config.skin + ' ' : '') + (config.className ? config.className : '') + ' ' + (config.anim ? 'layui-m-anim-' + config.anim : '') +'\" ' + ( config.style ? 'style=\"'+config.style+'\"' : '' ) +'>'\n          + title\n          +'<div class=\"layui-m-layercont\">'+ config.content +'</div>'\n          + button\n        +'</div>'\n      +'</div>'\n    +'</div>';\n    \n    if(!config.type || config.type === 2){\n      var dialogs = doc[claname](classs[0] + config.type), dialen = dialogs.length;\n      if(dialen >= 1){\n        layer.close(dialogs[0].getAttribute('index'))\n      }\n    }\n    \n    document.body.appendChild(layerbox);\n    var elem = that.elem = S('#'+that.id)[0];\n    config.success && config.success(elem);\n    \n    that.index = index++;\n    that.action(config, elem);\n  };\n\n  Layer.prototype.action = function(config, elem){\n    var that = this;\n    \n    //自动关闭\n    if(config.time){\n      ready.timer[that.index] = setTimeout(function(){\n        layer.close(that.index);\n      }, config.time*1000);\n    }\n    \n    //确认取消\n    var btn = function(){\n      var type = this.getAttribute('type');\n      if(type == 0){\n        config.no && config.no();\n        layer.close(that.index);\n      } else {\n        config.yes ? config.yes(that.index) : layer.close(that.index);\n      }\n    };\n    if(config.btn){\n      var btns = elem[claname]('layui-m-layerbtn')[0].children, btnlen = btns.length;\n      for(var ii = 0; ii < btnlen; ii++){\n        ready.touch(btns[ii], btn);\n      }\n    }\n    \n    //点遮罩关闭\n    if(config.shade && config.shadeClose){\n      var shade = elem[claname]('layui-m-layershade')[0];\n      ready.touch(shade, function(){\n        layer.close(that.index, config.end);\n      });\n    }\n\n    config.end && (ready.end[that.index] = config.end);\n  };\n\n  var layer = {\n    v: '2.0 m',\n    index: index,\n    \n    //核心方法\n    open: function(options){\n      var o = new Layer(options || {});\n      return o.index;\n    },\n    \n    close: function(index){\n      var ibox = S('#'+classs[0]+index)[0];\n      if(!ibox) return;\n      ibox.innerHTML = '';\n      doc.body.removeChild(ibox);\n      clearTimeout(ready.timer[index]);\n      delete ready.timer[index];\n      typeof ready.end[index] === 'function' && ready.end[index]();\n      delete ready.end[index];\n    },\n    \n    //关闭所有layer层\n    closeAll: function(){\n      var boxs = doc[claname](classs[0]);\n      for(var i = 0, len = boxs.length; i < len; i++){\n        layer.close((boxs[0].getAttribute('index')|0));\n      }\n    }\n  };\n\n  exports('layer-mobile', layer);\n\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/mobile/layim-mobile-open.js",
    "content": "/**\n\n @Name：layim mobile 开源包\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define(function(exports){\n  exports('layim-mobile', layui.v);\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/mobile/upload-mobile.js",
    "content": "/*!\n\n @Title: layui.upload 单文件上传 - 全浏览器兼容版\n @author 郑保乐\n @License：MIT\n\n */\n \nlayui.define(['layer-mobile', 'zepto'] , function(exports){\n  \"use strict\";\n  \n  var $ = layui.zepto;\n  var layer = layui['layer-mobile'];\n  var device = layui.device();\n  \n  var elemDragEnter = 'layui-upload-enter';\n  var elemIframe = 'layui-upload-iframe';\n \n  var msgConf = {\n    icon: 2\n    ,shift: 6\n  }, fileType = {\n    file: '文件'\n    ,video: '视频'\n    ,audio: '音频'\n  };\n  \n  layer.msg = function(content){\n    return layer.open({\n      content: content || ''\n      ,skin: 'msg'\n      ,time: 2 //2秒后自动关闭\n    });\n  };\n  \n  var Upload = function(options){\n    this.options = options;\n  };\n  \n  //初始化渲染\n  Upload.prototype.init = function(){\n    var that = this, options = that.options;\n    var body = $('body'), elem = $(options.elem || '.layui-upload-file');\n    var iframe = $('<iframe id=\"'+ elemIframe +'\" class=\"'+ elemIframe +'\" name=\"'+ elemIframe +'\"></iframe>');\n    \n    //插入iframe    \n    $('#'+elemIframe)[0] || body.append(iframe);\n    \n    return elem.each(function(index, item){\n      item = $(item);\n      var form = '<form target=\"'+ elemIframe +'\" method=\"'+ (options.method||'post') +'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+ (options.url||'') +'\"></form>';\n      \n      var type = item.attr('lay-type') || options.type; //获取文件类型\n\n      //包裹ui元素\n      if(!options.unwrap){\n        form = '<div class=\"layui-box layui-upload-button\">' + form + '<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+ (\n          item.attr('lay-title') || options.title|| ('上传'+ (fileType[type]||'图片') )\n        ) +'</span></div>';\n      }\n      \n      form = $(form);\n      \n      //拖拽支持\n      if(!options.unwrap){\n        form.on('dragover', function(e){\n          e.preventDefault();\n          $(this).addClass(elemDragEnter);\n        }).on('dragleave', function(){\n          $(this).removeClass(elemDragEnter);\n        }).on('drop', function(){\n          $(this).removeClass(elemDragEnter);\n        });\n      }\n      \n      //如果已经实例化，则移除包裹元素\n      if(item.parent('form').attr('target') === elemIframe){\n        if(options.unwrap){\n          item.unwrap();\n        } else {\n          item.parent().next().remove();\n          item.unwrap().unwrap();\n        }\n      };\n      \n      //包裹元素\n      item.wrap(form);\n      \n      //触发上传\n      item.off('change').on('change', function(){\n        that.action(this, type);\n      });\n    });\n  };\n  \n  //提交上传\n  Upload.prototype.action = function(input, type){\n    var that = this, options = that.options, val = input.value;\n    var item = $(input), ext = item.attr('lay-ext') || options.ext || ''; //获取支持上传的文件扩展名;\n\n    if(!val){\n      return;\n    };\n    \n    //校验文件\n    switch(type){\n      case 'file': //一般文件\n        if(ext && !RegExp('\\\\w\\\\.('+ ext +')$', 'i').test(escape(val))){\n          layer.msg('不支持该文件格式', msgConf);\n          return input.value = '';\n        }\n      break;\n      case 'video': //视频文件\n        if(!RegExp('\\\\w\\\\.('+ (ext||'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(val))){\n          layer.msg('不支持该视频格式', msgConf);\n          return input.value = '';\n        }\n      break;\n      case 'audio': //音频文件\n        if(!RegExp('\\\\w\\\\.('+ (ext||'mp3|wav|mid') +')$', 'i').test(escape(val))){\n          layer.msg('不支持该音频格式', msgConf);\n          return input.value = '';\n        }\n      break;\n      default: //图片文件\n        if(!RegExp('\\\\w\\\\.('+ (ext||'jpg|png|gif|bmp|jpeg') +')$', 'i').test(escape(val))){\n          layer.msg('不支持该图片格式', msgConf);\n          return input.value = '';\n        }\n      break;\n    }\n    \n    options.before && options.before(input);\n    item.parent().submit();\n\n    var iframe = $('#'+elemIframe), timer = setInterval(function() {\n      var res;\n      try {\n        res = iframe.contents().find('body').text();\n      } catch(e) {\n        layer.msg('上传接口存在跨域', msgConf);\n        clearInterval(timer);\n      }\n      if(res){\n        clearInterval(timer);\n        iframe.contents().find('body').html('');\n        try {\n          res = JSON.parse(res);\n        } catch(e){\n          res = {};\n          return layer.msg('请对上传接口返回JSON字符', msgConf);\n        }\n        typeof options.success === 'function' && options.success(res, input);\n      }\n    }, 30); \n    \n    input.value = '';\n  };\n  \n  //暴露接口\n  exports('upload-mobile', function(options){\n    var upload = new Upload(options = options || {});\n    upload.init();\n  });\n});\n\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/mobile/zepto.js",
    "content": "/* Zepto v1.2.0 - zepto event ajax form ie - zeptojs.com/license */\n\nlayui.define(function(exports){\n  \n  var Zepto = (function() {\n  var undefined, key, $, classList, emptyArray = [], concat = emptyArray.concat, filter = emptyArray.filter, slice = emptyArray.slice,\n    document = window.document,\n    elementDisplay = {}, classCache = {},\n    cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },\n    fragmentRE = /^\\s*<(\\w+|!)[^>]*>/,\n    singleTagRE = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n    tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n    rootNodeRE = /^(?:body|html)$/i,\n    capitalRE = /([A-Z])/g,\n\n    // special attributes that should be get/set via method calls\n    methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],\n\n    adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],\n    table = document.createElement('table'),\n    tableRow = document.createElement('tr'),\n    containers = {\n      'tr': document.createElement('tbody'),\n      'tbody': table, 'thead': table, 'tfoot': table,\n      'td': tableRow, 'th': tableRow,\n      '*': document.createElement('div')\n    },\n    readyRE = /complete|loaded|interactive/,\n    simpleSelectorRE = /^[\\w-]*$/,\n    class2type = {},\n    toString = class2type.toString,\n    zepto = {},\n    camelize, uniq,\n    tempParent = document.createElement('div'),\n    propMap = {\n      'tabindex': 'tabIndex',\n      'readonly': 'readOnly',\n      'for': 'htmlFor',\n      'class': 'className',\n      'maxlength': 'maxLength',\n      'cellspacing': 'cellSpacing',\n      'cellpadding': 'cellPadding',\n      'rowspan': 'rowSpan',\n      'colspan': 'colSpan',\n      'usemap': 'useMap',\n      'frameborder': 'frameBorder',\n      'contenteditable': 'contentEditable'\n    },\n    isArray = Array.isArray ||\n      function(object){ return object instanceof Array }\n\n  zepto.matches = function(element, selector) {\n    if (!selector || !element || element.nodeType !== 1) return false\n    var matchesSelector = element.matches || element.webkitMatchesSelector ||\n                          element.mozMatchesSelector || element.oMatchesSelector ||\n                          element.matchesSelector\n    if (matchesSelector) return matchesSelector.call(element, selector)\n    // fall back to performing a selector:\n    var match, parent = element.parentNode, temp = !parent\n    if (temp) (parent = tempParent).appendChild(element)\n    match = ~zepto.qsa(parent, selector).indexOf(element)\n    temp && tempParent.removeChild(element)\n    return match\n  }\n\n  function type(obj) {\n    return obj == null ? String(obj) :\n      class2type[toString.call(obj)] || \"object\"\n  }\n\n  function isFunction(value) { return type(value) == \"function\" }\n  function isWindow(obj)     { return obj != null && obj == obj.window }\n  function isDocument(obj)   { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }\n  function isObject(obj)     { return type(obj) == \"object\" }\n  function isPlainObject(obj) {\n    return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype\n  }\n\n  function likeArray(obj) {\n    var length = !!obj && 'length' in obj && obj.length,\n      type = $.type(obj)\n\n    return 'function' != type && !isWindow(obj) && (\n      'array' == type || length === 0 ||\n        (typeof length == 'number' && length > 0 && (length - 1) in obj)\n    )\n  }\n\n  function compact(array) { return filter.call(array, function(item){ return item != null }) }\n  function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }\n  camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }\n  function dasherize(str) {\n    return str.replace(/::/g, '/')\n           .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n           .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n           .replace(/_/g, '-')\n           .toLowerCase()\n  }\n  uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }\n\n  function classRE(name) {\n    return name in classCache ?\n      classCache[name] : (classCache[name] = new RegExp('(^|\\\\s)' + name + '(\\\\s|$)'))\n  }\n\n  function maybeAddPx(name, value) {\n    return (typeof value == \"number\" && !cssNumber[dasherize(name)]) ? value + \"px\" : value\n  }\n\n  function defaultDisplay(nodeName) {\n    var element, display\n    if (!elementDisplay[nodeName]) {\n      element = document.createElement(nodeName)\n      document.body.appendChild(element)\n      display = getComputedStyle(element, '').getPropertyValue(\"display\")\n      element.parentNode.removeChild(element)\n      display == \"none\" && (display = \"block\")\n      elementDisplay[nodeName] = display\n    }\n    return elementDisplay[nodeName]\n  }\n\n  function children(element) {\n    return 'children' in element ?\n      slice.call(element.children) :\n      $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })\n  }\n\n  function Z(dom, selector) {\n    var i, len = dom ? dom.length : 0\n    for (i = 0; i < len; i++) this[i] = dom[i]\n    this.length = len\n    this.selector = selector || ''\n  }\n\n  // `$.zepto.fragment` takes a html string and an optional tag name\n  // to generate DOM nodes from the given html string.\n  // The generated DOM nodes are returned as an array.\n  // This function can be overridden in plugins for example to make\n  // it compatible with browsers that don't support the DOM fully.\n  zepto.fragment = function(html, name, properties) {\n    var dom, nodes, container\n\n    // A special case optimization for a single tag\n    if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))\n\n    if (!dom) {\n      if (html.replace) html = html.replace(tagExpanderRE, \"<$1></$2>\")\n      if (name === undefined) name = fragmentRE.test(html) && RegExp.$1\n      if (!(name in containers)) name = '*'\n\n      container = containers[name]\n      container.innerHTML = '' + html\n      dom = $.each(slice.call(container.childNodes), function(){\n        container.removeChild(this)\n      })\n    }\n\n    if (isPlainObject(properties)) {\n      nodes = $(dom)\n      $.each(properties, function(key, value) {\n        if (methodAttributes.indexOf(key) > -1) nodes[key](value)\n        else nodes.attr(key, value)\n      })\n    }\n\n    return dom\n  }\n\n  // `$.zepto.Z` swaps out the prototype of the given `dom` array\n  // of nodes with `$.fn` and thus supplying all the Zepto functions\n  // to the array. This method can be overridden in plugins.\n  zepto.Z = function(dom, selector) {\n    return new Z(dom, selector)\n  }\n\n  // `$.zepto.isZ` should return `true` if the given object is a Zepto\n  // collection. This method can be overridden in plugins.\n  zepto.isZ = function(object) {\n    return object instanceof zepto.Z\n  }\n\n  // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and\n  // takes a CSS selector and an optional context (and handles various\n  // special cases).\n  // This method can be overridden in plugins.\n  zepto.init = function(selector, context) {\n    var dom\n    // If nothing given, return an empty Zepto collection\n    if (!selector) return zepto.Z()\n    // Optimize for string selectors\n    else if (typeof selector == 'string') {\n      selector = selector.trim()\n      // If it's a html fragment, create nodes from it\n      // Note: In both Chrome 21 and Firefox 15, DOM error 12\n      // is thrown if the fragment doesn't begin with <\n      if (selector[0] == '<' && fragmentRE.test(selector))\n        dom = zepto.fragment(selector, RegExp.$1, context), selector = null\n      // If there's a context, create a collection on that context first, and select\n      // nodes from there\n      else if (context !== undefined) return $(context).find(selector)\n      // If it's a CSS selector, use it to select nodes.\n      else dom = zepto.qsa(document, selector)\n    }\n    // If a function is given, call it when the DOM is ready\n    else if (isFunction(selector)) return $(document).ready(selector)\n    // If a Zepto collection is given, just return it\n    else if (zepto.isZ(selector)) return selector\n    else {\n      // normalize array if an array of nodes is given\n      if (isArray(selector)) dom = compact(selector)\n      // Wrap DOM nodes.\n      else if (isObject(selector))\n        dom = [selector], selector = null\n      // If it's a html fragment, create nodes from it\n      else if (fragmentRE.test(selector))\n        dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null\n      // If there's a context, create a collection on that context first, and select\n      // nodes from there\n      else if (context !== undefined) return $(context).find(selector)\n      // And last but no least, if it's a CSS selector, use it to select nodes.\n      else dom = zepto.qsa(document, selector)\n    }\n    // create a new Zepto collection from the nodes found\n    return zepto.Z(dom, selector)\n  }\n\n  // `$` will be the base `Zepto` object. When calling this\n  // function just call `$.zepto.init, which makes the implementation\n  // details of selecting nodes and creating Zepto collections\n  // patchable in plugins.\n  $ = function(selector, context){\n    return zepto.init(selector, context)\n  }\n\n  function extend(target, source, deep) {\n    for (key in source)\n      if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {\n        if (isPlainObject(source[key]) && !isPlainObject(target[key]))\n          target[key] = {}\n        if (isArray(source[key]) && !isArray(target[key]))\n          target[key] = []\n        extend(target[key], source[key], deep)\n      }\n      else if (source[key] !== undefined) target[key] = source[key]\n  }\n\n  // Copy all but undefined properties from one or more\n  // objects to the `target` object.\n  $.extend = function(target){\n    var deep, args = slice.call(arguments, 1)\n    if (typeof target == 'boolean') {\n      deep = target\n      target = args.shift()\n    }\n    args.forEach(function(arg){ extend(target, arg, deep) })\n    return target\n  }\n\n  // `$.zepto.qsa` is Zepto's CSS selector implementation which\n  // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.\n  // This method can be overridden in plugins.\n  zepto.qsa = function(element, selector){\n    var found,\n        maybeID = selector[0] == '#',\n        maybeClass = !maybeID && selector[0] == '.',\n        nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked\n        isSimple = simpleSelectorRE.test(nameOnly)\n    return (element.getElementById && isSimple && maybeID) ? // Safari DocumentFragment doesn't have getElementById\n      ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :\n      (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :\n      slice.call(\n        isSimple && !maybeID && element.getElementsByClassName ? // DocumentFragment doesn't have getElementsByClassName/TagName\n          maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class\n          element.getElementsByTagName(selector) : // Or a tag\n          element.querySelectorAll(selector) // Or it's not simple, and we need to query all\n      )\n  }\n\n  function filtered(nodes, selector) {\n    return selector == null ? $(nodes) : $(nodes).filter(selector)\n  }\n\n  $.contains = document.documentElement.contains ?\n    function(parent, node) {\n      return parent !== node && parent.contains(node)\n    } :\n    function(parent, node) {\n      while (node && (node = node.parentNode))\n        if (node === parent) return true\n      return false\n    }\n\n  function funcArg(context, arg, idx, payload) {\n    return isFunction(arg) ? arg.call(context, idx, payload) : arg\n  }\n\n  function setAttribute(node, name, value) {\n    value == null ? node.removeAttribute(name) : node.setAttribute(name, value)\n  }\n\n  // access className property while respecting SVGAnimatedString\n  function className(node, value){\n    var klass = node.className || '',\n        svg   = klass && klass.baseVal !== undefined\n\n    if (value === undefined) return svg ? klass.baseVal : klass\n    svg ? (klass.baseVal = value) : (node.className = value)\n  }\n\n  // \"true\"  => true\n  // \"false\" => false\n  // \"null\"  => null\n  // \"42\"    => 42\n  // \"42.5\"  => 42.5\n  // \"08\"    => \"08\"\n  // JSON    => parse if valid\n  // String  => self\n  function deserializeValue(value) {\n    try {\n      return value ?\n        value == \"true\" ||\n        ( value == \"false\" ? false :\n          value == \"null\" ? null :\n          +value + \"\" == value ? +value :\n          /^[\\[\\{]/.test(value) ? $.parseJSON(value) :\n          value )\n        : value\n    } catch(e) {\n      return value\n    }\n  }\n\n  $.type = type\n  $.isFunction = isFunction\n  $.isWindow = isWindow\n  $.isArray = isArray\n  $.isPlainObject = isPlainObject\n\n  $.isEmptyObject = function(obj) {\n    var name\n    for (name in obj) return false\n    return true\n  }\n\n  $.isNumeric = function(val) {\n    var num = Number(val), type = typeof val\n    return val != null && type != 'boolean' &&\n      (type != 'string' || val.length) &&\n      !isNaN(num) && isFinite(num) || false\n  }\n\n  $.inArray = function(elem, array, i){\n    return emptyArray.indexOf.call(array, elem, i)\n  }\n\n  $.camelCase = camelize\n  $.trim = function(str) {\n    return str == null ? \"\" : String.prototype.trim.call(str)\n  }\n\n  // plugin compatibility\n  $.uuid = 0\n  $.support = { }\n  $.expr = { }\n  $.noop = function() {}\n\n  $.map = function(elements, callback){\n    var value, values = [], i, key\n    if (likeArray(elements))\n      for (i = 0; i < elements.length; i++) {\n        value = callback(elements[i], i)\n        if (value != null) values.push(value)\n      }\n    else\n      for (key in elements) {\n        value = callback(elements[key], key)\n        if (value != null) values.push(value)\n      }\n    return flatten(values)\n  }\n\n  $.each = function(elements, callback){\n    var i, key\n    if (likeArray(elements)) {\n      for (i = 0; i < elements.length; i++)\n        if (callback.call(elements[i], i, elements[i]) === false) return elements\n    } else {\n      for (key in elements)\n        if (callback.call(elements[key], key, elements[key]) === false) return elements\n    }\n\n    return elements\n  }\n\n  $.grep = function(elements, callback){\n    return filter.call(elements, callback)\n  }\n\n  if (window.JSON) $.parseJSON = JSON.parse\n\n  // Populate the class2type map\n  $.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n    class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase()\n  })\n\n  // Define methods that will be available on all\n  // Zepto collections\n  $.fn = {\n    constructor: zepto.Z,\n    length: 0,\n\n    // Because a collection acts like an array\n    // copy over these useful array functions.\n    forEach: emptyArray.forEach,\n    reduce: emptyArray.reduce,\n    push: emptyArray.push,\n    sort: emptyArray.sort,\n    splice: emptyArray.splice,\n    indexOf: emptyArray.indexOf,\n    concat: function(){\n      var i, value, args = []\n      for (i = 0; i < arguments.length; i++) {\n        value = arguments[i]\n        args[i] = zepto.isZ(value) ? value.toArray() : value\n      }\n      return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)\n    },\n\n    // `map` and `slice` in the jQuery API work differently\n    // from their array counterparts\n    map: function(fn){\n      return $($.map(this, function(el, i){ return fn.call(el, i, el) }))\n    },\n    slice: function(){\n      return $(slice.apply(this, arguments))\n    },\n\n    ready: function(callback){\n      // need to check if document.body exists for IE as that browser reports\n      // document ready when it hasn't yet created the body element\n      if (readyRE.test(document.readyState) && document.body) callback($)\n      else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false)\n      return this\n    },\n    get: function(idx){\n      return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]\n    },\n    toArray: function(){ return this.get() },\n    size: function(){\n      return this.length\n    },\n    remove: function(){\n      return this.each(function(){\n        if (this.parentNode != null)\n          this.parentNode.removeChild(this)\n      })\n    },\n    each: function(callback){\n      emptyArray.every.call(this, function(el, idx){\n        return callback.call(el, idx, el) !== false\n      })\n      return this\n    },\n    filter: function(selector){\n      if (isFunction(selector)) return this.not(this.not(selector))\n      return $(filter.call(this, function(element){\n        return zepto.matches(element, selector)\n      }))\n    },\n    add: function(selector,context){\n      return $(uniq(this.concat($(selector,context))))\n    },\n    is: function(selector){\n      return this.length > 0 && zepto.matches(this[0], selector)\n    },\n    not: function(selector){\n      var nodes=[]\n      if (isFunction(selector) && selector.call !== undefined)\n        this.each(function(idx){\n          if (!selector.call(this,idx)) nodes.push(this)\n        })\n      else {\n        var excludes = typeof selector == 'string' ? this.filter(selector) :\n          (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)\n        this.forEach(function(el){\n          if (excludes.indexOf(el) < 0) nodes.push(el)\n        })\n      }\n      return $(nodes)\n    },\n    has: function(selector){\n      return this.filter(function(){\n        return isObject(selector) ?\n          $.contains(this, selector) :\n          $(this).find(selector).size()\n      })\n    },\n    eq: function(idx){\n      return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)\n    },\n    first: function(){\n      var el = this[0]\n      return el && !isObject(el) ? el : $(el)\n    },\n    last: function(){\n      var el = this[this.length - 1]\n      return el && !isObject(el) ? el : $(el)\n    },\n    find: function(selector){\n      var result, $this = this\n      if (!selector) result = $()\n      else if (typeof selector == 'object')\n        result = $(selector).filter(function(){\n          var node = this\n          return emptyArray.some.call($this, function(parent){\n            return $.contains(parent, node)\n          })\n        })\n      else if (this.length == 1) result = $(zepto.qsa(this[0], selector))\n      else result = this.map(function(){ return zepto.qsa(this, selector) })\n      return result\n    },\n    closest: function(selector, context){\n      var nodes = [], collection = typeof selector == 'object' && $(selector)\n      this.each(function(_, node){\n        while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))\n          node = node !== context && !isDocument(node) && node.parentNode\n        if (node && nodes.indexOf(node) < 0) nodes.push(node)\n      })\n      return $(nodes)\n    },\n    parents: function(selector){\n      var ancestors = [], nodes = this\n      while (nodes.length > 0)\n        nodes = $.map(nodes, function(node){\n          if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {\n            ancestors.push(node)\n            return node\n          }\n        })\n      return filtered(ancestors, selector)\n    },\n    parent: function(selector){\n      return filtered(uniq(this.pluck('parentNode')), selector)\n    },\n    children: function(selector){\n      return filtered(this.map(function(){ return children(this) }), selector)\n    },\n    contents: function() {\n      return this.map(function() { return this.contentDocument || slice.call(this.childNodes) })\n    },\n    siblings: function(selector){\n      return filtered(this.map(function(i, el){\n        return filter.call(children(el.parentNode), function(child){ return child!==el })\n      }), selector)\n    },\n    empty: function(){\n      return this.each(function(){ this.innerHTML = '' })\n    },\n    // `pluck` is borrowed from Prototype.js\n    pluck: function(property){\n      return $.map(this, function(el){ return el[property] })\n    },\n    show: function(){\n      return this.each(function(){\n        this.style.display == \"none\" && (this.style.display = '')\n        if (getComputedStyle(this, '').getPropertyValue(\"display\") == \"none\")\n          this.style.display = defaultDisplay(this.nodeName)\n      })\n    },\n    replaceWith: function(newContent){\n      return this.before(newContent).remove()\n    },\n    wrap: function(structure){\n      var func = isFunction(structure)\n      if (this[0] && !func)\n        var dom   = $(structure).get(0),\n            clone = dom.parentNode || this.length > 1\n\n      return this.each(function(index){\n        $(this).wrapAll(\n          func ? structure.call(this, index) :\n            clone ? dom.cloneNode(true) : dom\n        )\n      })\n    },\n    wrapAll: function(structure){\n      if (this[0]) {\n        $(this[0]).before(structure = $(structure))\n        var children\n        // drill down to the inmost element\n        while ((children = structure.children()).length) structure = children.first()\n        $(structure).append(this)\n      }\n      return this\n    },\n    wrapInner: function(structure){\n      var func = isFunction(structure)\n      return this.each(function(index){\n        var self = $(this), contents = self.contents(),\n            dom  = func ? structure.call(this, index) : structure\n        contents.length ? contents.wrapAll(dom) : self.append(dom)\n      })\n    },\n    unwrap: function(){\n      this.parent().each(function(){\n        $(this).replaceWith($(this).children())\n      })\n      return this\n    },\n    clone: function(){\n      return this.map(function(){ return this.cloneNode(true) })\n    },\n    hide: function(){\n      return this.css(\"display\", \"none\")\n    },\n    toggle: function(setting){\n      return this.each(function(){\n        var el = $(this)\n        ;(setting === undefined ? el.css(\"display\") == \"none\" : setting) ? el.show() : el.hide()\n      })\n    },\n    prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },\n    next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },\n    html: function(html){\n      return 0 in arguments ?\n        this.each(function(idx){\n          var originHtml = this.innerHTML\n          $(this).empty().append( funcArg(this, html, idx, originHtml) )\n        }) :\n        (0 in this ? this[0].innerHTML : null)\n    },\n    text: function(text){\n      return 0 in arguments ?\n        this.each(function(idx){\n          var newText = funcArg(this, text, idx, this.textContent)\n          this.textContent = newText == null ? '' : ''+newText\n        }) :\n        (0 in this ? this.pluck('textContent').join(\"\") : null)\n    },\n    attr: function(name, value){\n      var result\n      return (typeof name == 'string' && !(1 in arguments)) ?\n        (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) :\n        this.each(function(idx){\n          if (this.nodeType !== 1) return\n          if (isObject(name)) for (key in name) setAttribute(this, key, name[key])\n          else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))\n        })\n    },\n    removeAttr: function(name){\n      return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){\n        setAttribute(this, attribute)\n      }, this)})\n    },\n    prop: function(name, value){\n      name = propMap[name] || name\n      return (1 in arguments) ?\n        this.each(function(idx){\n          this[name] = funcArg(this, value, idx, this[name])\n        }) :\n        (this[0] && this[0][name])\n    },\n    removeProp: function(name){\n      name = propMap[name] || name\n      return this.each(function(){ delete this[name] })\n    },\n    data: function(name, value){\n      var attrName = 'data-' + name.replace(capitalRE, '-$1').toLowerCase()\n\n      var data = (1 in arguments) ?\n        this.attr(attrName, value) :\n        this.attr(attrName)\n\n      return data !== null ? deserializeValue(data) : undefined\n    },\n    val: function(value){\n      if (0 in arguments) {\n        if (value == null) value = \"\"\n        return this.each(function(idx){\n          this.value = funcArg(this, value, idx, this.value)\n        })\n      } else {\n        return this[0] && (this[0].multiple ?\n           $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') :\n           this[0].value)\n      }\n    },\n    offset: function(coordinates){\n      if (coordinates) return this.each(function(index){\n        var $this = $(this),\n            coords = funcArg(this, coordinates, index, $this.offset()),\n            parentOffset = $this.offsetParent().offset(),\n            props = {\n              top:  coords.top  - parentOffset.top,\n              left: coords.left - parentOffset.left\n            }\n\n        if ($this.css('position') == 'static') props['position'] = 'relative'\n        $this.css(props)\n      })\n      if (!this.length) return null\n      if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0]))\n        return {top: 0, left: 0}\n      var obj = this[0].getBoundingClientRect()\n      return {\n        left: obj.left + window.pageXOffset,\n        top: obj.top + window.pageYOffset,\n        width: Math.round(obj.width),\n        height: Math.round(obj.height)\n      }\n    },\n    css: function(property, value){\n      if (arguments.length < 2) {\n        var element = this[0]\n        if (typeof property == 'string') {\n          if (!element) return\n          return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)\n        } else if (isArray(property)) {\n          if (!element) return\n          var props = {}\n          var computedStyle = getComputedStyle(element, '')\n          $.each(property, function(_, prop){\n            props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))\n          })\n          return props\n        }\n      }\n\n      var css = ''\n      if (type(property) == 'string') {\n        if (!value && value !== 0)\n          this.each(function(){ this.style.removeProperty(dasherize(property)) })\n        else\n          css = dasherize(property) + \":\" + maybeAddPx(property, value)\n      } else {\n        for (key in property)\n          if (!property[key] && property[key] !== 0)\n            this.each(function(){ this.style.removeProperty(dasherize(key)) })\n          else\n            css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'\n      }\n\n      return this.each(function(){ this.style.cssText += ';' + css })\n    },\n    index: function(element){\n      return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])\n    },\n    hasClass: function(name){\n      if (!name) return false\n      return emptyArray.some.call(this, function(el){\n        return this.test(className(el))\n      }, classRE(name))\n    },\n    addClass: function(name){\n      if (!name) return this\n      return this.each(function(idx){\n        if (!('className' in this)) return\n        classList = []\n        var cls = className(this), newName = funcArg(this, name, idx, cls)\n        newName.split(/\\s+/g).forEach(function(klass){\n          if (!$(this).hasClass(klass)) classList.push(klass)\n        }, this)\n        classList.length && className(this, cls + (cls ? \" \" : \"\") + classList.join(\" \"))\n      })\n    },\n    removeClass: function(name){\n      return this.each(function(idx){\n        if (!('className' in this)) return\n        if (name === undefined) return className(this, '')\n        classList = className(this)\n        funcArg(this, name, idx, classList).split(/\\s+/g).forEach(function(klass){\n          classList = classList.replace(classRE(klass), \" \")\n        })\n        className(this, classList.trim())\n      })\n    },\n    toggleClass: function(name, when){\n      if (!name) return this\n      return this.each(function(idx){\n        var $this = $(this), names = funcArg(this, name, idx, className(this))\n        names.split(/\\s+/g).forEach(function(klass){\n          (when === undefined ? !$this.hasClass(klass) : when) ?\n            $this.addClass(klass) : $this.removeClass(klass)\n        })\n      })\n    },\n    scrollTop: function(value){\n      if (!this.length) return\n      var hasScrollTop = 'scrollTop' in this[0]\n      if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset\n      return this.each(hasScrollTop ?\n        function(){ this.scrollTop = value } :\n        function(){ this.scrollTo(this.scrollX, value) })\n    },\n    scrollLeft: function(value){\n      if (!this.length) return\n      var hasScrollLeft = 'scrollLeft' in this[0]\n      if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset\n      return this.each(hasScrollLeft ?\n        function(){ this.scrollLeft = value } :\n        function(){ this.scrollTo(value, this.scrollY) })\n    },\n    position: function() {\n      if (!this.length) return\n\n      var elem = this[0],\n        // Get *real* offsetParent\n        offsetParent = this.offsetParent(),\n        // Get correct offsets\n        offset       = this.offset(),\n        parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()\n\n      // Subtract element margins\n      // note: when an element has margin: auto the offsetLeft and marginLeft\n      // are the same in Safari causing offset.left to incorrectly be 0\n      offset.top  -= parseFloat( $(elem).css('margin-top') ) || 0\n      offset.left -= parseFloat( $(elem).css('margin-left') ) || 0\n\n      // Add offsetParent borders\n      parentOffset.top  += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0\n      parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0\n\n      // Subtract the two offsets\n      return {\n        top:  offset.top  - parentOffset.top,\n        left: offset.left - parentOffset.left\n      }\n    },\n    offsetParent: function() {\n      return this.map(function(){\n        var parent = this.offsetParent || document.body\n        while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css(\"position\") == \"static\")\n          parent = parent.offsetParent\n        return parent\n      })\n    }\n  }\n\n  // for now\n  $.fn.detach = $.fn.remove\n\n  // Generate the `width` and `height` functions\n  ;['width', 'height'].forEach(function(dimension){\n    var dimensionProperty =\n      dimension.replace(/./, function(m){ return m[0].toUpperCase() })\n\n    $.fn[dimension] = function(value){\n      var offset, el = this[0]\n      if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] :\n        isDocument(el) ? el.documentElement['scroll' + dimensionProperty] :\n        (offset = this.offset()) && offset[dimension]\n      else return this.each(function(idx){\n        el = $(this)\n        el.css(dimension, funcArg(this, value, idx, el[dimension]()))\n      })\n    }\n  })\n\n  function traverseNode(node, fun) {\n    fun(node)\n    for (var i = 0, len = node.childNodes.length; i < len; i++)\n      traverseNode(node.childNodes[i], fun)\n  }\n\n  // Generate the `after`, `prepend`, `before`, `append`,\n  // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.\n  adjacencyOperators.forEach(function(operator, operatorIndex) {\n    var inside = operatorIndex % 2 //=> prepend, append\n\n    $.fn[operator] = function(){\n      // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings\n      var argType, nodes = $.map(arguments, function(arg) {\n            var arr = []\n            argType = type(arg)\n            if (argType == \"array\") {\n              arg.forEach(function(el) {\n                if (el.nodeType !== undefined) return arr.push(el)\n                else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())\n                arr = arr.concat(zepto.fragment(el))\n              })\n              return arr\n            }\n            return argType == \"object\" || arg == null ?\n              arg : zepto.fragment(arg)\n          }),\n          parent, copyByClone = this.length > 1\n      if (nodes.length < 1) return this\n\n      return this.each(function(_, target){\n        parent = inside ? target : target.parentNode\n\n        // convert all methods to a \"before\" operation\n        target = operatorIndex == 0 ? target.nextSibling :\n                 operatorIndex == 1 ? target.firstChild :\n                 operatorIndex == 2 ? target :\n                 null\n\n        var parentInDocument = $.contains(document.documentElement, parent)\n\n        nodes.forEach(function(node){\n          if (copyByClone) node = node.cloneNode(true)\n          else if (!parent) return $(node).remove()\n\n          parent.insertBefore(node, target)\n          if (parentInDocument) traverseNode(node, function(el){\n            if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&\n               (!el.type || el.type === 'text/javascript') && !el.src){\n              var target = el.ownerDocument ? el.ownerDocument.defaultView : window\n              target['eval'].call(target, el.innerHTML)\n            }\n          })\n        })\n      })\n    }\n\n    // after    => insertAfter\n    // prepend  => prependTo\n    // before   => insertBefore\n    // append   => appendTo\n    $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){\n      $(html)[operator](this)\n      return this\n    }\n  })\n\n  zepto.Z.prototype = Z.prototype = $.fn\n\n  // Export internal API functions in the `$.zepto` namespace\n  zepto.uniq = uniq\n  zepto.deserializeValue = deserializeValue\n  $.zepto = zepto\n\n  return $\n})()\n\n;(function($){\n  var _zid = 1, undefined,\n      slice = Array.prototype.slice,\n      isFunction = $.isFunction,\n      isString = function(obj){ return typeof obj == 'string' },\n      handlers = {},\n      specialEvents={},\n      focusinSupported = 'onfocusin' in window,\n      focus = { focus: 'focusin', blur: 'focusout' },\n      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }\n\n  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'\n\n  function zid(element) {\n    return element._zid || (element._zid = _zid++)\n  }\n  function findHandlers(element, event, fn, selector) {\n    event = parse(event)\n    if (event.ns) var matcher = matcherFor(event.ns)\n    return (handlers[zid(element)] || []).filter(function(handler) {\n      return handler\n        && (!event.e  || handler.e == event.e)\n        && (!event.ns || matcher.test(handler.ns))\n        && (!fn       || zid(handler.fn) === zid(fn))\n        && (!selector || handler.sel == selector)\n    })\n  }\n  function parse(event) {\n    var parts = ('' + event).split('.')\n    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}\n  }\n  function matcherFor(ns) {\n    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')\n  }\n\n  function eventCapture(handler, captureSetting) {\n    return handler.del &&\n      (!focusinSupported && (handler.e in focus)) ||\n      !!captureSetting\n  }\n\n  function realEvent(type) {\n    return hover[type] || (focusinSupported && focus[type]) || type\n  }\n\n  function add(element, events, fn, data, selector, delegator, capture){\n    var id = zid(element), set = (handlers[id] || (handlers[id] = []))\n    events.split(/\\s/).forEach(function(event){\n      if (event == 'ready') return $(document).ready(fn)\n      var handler   = parse(event)\n      handler.fn    = fn\n      handler.sel   = selector\n      // emulate mouseenter, mouseleave\n      if (handler.e in hover) fn = function(e){\n        var related = e.relatedTarget\n        if (!related || (related !== this && !$.contains(this, related)))\n          return handler.fn.apply(this, arguments)\n      }\n      handler.del   = delegator\n      var callback  = delegator || fn\n      handler.proxy = function(e){\n        e = compatible(e)\n        if (e.isImmediatePropagationStopped()) return\n        e.data = data\n        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))\n        if (result === false) e.preventDefault(), e.stopPropagation()\n        return result\n      }\n      handler.i = set.length\n      set.push(handler)\n      if ('addEventListener' in element)\n        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))\n    })\n  }\n  function remove(element, events, fn, selector, capture){\n    var id = zid(element)\n    ;(events || '').split(/\\s/).forEach(function(event){\n      findHandlers(element, event, fn, selector).forEach(function(handler){\n        delete handlers[id][handler.i]\n      if ('removeEventListener' in element)\n        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))\n      })\n    })\n  }\n\n  $.event = { add: add, remove: remove }\n\n  $.proxy = function(fn, context) {\n    var args = (2 in arguments) && slice.call(arguments, 2)\n    if (isFunction(fn)) {\n      var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }\n      proxyFn._zid = zid(fn)\n      return proxyFn\n    } else if (isString(context)) {\n      if (args) {\n        args.unshift(fn[context], fn)\n        return $.proxy.apply(null, args)\n      } else {\n        return $.proxy(fn[context], fn)\n      }\n    } else {\n      throw new TypeError(\"expected function\")\n    }\n  }\n\n  $.fn.bind = function(event, data, callback){\n    return this.on(event, data, callback)\n  }\n  $.fn.unbind = function(event, callback){\n    return this.off(event, callback)\n  }\n  $.fn.one = function(event, selector, data, callback){\n    return this.on(event, selector, data, callback, 1)\n  }\n\n  var returnTrue = function(){return true},\n      returnFalse = function(){return false},\n      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,\n      eventMethods = {\n        preventDefault: 'isDefaultPrevented',\n        stopImmediatePropagation: 'isImmediatePropagationStopped',\n        stopPropagation: 'isPropagationStopped'\n      }\n\n  function compatible(event, source) {\n    if (source || !event.isDefaultPrevented) {\n      source || (source = event)\n\n      $.each(eventMethods, function(name, predicate) {\n        var sourceMethod = source[name]\n        event[name] = function(){\n          this[predicate] = returnTrue\n          return sourceMethod && sourceMethod.apply(source, arguments)\n        }\n        event[predicate] = returnFalse\n      })\n\n      event.timeStamp || (event.timeStamp = Date.now())\n\n      if (source.defaultPrevented !== undefined ? source.defaultPrevented :\n          'returnValue' in source ? source.returnValue === false :\n          source.getPreventDefault && source.getPreventDefault())\n        event.isDefaultPrevented = returnTrue\n    }\n    return event\n  }\n\n  function createProxy(event) {\n    var key, proxy = { originalEvent: event }\n    for (key in event)\n      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]\n\n    return compatible(proxy, event)\n  }\n\n  $.fn.delegate = function(selector, event, callback){\n    return this.on(event, selector, callback)\n  }\n  $.fn.undelegate = function(selector, event, callback){\n    return this.off(event, selector, callback)\n  }\n\n  $.fn.live = function(event, callback){\n    $(document.body).delegate(this.selector, event, callback)\n    return this\n  }\n  $.fn.die = function(event, callback){\n    $(document.body).undelegate(this.selector, event, callback)\n    return this\n  }\n\n  $.fn.on = function(event, selector, data, callback, one){\n    var autoRemove, delegator, $this = this\n    if (event && !isString(event)) {\n      $.each(event, function(type, fn){\n        $this.on(type, selector, data, fn, one)\n      })\n      return $this\n    }\n\n    if (!isString(selector) && !isFunction(callback) && callback !== false)\n      callback = data, data = selector, selector = undefined\n    if (callback === undefined || data === false)\n      callback = data, data = undefined\n\n    if (callback === false) callback = returnFalse\n\n    return $this.each(function(_, element){\n      if (one) autoRemove = function(e){\n        remove(element, e.type, callback)\n        return callback.apply(this, arguments)\n      }\n\n      if (selector) delegator = function(e){\n        var evt, match = $(e.target).closest(selector, element).get(0)\n        if (match && match !== element) {\n          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})\n          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))\n        }\n      }\n\n      add(element, event, callback, data, selector, delegator || autoRemove)\n    })\n  }\n  $.fn.off = function(event, selector, callback){\n    var $this = this\n    if (event && !isString(event)) {\n      $.each(event, function(type, fn){\n        $this.off(type, selector, fn)\n      })\n      return $this\n    }\n\n    if (!isString(selector) && !isFunction(callback) && callback !== false)\n      callback = selector, selector = undefined\n\n    if (callback === false) callback = returnFalse\n\n    return $this.each(function(){\n      remove(this, event, callback, selector)\n    })\n  }\n\n  $.fn.trigger = function(event, args){\n    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)\n    event._args = args\n    return this.each(function(){\n      // handle focus(), blur() by calling them directly\n      if (event.type in focus && typeof this[event.type] == \"function\") this[event.type]()\n      // items in the collection might not be DOM elements\n      else if ('dispatchEvent' in this) this.dispatchEvent(event)\n      else $(this).triggerHandler(event, args)\n    })\n  }\n\n  // triggers event handlers on current element just as if an event occurred,\n  // doesn't trigger an actual event, doesn't bubble\n  $.fn.triggerHandler = function(event, args){\n    var e, result\n    this.each(function(i, element){\n      e = createProxy(isString(event) ? $.Event(event) : event)\n      e._args = args\n      e.target = element\n      $.each(findHandlers(element, event.type || event), function(i, handler){\n        result = handler.proxy(e)\n        if (e.isImmediatePropagationStopped()) return false\n      })\n    })\n    return result\n  }\n\n  // shortcut methods for `.bind(event, fn)` for each event type\n  ;('focusin focusout focus blur load resize scroll unload click dblclick '+\n  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+\n  'change select keydown keypress keyup error').split(' ').forEach(function(event) {\n    $.fn[event] = function(callback) {\n      return (0 in arguments) ?\n        this.bind(event, callback) :\n        this.trigger(event)\n    }\n  })\n\n  $.Event = function(type, props) {\n    if (!isString(type)) props = type, type = props.type\n    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true\n    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])\n    event.initEvent(type, bubbles, true)\n    return compatible(event)\n  }\n\n})(Zepto)\n\n;(function($){\n  var jsonpID = +new Date(),\n      document = window.document,\n      key,\n      name,\n      rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n      scriptTypeRE = /^(?:text|application)\\/javascript/i,\n      xmlTypeRE = /^(?:text|application)\\/xml/i,\n      jsonType = 'application/json',\n      htmlType = 'text/html',\n      blankRE = /^\\s*$/,\n      originAnchor = document.createElement('a')\n\n  originAnchor.href = window.location.href\n\n  // trigger a custom event and return false if it was cancelled\n  function triggerAndReturn(context, eventName, data) {\n    var event = $.Event(eventName)\n    $(context).trigger(event, data)\n    return !event.isDefaultPrevented()\n  }\n\n  // trigger an Ajax \"global\" event\n  function triggerGlobal(settings, context, eventName, data) {\n    if (settings.global) return triggerAndReturn(context || document, eventName, data)\n  }\n\n  // Number of active Ajax requests\n  $.active = 0\n\n  function ajaxStart(settings) {\n    if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')\n  }\n  function ajaxStop(settings) {\n    if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')\n  }\n\n  // triggers an extra global event \"ajaxBeforeSend\" that's like \"ajaxSend\" but cancelable\n  function ajaxBeforeSend(xhr, settings) {\n    var context = settings.context\n    if (settings.beforeSend.call(context, xhr, settings) === false ||\n        triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)\n      return false\n\n    triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])\n  }\n  function ajaxSuccess(data, xhr, settings, deferred) {\n    var context = settings.context, status = 'success'\n    settings.success.call(context, data, status, xhr)\n    if (deferred) deferred.resolveWith(context, [data, status, xhr])\n    triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])\n    ajaxComplete(status, xhr, settings)\n  }\n  // type: \"timeout\", \"error\", \"abort\", \"parsererror\"\n  function ajaxError(error, type, xhr, settings, deferred) {\n    var context = settings.context\n    settings.error.call(context, xhr, type, error)\n    if (deferred) deferred.rejectWith(context, [xhr, type, error])\n    triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type])\n    ajaxComplete(type, xhr, settings)\n  }\n  // status: \"success\", \"notmodified\", \"error\", \"timeout\", \"abort\", \"parsererror\"\n  function ajaxComplete(status, xhr, settings) {\n    var context = settings.context\n    settings.complete.call(context, xhr, status)\n    triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])\n    ajaxStop(settings)\n  }\n\n  function ajaxDataFilter(data, type, settings) {\n    if (settings.dataFilter == empty) return data\n    var context = settings.context\n    return settings.dataFilter.call(context, data, type)\n  }\n\n  // Empty function, used as default callback\n  function empty() {}\n\n  $.ajaxJSONP = function(options, deferred){\n    if (!('type' in options)) return $.ajax(options)\n\n    var _callbackName = options.jsonpCallback,\n      callbackName = ($.isFunction(_callbackName) ?\n        _callbackName() : _callbackName) || ('Zepto' + (jsonpID++)),\n      script = document.createElement('script'),\n      originalCallback = window[callbackName],\n      responseData,\n      abort = function(errorType) {\n        $(script).triggerHandler('error', errorType || 'abort')\n      },\n      xhr = { abort: abort }, abortTimeout\n\n    if (deferred) deferred.promise(xhr)\n\n    $(script).on('load error', function(e, errorType){\n      clearTimeout(abortTimeout)\n      $(script).off().remove()\n\n      if (e.type == 'error' || !responseData) {\n        ajaxError(null, errorType || 'error', xhr, options, deferred)\n      } else {\n        ajaxSuccess(responseData[0], xhr, options, deferred)\n      }\n\n      window[callbackName] = originalCallback\n      if (responseData && $.isFunction(originalCallback))\n        originalCallback(responseData[0])\n\n      originalCallback = responseData = undefined\n    })\n\n    if (ajaxBeforeSend(xhr, options) === false) {\n      abort('abort')\n      return xhr\n    }\n\n    window[callbackName] = function(){\n      responseData = arguments\n    }\n\n    script.src = options.url.replace(/\\?(.+)=\\?/, '?$1=' + callbackName)\n    document.head.appendChild(script)\n\n    if (options.timeout > 0) abortTimeout = setTimeout(function(){\n      abort('timeout')\n    }, options.timeout)\n\n    return xhr\n  }\n\n  $.ajaxSettings = {\n    // Default type of request\n    type: 'GET',\n    // Callback that is executed before request\n    beforeSend: empty,\n    // Callback that is executed if the request succeeds\n    success: empty,\n    // Callback that is executed the the server drops error\n    error: empty,\n    // Callback that is executed on request complete (both: error and success)\n    complete: empty,\n    // The context for the callbacks\n    context: null,\n    // Whether to trigger \"global\" Ajax events\n    global: true,\n    // Transport\n    xhr: function () {\n      return new window.XMLHttpRequest()\n    },\n    // MIME types mapping\n    // IIS returns Javascript as \"application/x-javascript\"\n    accepts: {\n      script: 'text/javascript, application/javascript, application/x-javascript',\n      json:   jsonType,\n      xml:    'application/xml, text/xml',\n      html:   htmlType,\n      text:   'text/plain'\n    },\n    // Whether the request is to another domain\n    crossDomain: false,\n    // Default timeout\n    timeout: 0,\n    // Whether data should be serialized to string\n    processData: true,\n    // Whether the browser should be allowed to cache GET responses\n    cache: true,\n    //Used to handle the raw response data of XMLHttpRequest.\n    //This is a pre-filtering function to sanitize the response.\n    //The sanitized response should be returned\n    dataFilter: empty\n  }\n\n  function mimeToDataType(mime) {\n    if (mime) mime = mime.split(';', 2)[0]\n    return mime && ( mime == htmlType ? 'html' :\n      mime == jsonType ? 'json' :\n      scriptTypeRE.test(mime) ? 'script' :\n      xmlTypeRE.test(mime) && 'xml' ) || 'text'\n  }\n\n  function appendQuery(url, query) {\n    if (query == '') return url\n    return (url + '&' + query).replace(/[&?]{1,2}/, '?')\n  }\n\n  // serialize payload and append it to the URL for GET requests\n  function serializeData(options) {\n    if (options.processData && options.data && $.type(options.data) != \"string\")\n      options.data = $.param(options.data, options.traditional)\n    if (options.data && (!options.type || options.type.toUpperCase() == 'GET' || 'jsonp' == options.dataType))\n      options.url = appendQuery(options.url, options.data), options.data = undefined\n  }\n\n  $.ajax = function(options){\n    var settings = $.extend({}, options || {}),\n        deferred = $.Deferred && $.Deferred(),\n        urlAnchor, hashIndex\n    for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key]\n\n    ajaxStart(settings)\n\n    if (!settings.crossDomain) {\n      urlAnchor = document.createElement('a')\n      urlAnchor.href = settings.url\n      // cleans up URL for .href (IE only), see https://github.com/madrobby/zepto/pull/1049\n      urlAnchor.href = urlAnchor.href\n      settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host)\n    }\n\n    if (!settings.url) settings.url = window.location.toString()\n    if ((hashIndex = settings.url.indexOf('#')) > -1) settings.url = settings.url.slice(0, hashIndex)\n    serializeData(settings)\n\n    var dataType = settings.dataType, hasPlaceholder = /\\?.+=\\?/.test(settings.url)\n    if (hasPlaceholder) dataType = 'jsonp'\n\n    if (settings.cache === false || (\n         (!options || options.cache !== true) &&\n         ('script' == dataType || 'jsonp' == dataType)\n        ))\n      settings.url = appendQuery(settings.url, '_=' + Date.now())\n\n    if ('jsonp' == dataType) {\n      if (!hasPlaceholder)\n        settings.url = appendQuery(settings.url,\n          settings.jsonp ? (settings.jsonp + '=?') : settings.jsonp === false ? '' : 'callback=?')\n      return $.ajaxJSONP(settings, deferred)\n    }\n\n    var mime = settings.accepts[dataType],\n        headers = { },\n        setHeader = function(name, value) { headers[name.toLowerCase()] = [name, value] },\n        protocol = /^([\\w-]+:)\\/\\//.test(settings.url) ? RegExp.$1 : window.location.protocol,\n        xhr = settings.xhr(),\n        nativeSetHeader = xhr.setRequestHeader,\n        abortTimeout\n\n    if (deferred) deferred.promise(xhr)\n\n    if (!settings.crossDomain) setHeader('X-Requested-With', 'XMLHttpRequest')\n    setHeader('Accept', mime || '*/*')\n    if (mime = settings.mimeType || mime) {\n      if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]\n      xhr.overrideMimeType && xhr.overrideMimeType(mime)\n    }\n    if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET'))\n      setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded')\n\n    if (settings.headers) for (name in settings.headers) setHeader(name, settings.headers[name])\n    xhr.setRequestHeader = setHeader\n\n    xhr.onreadystatechange = function(){\n      if (xhr.readyState == 4) {\n        xhr.onreadystatechange = empty\n        clearTimeout(abortTimeout)\n        var result, error = false\n        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {\n          dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type'))\n\n          if (xhr.responseType == 'arraybuffer' || xhr.responseType == 'blob')\n            result = xhr.response\n          else {\n            result = xhr.responseText\n\n            try {\n              // http://perfectionkills.com/global-eval-what-are-the-options/\n              // sanitize response accordingly if data filter callback provided\n              result = ajaxDataFilter(result, dataType, settings)\n              if (dataType == 'script')    (1,eval)(result)\n              else if (dataType == 'xml')  result = xhr.responseXML\n              else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result)\n            } catch (e) { error = e }\n\n            if (error) return ajaxError(error, 'parsererror', xhr, settings, deferred)\n          }\n\n          ajaxSuccess(result, xhr, settings, deferred)\n        } else {\n          ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred)\n        }\n      }\n    }\n\n    if (ajaxBeforeSend(xhr, settings) === false) {\n      xhr.abort()\n      ajaxError(null, 'abort', xhr, settings, deferred)\n      return xhr\n    }\n\n    var async = 'async' in settings ? settings.async : true\n    xhr.open(settings.type, settings.url, async, settings.username, settings.password)\n\n    if (settings.xhrFields) for (name in settings.xhrFields) xhr[name] = settings.xhrFields[name]\n\n    for (name in headers) nativeSetHeader.apply(xhr, headers[name])\n\n    if (settings.timeout > 0) abortTimeout = setTimeout(function(){\n        xhr.onreadystatechange = empty\n        xhr.abort()\n        ajaxError(null, 'timeout', xhr, settings, deferred)\n      }, settings.timeout)\n\n    // avoid sending empty string (#319)\n    xhr.send(settings.data ? settings.data : null)\n    return xhr\n  }\n\n  // handle optional data/success arguments\n  function parseArguments(url, data, success, dataType) {\n    if ($.isFunction(data)) dataType = success, success = data, data = undefined\n    if (!$.isFunction(success)) dataType = success, success = undefined\n    return {\n      url: url\n    , data: data\n    , success: success\n    , dataType: dataType\n    }\n  }\n\n  $.get = function(/* url, data, success, dataType */){\n    return $.ajax(parseArguments.apply(null, arguments))\n  }\n\n  $.post = function(/* url, data, success, dataType */){\n    var options = parseArguments.apply(null, arguments)\n    options.type = 'POST'\n    return $.ajax(options)\n  }\n\n  $.getJSON = function(/* url, data, success */){\n    var options = parseArguments.apply(null, arguments)\n    options.dataType = 'json'\n    return $.ajax(options)\n  }\n\n  $.fn.load = function(url, data, success){\n    if (!this.length) return this\n    var self = this, parts = url.split(/\\s/), selector,\n        options = parseArguments(url, data, success),\n        callback = options.success\n    if (parts.length > 1) options.url = parts[0], selector = parts[1]\n    options.success = function(response){\n      self.html(selector ?\n        $('<div>').html(response.replace(rscript, \"\")).find(selector)\n        : response)\n      callback && callback.apply(self, arguments)\n    }\n    $.ajax(options)\n    return this\n  }\n\n  var escape = encodeURIComponent\n\n  function serialize(params, obj, traditional, scope){\n    var type, array = $.isArray(obj), hash = $.isPlainObject(obj)\n    $.each(obj, function(key, value) {\n      type = $.type(value)\n      if (scope) key = traditional ? scope :\n        scope + '[' + (hash || type == 'object' || type == 'array' ? key : '') + ']'\n      // handle data in serializeArray() format\n      if (!scope && array) params.add(value.name, value.value)\n      // recurse into nested objects\n      else if (type == \"array\" || (!traditional && type == \"object\"))\n        serialize(params, value, traditional, key)\n      else params.add(key, value)\n    })\n  }\n\n  $.param = function(obj, traditional){\n    var params = []\n    params.add = function(key, value) {\n      if ($.isFunction(value)) value = value()\n      if (value == null) value = \"\"\n      this.push(escape(key) + '=' + escape(value))\n    }\n    serialize(params, obj, traditional)\n    return params.join('&').replace(/%20/g, '+')\n  }\n})(Zepto)\n\n;(function($){\n  $.fn.serializeArray = function() {\n    var name, type, result = [],\n      add = function(value) {\n        if (value.forEach) return value.forEach(add)\n        result.push({ name: name, value: value })\n      }\n    if (this[0]) $.each(this[0].elements, function(_, field){\n      type = field.type, name = field.name\n      if (name && field.nodeName.toLowerCase() != 'fieldset' &&\n        !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' &&\n        ((type != 'radio' && type != 'checkbox') || field.checked))\n          add($(field).val())\n    })\n    return result\n  }\n\n  $.fn.serialize = function(){\n    var result = []\n    this.serializeArray().forEach(function(elm){\n      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))\n    })\n    return result.join('&')\n  }\n\n  $.fn.submit = function(callback) {\n    if (0 in arguments) this.bind('submit', callback)\n    else if (this.length) {\n      var event = $.Event('submit')\n      this.eq(0).trigger(event)\n      if (!event.isDefaultPrevented()) this.get(0).submit()\n    }\n    return this\n  }\n\n})(Zepto)\n\n;(function(){\n  // getComputedStyle shouldn't freak out when called\n  // without a valid element as argument\n  try {\n    getComputedStyle(undefined)\n  } catch(e) {\n    var nativeGetComputedStyle = getComputedStyle\n    window.getComputedStyle = function(element, pseudoElement){\n      try {\n        return nativeGetComputedStyle(element, pseudoElement)\n      } catch(e) {\n        return null\n      }\n    }\n  }\n})()\n  \n  \n  exports('zepto', Zepto)\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/mobile.js",
    "content": "/**\n\n @Name：layui 移动模块入口 | 构建后则为移动模块集合\n @author 郑保乐\n @License：MIT\n    \n */\n\n \nif(!layui['layui.mobile']){\n  layui.config({\n    base: layui.cache.dir + 'lay/modules/mobile/'\n  }).extend({\n    'layer-mobile': 'layer-mobile'\n    ,'zepto': 'zepto'\n    ,'upload-mobile': 'upload-mobile'\n    ,'layim-mobile': 'layim-mobile'\n  });\n}  \n\nlayui.define([\n  'layer-mobile'\n  ,'zepto'\n  ,'layim-mobile'\n], function(exports){\n  exports('mobile', {\n    layer: layui['layer-mobile'] //弹层\n    ,layim: layui['layim-mobile'] //WebIM\n  });\n});"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/table.js",
    "content": "/**\n\n @Name：layui.table 表格操作\n @author 郑保乐\n @License：MIT\n    \n */\n \nlayui.define(['laytpl', 'laypage', 'layer', 'form'], function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,laytpl = layui.laytpl\n  ,laypage = layui.laypage\n  ,layer = layui.layer\n  ,form = layui.form\n  ,hint = layui.hint()\n  ,device = layui.device()\n\n  //外部接口\n  ,table = {\n    config: {\n      checkName: 'LAY_CHECKED' //是否选中状态的字段名\n      ,indexName: 'LAY_TABLE_INDEX' //下标索引名\n    } //全局配置项\n    ,cache: {} //数据缓存\n    ,index: layui.table ? (layui.table.index + 10000) : 0\n    \n    //设置全局项\n    ,set: function(options){\n      var that = this;\n      that.config = $.extend({}, that.config, options);\n      return that;\n    }\n    \n    //事件监听\n    ,on: function(events, callback){\n      return layui.onevent.call(this, MOD_NAME, events, callback);\n    }\n  }\n  \n  //操作当前实例\n  ,thisTable = function(){\n    var that = this\n    ,options = that.config\n    ,id = options.id;\n    \n    id && (thisTable.config[id] = options);\n    \n    return {\n      reload: function(options){\n        that.reload.call(that, options);\n      }\n      ,config: options\n    }\n  }\n  \n  //字符常量\n  ,MOD_NAME = 'table', ELEM = '.layui-table', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled', NONE = 'layui-none'\n  \n  ,ELEM_VIEW = 'layui-table-view', ELEM_HEADER = '.layui-table-header', ELEM_BODY = '.layui-table-body', ELEM_MAIN = '.layui-table-main', ELEM_FIXED = '.layui-table-fixed', ELEM_FIXL = '.layui-table-fixed-l', ELEM_FIXR = '.layui-table-fixed-r', ELEM_TOOL = '.layui-table-tool', ELEM_SORT = '.layui-table-sort', ELEM_EDIT = 'layui-table-edit', ELEM_HOVER = 'layui-table-hover'\n  \n  //thead区域模板\n  ,TPL_HEADER = function(options){\n    options = options || {};\n    return ['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" '\n      ,'{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>'\n      ,'<thead>'\n      ,'{{# layui.each(d.data.cols, function(i1, item1){ }}'\n        ,'<tr>'\n        ,'{{# layui.each(item1, function(i2, item2){ }}'\n          ,'{{# if(item2.fixed && item2.fixed !== \"right\"){ left = true; } }}'\n          ,'{{# if(item2.fixed === \"right\"){ right = true; } }}'\n          ,function(){\n            if(options.fixed && options.fixed !== 'right'){\n              return '{{# if(item2.fixed && item2.fixed !== \"right\"){ }}';\n            }\n            if(options.fixed === 'right'){\n              return '{{# if(item2.fixed === \"right\"){ }}';\n            }\n            return '';\n          }()\n          ,'{{# if(item2.checkbox){ }}'\n            ,'<th data-field=\"{{ item2.field||i2 }}\" data-type=\"checkbox\" {{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}} unresize=\"true\"><div class=\"layui-table-cell laytable-cell-checkbox\"><input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" lay-filter=\"layTableAllChoose\" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}></div></th>'\n          ,'{{# } else if(item2.space){ }}'\n            ,'<th data-field=\"{{ item2.field||i2 }}\" {{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}} unresize=\"true\"><div class=\"layui-table-cell laytable-cell-space\"></div></th>'\n          ,'{{# } else { }}'\n            ,'<th data-field=\"{{ item2.field||i2 }}\" {{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}} {{# if(item2.unresize){ }}unresize=\"true\"{{# } }}>'\n              ,'{{# if(item2.colspan > 1){ }}'\n                ,'<div class=\"layui-table-cell laytable-cell-group\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>'\n                  ,'<span>{{item2.title||\"\"}}</span>'\n                ,'</div>'\n              ,'{{# } else { }}'\n                ,'<div class=\"layui-table-cell laytable-cell-{{d.index}}-{{item2.field||i2}}\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>'\n                  ,'<span>{{item2.title||\"\"}}</span>'\n                  ,'{{# if(item2.sort){ }}'\n                    ,'<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>'\n                  ,'{{# } }}'\n                ,'</div>'\n              ,'{{# } }}'\n            ,'</th>'\n          ,'{{# }; }}'\n          ,(options.fixed ? '{{# }; }}' : '')\n        ,'{{# }); }}'\n        ,'</tr>'\n      ,'{{# }); }}'\n      ,'</thead>'\n    ,'</table>'].join('');\n  }\n  \n  //tbody区域模板\n  ,TPL_BODY = ['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" '\n    ,'{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>'\n    ,'<tbody></tbody>'\n  ,'</table>'].join('')\n  \n  //主模板\n  ,TPL_MAIN = ['<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;{{# } }}\">'\n    ,'{{# var left, right; }}'\n    ,'<div class=\"layui-table-header\">'\n      ,TPL_HEADER()\n    ,'</div>'\n    ,'<div class=\"layui-table-body layui-table-main\">'\n      ,TPL_BODY\n    ,'</div>'\n    \n    ,'{{# if(left){ }}'\n    ,'<div class=\"layui-table-fixed layui-table-fixed-l\">'\n      ,'<div class=\"layui-table-header\">'\n        ,TPL_HEADER({fixed: true}) \n      ,'</div>'\n      ,'<div class=\"layui-table-body\">'\n        ,TPL_BODY\n      ,'</div>'      \n    ,'</div>'\n    ,'{{# }; }}'\n    \n    ,'{{# if(right){ }}'\n    ,'<div class=\"layui-table-fixed layui-table-fixed-r\">'\n      ,'<div class=\"layui-table-header\">'\n        ,TPL_HEADER({fixed: 'right'})\n        ,'<div class=\"layui-table-mend\"></div>'\n      ,'</div>'\n      ,'<div class=\"layui-table-body\">'\n        ,TPL_BODY\n      ,'</div>'\n    ,'</div>'\n    ,'{{# }; }}'\n    \n    ,'{{# if(d.data.page){ }}'\n    ,'<div class=\"layui-table-tool\">'\n      ,'<div class=\"layui-inline layui-table-page\" id=\"layui-table-page{{d.index}}\"></div>'\n    ,'</div>'\n    ,'{{# } }}'\n    \n    ,'<style>'\n    ,'{{# layui.each(d.data.cols, function(i1, item1){'\n      ,'layui.each(item1, function(i2, item2){ }}'\n        ,'.laytable-cell-{{d.index}}-{{item2.field||i2}}{ width:{{item2.width||50}}px }'\n      ,'{{# });'\n    ,'}); }}'\n    ,'</style>'\n  ,'</div>'].join('')\n  \n  ,_WIN = $(window)\n  ,_DOC = $(document)\n  \n  //构造器\n  ,Class = function(options){\n    var that = this;\n    that.index = ++table.index;\n    that.config = $.extend({}, that.config, table.config, options);\n    that.render();\n  };\n  \n  //默认配置\n  Class.prototype.config = {\n    limit: 30 //每页显示的数量\n    ,loading: true //请求数据时，是否显示loading\n  };\n\n  //表格渲染\n  Class.prototype.render = function(sets){\n    var that = this, options;\n    \n    if(sets) that.config = sets;\n    options = that.config;\n    \n    options.elem = $(options.elem);\n    options.where = options.where || {};\n    \n    //请求参数的自定义格式\n    options.request = $.extend({\n      pageName: 'page'\n      ,limitName: 'limit'\n    }, options.request)\n    \n    //响应数据的自定义格式\n    options.response = $.extend({\n      statusName: 'code'\n      ,statusCode: 0\n      ,msgName: 'msg'\n      ,dataName: 'data'\n      ,countName: 'count'\n    }, options.response);\n    \n    if(!options.elem[0]) return that;\n\n    var othis = options.elem\n    ,hasRender = othis.next('.' + ELEM_VIEW);\n    \n    if(options.height && /^full-\\d+$/.test(options.height)){ //full-差距值\n      that.fullHeightGap = options.height.split('-')[1];\n      options.height = _WIN.height() - that.fullHeightGap;\n    }\n\n    //替代元素\n    var reElem = that.elem = $(laytpl(TPL_MAIN).render({\n      VIEW_CLASS: ELEM_VIEW\n      ,data: options\n      ,index: that.index //索引\n    }));\n    \n    options.index = that.index;\n    \n    //生成替代元素\n    hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender\n    othis.after(reElem);\n    \n    //各级容器\n    that.layHeader = reElem.find(ELEM_HEADER);\n    that.layMain = reElem.find(ELEM_MAIN);\n    that.layBody = reElem.find(ELEM_BODY);\n    that.layFixed = reElem.find(ELEM_FIXED);\n    that.layFixLeft = reElem.find(ELEM_FIXL);\n    that.layFixRight = reElem.find(ELEM_FIXR);\n    that.layTool = reElem.find(ELEM_TOOL);\n    \n    //设置body区域高度\n    if(options.height){\n      that.fullSize();\n    }\n    \n    //如果多级表头，则填补表头高度\n    if(options.cols.length > 1){\n      var th = that.layFixed.find(ELEM_HEADER).find('th');\n      th.height(that.layHeader.height() - 1 - parseFloat(th.css('padding-top')) - parseFloat(th.css('padding-bottom')));\n    }\n    \n    that.pullData(1);\n    that.events();\n  };\n  \n  //表格重载\n  Class.prototype.reload = function(options){\n    var that = this;\n    that.config = $.extend({}, that.config, options);\n    that.render();\n  };\n  \n  //获得数据\n  Class.prototype.pullData = function(curr, loadIndex){\n    var that = this\n    ,options = that.config\n    ,request = options.request\n    ,response = options.response\n    ,sort = function(){\n      if(typeof options.initSort === 'object'){\n        that.sort(options.initSort.field, options.initSort.type);\n      }\n    };\n    \n    if(options.url){ //Ajax请求\n      var params = {};\n      params[request.pageName] = curr;\n      params[request.limitName] = options.limit;\n      $.ajax({\n        type: options.method || 'get'\n        ,url: options.url\n        ,data: $.extend(params, options.where)\n        ,dataType: 'json'\n        ,success: function(res){\n          if(res[response.statusName] != response.statusCode){\n            that.renderForm();\n            return that.layMain.html('<div class=\"'+ NONE +'\">'+ (res[response.msgName] || '返回的数据状态异常') +'</div>');\n          }\n          that.renderData(res, curr, res[response.countName]), sort();\n          loadIndex && layer.close(loadIndex);\n          typeof options.done === 'function' && options.done(res, curr, res[response.countName]);\n        }\n        ,error: function(e, m){\n          that.layMain.html('<div class=\"'+ NONE +'\">数据接口请求异常</div>');\n          that.renderForm();\n          loadIndex && layer.close(loadIndex);\n        }\n      });\n    } else if(options.data && options.data.constructor === Array){ //已知数据\n      var res = {}\n      ,startLimit = curr*options.limit - options.limit\n      \n      res[response.dataName] = options.data.concat().splice(startLimit, options.limit);\n      res[response.countName] = options.data.length;\n\n      that.renderData(res, curr, options.data.length), sort();\n      typeof options.done === 'function' && options.done(res, curr, res[response.countName]);\n    }\n  };\n  \n  //页码\n  Class.prototype.page = 1;\n  \n  //遍历表头\n  Class.prototype.eachCols = function(callback){\n    var cols = $.extend(true, [], this.config.cols)\n    ,arrs = [], index = 0;\n\n    //重新整理表头结构\n    layui.each(cols, function(i1, item1){\n      layui.each(item1, function(i2, item2){\n        //如果是组合列，则捕获对应的子列\n        if(item2.colspan > 1){\n          var childIndex = 0;\n          index++\n          item2.CHILD_COLS = [];\n          layui.each(cols[i1 + 1], function(i22, item22){\n            if(item22.PARENT_COL || childIndex == item2.colspan) return;\n            item22.PARENT_COL = index;\n            item2.CHILD_COLS.push(item22);\n            childIndex = childIndex + (item22.colspan > 1 ? item22.colspan : 1);\n          });\n        }\n        if(item2.PARENT_COL) return; //如果是子列，则不进行追加，因为已经存储在父列中\n        arrs.push(item2)\n      });\n    });\n\n    //重新遍历列，如果有子列，则进入递归\n    var eachArrs = function(obj){\n      layui.each(obj || arrs, function(i, item){\n        if(item.CHILD_COLS) return eachArrs(item.CHILD_COLS);\n        callback(i, item);\n      });\n    };\n    \n    eachArrs();\n  };\n  \n  //数据渲染\n  Class.prototype.renderData = function(res, curr, count, sort){\n    var that = this\n    ,options = that.config\n    ,data = res[options.response.dataName] || []\n    ,trs = []\n    ,trs_fixed = []\n    ,trs_fixed_r = []\n    \n    //渲染视图\n    ,render = function(){\n      if(!sort && that.sortKey){\n        return that.sort(that.sortKey.field, that.sortKey.sort, true);\n      }\n      layui.each(data, function(i1, item1){\n        var tds = [], tds_fixed = [], tds_fixed_r = [];\n        if(item1.length === 0) return;\n        if(!sort){\n          item1[table.config.indexName] = i1;\n        }\n        that.eachCols(function(i3, item3){\n          var content = item1[item3.field||i3];\n          if(content === undefined || content === null) content = '';\n          if(item3.colspan > 1) return;\n          \n          var td = ['<td data-field=\"'+ (item3.field||i3) +'\"'+ function(){\n            var attr = [];\n            if(item3.edit) attr.push(' data-edit=\"true\"'); //是否允许单元格编辑\n            if(item3.align) attr.push(' align=\"'+ item3.align +'\"'); //对齐方式\n            if(item3.templet) attr.push(' data-content=\"'+ content +'\"'); //自定义模板\n            if(item3.toolbar) attr.push(' data-off=\"true\"'); //自定义模板\n            if(item3.event) attr.push(' lay-event=\"'+ item3.event +'\"'); //自定义事件\n            if(item3.style) attr.push(' style=\"'+ item3.style +'\"'); //自定义样式\n            return attr.join('');\n          }() +'>'\n            ,'<div class=\"layui-table-cell laytable-cell-'+ function(){\n              if(item3.checkbox) return 'checkbox';\n              if(item3.space) return 'space'; //间距\n              return options.index + '-' + (item3.field||i3);\n            }() +'\">' + function(){\n              if(item3.checkbox){\n                return '<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" '+ function(){\n                  var checkName = table.config.checkName;\n                  if(item3[checkName]){\n                    item1[checkName] = item3[checkName];\n                    return item3[checkName] ? 'checked' : ''; \n                  }\n                  return item1[checkName] ? 'checked' : '';                   \n                }() +'>';\n              }\n              if(item3.toolbar){\n                return laytpl($(item3.toolbar).html()||'').render(item1);\n              }\n              return item3.templet ? laytpl($(item3.templet).html() || String(content)).render(item1) : content;\n            }()\n          ,'</div></td>'].join('');\n          \n          tds.push(td);\n          if(item3.fixed && item3.fixed !== 'right') tds_fixed.push(td);\n          if(item3.fixed === 'right') tds_fixed_r.push(td);\n        });\n        trs.push('<tr data-index=\"'+ i1 +'\">'+ tds.join('') + '</tr>');\n        trs_fixed.push('<tr data-index=\"'+ i1 +'\">'+ tds_fixed.join('') + '</tr>');\n        trs_fixed_r.push('<tr data-index=\"'+ i1 +'\">'+ tds_fixed_r.join('') + '</tr>');\n      });\n      \n      that.layBody.scrollTop(0);\n      that.layMain.find('.'+ NONE).remove();\n      that.layMain.find('tbody').html(trs.join(''));\n      that.layFixLeft.find('tbody').html(trs_fixed.join(''));\n      that.layFixRight.find('tbody').html(trs_fixed_r.join(''));\n      \n      that.renderForm();\n      that.syncCheckAll();\n      that.haveInit ? that.scrollPatch() : setTimeout(function(){\n        that.scrollPatch();\n      }, 50);\n      that.haveInit = true;\n      layer.close(that.tipsIndex);\n    };\n    \n    that.key = options.id || options.index;\n    table.cache[that.key] = data; //记录数据\n    \n    //排序\n    if(sort){\n      return render();\n    }\n    \n    if(data.length === 0){\n      that.renderForm();\n      that.layFixed.remove();\n      that.layMain.find('tbody').html('');\n      that.layMain.find('.'+ NONE).remove();\n      return that.layMain.append('<div class=\"'+ NONE +'\">无数据</div>');\n    }\n\n    render();\n    \n    //分页\n    if(options.page){\n      that.page = curr;\n      that.count = count;\n      laypage.render({\n        elem: 'layui-table-page' + options.index\n        ,count: count\n        ,groups: 3\n        ,limits: options.limits || [10,20,30,40,50,60,70,80,90]\n        ,limit: options.limit\n        ,curr: curr\n        ,layout: ['prev', 'page', 'next', 'skip', 'count', 'limit']\n        ,prev: '<i class=\"layui-icon\">&#xe603;</i>'\n        ,next: '<i class=\"layui-icon\">&#xe602;</i>'\n        ,jump: function(obj, first){\n          if(!first){\n            that.page = obj.curr;\n            options.limit = obj.limit;\n            that.pullData(obj.curr, that.loading());\n          }\n        }\n      });\n      that.layTool.find('.layui-table-count span').html(count)\n    }\n  };\n  \n  //渲染表单\n  Class.prototype.renderForm = function(type){\n    form.render((type || 'checkbox'), 'LAY-table-'+ this.index);\n  }\n  \n  //数据排序\n  Class.prototype.sort = function(th, type, pull, formEvent){\n    var that = this\n    ,field\n    ,res = {}\n    ,config = that.config\n    ,filter = config.elem.attr('lay-filter')\n    ,data = table.cache[that.key], thisData;\n    \n    //字段匹配\n    if(typeof th === 'string'){\n      that.layHeader.find('th').each(function(i, item){\n        var othis = $(this)\n        ,_field = othis.data('field');\n        if(_field === th){\n          th = othis;\n          field = _field;\n          return false;\n        }\n      });\n    }\n\n    try {\n      var field = field || th.data('field');\n      \n      //如果欲执行的排序已在状态中，则不执行渲染\n      if(that.sortKey && !pull){\n        if(field === that.sortKey.field && type === that.sortKey.sort){\n          return;\n        }\n      }\n      \n      var elemSort = that.layHeader.find('th .laytable-cell-'+ config.index +'-'+ field).find(ELEM_SORT);\n      that.layHeader.find('th').find(ELEM_SORT).removeAttr('lay-sort'); //清除其它标题排序状态\n      elemSort.attr('lay-sort', type || null);\n      that.layFixed.find('th')\n    } catch(e){\n      return hint.error('Table modules: Did not match to field');\n    }\n    \n    //记录排序索引和类型\n    that.sortKey = {\n      field: field\n      ,sort: type\n    };\n\n    if(type === 'asc'){ //升序\n      thisData = layui.sort(data, field);\n    } else if(type === 'desc'){ //降序\n      thisData = layui.sort(data, field, true);\n    } else { //清除排序\n      thisData = layui.sort(data, table.config.indexName);\n      delete that.sortKey;\n    }\n    \n    res[config.response.dataName] = thisData;\n    that.renderData(res, that.page, that.count, true);\n    layer.close(that.tipsIndex);\n    \n    if(formEvent){\n      layui.event.call(th, MOD_NAME, 'sort('+ filter +')', {\n        field: field\n        ,type: type\n      });\n    }\n  };\n  \n  //请求loading\n  Class.prototype.loading = function(){\n    var that = this\n    ,config = that.config;\n    if(config.loading && config.url){\n      return layer.msg('数据请求中', {\n        icon: 16\n        ,offset: [\n          that.elem.offset().top + that.elem.height()/2 - 35 - _WIN.scrollTop() + 'px'\n          ,that.elem.offset().left + that.elem.width()/2 - 90 - _WIN.scrollLeft() + 'px'\n        ]\n        ,anim: -1\n        ,fixed: false\n      });\n    }\n  };\n  \n  //同步选中值状态\n  Class.prototype.setCheckData = function(index, checked){\n    var that = this\n    ,config = that.config\n    ,thisData = table.cache[that.key];\n    if(!thisData[index]) return;\n    thisData[index][config.checkName] = checked;\n  };\n  \n  //同步全选按钮状态\n  Class.prototype.syncCheckAll = function(){\n    var that = this\n    ,config = that.config\n    ,checkAllElem = that.layHeader.find('input[name=\"layTableCheckbox\"]')\n    ,syncColsCheck = function(checked){\n      that.eachCols(function(i, item){\n        if(item.checkbox){\n          item[config.checkName] = checked;\n        }\n      });\n      return checked;\n    };\n    \n    if(!checkAllElem[0]) return\n\n    if(table.checkStatus(that.key).isAll){\n      if(!checkAllElem[0].checked){\n        checkAllElem.prop('checked', true);\n        that.renderForm();\n      }\n      syncColsCheck(true);\n    } else {\n      if(checkAllElem[0].checked){\n        checkAllElem.prop('checked', false);\n        that.renderForm();\n      }\n      syncColsCheck(false);\n    }\n  };\n  \n  //获取cssRule\n  Class.prototype.getCssRule = function(field, callback){\n    var that = this\n    ,style = that.elem.find('style')[0]\n    ,sheet = style.sheet || style.styleSheet\n    ,rules = sheet.cssRules || sheet.rules;\n    layui.each(rules, function(i, item){\n      if(item.selectorText === ('.laytable-cell-'+ that.index +'-'+ field)){\n        return callback(item), true;\n      }\n    });\n  };\n  \n  //尺寸始终铺满\n  Class.prototype.fullSize = function(){\n    var that = this\n    ,options = that.config\n    ,height = options.height, bodyHeight;\n    \n    if(that.fullHeightGap){\n      height = _WIN.height() - that.fullHeightGap;\n      if(height < 135) height = 135;\n      that.elem.css('height', height);\n    }\n\n    //tbody区域高度\n    bodyHeight = parseFloat(height) - parseFloat(that.layHeader.height()) - 1;  \n    if(options.page){\n      bodyHeight = bodyHeight - parseFloat(that.layTool.outerHeight() + 1);\n    }\n    that.layMain.css('height', bodyHeight);\n    \n  };\n  \n  //滚动条补丁\n  Class.prototype.scrollPatch = function(){\n    var that = this\n    ,layMainTable = that.layMain.children('table')\n    ,scollWidth = that.layMain.width() - that.layMain.prop('clientWidth') //纵向滚动条宽度\n    ,scollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); //横向滚动条高度\n    \n    if(scollWidth && scollHeight){\n      if(!that.elem.find('.layui-table-patch')[0]){\n        var patchElem = $('<th class=\"layui-table-patch\"><div class=\"layui-table-cell\"></div></th>'); //补丁元素\n        patchElem.find('div').css({\n          width: scollWidth\n        });\n        that.layHeader.eq(0).find('thead tr').append(patchElem)\n      }\n    } else {\n      that.layHeader.eq(0).find('.layui-table-patch').remove();\n    }\n    \n    //固定列区域高度\n    var mainHeight = that.layMain.height()\n    ,fixHeight = mainHeight - scollHeight;\n    that.layFixed.find(ELEM_BODY).css('height', layMainTable.height() > fixHeight ? fixHeight : 'auto');\n    \n    //表格宽度小于容器宽度时，隐藏固定列\n    that.layFixRight[layMainTable.width() > that.layMain.width() ? 'removeClass' : 'addClass'](HIDE); \n    \n    //操作栏\n    that.layFixRight.css('right', scollWidth - 1); \n  };\n\n  //事件处理\n  Class.prototype.events = function(){\n    var that = this\n    ,config = that.config\n    ,_BODY = $('body')\n    ,dict = {}\n    ,th = that.layHeader.find('th')\n    ,resizing\n    ,ELEM_CELL = '.layui-table-cell'\n    ,filter = config.elem.attr('lay-filter');\n\n    //拖拽调整宽度    \n    th.on('mousemove', function(e){\n      var othis = $(this)\n      ,oLeft = othis.offset().left\n      ,pLeft = e.clientX - oLeft;\n      if(othis.attr('colspan') > 1 || othis.attr('unresize') || dict.resizeStart){\n        return;\n      }\n      dict.allowResize = othis.width() - pLeft <= 10; //是否处于拖拽允许区域\n      _BODY.css('cursor', (dict.allowResize ? 'col-resize' : ''));\n    }).on('mouseleave', function(){\n      var othis = $(this);\n      if(dict.resizeStart) return;\n      _BODY.css('cursor', '');\n    }).on('mousedown', function(e){\n      if(dict.allowResize){\n        var field = $(this).data('field');\n        e.preventDefault();\n        dict.resizeStart = true; //开始拖拽\n        dict.offset = [e.clientX, e.clientY]; //记录初始坐标\n        \n        that.getCssRule(field, function(item){\n          dict.rule = item;\n          dict.ruleWidth = parseFloat(item.style.width);\n        });\n      }\n    });\n    //拖拽中\n    _DOC.on('mousemove', function(e){\n      if(dict.resizeStart){\n        e.preventDefault();\n        if(dict.rule){\n          var setWidth = dict.ruleWidth + e.clientX - dict.offset[0];\n          dict.rule.style.width = setWidth + 'px';\n          layer.close(that.tipsIndex);\n        }\n        resizing = 1\n      }\n    }).on('mouseup', function(e){\n      if(dict.resizeStart){\n        dict = {};\n        _BODY.css('cursor', '');\n        that.scrollPatch();\n      }\n      if(resizing === 2){\n        resizing = null;\n      }\n    });\n    \n    //排序\n    th.on('click', function(){\n      var othis = $(this)\n      ,elemSort = othis.find(ELEM_SORT)\n      ,nowType = elemSort.attr('lay-sort')\n      ,type;\n\n      if(!elemSort[0] || resizing === 1) return resizing = 2;      \n      \n      if(nowType === 'asc'){\n        type = 'desc';\n      } else if(nowType === 'desc'){\n        type = null;\n      } else {\n        type = 'asc';\n      }\n      that.sort(othis, type, null, true);\n    }).find(ELEM_SORT+' .layui-edge ').on('click', function(e){\n      var othis = $(this)\n      ,index = othis.index()\n      ,field = othis.parents('th').eq(0).data('field')\n      layui.stope(e);\n      if(index === 0){\n        that.sort(field, 'asc', null, true);\n      } else {\n        that.sort(field, 'desc', null, true);\n      }\n    });\n    \n    //复选框选择\n    that.elem.on('click', 'input[name=\"layTableCheckbox\"]+', function(){\n      var checkbox = $(this).prev()\n      ,childs = that.layBody.find('input[name=\"layTableCheckbox\"]')\n      ,index = checkbox.parents('tr').eq(0).data('index')\n      ,checked = checkbox[0].checked\n      ,isAll = checkbox.attr('lay-filter') === 'layTableAllChoose';\n      \n      //全选\n      if(isAll){\n        childs.each(function(i, item){\n          item.checked = checked;\n          that.setCheckData(i, checked);\n        });\n        that.syncCheckAll();\n        that.renderForm();\n      } else {\n        that.setCheckData(index, checked);\n        that.syncCheckAll();\n      }\n      layui.event.call(this, MOD_NAME, 'checkbox('+ filter +')', {\n        checked: checked\n        ,data: table.cache[that.key][index]\n        ,type: isAll ? 'all' : 'one'\n      });\n    });\n    \n    //行事件\n    that.layBody.on('mouseenter', 'tr', function(){\n      var othis = $(this)\n      ,index = othis.index();\n      that.layBody.find('tr:eq('+ index +')').addClass(ELEM_HOVER)\n    }).on('mouseleave', 'tr', function(){\n      var othis = $(this)\n      ,index = othis.index();\n      that.layBody.find('tr:eq('+ index +')').removeClass(ELEM_HOVER)\n    });\n    \n    //单元格编辑\n    that.layBody.on('change', '.'+ELEM_EDIT, function(){\n      var othis = $(this)\n      ,value = this.value\n      ,field = othis.parent().data('field')\n      ,index = othis.parents('tr').eq(0).data('index')\n      ,data = table.cache[that.key][index];\n      \n      data[field] = value; //更新缓存中的值\n      \n      layui.event.call(this, MOD_NAME, 'edit('+ filter +')', {\n        value: value\n        ,data: data\n        ,field: field\n      });\n    }).on('blur', '.'+ELEM_EDIT, function(){\n      var templet\n      ,othis = $(this)\n      ,field = othis.parent().data('field')\n      ,index = othis.parents('tr').eq(0).data('index')\n      ,data = table.cache[that.key][index];\n      that.eachCols(function(i, item){\n        if(item.field == field && item.templet){\n          templet = item.templet;\n        }\n      });\n      othis.siblings(ELEM_CELL).html(\n        templet ? laytpl($(templet).html() || this.value).render(data) : this.value\n      );\n      othis.parent().data('content', this.value);\n      othis.remove();\n    });\n    \n    //单元格事件\n    that.layBody.on('click', 'td', function(){\n      var othis = $(this)\n      ,field = othis.data('field')\n      ,elemCell = othis.children(ELEM_CELL);\n      \n      if(othis.data('off')) return;\n      \n      //显示编辑框\n      if(othis.data('edit')){\n        var input = $('<input class=\"'+ ELEM_EDIT +'\">');\n        input[0].value = othis.data('content') || elemCell.text();\n        othis.find('.'+ELEM_EDIT)[0] || othis.append(input);\n        return input.focus();\n      }\n      \n      //如果出现省略，则可查看更多\n      if(elemCell.prop('scrollWidth') > elemCell.outerWidth()){\n        that.tipsIndex = layer.tips([\n          '<div class=\"layui-table-tips-main\" style=\"margin-top: -'+ (elemCell.height() + 16) +'px;'+ function(){\n            if(config.size === 'sm'){\n              return 'padding: 4px 15px; font-size: 12px;';\n            }\n            if(config.size === 'lg'){\n              return 'padding: 14px 15px;';\n            }\n            return '';\n          }() +'\">'\n            ,elemCell.html()\n          ,'</div>'\n          ,'<i class=\"layui-icon layui-table-tips-c\">&#x1006;</i>'\n        ].join(''), elemCell[0], {\n          tips: [3, '']\n          ,time: -1\n          ,anim: -1\n          ,maxWidth: (device.ios || device.android) ? 300 : 600\n          ,isOutAnim: false\n          ,skin: 'layui-table-tips'\n          ,success: function(layero, index){\n            layero.find('.layui-table-tips-c').on('click', function(){\n              layer.close(index);\n            });\n          }\n        });\n      }\n    });\n    \n    //工具条操作事件\n    that.layBody.on('click', '*[lay-event]', function(){\n      var othis = $(this)\n      ,index = othis.parents('tr').eq(0).data('index')\n      ,tr = that.layBody.find('tr[data-index=\"'+ index +'\"]')\n      ,ELEM_CLICK = 'layui-table-click'\n      ,data = table.cache[that.key][index];\n      \n      layui.event.call(this, MOD_NAME, 'tool('+ filter +')', {\n        data: table.clearCacheKey(data)\n        ,event: othis.attr('lay-event')\n        ,tr: tr\n        ,del: function(){\n          table.cache[that.key][index] = [];\n          tr.remove();\n          that.scrollPatch();\n        }\n        ,update: function(fields){\n          fields = fields || {};\n          layui.each(fields, function(key, value){\n            if(key in data){\n              var templet, td = tr.children('td[data-field=\"'+ key +'\"]');\n              data[key] = value;\n              that.eachCols(function(i, item2){\n                if(item2.field == key && item2.templet){\n                  templet = item2.templet;\n                }\n              });\n              td.children(ELEM_CELL).html(\n                templet ? laytpl($(templet).html() || value).render(data) : value\n              );\n              td.data('content', value);\n            }\n          });\n        }\n      });\n      tr.addClass(ELEM_CLICK).siblings('tr').removeClass(ELEM_CLICK);\n    });\n    \n    //同步滚动条\n    that.layMain.on('scroll', function(){\n      var othis = $(this)\n      ,scrollLeft = othis.scrollLeft()\n      ,scrollTop = othis.scrollTop();\n      \n      that.layHeader.scrollLeft(scrollLeft);\n      that.layFixed.find(ELEM_BODY).scrollTop(scrollTop);\n      \n      layer.close(that.tipsIndex);\n    });\n    \n    _WIN.on('resize', function(){ //自适应\n       that.fullSize();\n       that.scrollPatch();\n    });\n  };\n  \n  //初始化\n  table.init = function(filter, settings){\n    settings = settings || {};\n    var that = this\n    ,elemTable = filter ? $('table[lay-filter=\"'+ filter +'\"]') : $(ELEM + '[lay-data]')\n    ,errorTips = 'Table element property lay-data configuration item has a syntax error: ';\n\n    //遍历数据表格\n    elemTable.each(function(){\n      var othis = $(this), tableData = othis.attr('lay-data');\n      \n      try{\n        tableData = new Function('return '+ tableData)();\n      } catch(e){\n        hint.error(errorTips + tableData)\n      }\n      \n      var cols = [], options = $.extend({\n        elem: this\n        ,cols: []\n        ,data: []\n        ,skin: othis.attr('lay-skin') //风格\n        ,size: othis.attr('lay-size') //尺寸\n        ,even: typeof othis.attr('lay-even') === 'string' //偶数行背景\n      }, table.config, settings, tableData);\n      \n      filter && othis.hide();\n      \n      //获取表头数据\n      othis.find('thead>tr').each(function(i){\n        options.cols[i] = [];\n        $(this).children().each(function(ii){\n          var th = $(this), itemData = th.attr('lay-data');\n          \n          try{\n            itemData = new Function('return '+ itemData)();\n          } catch(e){\n            return hint.error(errorTips + itemData)\n          }\n          \n          var row = $.extend({\n            title: th.text()\n            ,colspan: th.attr('colspan') || 0 //列单元格\n            ,rowspan: th.attr('rowspan') || 0 //行单元格\n          }, itemData);\n\n          if(row.colspan < 2) cols.push(row);\n          options.cols[i].push(row);\n        });\n      });\n\n      //获取表体数据\n      othis.find('tbody>tr').each(function(i1){\n        var tr = $(this), row = {};\n        //如果定义了字段名\n        tr.children('td').each(function(i2, item2){\n          var td = $(this)\n          ,field = td.data('field');\n          if(field){\n            return row[field] = td.html();\n          }\n        });\n        //如果未定义字段名\n        layui.each(cols, function(i3, item3){\n          var td = tr.children('td').eq(i3);\n          row[item3.field] = td.html();\n        });\n        options.data[i1] = row;\n      });\n      table.render(options);\n    });\n\n    return that;\n  };\n  \n  //表格选中状态\n  table.checkStatus = function(id){\n    var nums = 0\n    ,arr = []\n    ,data = table.cache[id];\n    if(!data) return {};\n    //计算全选个数\n    layui.each(data, function(i, item){\n      if(item[table.config.checkName]){\n        nums++;\n        arr.push(table.clearCacheKey(item));\n      }\n    });\n    return {\n      data: arr //选中的数据\n      ,isAll: nums === data.length //是否全选\n    };\n  };\n  \n  //表格重载\n  thisTable.config = {};\n  table.reload = function(id, options){\n    var config = thisTable.config[id];\n    if(!config) return hint.error('The ID option was not found in the table instance');\n    return table.render($.extend({}, config, options));\n  };\n \n  //核心入口\n  table.render = function(options){\n    var inst = new Class(options);\n    return thisTable.call(inst);\n  };\n  \n  //清除临时Key\n  table.clearCacheKey = function(data){\n    data = $.extend({}, data);\n    delete data[table.config.checkName];\n    delete data[table.config.indexName];\n    return data;\n  };\n  \n  //自动完成渲染\n  table.init();\n  \n  exports(MOD_NAME, table);\n});\n\n \n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/tree.js",
    "content": "/**\n\n @Name：layui.tree 树组件\n @author 郑保乐\n @License：MIT\n    \n */\n \n \nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,hint = layui.hint();\n  \n  var enterSkin = 'layui-tree-enter', Tree = function(options){\n    this.options = options;\n  };\n  \n  //图标\n  var icon = {\n    arrow: ['&#xe623;', '&#xe625;'] //箭头\n    ,checkbox: ['&#xe626;', '&#xe627;'] //复选框\n    ,radio: ['&#xe62b;', '&#xe62a;'] //单选框\n    ,branch: ['&#xe622;', '&#xe624;'] //父节点\n    ,leaf: '&#xe621;' //叶节点\n  };\n  \n  //初始化\n  Tree.prototype.init = function(elem){\n    var that = this;\n    elem.addClass('layui-box layui-tree'); //添加tree样式\n    if(that.options.skin){\n      elem.addClass('layui-tree-skin-'+ that.options.skin);\n    }\n    that.tree(elem);\n    that.on(elem);\n  };\n  \n  //树节点解析\n  Tree.prototype.tree = function(elem, children){\n    var that = this, options = that.options\n    var nodes = children || options.nodes;\n    \n    layui.each(nodes, function(index, item){\n      var hasChild = item.children && item.children.length > 0;\n      var ul = $('<ul class=\"'+ (item.spread ? \"layui-show\" : \"\") +'\"></ul>');\n      var li = $(['<li '+ (item.spread ? 'data-spread=\"'+ item.spread +'\"' : '') +'>'\n        //展开箭头\n        ,function(){\n          return hasChild ? '<i class=\"layui-icon layui-tree-spread\">'+ (\n            item.spread ? icon.arrow[1] : icon.arrow[0]\n          ) +'</i>' : '';\n        }()\n        \n        //复选框/单选框\n        ,function(){\n          return options.check ? (\n            '<i class=\"layui-icon layui-tree-check\">'+ (\n              options.check === 'checkbox' ? icon.checkbox[0] : (\n                options.check === 'radio' ? icon.radio[0] : ''\n              )\n            ) +'</i>'\n          ) : '';\n        }()\n        \n        //节点\n        ,function(){\n          return '<a href=\"'+ (item.href || 'javascript:;') +'\" '+ (\n            options.target && item.href ? 'target=\\\"'+ options.target +'\\\"' : ''\n          ) +'>'\n          + ('<i class=\"layui-icon layui-tree-'+ (hasChild ? \"branch\" : \"leaf\") +'\">'+ (\n            hasChild ? (\n              item.spread ? icon.branch[1] : icon.branch[0]\n            ) : icon.leaf\n          ) +'</i>') //节点图标\n          + ('<cite>'+ (item.name||'未命名') +'</cite></a>');\n        }()\n      \n      ,'</li>'].join(''));\n      \n      //如果有子节点，则递归继续生成树\n      if(hasChild){\n        li.append(ul);\n        that.tree(ul, item.children);\n      }\n      \n      elem.append(li);\n      \n      //触发点击节点回调\n      typeof options.click === 'function' && that.click(li, item); \n      \n      //伸展节点\n      that.spread(li, item);\n      \n      //拖拽节点\n      options.drag && that.drag(li, item); \n    });\n  };\n  \n  //点击节点回调\n  Tree.prototype.click = function(elem, item){\n    var that = this, options = that.options;\n    elem.children('a').on('click', function(e){\n      layui.stope(e);\n      options.click(item)\n    });\n  };\n  \n  //伸展节点\n  Tree.prototype.spread = function(elem, item){\n    var that = this, options = that.options;\n    var arrow = elem.children('.layui-tree-spread')\n    var ul = elem.children('ul'), a = elem.children('a');\n    \n    //执行伸展\n    var open = function(){\n      if(elem.data('spread')){\n        elem.data('spread', null)\n        ul.removeClass('layui-show');\n        arrow.html(icon.arrow[0]);\n        a.find('.layui-icon').html(icon.branch[0]);\n      } else {\n        elem.data('spread', true);\n        ul.addClass('layui-show');\n        arrow.html(icon.arrow[1]);\n        a.find('.layui-icon').html(icon.branch[1]);\n      }\n    };\n    \n    //如果没有子节点，则不执行\n    if(!ul[0]) return;\n    \n    arrow.on('click', open);\n    a.on('dblclick', open);\n  }\n  \n  //通用事件\n  Tree.prototype.on = function(elem){\n    var that = this, options = that.options;\n    var dragStr = 'layui-tree-drag';\n    \n    //屏蔽选中文字\n    elem.find('i').on('selectstart', function(e){\n      return false\n    });\n    \n    //拖拽\n    if(options.drag){\n      $(document).on('mousemove', function(e){\n        var move = that.move;\n        if(move.from){\n          var to = move.to, treeMove = $('<div class=\"layui-box '+ dragStr +'\"></div>');\n          e.preventDefault();\n          $('.' + dragStr)[0] || $('body').append(treeMove);\n          var dragElem = $('.' + dragStr)[0] ? $('.' + dragStr) : treeMove;\n          (dragElem).addClass('layui-show').html(move.from.elem.children('a').html());\n          dragElem.css({\n            left: e.pageX + 10\n            ,top: e.pageY + 10\n          })\n        }\n      }).on('mouseup', function(){\n        var move = that.move;\n        if(move.from){\n          move.from.elem.children('a').removeClass(enterSkin);\n          move.to && move.to.elem.children('a').removeClass(enterSkin);\n          that.move = {};\n          $('.' + dragStr).remove();\n        }\n      });\n    }\n  };\n    \n  //拖拽节点\n  Tree.prototype.move = {};\n  Tree.prototype.drag = function(elem, item){\n    var that = this, options = that.options;\n    var a = elem.children('a'), mouseenter = function(){\n      var othis = $(this), move = that.move;\n      if(move.from){\n        move.to = {\n          item: item\n          ,elem: elem\n        };\n        othis.addClass(enterSkin);\n      }\n    };\n    a.on('mousedown', function(){\n      var move = that.move\n      move.from = {\n        item: item\n        ,elem: elem\n      };\n    });\n    a.on('mouseenter', mouseenter).on('mousemove', mouseenter)\n    .on('mouseleave', function(){\n      var othis = $(this), move = that.move;\n      if(move.from){\n        delete move.to;\n        othis.removeClass(enterSkin);\n      }\n    });\n  };\n  \n  //暴露接口\n  exports('tree', function(options){\n    var tree = new Tree(options = options || {});\n    var elem = $(options.elem);\n    if(!elem[0]){\n      return hint.error('layui.tree 没有找到'+ options.elem +'元素');\n    }\n    tree.init(elem);\n  });\n});\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/upload.js",
    "content": "/**\n\n @Title: layui.upload 文件上传\n @author 郑保乐\n @License：MIT\n\n */\n \nlayui.define('layer' , function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  ,layer = layui.layer\n  ,hint = layui.hint()\n  ,device = layui.device()\n\n  //外部接口\n  ,upload = {\n    config: {} //全局配置项\n\n    //设置全局项\n    ,set: function(options){\n      var that = this;\n      that.config = $.extend({}, that.config, options);\n      return that;\n    }\n    \n    //事件监听\n    ,on: function(events, callback){\n      return layui.onevent.call(this, MOD_NAME, events, callback);\n    }\n  }\n  \n  //操作当前实例\n  ,thisUpload = function(){\n    var that = this;\n    return {\n      upload: function(files){\n        that.upload.call(that, files);\n      }\n      ,config: that.config\n    }\n  }\n  \n  //字符常量\n  ,MOD_NAME = 'upload', ELEM = '.layui-upload', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'\n  \n  ,ELEM_FILE = 'layui-upload-file', ELEM_FORM = 'layui-upload-form', ELEM_IFRAME = 'layui-upload-iframe', ELEM_CHOOSE = 'layui-upload-choose', ELEM_DRAG = 'layui-upload-drag'\n  \n  \n  //构造器\n  ,Class = function(options){\n    var that = this;\n    that.config = $.extend({}, that.config, upload.config, options);\n    that.render();\n  };\n  \n  //默认配置\n  Class.prototype.config = {\n    accept: 'images' //允许上传的文件类型：images/file/video/audio\n    ,exts: '' //允许上传的文件后缀名\n    ,auto: true //是否选完文件后自动上传\n    ,bindAction: '' //手动上传触发的元素\n    ,url: '' //上传地址\n    ,field: 'file' //文件字段名\n    ,method: 'post' //请求上传的http类型\n    ,data: {} //请求上传的额外参数\n    ,drag: true //是否允许拖拽上传\n    ,size: 0 //文件限制大小，默认不限制\n    ,multiple: false //是否允许多文件上传，不支持ie8-9\n  };\n  \n  //初始渲染\n  Class.prototype.render = function(options){\n    var that = this\n    ,options = that.config;\n\n    options.elem = $(options.elem);\n    options.bindAction = $(options.bindAction);\n\n    that.file();\n    that.events();\n  };\n  \n  //追加文件域\n  Class.prototype.file = function(){\n    var that = this\n    ,options = that.config\n    ,elemFile = that.elemFile = $([\n      '<input class=\"'+ ELEM_FILE +'\" type=\"file\" name=\"'+ options.field +'\"'\n      ,(options.multiple ? ' multiple' : '') \n      ,'>'\n    ].join(''))\n    ,next = options.elem.next();\n    \n    if(next.hasClass(ELEM_FILE) || next.hasClass(ELEM_FORM)){\n      next.remove();\n    }\n    \n    //包裹ie8/9容器\n    if(device.ie && device.ie < 10){\n      options.elem.wrap('<div class=\"layui-upload-wrap\"></div>');\n    }\n    \n    that.isFile() ? (\n      that.elemFile = options.elem\n      ,options.field = options.elem[0].name\n    ) : options.elem.after(elemFile);\n    \n    //初始化ie8/9的Form域\n    if(device.ie && device.ie < 10){\n      that.initIE();\n    }\n  };\n  \n  //ie8-9初始化\n  Class.prototype.initIE = function(){\n    var that = this\n    ,options = that.config\n    ,iframe = $('<iframe id=\"'+ ELEM_IFRAME +'\" class=\"'+ ELEM_IFRAME +'\" name=\"'+ ELEM_IFRAME +'\" frameborder=\"0\"></iframe>')\n    ,elemForm = $(['<form target=\"'+ ELEM_IFRAME +'\" class=\"'+ ELEM_FORM +'\" method=\"'+ options.method\n      ,'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+ options.url +'\">'\n    ,'</form>'].join(''));\n    \n    //插入iframe    \n    $('#'+ ELEM_IFRAME)[0] || $('body').append(iframe);\n\n    //包裹文件域\n    if(!options.elem.next().hasClass(ELEM_IFRAME)){\n      that.elemFile.wrap(elemForm);      \n      \n      //追加额外的参数\n      options.elem.next('.'+ ELEM_IFRAME).append(function(){\n        var arr = [];\n        layui.each(options.data, function(key, value){\n          arr.push('<input type=\"hidden\" name=\"'+ key +'\" value=\"'+ value +'\">')\n        });\n        return arr.join('');\n      }());\n    }\n  };\n  \n  //异常提示\n  Class.prototype.msg = function(content){\n    return layer.msg(content, {\n      icon: 2\n      ,shift: 6\n    });\n  };\n  \n  //判断绑定元素是否为文件域本身\n  Class.prototype.isFile = function(){\n    var elem = this.config.elem[0];\n    if(!elem) return;\n    return elem.tagName.toLocaleLowerCase() === 'input' && elem.type === 'file'\n  }\n  \n  //预读图片信息\n  Class.prototype.preview = function(callback){\n    var that = this;\n    if(window.FileReader){\n      layui.each(that.chooseFiles, function(index, file){\n        var reader = new FileReader();\n        reader.readAsDataURL(file);  \n        reader.onload = function(){\n          callback && callback(index, file, this.result);\n        }\n      });\n    }\n  };\n  \n  //执行上传\n  Class.prototype.upload = function(files, type){\n    var that = this\n    ,options = that.config\n    ,elemFile = that.elemFile[0]\n    \n    //高级浏览器处理方式，支持跨域\n    ,ajaxSend = function(){\n      layui.each(files || that.files || that.chooseFiles || elemFile.files, function(index, file){\n        var formData = new FormData();\n        \n        formData.append(options.field, file);\n        \n        //追加额外的参数\n        layui.each(options.data, function(key, value){\n          formData.append(key, value);\n        });\n\n        $.ajax({\n          url: options.url\n          ,type: options.method\n          ,data: formData\n          ,contentType: false \n          ,processData: false\n          ,dataType: 'json'\n          ,success: function(res){\n            done(index, res);\n          }\n          ,error: function(){\n            that.msg('请求上传接口出现异常');\n            error(index);\n          }\n        });\n      });\n    }\n    \n    //低版本IE处理方式，不支持跨域\n    ,iframeSend = function(){\n      var iframe = $('#'+ ELEM_IFRAME);\n    \n      that.elemFile.parent().submit();\n\n      //获取响应信息\n      clearInterval(Class.timer);\n      Class.timer = setInterval(function() {\n        var res, iframeBody = iframe.contents().find('body');\n        try {\n          res = iframeBody.text();\n        } catch(e) {\n          that.msg('获取上传后的响应信息出现异常');\n          clearInterval(Class.timer);\n          error();\n        }\n        if(res){\n          clearInterval(Class.timer);\n          iframeBody.html('');\n          done(0, res);\n        }\n      }, 30); \n    }\n    \n    //统一回调\n    ,done = function(index, res){\n      that.elemFile.next('.'+ ELEM_CHOOSE).remove();\n      elemFile.value = '';\n      if(typeof res !== 'object'){\n        try {\n          res = JSON.parse(res);\n        } catch(e){\n          res = {};\n          return that.msg('请对上传接口返回有效JSON');\n        }\n      }\n      typeof options.done === 'function' && options.done(res, index || 0, function(files){\n        that.upload(files);\n      });\n    }\n    \n    //统一网络异常回调\n    ,error = function(index){\n      if(options.auto){\n        elemFile.value = '';\n      }\n      typeof options.error === 'function' && options.error(index || 0, function(files){\n        that.upload(files);\n      });\n    }\n    \n    ,exts = options.exts\n    ,check ,value = function(){\n      var arr = [];\n      layui.each(files || that.chooseFiles, function(i, item){\n        arr.push(item.name);\n      });\n      return arr;\n    }()\n    \n    //回调返回的参数\n    ,args = {\n      preview: function(callback){\n        that.preview(callback);\n      }\n      ,upload: function(index, file){\n        var thisFile = {};\n        thisFile[index] = file;\n        that.upload(thisFile);\n      }\n      ,pushFile: function(){\n        that.files = that.files || {};\n        layui.each(that.chooseFiles, function(index, item){\n          that.files[index] = item;\n        });\n        return that.files;\n      }\n    }\n    \n    //提交上传\n    ,send = function(){\n      if(type === 'choose'){\n        return options.choose && options.choose(args);\n      }\n      \n      //上传前的回调\n      options.before && options.before(args);\n\n      //IE兼容处理\n      if(device.ie){\n        return device.ie > 9 ? ajaxSend() : iframeSend();\n      }\n      \n      ajaxSend();\n    }\n\n    //校验文件格式\n    value = value.length === 0 \n      ? ((elemFile.value.match(/[^\\/\\\\]+\\..+/g)||[]) || '')\n    : value;\n    \n    switch(options.accept){\n      case 'file': //一般文件\n        if(exts && !RegExp('\\\\w\\\\.('+ exts +')$', 'i').test(escape(value))){\n          that.msg('选择的文件中包含不支持的格式');\n          return elemFile.value = '';\n        }\n      break;\n      case 'video': //视频文件\n        if(!RegExp('\\\\w\\\\.('+ (exts || 'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(value))){\n          that.msg('选择的视频中包含不支持的格式');\n          return elemFile.value = '';\n        }\n      break;\n      case 'audio': //音频文件\n        if(!RegExp('\\\\w\\\\.('+ (exts || 'mp3|wav|mid') +')$', 'i').test(escape(value))){\n          that.msg('选择的音频中包含不支持的格式');\n          return elemFile.value = '';\n        }\n      break;\n      default: //图片文件\n        layui.each(value, function(i, item){\n          if(!RegExp('\\\\w\\\\.('+ (exts || 'jpg|png|gif|bmp|jpeg$') +')', 'i').test(escape(item))){\n            check = true;\n          }\n        });\n        if(check){\n          that.msg('选择的图片中包含不支持的格式');\n          return elemFile.value = '';\n        }\n      break;\n    }\n    \n    //检验文件大小\n    if(options.size > 0 && !(device.ie && device.ie < 10)){\n      var limitSize;\n      layui.each(that.chooseFiles, function(index, file){\n        if(file.size > 1024*options.size){\n          var size = options.size/1024;\n          size = size >= 1 \n            ? (Math.floor(size) + (size%1 > 0 ? size.toFixed(1) : 0)) + 'MB' \n          : options.size + 'KB'\n          elemFile.value = '';\n          limitSize = size;\n          \n        }\n      });\n      if(limitSize) return that.msg('文件不能超过'+ limitSize);\n    }\n    send();\n  };\n  \n  //事件处理\n  Class.prototype.events = function(){\n    var that = this\n    ,options = that.config\n    \n    //设置当前选择的文件队列\n    ,setChooseFile = function(files){\n      that.chooseFiles = {};\n      layui.each(files, function(i, item){\n        var time = new Date().getTime();\n        that.chooseFiles[time + '-' + i] = item;\n      });\n    }\n    \n    //设置选择的文本\n    ,setChooseText = function(files, filename){\n      var elemFile = that.elemFile\n      ,value = files.length > 1 \n        ? files.length + '个文件' \n      : ((files[0] || {}).name || (elemFile[0].value.match(/[^\\/\\\\]+\\..+/g)||[]) || '');\n      \n      if(elemFile.next().hasClass(ELEM_CHOOSE)){\n        elemFile.next().remove();\n      }\n      that.upload(null, 'choose');\n      if(that.isFile() || options.choose) return;\n      elemFile.after('<span class=\"layui-inline '+ ELEM_CHOOSE +'\">'+ value +'</span>');\n    };\n\n    //点击上传容器\n    options.elem.off('upload.start').on('upload.start', function(){\n      var othis = $(this), data = othis.attr('lay-data');\n      \n      if(data){\n        try{\n          data = new Function('return '+ data)();\n          that.config = $.extend({}, options, data);\n        } catch(e){\n          hint.error('Upload element property lay-data configuration item has a syntax error: ' + data)\n        }\n      }\n      \n      that.config.item = othis;\n      that.elemFile[0].click();\n    });\n    \n    //拖拽上传\n    if(!(device.ie && device.ie < 10)){\n      options.elem.off('upload.over').on('upload.over', function(){\n        var othis = $(this)\n        othis.attr('lay-over', '');\n      })\n      .off('upload.leave').on('upload.leave', function(){\n        var othis = $(this)\n        othis.removeAttr('lay-over');\n      })\n      .off('upload.drop').on('upload.drop', function(e, param){\n        var othis = $(this), files = param.originalEvent.dataTransfer.files || [];\n        \n        othis.removeAttr('lay-over');\n        setChooseFile(files);\n        \n        if(options.auto){\n          that.upload(files);\n        } else {\n          setChooseText(files);\n        }\n      });\n    }\n    \n    //文件选择\n    that.elemFile.off('upload.change').on('upload.change', function(){\n      var files = this.files || [];\n      setChooseFile(files);\n      options.auto ? that.upload() : setChooseText(files); //是否自动触发上传\n    });\n    \n    //手动触发上传\n    options.bindAction.off('upload.action').on('upload.action', function(){\n      that.upload();\n    });\n    \n    //防止事件重复绑定\n    if(options.elem.data('haveEvents')) return;\n    \n    that.elemFile.on('change', function(){\n      $(this).trigger('upload.change');\n    });\n    \n    options.elem.on('click', function(){\n      if(that.isFile()) return;\n      $(this).trigger('upload.start');\n    });\n    \n    if(options.drag){\n      options.elem.on('dragover', function(e){\n        e.preventDefault();\n        $(this).trigger('upload.over');\n      }).on('dragleave', function(e){\n        $(this).trigger('upload.leave');\n      }).on('drop', function(e){\n        e.preventDefault();\n        $(this).trigger('upload.drop', e);\n      });\n    }\n    \n    options.bindAction.on('click', function(){\n      $(this).trigger('upload.action');\n    });\n    \n    options.elem.data('haveEvents', true);\n  };\n  \n  //核心入口  \n  upload.render = function(options){\n    var inst = new Class(options);\n    return thisUpload.call(inst);\n  };\n  \n  exports(MOD_NAME, upload);\n});\n\n"
  },
  {
    "path": "src/main/resources/static/js/lay/modules/util.js",
    "content": "/**\n\n @Name：layui.util 工具集\n @author 郑保乐\n @License：MIT\n    \n*/\n\nlayui.define('jquery', function(exports){\n  \"use strict\";\n  \n  var $ = layui.$\n  \n  //外部接口\n  ,util = {\n    //固定块\n    fixbar: function(options){\n      var ELEM = 'layui-fixbar', TOP_BAR = 'layui-fixbar-top'\n      ,dom = $(document), body = $('body')\n      ,is, timer;\n\n      options = $.extend({\n        showHeight: 200 //出现TOP的滚动条高度临界值\n      }, options);\n      \n      options.bar1 = options.bar1 === true ? '&#xe606;' : options.bar1;\n      options.bar2 = options.bar2 === true ? '&#xe607;' : options.bar2;\n      options.bgcolor = options.bgcolor ? ('background-color:' + options.bgcolor) : '';\n      \n      var icon = [options.bar1, options.bar2, '&#xe604;'] //图标：信息、问号、TOP\n      ,elem = $(['<ul class=\"'+ ELEM +'\">'\n        ,options.bar1 ? '<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+ options.bgcolor +'\">'+ icon[0] +'</li>' : ''\n        ,options.bar2 ? '<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+ options.bgcolor +'\">'+ icon[1] +'</li>' : ''\n        ,'<li class=\"layui-icon '+ TOP_BAR +'\" lay-type=\"top\" style=\"'+ options.bgcolor +'\">'+ icon[2] +'</li>'\n      ,'</ul>'].join(''))\n      ,topBar = elem.find('.'+TOP_BAR)\n      ,scroll = function(){\n        var stop = dom.scrollTop();\n        if(stop >= (options.showHeight)){\n          is || (topBar.show(), is = 1);\n        } else {\n          is && (topBar.hide(), is = 0);\n        }\n      };\n      if($('.'+ ELEM)[0]) return;\n      \n      typeof options.css === 'object' && elem.css(options.css);\n      body.append(elem), scroll();\n      \n      //bar点击事件\n      elem.find('li').on('click', function(){\n        var othis = $(this), type = othis.attr('lay-type');\n        if(type === 'top'){\n          $('html,body').animate({\n            scrollTop : 0\n          }, 200);\n        }\n        options.click && options.click.call(this, type);\n      });\n      \n      //Top显示控制\n      dom.on('scroll', function(){\n        clearTimeout(timer);\n        timer = setTimeout(function(){\n          scroll();\n        }, 100);\n      }); \n    }\n    \n    //倒计时\n    ,countdown: function(endTime, serverTime, callback){\n      var that = this\n      ,type = typeof serverTime === 'function'\n      ,end = new Date(endTime).getTime()\n      ,now = new Date((!serverTime || type) ? new Date().getTime() : serverTime).getTime()\n      ,count = end - now\n      ,time = [\n        Math.floor(count/(1000*60*60*24)) //天\n        ,Math.floor(count/(1000*60*60)) % 24 //时\n        ,Math.floor(count/(1000*60)) % 60 //分\n        ,Math.floor(count/1000) % 60 //秒\n      ];\n      \n      if(type) callback = serverTime;\n       \n      var timer = setTimeout(function(){\n        that.countdown(endTime, now + 1000, callback);\n      }, 1000);\n      \n      callback && callback(count > 0 ? time : [0,0,0,0], serverTime, timer);\n      \n      if(count <= 0) clearTimeout(timer);\n      return timer;\n    }\n    \n    //某个时间在当前时间的多久前\n    ,timeAgo: function(time, onlyDate){\n      var stamp = new Date().getTime() - new Date(time).getTime();\n      \n      //超过30天，返回具体日期\n      if(stamp > 1000*60*60*24*30){\n        stamp =  new Date(time).toLocaleString();\n        onlyDate && (stamp = stamp.replace(/\\s[\\S]+$/g, ''));\n        return stamp;\n      }\n      \n      //30天以内，返回“多久前”\n      if(stamp >= 1000*60*60*24){\n        return ((stamp/1000/60/60/24)|0) + '天前';\n      } else if(stamp >= 1000*60*60){\n        return ((stamp/1000/60/60)|0) + '小时前';\n      } else if(stamp >= 1000*60*3){ //3分钟以内为：刚刚\n        return ((stamp/1000/60)|0) + '分钟前';\n      } else if(stamp < 0){\n        return '未来';\n      } else {\n        return '刚刚';\n      }\n    }\n  };\n  \n  exports('util', util);\n});"
  },
  {
    "path": "src/main/resources/static/js/layui.js",
    "content": "/*!\n\n @Title: Layui\n @Description：经典模块化前端框架\n @Site: www.layui.com\n @author 郑保乐\n @License：MIT\n\n */\n \n;!function(win){\n  \"use strict\";\n\n  var doc = document, config = {\n    modules: {} //记录模块物理路径\n    ,status: {} //记录模块加载状态\n    ,timeout: 10 //符合规范的模块请求最长等待秒数\n    ,event: {} //记录模块自定义事件\n  }\n\n  ,Layui = function(){\n    this.v = '2.1.5'; //版本号\n  }\n\n  //获取layui所在目录\n  ,getPath = function(){\n    var js = doc.scripts\n    ,jsPath = js[js.length - 1].src;\n    return jsPath.substring(0, jsPath.lastIndexOf('/') + 1);\n  }()\n\n  //异常提示\n  ,error = function(msg){\n    win.console && console.error && console.error('Layui hint: ' + msg);\n  }\n\n  ,isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]'\n\n  //内置模块\n  ,modules = {\n    layer: 'modules/layer' //弹层\n    ,laydate: 'modules/laydate' //日期\n    ,laypage: 'modules/laypage' //分页\n    ,laytpl: 'modules/laytpl' //模板引擎\n    ,layim: 'modules/layim' //web通讯\n    ,layedit: 'modules/layedit' //富文本编辑器\n    ,form: 'modules/form' //表单集\n    ,upload: 'modules/upload' //上传\n    ,tree: 'modules/tree' //树结构\n    ,table: 'modules/table' //表格\n    ,element: 'modules/element' //常用元素操作\n    ,util: 'modules/util' //工具块\n    ,flow: 'modules/flow' //流加载\n    ,carousel: 'modules/carousel' //轮播\n    ,code: 'modules/code' //代码修饰器\n    ,jquery: 'modules/jquery' //DOM库（第三方）\n    \n    ,mobile: 'modules/mobile' //移动大模块 | 若当前为开发目录，则为移动模块入口，否则为移动模块集合\n    ,'layui.all': '../layui.all' //PC模块合并版\n  };\n\n  //记录基础数据\n  Layui.prototype.cache = config;\n\n  //定义模块\n  Layui.prototype.define = function(deps, callback){\n    var that = this\n    ,type = typeof deps === 'function'\n    ,mods = function(){\n      typeof callback === 'function' && callback(function(app, exports){\n        layui[app] = exports;\n        config.status[app] = true;\n      });\n      return this;\n    };\n    \n    type && (\n      callback = deps,\n      deps = []\n    );\n    \n    if(layui['layui.all'] || (!layui['layui.all'] && layui['layui.mobile'])){\n      return mods.call(that);\n    }\n    \n    that.use(deps, mods);\n    return that;\n  };\n\n  //使用特定模块\n  Layui.prototype.use = function(apps, callback, exports){\n    var that = this\n    ,dir = config.dir = config.dir ? config.dir : getPath\n    ,head = doc.getElementsByTagName('head')[0];\n\n    apps = typeof apps === 'string' ? [apps] : apps;\n    \n    //如果页面已经存在jQuery1.7+库且所定义的模块依赖jQuery，则不加载内部jquery模块\n    if(window.jQuery && jQuery.fn.on){\n      that.each(apps, function(index, item){\n        if(item === 'jquery'){\n          apps.splice(index, 1);\n        }\n      });\n      layui.jquery = layui.$ = jQuery;\n    }\n    \n    var item = apps[0]\n    ,timeout = 0;\n    exports = exports || [];\n\n    //静态资源host\n    config.host = config.host || (dir.match(/\\/\\/([\\s\\S]+?)\\//)||['//'+ location.host +'/'])[0];\n    \n    //加载完毕\n    function onScriptLoad(e, url){\n      var readyRegExp = navigator.platform === 'PLaySTATION 3' ? /^complete$/ : /^(complete|loaded)$/\n      if (e.type === 'load' || (readyRegExp.test((e.currentTarget || e.srcElement).readyState))) {\n        config.modules[item] = url;\n        head.removeChild(node);\n        (function poll() {\n          if(++timeout > config.timeout * 1000 / 4){\n            return error(item + ' is not a valid module');\n          };\n          config.status[item] ? onCallback() : setTimeout(poll, 4);\n        }());\n      }\n    }\n    \n    //回调\n    function onCallback(){\n      exports.push(layui[item]);\n      apps.length > 1 ?\n        that.use(apps.slice(1), callback, exports)\n      : ( typeof callback === 'function' && callback.apply(layui, exports) );\n    }\n    \n    //如果使用了 layui.all.js\n    if(apps.length === 0 \n    || (layui['layui.all'] && modules[item]) \n    || (!layui['layui.all'] && layui['layui.mobile'] && modules[item])\n    ){\n      return onCallback(), that;\n    }\n\n    //首次加载模块\n    if(!config.modules[item]){\n      var node = doc.createElement('script')\n      ,url =  (\n        modules[item] ? (dir + 'lay/') : (config.base || '')\n      ) + (that.modules[item] || item) + '.js';\n      \n      node.async = true;\n      node.charset = 'utf-8';\n      node.src = url + function(){\n        var version = config.version === true \n        ? (config.v || (new Date()).getTime())\n        : (config.version||'');\n        return version ? ('?v=' + version) : '';\n      }();\n      \n      head.appendChild(node);\n      \n      if(node.attachEvent && !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && !isOpera){\n        node.attachEvent('onreadystatechange', function(e){\n          onScriptLoad(e, url);\n        });\n      } else {\n        node.addEventListener('load', function(e){\n          onScriptLoad(e, url);\n        }, false);\n      }\n      \n      config.modules[item] = url;\n    } else { //缓存\n      (function poll() {\n        if(++timeout > config.timeout * 1000 / 4){\n          return error(item + ' is not a valid module');\n        };\n        (typeof config.modules[item] === 'string' && config.status[item]) \n        ? onCallback() \n        : setTimeout(poll, 4);\n      }());\n    }\n    \n    return that;\n  };\n\n  //获取节点的style属性值\n  Layui.prototype.getStyle = function(node, name){\n    var style = node.currentStyle ? node.currentStyle : win.getComputedStyle(node, null);\n    return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name);\n  };\n\n  //css外部加载器\n  Layui.prototype.link = function(href, fn, cssname){\n    var that = this\n    ,link = doc.createElement('link')\n    ,head = doc.getElementsByTagName('head')[0];\n    \n    if(typeof fn === 'string') cssname = fn;\n    \n    var app = (cssname || href).replace(/\\.|\\//g, '')\n    ,id = link.id = 'layuicss-'+app\n    ,timeout = 0;\n    \n    link.rel = 'stylesheet';\n    link.href = href + (config.debug ? '?v='+new Date().getTime() : '');\n    link.media = 'all';\n    \n    if(!doc.getElementById(id)){\n      head.appendChild(link);\n    }\n\n    if(typeof fn !== 'function') return that;\n    \n    //轮询css是否加载完毕\n    (function poll() {\n      if(++timeout > config.timeout * 1000 / 100){\n        return error(href + ' timeout');\n      };\n      parseInt(that.getStyle(doc.getElementById(id), 'width')) === 1989 ? function(){\n        fn();\n      }() : setTimeout(poll, 100);\n    }());\n    \n    return that;\n  };\n\n  //css内部加载器\n  Layui.prototype.addcss = function(firename, fn, cssname){\n    return layui.link(config.dir + 'css/' + firename, fn, cssname);\n  };\n\n  //图片预加载\n  Layui.prototype.img = function(url, callback, error) {   \n    var img = new Image();\n    img.src = url; \n    if(img.complete){\n      return callback(img);\n    }\n    img.onload = function(){\n      img.onload = null;\n      callback(img);\n    };\n    img.onerror = function(e){\n      img.onerror = null;\n      error(e);\n    };  \n  };\n\n  //全局配置\n  Layui.prototype.config = function(options){\n    options = options || {};\n    for(var key in options){\n      config[key] = options[key];\n    }\n    return this;\n  };\n\n  //记录全部模块\n  Layui.prototype.modules = function(){\n    var clone = {};\n    for(var o in modules){\n      clone[o] = modules[o];\n    }\n    return clone;\n  }();\n\n  //拓展模块\n  Layui.prototype.extend = function(options){\n    var that = this;\n\n    //验证模块是否被占用\n    options = options || {};\n    for(var o in options){\n      if(that[o] || that.modules[o]){\n        error('\\u6A21\\u5757\\u540D '+ o +' \\u5DF2\\u88AB\\u5360\\u7528');\n      } else {\n        that.modules[o] = options[o];\n      }\n    }\n    \n    return that;\n  };\n\n  //路由解析\n  Layui.prototype.router = function(hash){\n    var that = this\n    ,hash = hash || location.hash\n    ,data = {\n      path: []\n      ,search: {}\n      ,hash: (hash.match(/[^#](#.*$)/) || [])[1] || ''\n    };\n    \n    if(!/^#\\//.test(hash)) return data; //禁止非路由规范\n    hash = hash.replace(/^#\\//, '').replace(/([^#])(#.*$)/, '$1').split('/') || [];\n    \n    //提取Hash结构\n    that.each(hash, function(index, item){\n      /^\\w+=/.test(item) ? function(){\n        item = item.split('=');\n        data.search[item[0]] = item[1];\n      }() : data.path.push(item);\n    });\n\n    return data;\n  };\n\n  //本地存储\n  Layui.prototype.data = function(table, settings){\n    table = table || 'layui';\n    \n    if(!win.JSON || !win.JSON.parse) return;\n    \n    //如果settings为null，则删除表\n    if(settings === null){\n      return delete localStorage[table];\n    }\n    \n    settings = typeof settings === 'object' \n      ? settings \n    : {key: settings};\n    \n    try{\n      var data = JSON.parse(localStorage[table]);\n    } catch(e){\n      var data = {};\n    }\n    \n    if(settings.value) data[settings.key] = settings.value;\n    if(settings.remove) delete data[settings.key];\n    localStorage[table] = JSON.stringify(data);\n    \n    return settings.key ? data[settings.key] : data;\n  };\n\n  //设备信息\n  Layui.prototype.device = function(key){\n    var agent = navigator.userAgent.toLowerCase()\n\n    //获取版本号\n    ,getVersion = function(label){\n      var exp = new RegExp(label + '/([^\\\\s\\\\_\\\\-]+)');\n      label = (agent.match(exp)||[])[1];\n      return label || false;\n    }\n    \n    //返回结果集\n    ,result = {\n      os: function(){ //底层操作系统\n        if(/windows/.test(agent)){\n          return 'windows';\n        } else if(/linux/.test(agent)){\n          return 'linux';\n        } else if(/iphone|ipod|ipad|ios/.test(agent)){\n          return 'ios';\n        } else if(/mac/.test(agent)){\n          return 'mac';\n        } \n      }()\n      ,ie: function(){ //ie版本\n        return (!!win.ActiveXObject || \"ActiveXObject\" in win) ? (\n          (agent.match(/msie\\s(\\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识\n        ) : false;\n      }()\n      ,weixin: getVersion('micromessenger')  //是否微信\n    };\n    \n    //任意的key\n    if(key && !result[key]){\n      result[key] = getVersion(key);\n    }\n    \n    //移动设备\n    result.android = /android/.test(agent);\n    result.ios = result.os === 'ios';\n    \n    return result;\n  };\n\n  //提示\n  Layui.prototype.hint = function(){\n    return {\n      error: error\n    }\n  };\n\n  //遍历\n  Layui.prototype.each = function(obj, fn){\n    var key\n    ,that = this;\n    if(typeof fn !== 'function') return that;\n    obj = obj || [];\n    if(obj.constructor === Object){\n      for(key in obj){\n        if(fn.call(obj[key], key, obj[key])) break;\n      }\n    } else {\n      for(key = 0; key < obj.length; key++){\n        if(fn.call(obj[key], key, obj[key])) break;\n      }\n    }\n    return that;\n  };\n\n  //将数组中的对象按其某个成员排序\n  Layui.prototype.sort = function(obj, key, desc){\n    var clone = JSON.parse(\n      JSON.stringify(obj)\n    );\n    \n    if(!key) return clone;\n    \n    //如果是数字，按大小排序，如果是非数字，按字典序排序\n    clone.sort(function(o1, o2){\n      var isNum = /^-?\\d+$/\n      ,v1 = o1[key]\n      ,v2 = o2[key];\n      \n      if(isNum.test(v1)) v1 = parseFloat(v1);\n      if(isNum.test(v2)) v2 = parseFloat(v2);\n      \n      if(v1 && !v2){\n        return 1;\n      } else if(!v1 && v2){\n        return -1;\n      }\n        \n      if(v1 > v2){\n        return 1;\n      } else if (v1 < v2) {\n        return -1;\n      } else {\n        return 0;\n      }\n    });\n\n    desc && clone.reverse(); //倒序\n    return clone;\n  };\n\n  //阻止事件冒泡\n  Layui.prototype.stope = function(e){\n    e = e || win.event;\n    e.stopPropagation \n      ? e.stopPropagation() \n    : e.cancelBubble = true;\n  };\n\n  //自定义模块事件\n  Layui.prototype.onevent = function(modName, events, callback){\n    if(typeof modName !== 'string' \n    || typeof callback !== 'function') return this;\n    config.event[modName + '.' + events] = [callback];\n    \n    //不再对多次事件监听做支持\n    /*\n    config.event[modName + '.' + events] \n      ? config.event[modName + '.' + events].push(callback) \n    : config.event[modName + '.' + events] = [callback];\n    */\n    \n    return this;\n  };\n\n  //执行自定义模块事件\n  Layui.prototype.event = function(modName, events, params){\n    var that = this\n    ,result = null\n    ,filter = events.match(/\\(.*\\)$/)||[] //提取事件过滤器\n    ,set = (events = modName + '.'+ events).replace(filter, '') //获取事件本体名\n    ,callback = function(_, item){\n      var res = item && item.call(that, params);\n      res === false && result === null && (result = false);\n    };\n    layui.each(config.event[set], callback);\n    filter[0] && layui.each(config.event[events], callback); //执行过滤器中的事件\n    return result;\n  };\n\n  win.layui = new Layui();\n\n}(window);\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/beautifyhtml/beautifyhtml.js",
    "content": "/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */\n/*\n\n  The MIT License (MIT)\n\n  Copyright (c) 2007-2013 Einar Lielmanis and contributors.\n\n  Permission is hereby granted, free of charge, to any person\n  obtaining a copy of this software and associated documentation files\n  (the \"Software\"), to deal in the Software without restriction,\n  including without limitation the rights to use, copy, modify, merge,\n  publish, distribute, sublicense, and/or sell copies of the Software,\n  and to permit persons to whom the Software is furnished to do so,\n  subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be\n  included in all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n  SOFTWARE.\n\n\n Style HTML\n---------------\n\n  Written by Nochum Sossonko, (nsossonko@hotmail.com)\n\n  Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>\n    http://jsbeautifier.org/\n\n  Usage:\n    style_html(html_source);\n\n    style_html(html_source, options);\n\n  The options are:\n    indent_size (default 4)          — indentation size,\n    indent_char (default space)      — character to indent with,\n    max_char (default 250)            -  maximum amount of characters per line (0 = disable)\n    brace_style (default \"collapse\") - \"collapse\" | \"expand\" | \"end-expand\"\n            put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.\n    unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted\n    indent_scripts (default normal)  - \"keep\"|\"separate\"|\"normal\"\n\n    e.g.\n\n    style_html(html_source, {\n      'indent_size': 2,\n      'indent_char': ' ',\n      'max_char': 78,\n      'brace_style': 'expand',\n      'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u']\n    });\n*/\n\n(function() {\n\n    function style_html(html_source, options, js_beautify, css_beautify) {\n    //Wrapper function to invoke all the necessary constructors and deal with the output.\n\n      var multi_parser,\n          indent_size,\n          indent_character,\n          max_char,\n          brace_style,\n          unformatted;\n\n      options = options || {};\n      indent_size = options.indent_size || 4;\n      indent_character = options.indent_char || ' ';\n      brace_style = options.brace_style || 'collapse';\n      max_char = options.max_char === 0 ? Infinity : options.max_char || 250;\n      unformatted = options.unformatted || ['a', 'span', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike', 'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n      function Parser() {\n\n        this.pos = 0; //Parser position\n        this.token = '';\n        this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT\n        this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values\n          parent: 'parent1',\n          parentcount: 1,\n          parent1: ''\n        };\n        this.tag_type = '';\n        this.token_text = this.last_token = this.last_text = this.token_type = '';\n\n        this.Utils = { //Uilities made available to the various functions\n          whitespace: \"\\n\\r\\t \".split(''),\n          single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?='.split(','), //all the single tags for HTML\n          extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them\n          in_array: function (what, arr) {\n            for (var i=0; i<arr.length; i++) {\n              if (what === arr[i]) {\n                return true;\n              }\n            }\n            return false;\n          }\n        };\n\n        this.get_content = function () { //function to capture regular content between tags\n\n          var input_char = '',\n              content = [],\n              space = false; //if a space is needed\n\n          while (this.input.charAt(this.pos) !== '<') {\n            if (this.pos >= this.input.length) {\n              return content.length?content.join(''):['', 'TK_EOF'];\n            }\n\n            input_char = this.input.charAt(this.pos);\n            this.pos++;\n            this.line_char_count++;\n\n            if (this.Utils.in_array(input_char, this.Utils.whitespace)) {\n              if (content.length) {\n                space = true;\n              }\n              this.line_char_count--;\n              continue; //don't want to insert unnecessary space\n            }\n            else if (space) {\n              if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached\n                content.push('\\n');\n                for (var i=0; i<this.indent_level; i++) {\n                  content.push(this.indent_string);\n                }\n                this.line_char_count = 0;\n              }\n              else{\n                content.push(' ');\n                this.line_char_count++;\n              }\n              space = false;\n            }\n            content.push(input_char); //letter at-a-time (or string) inserted to an array\n          }\n          return content.length?content.join(''):'';\n        };\n\n        this.get_contents_to = function (name) { //get the full content of a script or style to pass to js_beautify\n          if (this.pos === this.input.length) {\n            return ['', 'TK_EOF'];\n          }\n          var input_char = '';\n          var content = '';\n          var reg_match = new RegExp('</' + name + '\\\\s*>', 'igm');\n          reg_match.lastIndex = this.pos;\n          var reg_array = reg_match.exec(this.input);\n          var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script\n          if(this.pos < end_script) { //get everything in between the script tags\n            content = this.input.substring(this.pos, end_script);\n            this.pos = end_script;\n          }\n          return content;\n        };\n\n        this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object\n          if (this.tags[tag + 'count']) { //check for the existence of this tag type\n            this.tags[tag + 'count']++;\n            this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level\n          }\n          else { //otherwise initialize this tag type\n            this.tags[tag + 'count'] = 1;\n            this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level\n          }\n          this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)\n          this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')\n        };\n\n        this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer\n          if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it\n            var temp_parent = this.tags.parent; //check to see if it's a closable tag.\n            while (temp_parent) { //till we reach '' (the initial value);\n              if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it\n                break;\n              }\n              temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree\n            }\n            if (temp_parent) { //if we caught something\n              this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly\n              this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent\n            }\n            delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...\n            delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself\n            if (this.tags[tag + 'count'] === 1) {\n              delete this.tags[tag + 'count'];\n            }\n            else {\n              this.tags[tag + 'count']--;\n            }\n          }\n        };\n\n        this.get_tag = function (peek) { //function to get a full tag and parse its type\n          var input_char = '',\n              content = [],\n              comment = '',\n              space = false,\n              tag_start, tag_end,\n              orig_pos = this.pos,\n              orig_line_char_count = this.line_char_count;\n\n          peek = peek !== undefined ? peek : false;\n\n          do {\n            if (this.pos >= this.input.length) {\n              if (peek) {\n                this.pos = orig_pos;\n                this.line_char_count = orig_line_char_count;\n              }\n              return content.length?content.join(''):['', 'TK_EOF'];\n            }\n\n            input_char = this.input.charAt(this.pos);\n            this.pos++;\n            this.line_char_count++;\n\n            if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space\n              space = true;\n              this.line_char_count--;\n              continue;\n            }\n\n            if (input_char === \"'\" || input_char === '\"') {\n              if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially\n                input_char += this.get_unformatted(input_char);\n                space = true;\n              }\n            }\n\n            if (input_char === '=') { //no space before =\n              space = false;\n            }\n\n            if (content.length && content[content.length-1] !== '=' && input_char !== '>' && space) {\n                //no space after = or before >\n              if (this.line_char_count >= this.max_char) {\n                this.print_newline(false, content);\n                this.line_char_count = 0;\n              }\n              else {\n                content.push(' ');\n                this.line_char_count++;\n              }\n              space = false;\n            }\n            if (input_char === '<') {\n              tag_start = this.pos - 1;\n            }\n            content.push(input_char); //inserts character at-a-time (or string)\n          } while (input_char !== '>');\n\n          var tag_complete = content.join('');\n          var tag_index;\n          if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends\n            tag_index = tag_complete.indexOf(' ');\n          }\n          else { //otherwise go with the tag ending\n            tag_index = tag_complete.indexOf('>');\n          }\n          var tag_check = tag_complete.substring(1, tag_index).toLowerCase();\n          if (tag_complete.charAt(tag_complete.length-2) === '/' ||\n            this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)\n            if ( ! peek) {\n              this.tag_type = 'SINGLE';\n            }\n          }\n          else if (tag_check === 'script') { //for later script handling\n            if ( ! peek) {\n              this.record_tag(tag_check);\n              this.tag_type = 'SCRIPT';\n            }\n          }\n          else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)\n            if ( ! peek) {\n              this.record_tag(tag_check);\n              this.tag_type = 'STYLE';\n            }\n          }\n          else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the \"unformatted\" tags\n            comment = this.get_unformatted('</'+tag_check+'>', tag_complete); //...delegate to get_unformatted function\n            content.push(comment);\n            // Preserve collapsed whitespace either before or after this tag.\n            if (tag_start > 0 && this.Utils.in_array(this.input.charAt(tag_start - 1), this.Utils.whitespace)){\n                content.splice(0, 0, this.input.charAt(tag_start - 1));\n            }\n            tag_end = this.pos - 1;\n            if (this.Utils.in_array(this.input.charAt(tag_end + 1), this.Utils.whitespace)){\n                content.push(this.input.charAt(tag_end + 1));\n            }\n            this.tag_type = 'SINGLE';\n          }\n          else if (tag_check.charAt(0) === '!') { //peek for <!-- comment\n            if (tag_check.indexOf('[if') !== -1) { //peek for <!--[if conditional comment\n              if (tag_complete.indexOf('!IE') !== -1) { //this type needs a closing --> so...\n                comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted\n                content.push(comment);\n              }\n              if ( ! peek) {\n                this.tag_type = 'START';\n              }\n            }\n            else if (tag_check.indexOf('[endif') !== -1) {//peek for <!--[endif end conditional comment\n              this.tag_type = 'END';\n              this.unindent();\n            }\n            else if (tag_check.indexOf('[cdata[') !== -1) { //if it's a <[cdata[ comment...\n              comment = this.get_unformatted(']]>', tag_complete); //...delegate to get_unformatted function\n              content.push(comment);\n              if ( ! peek) {\n                this.tag_type = 'SINGLE'; //<![CDATA[ comments are treated like single tags\n              }\n            }\n            else {\n              comment = this.get_unformatted('-->', tag_complete);\n              content.push(comment);\n              this.tag_type = 'SINGLE';\n            }\n          }\n          else if ( ! peek) {\n            if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending\n              this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors\n              this.tag_type = 'END';\n            }\n            else { //otherwise it's a start-tag\n              this.record_tag(tag_check); //push it on the tag stack\n              this.tag_type = 'START';\n            }\n            if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line\n              this.print_newline(true, this.output);\n            }\n          }\n\n          if (peek) {\n            this.pos = orig_pos;\n            this.line_char_count = orig_line_char_count;\n          }\n\n          return content.join(''); //returns fully formatted tag\n        };\n\n        this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety\n\n          if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {\n            return '';\n          }\n          var input_char = '';\n          var content = '';\n          var space = true;\n          do {\n\n            if (this.pos >= this.input.length) {\n              return content;\n            }\n\n            input_char = this.input.charAt(this.pos);\n            this.pos++;\n\n            if (this.Utils.in_array(input_char, this.Utils.whitespace)) {\n              if (!space) {\n                this.line_char_count--;\n                continue;\n              }\n              if (input_char === '\\n' || input_char === '\\r') {\n                content += '\\n';\n                /*  Don't change tab indention for unformatted blocks.  If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'\n                for (var i=0; i<this.indent_level; i++) {\n                  content += this.indent_string;\n                }\n                space = false; //...and make sure other indentation is erased\n                */\n                this.line_char_count = 0;\n                continue;\n              }\n            }\n            content += input_char;\n            this.line_char_count++;\n            space = true;\n\n\n          } while (content.toLowerCase().indexOf(delimiter) === -1);\n          return content;\n        };\n\n        this.get_token = function () { //initial handler for token-retrieval\n          var token;\n\n          if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript\n           var type = this.last_token.substr(7);\n           token = this.get_contents_to(type);\n            if (typeof token !== 'string') {\n              return token;\n            }\n            return [token, 'TK_' + type];\n          }\n          if (this.current_mode === 'CONTENT') {\n            token = this.get_content();\n            if (typeof token !== 'string') {\n              return token;\n            }\n            else {\n              return [token, 'TK_CONTENT'];\n            }\n          }\n\n          if (this.current_mode === 'TAG') {\n            token = this.get_tag();\n            if (typeof token !== 'string') {\n              return token;\n            }\n            else {\n              var tag_name_type = 'TK_TAG_' + this.tag_type;\n              return [token, tag_name_type];\n            }\n          }\n        };\n\n        this.get_full_indent = function (level) {\n          level = this.indent_level + level || 0;\n          if (level < 1) {\n            return '';\n          }\n\n          return Array(level + 1).join(this.indent_string);\n        };\n\n        this.is_unformatted = function(tag_check, unformatted) {\n            //is this an HTML5 block-level link?\n            if (!this.Utils.in_array(tag_check, unformatted)){\n                return false;\n            }\n\n            if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)){\n                return true;\n            }\n\n            //at this point we have an  tag; is its first child something we want to remain\n            //unformatted?\n            var next_tag = this.get_tag(true /* peek. */);\n\n            // tets next_tag to see if it is just html tag (no external content)\n            var tag = (next_tag || \"\").match(/^\\s*<\\s*\\/?([a-z]*)\\s*[^>]*>\\s*$/);\n\n            // if next_tag comes back but is not an isolated tag, then\n            // let's treat the 'a' tag as having content\n            // and respect the unformatted option\n            if (!tag || this.Utils.in_array(tag, unformatted)){\n                return true;\n            } else {\n                return false;\n            }\n        };\n\n        this.printer = function (js_source, indent_character, indent_size, max_char, brace_style) { //handles input/output and some other printing functions\n\n          this.input = js_source || ''; //gets the input for the Parser\n          this.output = [];\n          this.indent_character = indent_character;\n          this.indent_string = '';\n          this.indent_size = indent_size;\n          this.brace_style = brace_style;\n          this.indent_level = 0;\n          this.max_char = max_char;\n          this.line_char_count = 0; //count to see if max_char was exceeded\n\n          for (var i=0; i<this.indent_size; i++) {\n            this.indent_string += this.indent_character;\n          }\n\n          this.print_newline = function (ignore, arr) {\n            this.line_char_count = 0;\n            if (!arr || !arr.length) {\n              return;\n            }\n            if (!ignore) { //we might want the extra line\n              while (this.Utils.in_array(arr[arr.length-1], this.Utils.whitespace)) {\n                arr.pop();\n              }\n            }\n            arr.push('\\n');\n            for (var i=0; i<this.indent_level; i++) {\n              arr.push(this.indent_string);\n            }\n          };\n\n          this.print_token = function (text) {\n            this.output.push(text);\n          };\n\n          this.indent = function () {\n            this.indent_level++;\n          };\n\n          this.unindent = function () {\n            if (this.indent_level > 0) {\n              this.indent_level--;\n            }\n          };\n        };\n        return this;\n      }\n\n      /*_____________________--------------------_____________________*/\n\n      multi_parser = new Parser(); //wrapping functions Parser\n      multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values\n\n      while (true) {\n          var t = multi_parser.get_token();\n          multi_parser.token_text = t[0];\n          multi_parser.token_type = t[1];\n\n        if (multi_parser.token_type === 'TK_EOF') {\n          break;\n        }\n\n        switch (multi_parser.token_type) {\n          case 'TK_TAG_START':\n            multi_parser.print_newline(false, multi_parser.output);\n            multi_parser.print_token(multi_parser.token_text);\n            multi_parser.indent();\n            multi_parser.current_mode = 'CONTENT';\n            break;\n          case 'TK_TAG_STYLE':\n          case 'TK_TAG_SCRIPT':\n            multi_parser.print_newline(false, multi_parser.output);\n            multi_parser.print_token(multi_parser.token_text);\n            multi_parser.current_mode = 'CONTENT';\n            break;\n          case 'TK_TAG_END':\n            //Print new line only if the tag has no content and has child\n            if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {\n                var tag_name = multi_parser.token_text.match(/\\w+/)[0];\n                var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\\s*(\\w+)/);\n                if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name) {\n                    multi_parser.print_newline(true, multi_parser.output);\n                }\n            }\n            multi_parser.print_token(multi_parser.token_text);\n            multi_parser.current_mode = 'CONTENT';\n            break;\n          case 'TK_TAG_SINGLE':\n            // Don't add a newline before elements that should remain unformatted.\n            var tag_check = multi_parser.token_text.match(/^\\s*<([a-z]+)/i);\n            if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)){\n                multi_parser.print_newline(false, multi_parser.output);\n            }\n            multi_parser.print_token(multi_parser.token_text);\n            multi_parser.current_mode = 'CONTENT';\n            break;\n          case 'TK_CONTENT':\n            if (multi_parser.token_text !== '') {\n              multi_parser.print_token(multi_parser.token_text);\n            }\n            multi_parser.current_mode = 'TAG';\n            break;\n          case 'TK_STYLE':\n          case 'TK_SCRIPT':\n            if (multi_parser.token_text !== '') {\n              multi_parser.output.push('\\n');\n              var text = multi_parser.token_text,\n                  _beautifier,\n                  script_indent_level = 1;\n              if (multi_parser.token_type === 'TK_SCRIPT') {\n                _beautifier = typeof js_beautify === 'function' && js_beautify;\n              } else if (multi_parser.token_type === 'TK_STYLE') {\n                _beautifier = typeof css_beautify === 'function' && css_beautify;\n              }\n\n              if (options.indent_scripts === \"keep\") {\n                script_indent_level = 0;\n              } else if (options.indent_scripts === \"separate\") {\n                script_indent_level = -multi_parser.indent_level;\n              }\n\n              var indentation = multi_parser.get_full_indent(script_indent_level);\n              if (_beautifier) {\n                // call the Beautifier if avaliable\n                text = _beautifier(text.replace(/^\\s*/, indentation), options);\n              } else {\n                // simply indent the string otherwise\n                var white = text.match(/^\\s*/)[0];\n                var _level = white.match(/[^\\n\\r]*$/)[0].split(multi_parser.indent_string).length - 1;\n                var reindent = multi_parser.get_full_indent(script_indent_level -_level);\n                text = text.replace(/^\\s*/, indentation)\n                       .replace(/\\r\\n|\\r|\\n/g, '\\n' + reindent)\n                       .replace(/\\s*$/, '');\n              }\n              if (text) {\n                multi_parser.print_token(text);\n                multi_parser.print_newline(true, multi_parser.output);\n              }\n            }\n            multi_parser.current_mode = 'TAG';\n            break;\n        }\n        multi_parser.last_token = multi_parser.token_type;\n        multi_parser.last_text = multi_parser.token_text;\n      }\n      return multi_parser.output.join('');\n    }\n\n    // If we're running a web page and don't have either of the above, add our one global\n    window.html_beautify = function(html_source, options) {\n        return style_html(html_source, options, window.js_beautify, window.css_beautify);\n    };\n\n}());\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js",
    "content": "/**\n * Bootstrap Table Chinese translation\n * Author: Zhixin Wen<wenzhixin2010@gmail.com>\n */\n(function ($) {\n    'use strict';\n\n    $.fn.bootstrapTable.locales['zh-CN'] = {\n        formatLoadingMessage: function () {\n            return '正在努力地加载数据中，请稍候……';\n        },\n        formatRecordsPerPage: function (pageNumber) {\n            return '每页显示 ' + pageNumber + ' 条记录';\n        },\n        formatShowingRows: function (pageFrom, pageTo, totalRows) {\n            return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录，总共 ' + totalRows + ' 条记录';\n        },\n        formatSearch: function () {\n            return '搜索';\n        },\n        formatNoMatches: function () {\n            return '没有找到匹配的记录';\n        },\n        formatPaginationSwitch: function () {\n            return '隐藏/显示分页';\n        },\n        formatRefresh: function () {\n            return '刷新';\n        },\n        formatToggle: function () {\n            return '切换';\n        },\n        formatColumns: function () {\n            return '列';\n        }\n    };\n\n    $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);\n\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/chosen/chosen.jquery.js",
    "content": "/*!\n Chosen, a Select Box Enhancer for jQuery and Prototype\n by Patrick Filler for Harvest, http://getharvest.com\n\n Version 1.1.0\n Full source at https://github.com/harvesthq/chosen\n Copyright (c) 2011 Harvest http://getharvest.com\n\n MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md\n This file is generated by `grunt build`, do not edit it by hand.\n */\n\n(function() {\n    var $, AbstractChosen, Chosen, SelectParser, _ref,\n        __hasProp = {}.hasOwnProperty,\n        __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\n    SelectParser = (function() {\n        function SelectParser() {\n            this.options_index = 0;\n            this.parsed = [];\n        }\n\n        SelectParser.prototype.add_node = function(child) {\n            if (child.nodeName.toUpperCase() === \"OPTGROUP\") {\n                return this.add_group(child);\n            } else {\n                return this.add_option(child);\n            }\n        };\n\n        SelectParser.prototype.add_group = function(group) {\n            var group_position, option, _i, _len, _ref, _results;\n            group_position = this.parsed.length;\n            this.parsed.push({\n                array_index: group_position,\n                group: true,\n                label: this.escapeExpression(group.label),\n                children: 0,\n                disabled: group.disabled\n            });\n            _ref = group.childNodes;\n            _results = [];\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                option = _ref[_i];\n                _results.push(this.add_option(option, group_position, group.disabled));\n            }\n            return _results;\n        };\n\n        SelectParser.prototype.add_option = function(option, group_position, group_disabled) {\n            if (option.nodeName.toUpperCase() === \"OPTION\") {\n                if (option.text !== \"\") {\n                    if (group_position != null) {\n                        this.parsed[group_position].children += 1;\n                    }\n                    this.parsed.push({\n                        array_index: this.parsed.length,\n                        options_index: this.options_index,\n                        value: option.value,\n                        text: option.text,\n                        html: option.innerHTML,\n                        selected: option.selected,\n                        disabled: group_disabled === true ? group_disabled : option.disabled,\n                        group_array_index: group_position,\n                        classes: option.className,\n                        style: option.style.cssText\n                    });\n                } else {\n                    this.parsed.push({\n                        array_index: this.parsed.length,\n                        options_index: this.options_index,\n                        empty: true\n                    });\n                }\n                return this.options_index += 1;\n            }\n        };\n\n        SelectParser.prototype.escapeExpression = function(text) {\n            var map, unsafe_chars;\n            if ((text == null) || text === false) {\n                return \"\";\n            }\n            if (!/[\\&\\<\\>\\\"\\'\\`]/.test(text)) {\n                return text;\n            }\n            map = {\n                \"<\": \"&lt;\",\n                \">\": \"&gt;\",\n                '\"': \"&quot;\",\n                \"'\": \"&#x27;\",\n                \"`\": \"&#x60;\"\n            };\n            unsafe_chars = /&(?!\\w+;)|[\\<\\>\\\"\\'\\`]/g;\n            return text.replace(unsafe_chars, function(chr) {\n                return map[chr] || \"&amp;\";\n            });\n        };\n\n        return SelectParser;\n\n    })();\n\n    SelectParser.select_to_array = function(select) {\n        var child, parser, _i, _len, _ref;\n        parser = new SelectParser();\n        _ref = select.childNodes;\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            child = _ref[_i];\n            parser.add_node(child);\n        }\n        return parser.parsed;\n    };\n\n    AbstractChosen = (function() {\n        function AbstractChosen(form_field, options) {\n            this.form_field = form_field;\n            this.options = options != null ? options : {};\n            if (!AbstractChosen.browser_is_supported()) {\n                return;\n            }\n            this.is_multiple = this.form_field.multiple;\n            this.set_default_text();\n            this.set_default_values();\n            this.setup();\n            this.set_up_html();\n            this.register_observers();\n        }\n\n        AbstractChosen.prototype.set_default_values = function() {\n            var _this = this;\n            this.click_test_action = function(evt) {\n                return _this.test_active_click(evt);\n            };\n            this.activate_action = function(evt) {\n                return _this.activate_field(evt);\n            };\n            this.active_field = false;\n            this.mouse_on_container = false;\n            this.results_showing = false;\n            this.result_highlighted = null;\n            this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === \"\" ? this.options.allow_single_deselect : false;\n            this.disable_search_threshold = this.options.disable_search_threshold || 0;\n            this.disable_search = this.options.disable_search || false;\n            this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;\n            this.group_search = this.options.group_search != null ? this.options.group_search : true;\n            this.search_contains = this.options.search_contains || false;\n            this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;\n            this.max_selected_options = this.options.max_selected_options || Infinity;\n            this.inherit_select_classes = this.options.inherit_select_classes || false;\n            this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;\n            return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;\n        };\n\n        AbstractChosen.prototype.set_default_text = function() {\n            if (this.form_field.getAttribute(\"data-placeholder\")) {\n                this.default_text = this.form_field.getAttribute(\"data-placeholder\");\n            } else if (this.is_multiple) {\n                this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;\n            } else {\n                this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;\n            }\n            return this.results_none_found = this.form_field.getAttribute(\"data-no_results_text\") || this.options.no_results_text || AbstractChosen.default_no_result_text;\n        };\n\n        AbstractChosen.prototype.mouse_enter = function() {\n            return this.mouse_on_container = true;\n        };\n\n        AbstractChosen.prototype.mouse_leave = function() {\n            return this.mouse_on_container = false;\n        };\n\n        AbstractChosen.prototype.input_focus = function(evt) {\n            var _this = this;\n            if (this.is_multiple) {\n                if (!this.active_field) {\n                    return setTimeout((function() {\n                        return _this.container_mousedown();\n                    }), 50);\n                }\n            } else {\n                if (!this.active_field) {\n                    return this.activate_field();\n                }\n            }\n        };\n\n        AbstractChosen.prototype.input_blur = function(evt) {\n            var _this = this;\n            if (!this.mouse_on_container) {\n                this.active_field = false;\n                return setTimeout((function() {\n                    return _this.blur_test();\n                }), 100);\n            }\n        };\n\n        AbstractChosen.prototype.results_option_build = function(options) {\n            var content, data, _i, _len, _ref;\n            content = '';\n            _ref = this.results_data;\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                data = _ref[_i];\n                if (data.group) {\n                    content += this.result_add_group(data);\n                } else {\n                    content += this.result_add_option(data);\n                }\n                if (options != null ? options.first : void 0) {\n                    if (data.selected && this.is_multiple) {\n                        this.choice_build(data);\n                    } else if (data.selected && !this.is_multiple) {\n                        this.single_set_selected_text(data.text);\n                    }\n                }\n            }\n            return content;\n        };\n\n        AbstractChosen.prototype.result_add_option = function(option) {\n            var classes, option_el;\n            if (!option.search_match) {\n                return '';\n            }\n            if (!this.include_option_in_results(option)) {\n                return '';\n            }\n            classes = [];\n            if (!option.disabled && !(option.selected && this.is_multiple)) {\n                classes.push(\"active-result\");\n            }\n            if (option.disabled && !(option.selected && this.is_multiple)) {\n                classes.push(\"disabled-result\");\n            }\n            if (option.selected) {\n                classes.push(\"result-selected\");\n            }\n            if (option.group_array_index != null) {\n                classes.push(\"group-option\");\n            }\n            if (option.classes !== \"\") {\n                classes.push(option.classes);\n            }\n            option_el = document.createElement(\"li\");\n            option_el.className = classes.join(\" \");\n            option_el.style.cssText = option.style;\n            option_el.setAttribute(\"data-option-array-index\", option.array_index);\n            option_el.innerHTML = option.search_text;\n            return this.outerHTML(option_el);\n        };\n\n        AbstractChosen.prototype.result_add_group = function(group) {\n            var group_el;\n            if (!(group.search_match || group.group_match)) {\n                return '';\n            }\n            if (!(group.active_options > 0)) {\n                return '';\n            }\n            group_el = document.createElement(\"li\");\n            group_el.className = \"group-result\";\n            group_el.innerHTML = group.search_text;\n            return this.outerHTML(group_el);\n        };\n\n        AbstractChosen.prototype.results_update_field = function() {\n            this.set_default_text();\n            if (!this.is_multiple) {\n                this.results_reset_cleanup();\n            }\n            this.result_clear_highlight();\n            this.results_build();\n            if (this.results_showing) {\n                return this.winnow_results();\n            }\n        };\n\n        AbstractChosen.prototype.reset_single_select_options = function() {\n            var result, _i, _len, _ref, _results;\n            _ref = this.results_data;\n            _results = [];\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                result = _ref[_i];\n                if (result.selected) {\n                    _results.push(result.selected = false);\n                } else {\n                    _results.push(void 0);\n                }\n            }\n            return _results;\n        };\n\n        AbstractChosen.prototype.results_toggle = function() {\n            if (this.results_showing) {\n                return this.results_hide();\n            } else {\n                return this.results_show();\n            }\n        };\n\n        AbstractChosen.prototype.results_search = function(evt) {\n            if (this.results_showing) {\n                return this.winnow_results();\n            } else {\n                return this.results_show();\n            }\n        };\n\n        AbstractChosen.prototype.winnow_results = function() {\n            var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;\n            this.no_results_clear();\n            results = 0;\n            searchText = this.get_search_text();\n            escapedSearchText = searchText.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\");\n            regexAnchor = this.search_contains ? \"\" : \"^\";\n            regex = new RegExp(regexAnchor + escapedSearchText, 'i');\n            zregex = new RegExp(escapedSearchText, 'i');\n            _ref = this.results_data;\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                option = _ref[_i];\n                option.search_match = false;\n                results_group = null;\n                if (this.include_option_in_results(option)) {\n                    if (option.group) {\n                        option.group_match = false;\n                        option.active_options = 0;\n                    }\n                    if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {\n                        results_group = this.results_data[option.group_array_index];\n                        if (results_group.active_options === 0 && results_group.search_match) {\n                            results += 1;\n                        }\n                        results_group.active_options += 1;\n                    }\n                    if (!(option.group && !this.group_search)) {\n                        option.search_text = option.group ? option.label : option.html;\n                        option.search_match = this.search_string_match(option.search_text, regex);\n                        if (option.search_match && !option.group) {\n                            results += 1;\n                        }\n                        if (option.search_match) {\n                            if (searchText.length) {\n                                startpos = option.search_text.search(zregex);\n                                text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);\n                                option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);\n                            }\n                            if (results_group != null) {\n                                results_group.group_match = true;\n                            }\n                        } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {\n                            option.search_match = true;\n                        }\n                    }\n                }\n            }\n            this.result_clear_highlight();\n            if (results < 1 && searchText.length) {\n                this.update_results_content(\"\");\n                return this.no_results(searchText);\n            } else {\n                this.update_results_content(this.results_option_build());\n                return this.winnow_results_set_highlight();\n            }\n        };\n\n        AbstractChosen.prototype.search_string_match = function(search_string, regex) {\n            var part, parts, _i, _len;\n            if (regex.test(search_string)) {\n                return true;\n            } else if (this.enable_split_word_search && (search_string.indexOf(\" \") >= 0 || search_string.indexOf(\"[\") === 0)) {\n                parts = search_string.replace(/\\[|\\]/g, \"\").split(\" \");\n                if (parts.length) {\n                    for (_i = 0, _len = parts.length; _i < _len; _i++) {\n                        part = parts[_i];\n                        if (regex.test(part)) {\n                            return true;\n                        }\n                    }\n                }\n            }\n        };\n\n        AbstractChosen.prototype.choices_count = function() {\n            var option, _i, _len, _ref;\n            if (this.selected_option_count != null) {\n                return this.selected_option_count;\n            }\n            this.selected_option_count = 0;\n            _ref = this.form_field.options;\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                option = _ref[_i];\n                if (option.selected) {\n                    this.selected_option_count += 1;\n                }\n            }\n            return this.selected_option_count;\n        };\n\n        AbstractChosen.prototype.choices_click = function(evt) {\n            evt.preventDefault();\n            if (!(this.results_showing || this.is_disabled)) {\n                return this.results_show();\n            }\n        };\n\n        AbstractChosen.prototype.keyup_checker = function(evt) {\n            var stroke, _ref;\n            stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;\n            this.search_field_scale();\n            switch (stroke) {\n                case 8:\n                    if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {\n                        return this.keydown_backstroke();\n                    } else if (!this.pending_backstroke) {\n                        this.result_clear_highlight();\n                        return this.results_search();\n                    }\n                    break;\n                case 13:\n                    evt.preventDefault();\n                    if (this.results_showing) {\n                        return this.result_select(evt);\n                    }\n                    break;\n                case 27:\n                    if (this.results_showing) {\n                        this.results_hide();\n                    }\n                    return true;\n                case 9:\n                case 38:\n                case 40:\n                case 16:\n                case 91:\n                case 17:\n                    break;\n                default:\n                    return this.results_search();\n            }\n        };\n\n        AbstractChosen.prototype.clipboard_event_checker = function(evt) {\n            var _this = this;\n            return setTimeout((function() {\n                return _this.results_search();\n            }), 50);\n        };\n\n        AbstractChosen.prototype.container_width = function() {\n            if (this.options.width != null) {\n                return this.options.width;\n            } else {\n                return \"\" + this.form_field.offsetWidth + \"px\";\n            }\n        };\n\n        AbstractChosen.prototype.include_option_in_results = function(option) {\n            if (this.is_multiple && (!this.display_selected_options && option.selected)) {\n                return false;\n            }\n            if (!this.display_disabled_options && option.disabled) {\n                return false;\n            }\n            if (option.empty) {\n                return false;\n            }\n            return true;\n        };\n\n        AbstractChosen.prototype.search_results_touchstart = function(evt) {\n            this.touch_started = true;\n            return this.search_results_mouseover(evt);\n        };\n\n        AbstractChosen.prototype.search_results_touchmove = function(evt) {\n            this.touch_started = false;\n            return this.search_results_mouseout(evt);\n        };\n\n        AbstractChosen.prototype.search_results_touchend = function(evt) {\n            if (this.touch_started) {\n                return this.search_results_mouseup(evt);\n            }\n        };\n\n        AbstractChosen.prototype.outerHTML = function(element) {\n            var tmp;\n            if (element.outerHTML) {\n                return element.outerHTML;\n            }\n            tmp = document.createElement(\"div\");\n            tmp.appendChild(element);\n            return tmp.innerHTML;\n        };\n\n        AbstractChosen.browser_is_supported = function() {\n            if (window.navigator.appName === \"Microsoft Internet Explorer\") {\n                return document.documentMode >= 8;\n            }\n            if (/iP(od|hone)/i.test(window.navigator.userAgent)) {\n                return false;\n            }\n            if (/Android/i.test(window.navigator.userAgent)) {\n                if (/Mobile/i.test(window.navigator.userAgent)) {\n                    return false;\n                }\n            }\n            return true;\n        };\n\n        AbstractChosen.default_multiple_text = \"Select Some Options\";\n\n        AbstractChosen.default_single_text = \"Select an Option\";\n\n        AbstractChosen.default_no_result_text = \"No results match\";\n\n        return AbstractChosen;\n\n    })();\n\n    $ = jQuery;\n\n    $.fn.extend({\n        chosen: function(options) {\n            if (!AbstractChosen.browser_is_supported()) {\n                return this;\n            }\n            return this.each(function(input_field) {\n                var $this, chosen;\n                $this = $(this);\n                chosen = $this.data('chosen');\n                if (options === 'destroy' && chosen) {\n                    chosen.destroy();\n                } else if (!chosen) {\n                    $this.data('chosen', new Chosen(this, options));\n                }\n            });\n        }\n    });\n\n    Chosen = (function(_super) {\n        __extends(Chosen, _super);\n\n        function Chosen() {\n            _ref = Chosen.__super__.constructor.apply(this, arguments);\n            return _ref;\n        }\n\n        Chosen.prototype.setup = function() {\n            this.form_field_jq = $(this.form_field);\n            this.current_selectedIndex = this.form_field.selectedIndex;\n            return this.is_rtl = this.form_field_jq.hasClass(\"chosen-rtl\");\n        };\n\n        Chosen.prototype.set_up_html = function() {\n            var container_classes, container_props;\n            container_classes = [\"chosen-container\"];\n            container_classes.push(\"chosen-container-\" + (this.is_multiple ? \"multi\" : \"single\"));\n            if (this.inherit_select_classes && this.form_field.className) {\n                container_classes.push(this.form_field.className);\n            }\n            if (this.is_rtl) {\n                container_classes.push(\"chosen-rtl\");\n            }\n            container_props = {\n                'class': container_classes.join(' '),\n                'style': \"width: \" + (this.container_width()) + \";\",\n                'title': this.form_field.title\n            };\n            if (this.form_field.id.length) {\n                container_props.id = this.form_field.id.replace(/[^\\w]/g, '_') + \"_chosen\";\n            }\n            this.container = $(\"<div />\", container_props);\n            if (this.is_multiple) {\n                this.container.html('<ul class=\"chosen-choices\"><li class=\"search-field\"><input type=\"text\" value=\"' + this.default_text + '\" class=\"default\" autocomplete=\"off\" style=\"width:25px;\" /></li></ul><div class=\"chosen-drop\"><ul class=\"chosen-results\"></ul></div>');\n            } else {\n                this.container.html('<a class=\"chosen-single chosen-default\" tabindex=\"-1\"><span>' + this.default_text + '</span><div><b></b></div></a><div class=\"chosen-drop\"><div class=\"chosen-search\"><input type=\"text\" autocomplete=\"off\" /></div><ul class=\"chosen-results\"></ul></div>');\n            }\n            this.form_field_jq.hide().after(this.container);\n            this.dropdown = this.container.find('div.chosen-drop').first();\n            this.search_field = this.container.find('input').first();\n            this.search_results = this.container.find('ul.chosen-results').first();\n            this.search_field_scale();\n            this.search_no_results = this.container.find('li.no-results').first();\n            if (this.is_multiple) {\n                this.search_choices = this.container.find('ul.chosen-choices').first();\n                this.search_container = this.container.find('li.search-field').first();\n            } else {\n                this.search_container = this.container.find('div.chosen-search').first();\n                this.selected_item = this.container.find('.chosen-single').first();\n            }\n            this.results_build();\n            this.set_tab_index();\n            this.set_label_behavior();\n            return this.form_field_jq.trigger(\"chosen:ready\", {\n                chosen: this\n            });\n        };\n\n        Chosen.prototype.register_observers = function() {\n            var _this = this;\n            this.container.bind('mousedown.chosen', function(evt) {\n                _this.container_mousedown(evt);\n            });\n            this.container.bind('mouseup.chosen', function(evt) {\n                _this.container_mouseup(evt);\n            });\n            this.container.bind('mouseenter.chosen', function(evt) {\n                _this.mouse_enter(evt);\n            });\n            this.container.bind('mouseleave.chosen', function(evt) {\n                _this.mouse_leave(evt);\n            });\n            this.search_results.bind('mouseup.chosen', function(evt) {\n                _this.search_results_mouseup(evt);\n            });\n            this.search_results.bind('mouseover.chosen', function(evt) {\n                _this.search_results_mouseover(evt);\n            });\n            this.search_results.bind('mouseout.chosen', function(evt) {\n                _this.search_results_mouseout(evt);\n            });\n            this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {\n                _this.search_results_mousewheel(evt);\n            });\n            this.search_results.bind('touchstart.chosen', function(evt) {\n                _this.search_results_touchstart(evt);\n            });\n            this.search_results.bind('touchmove.chosen', function(evt) {\n                _this.search_results_touchmove(evt);\n            });\n            this.search_results.bind('touchend.chosen', function(evt) {\n                _this.search_results_touchend(evt);\n            });\n            this.form_field_jq.bind(\"chosen:updated.chosen\", function(evt) {\n                _this.results_update_field(evt);\n            });\n            this.form_field_jq.bind(\"chosen:activate.chosen\", function(evt) {\n                _this.activate_field(evt);\n            });\n            this.form_field_jq.bind(\"chosen:open.chosen\", function(evt) {\n                _this.container_mousedown(evt);\n            });\n            this.form_field_jq.bind(\"chosen:close.chosen\", function(evt) {\n                _this.input_blur(evt);\n            });\n            this.search_field.bind('blur.chosen', function(evt) {\n                _this.input_blur(evt);\n            });\n            this.search_field.bind('keyup.chosen', function(evt) {\n                _this.keyup_checker(evt);\n            });\n            this.search_field.bind('keydown.chosen', function(evt) {\n                _this.keydown_checker(evt);\n            });\n            this.search_field.bind('focus.chosen', function(evt) {\n                _this.input_focus(evt);\n            });\n            this.search_field.bind('cut.chosen', function(evt) {\n                _this.clipboard_event_checker(evt);\n            });\n            this.search_field.bind('paste.chosen', function(evt) {\n                _this.clipboard_event_checker(evt);\n            });\n            if (this.is_multiple) {\n                return this.search_choices.bind('click.chosen', function(evt) {\n                    _this.choices_click(evt);\n                });\n            } else {\n                return this.container.bind('click.chosen', function(evt) {\n                    evt.preventDefault();\n                });\n            }\n        };\n\n        Chosen.prototype.destroy = function() {\n            $(this.container[0].ownerDocument).unbind(\"click.chosen\", this.click_test_action);\n            if (this.search_field[0].tabIndex) {\n                this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;\n            }\n            this.container.remove();\n            this.form_field_jq.removeData('chosen');\n            return this.form_field_jq.show();\n        };\n\n        Chosen.prototype.search_field_disabled = function() {\n            this.is_disabled = this.form_field_jq[0].disabled;\n            if (this.is_disabled) {\n                this.container.addClass('chosen-disabled');\n                this.search_field[0].disabled = true;\n                if (!this.is_multiple) {\n                    this.selected_item.unbind(\"focus.chosen\", this.activate_action);\n                }\n                return this.close_field();\n            } else {\n                this.container.removeClass('chosen-disabled');\n                this.search_field[0].disabled = false;\n                if (!this.is_multiple) {\n                    return this.selected_item.bind(\"focus.chosen\", this.activate_action);\n                }\n            }\n        };\n\n        Chosen.prototype.container_mousedown = function(evt) {\n            if (!this.is_disabled) {\n                if (evt && evt.type === \"mousedown\" && !this.results_showing) {\n                    evt.preventDefault();\n                }\n                if (!((evt != null) && ($(evt.target)).hasClass(\"search-choice-close\"))) {\n                    if (!this.active_field) {\n                        if (this.is_multiple) {\n                            this.search_field.val(\"\");\n                        }\n                        $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);\n                        this.results_show();\n                    } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents(\"a.chosen-single\").length)) {\n                        evt.preventDefault();\n                        this.results_toggle();\n                    }\n                    return this.activate_field();\n                }\n            }\n        };\n\n        Chosen.prototype.container_mouseup = function(evt) {\n            if (evt.target.nodeName === \"ABBR\" && !this.is_disabled) {\n                return this.results_reset(evt);\n            }\n        };\n\n        Chosen.prototype.search_results_mousewheel = function(evt) {\n            var delta;\n            if (evt.originalEvent) {\n                delta = -evt.originalEvent.wheelDelta || evt.originalEvent.detail;\n            }\n            if (delta != null) {\n                evt.preventDefault();\n                if (evt.type === 'DOMMouseScroll') {\n                    delta = delta * 40;\n                }\n                return this.search_results.scrollTop(delta + this.search_results.scrollTop());\n            }\n        };\n\n        Chosen.prototype.blur_test = function(evt) {\n            if (!this.active_field && this.container.hasClass(\"chosen-container-active\")) {\n                return this.close_field();\n            }\n        };\n\n        Chosen.prototype.close_field = function() {\n            $(this.container[0].ownerDocument).unbind(\"click.chosen\", this.click_test_action);\n            this.active_field = false;\n            this.results_hide();\n            this.container.removeClass(\"chosen-container-active\");\n            this.clear_backstroke();\n            this.show_search_field_default();\n            return this.search_field_scale();\n        };\n\n        Chosen.prototype.activate_field = function() {\n            this.container.addClass(\"chosen-container-active\");\n            this.active_field = true;\n            this.search_field.val(this.search_field.val());\n            return this.search_field.focus();\n        };\n\n        Chosen.prototype.test_active_click = function(evt) {\n            var active_container;\n            active_container = $(evt.target).closest('.chosen-container');\n            if (active_container.length && this.container[0] === active_container[0]) {\n                return this.active_field = true;\n            } else {\n                return this.close_field();\n            }\n        };\n\n        Chosen.prototype.results_build = function() {\n            this.parsing = true;\n            this.selected_option_count = null;\n            this.results_data = SelectParser.select_to_array(this.form_field);\n            if (this.is_multiple) {\n                this.search_choices.find(\"li.search-choice\").remove();\n            } else if (!this.is_multiple) {\n                this.single_set_selected_text();\n                if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {\n                    this.search_field[0].readOnly = true;\n                    this.container.addClass(\"chosen-container-single-nosearch\");\n                } else {\n                    this.search_field[0].readOnly = false;\n                    this.container.removeClass(\"chosen-container-single-nosearch\");\n                }\n            }\n            this.update_results_content(this.results_option_build({\n                first: true\n            }));\n            this.search_field_disabled();\n            this.show_search_field_default();\n            this.search_field_scale();\n            return this.parsing = false;\n        };\n\n        Chosen.prototype.result_do_highlight = function(el) {\n            var high_bottom, high_top, maxHeight, visible_bottom, visible_top;\n            if (el.length) {\n                this.result_clear_highlight();\n                this.result_highlight = el;\n                this.result_highlight.addClass(\"highlighted\");\n                maxHeight = parseInt(this.search_results.css(\"maxHeight\"), 10);\n                visible_top = this.search_results.scrollTop();\n                visible_bottom = maxHeight + visible_top;\n                high_top = this.result_highlight.position().top + this.search_results.scrollTop();\n                high_bottom = high_top + this.result_highlight.outerHeight();\n                if (high_bottom >= visible_bottom) {\n                    return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);\n                } else if (high_top < visible_top) {\n                    return this.search_results.scrollTop(high_top);\n                }\n            }\n        };\n\n        Chosen.prototype.result_clear_highlight = function() {\n            if (this.result_highlight) {\n                this.result_highlight.removeClass(\"highlighted\");\n            }\n            return this.result_highlight = null;\n        };\n\n        Chosen.prototype.results_show = function() {\n            if (this.is_multiple && this.max_selected_options <= this.choices_count()) {\n                this.form_field_jq.trigger(\"chosen:maxselected\", {\n                    chosen: this\n                });\n                return false;\n            }\n            this.container.addClass(\"chosen-with-drop\");\n            this.results_showing = true;\n            this.search_field.focus();\n            this.search_field.val(this.search_field.val());\n            this.winnow_results();\n            return this.form_field_jq.trigger(\"chosen:showing_dropdown\", {\n                chosen: this\n            });\n        };\n\n        Chosen.prototype.update_results_content = function(content) {\n            return this.search_results.html(content);\n        };\n\n        Chosen.prototype.results_hide = function() {\n            if (this.results_showing) {\n                this.result_clear_highlight();\n                this.container.removeClass(\"chosen-with-drop\");\n                this.form_field_jq.trigger(\"chosen:hiding_dropdown\", {\n                    chosen: this\n                });\n            }\n            return this.results_showing = false;\n        };\n\n        Chosen.prototype.set_tab_index = function(el) {\n            var ti;\n            if (this.form_field.tabIndex) {\n                ti = this.form_field.tabIndex;\n                this.form_field.tabIndex = -1;\n                return this.search_field[0].tabIndex = ti;\n            }\n        };\n\n        Chosen.prototype.set_label_behavior = function() {\n            var _this = this;\n            this.form_field_label = this.form_field_jq.parents(\"label\");\n            if (!this.form_field_label.length && this.form_field.id.length) {\n                this.form_field_label = $(\"label[for='\" + this.form_field.id + \"']\");\n            }\n            if (this.form_field_label.length > 0) {\n                return this.form_field_label.bind('click.chosen', function(evt) {\n                    if (_this.is_multiple) {\n                        return _this.container_mousedown(evt);\n                    } else {\n                        return _this.activate_field();\n                    }\n                });\n            }\n        };\n\n        Chosen.prototype.show_search_field_default = function() {\n            if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {\n                this.search_field.val(this.default_text);\n                return this.search_field.addClass(\"default\");\n            } else {\n                this.search_field.val(\"\");\n                return this.search_field.removeClass(\"default\");\n            }\n        };\n\n        Chosen.prototype.search_results_mouseup = function(evt) {\n            var target;\n            target = $(evt.target).hasClass(\"active-result\") ? $(evt.target) : $(evt.target).parents(\".active-result\").first();\n            if (target.length) {\n                this.result_highlight = target;\n                this.result_select(evt);\n                return this.search_field.focus();\n            }\n        };\n\n        Chosen.prototype.search_results_mouseover = function(evt) {\n            var target;\n            target = $(evt.target).hasClass(\"active-result\") ? $(evt.target) : $(evt.target).parents(\".active-result\").first();\n            if (target) {\n                return this.result_do_highlight(target);\n            }\n        };\n\n        Chosen.prototype.search_results_mouseout = function(evt) {\n            if ($(evt.target).hasClass(\"active-result\" || $(evt.target).parents('.active-result').first())) {\n                return this.result_clear_highlight();\n            }\n        };\n\n        Chosen.prototype.choice_build = function(item) {\n            var choice, close_link,\n                _this = this;\n            choice = $('<li />', {\n                \"class\": \"search-choice\"\n            }).html(\"<span>\" + item.html + \"</span>\");\n            if (item.disabled) {\n                choice.addClass('search-choice-disabled');\n            } else {\n                close_link = $('<a />', {\n                    \"class\": 'search-choice-close',\n                    'data-option-array-index': item.array_index\n                });\n                close_link.bind('click.chosen', function(evt) {\n                    return _this.choice_destroy_link_click(evt);\n                });\n                choice.append(close_link);\n            }\n            return this.search_container.before(choice);\n        };\n\n        Chosen.prototype.choice_destroy_link_click = function(evt) {\n            evt.preventDefault();\n            evt.stopPropagation();\n            if (!this.is_disabled) {\n                return this.choice_destroy($(evt.target));\n            }\n        };\n\n        Chosen.prototype.choice_destroy = function(link) {\n            if (this.result_deselect(link[0].getAttribute(\"data-option-array-index\"))) {\n                this.show_search_field_default();\n                if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {\n                    this.results_hide();\n                }\n                link.parents('li').first().remove();\n                return this.search_field_scale();\n            }\n        };\n\n        Chosen.prototype.results_reset = function() {\n            this.reset_single_select_options();\n            this.form_field.options[0].selected = true;\n            this.single_set_selected_text();\n            this.show_search_field_default();\n            this.results_reset_cleanup();\n            this.form_field_jq.trigger(\"change\");\n            if (this.active_field) {\n                return this.results_hide();\n            }\n        };\n\n        Chosen.prototype.results_reset_cleanup = function() {\n            this.current_selectedIndex = this.form_field.selectedIndex;\n            return this.selected_item.find(\"abbr\").remove();\n        };\n\n        Chosen.prototype.result_select = function(evt) {\n            var high, item;\n            if (this.result_highlight) {\n                high = this.result_highlight;\n                this.result_clear_highlight();\n                if (this.is_multiple && this.max_selected_options <= this.choices_count()) {\n                    this.form_field_jq.trigger(\"chosen:maxselected\", {\n                        chosen: this\n                    });\n                    return false;\n                }\n                if (this.is_multiple) {\n                    high.removeClass(\"active-result\");\n                } else {\n                    this.reset_single_select_options();\n                }\n                item = this.results_data[high[0].getAttribute(\"data-option-array-index\")];\n                item.selected = true;\n                this.form_field.options[item.options_index].selected = true;\n                this.selected_option_count = null;\n                if (this.is_multiple) {\n                    this.choice_build(item);\n                } else {\n                    this.single_set_selected_text(item.text);\n                }\n                if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {\n                    this.results_hide();\n                }\n                this.search_field.val(\"\");\n                if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {\n                    this.form_field_jq.trigger(\"change\", {\n                        'selected': this.form_field.options[item.options_index].value\n                    });\n                }\n                this.current_selectedIndex = this.form_field.selectedIndex;\n                return this.search_field_scale();\n            }\n        };\n\n        Chosen.prototype.single_set_selected_text = function(text) {\n            if (text == null) {\n                text = this.default_text;\n            }\n            if (text === this.default_text) {\n                this.selected_item.addClass(\"chosen-default\");\n            } else {\n                this.single_deselect_control_build();\n                this.selected_item.removeClass(\"chosen-default\");\n            }\n            return this.selected_item.find(\"span\").text(text);\n        };\n\n        Chosen.prototype.result_deselect = function(pos) {\n            var result_data;\n            result_data = this.results_data[pos];\n            if (!this.form_field.options[result_data.options_index].disabled) {\n                result_data.selected = false;\n                this.form_field.options[result_data.options_index].selected = false;\n                this.selected_option_count = null;\n                this.result_clear_highlight();\n                if (this.results_showing) {\n                    this.winnow_results();\n                }\n                this.form_field_jq.trigger(\"change\", {\n                    deselected: this.form_field.options[result_data.options_index].value\n                });\n                this.search_field_scale();\n                return true;\n            } else {\n                return false;\n            }\n        };\n\n        Chosen.prototype.single_deselect_control_build = function() {\n            if (!this.allow_single_deselect) {\n                return;\n            }\n            if (!this.selected_item.find(\"abbr\").length) {\n                this.selected_item.find(\"span\").first().after(\"<abbr class=\\\"search-choice-close\\\"></abbr>\");\n            }\n            return this.selected_item.addClass(\"chosen-single-with-deselect\");\n        };\n\n        Chosen.prototype.get_search_text = function() {\n            if (this.search_field.val() === this.default_text) {\n                return \"\";\n            } else {\n                return $('<div/>').text($.trim(this.search_field.val())).html();\n            }\n        };\n\n        Chosen.prototype.winnow_results_set_highlight = function() {\n            var do_high, selected_results;\n            selected_results = !this.is_multiple ? this.search_results.find(\".result-selected.active-result\") : [];\n            do_high = selected_results.length ? selected_results.first() : this.search_results.find(\".active-result\").first();\n            if (do_high != null) {\n                return this.result_do_highlight(do_high);\n            }\n        };\n\n        Chosen.prototype.no_results = function(terms) {\n            var no_results_html;\n            no_results_html = $('<li class=\"no-results\">' + this.results_none_found + ' \"<span></span>\"</li>');\n            no_results_html.find(\"span\").first().html(terms);\n            this.search_results.append(no_results_html);\n            return this.form_field_jq.trigger(\"chosen:no_results\", {\n                chosen: this\n            });\n        };\n\n        Chosen.prototype.no_results_clear = function() {\n            return this.search_results.find(\".no-results\").remove();\n        };\n\n        Chosen.prototype.keydown_arrow = function() {\n            var next_sib;\n            if (this.results_showing && this.result_highlight) {\n                next_sib = this.result_highlight.nextAll(\"li.active-result\").first();\n                if (next_sib) {\n                    return this.result_do_highlight(next_sib);\n                }\n            } else {\n                return this.results_show();\n            }\n        };\n\n        Chosen.prototype.keyup_arrow = function() {\n            var prev_sibs;\n            if (!this.results_showing && !this.is_multiple) {\n                return this.results_show();\n            } else if (this.result_highlight) {\n                prev_sibs = this.result_highlight.prevAll(\"li.active-result\");\n                if (prev_sibs.length) {\n                    return this.result_do_highlight(prev_sibs.first());\n                } else {\n                    if (this.choices_count() > 0) {\n                        this.results_hide();\n                    }\n                    return this.result_clear_highlight();\n                }\n            }\n        };\n\n        Chosen.prototype.keydown_backstroke = function() {\n            var next_available_destroy;\n            if (this.pending_backstroke) {\n                this.choice_destroy(this.pending_backstroke.find(\"a\").first());\n                return this.clear_backstroke();\n            } else {\n                next_available_destroy = this.search_container.siblings(\"li.search-choice\").last();\n                if (next_available_destroy.length && !next_available_destroy.hasClass(\"search-choice-disabled\")) {\n                    this.pending_backstroke = next_available_destroy;\n                    if (this.single_backstroke_delete) {\n                        return this.keydown_backstroke();\n                    } else {\n                        return this.pending_backstroke.addClass(\"search-choice-focus\");\n                    }\n                }\n            }\n        };\n\n        Chosen.prototype.clear_backstroke = function() {\n            if (this.pending_backstroke) {\n                this.pending_backstroke.removeClass(\"search-choice-focus\");\n            }\n            return this.pending_backstroke = null;\n        };\n\n        Chosen.prototype.keydown_checker = function(evt) {\n            var stroke, _ref1;\n            stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;\n            this.search_field_scale();\n            if (stroke !== 8 && this.pending_backstroke) {\n                this.clear_backstroke();\n            }\n            switch (stroke) {\n                case 8:\n                    this.backstroke_length = this.search_field.val().length;\n                    break;\n                case 9:\n                    if (this.results_showing && !this.is_multiple) {\n                        this.result_select(evt);\n                    }\n                    this.mouse_on_container = false;\n                    break;\n                case 13:\n                    evt.preventDefault();\n                    break;\n                case 38:\n                    evt.preventDefault();\n                    this.keyup_arrow();\n                    break;\n                case 40:\n                    evt.preventDefault();\n                    this.keydown_arrow();\n                    break;\n            }\n        };\n\n        Chosen.prototype.search_field_scale = function() {\n            var div, f_width, h, style, style_block, styles, w, _i, _len;\n            if (this.is_multiple) {\n                h = 0;\n                w = 0;\n                style_block = \"position:absolute; left: -1000px; top: -1000px; display:none;\";\n                styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];\n                for (_i = 0, _len = styles.length; _i < _len; _i++) {\n                    style = styles[_i];\n                    style_block += style + \":\" + this.search_field.css(style) + \";\";\n                }\n                div = $('<div />', {\n                    'style': style_block\n                });\n                div.text(this.search_field.val());\n                $('body').append(div);\n                w = div.width() + 25;\n                div.remove();\n                f_width = this.container.outerWidth();\n                if (w > f_width - 10) {\n                    w = f_width - 10;\n                }\n                return this.search_field.css({\n                    'width': w + 'px'\n                });\n            }\n        };\n\n        return Chosen;\n\n    })(AbstractChosen);\n\n}).call(this);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/clockpicker/clockpicker.js",
    "content": "/*!\n * ClockPicker v{package.version} (http://weareoutman.github.io/clockpicker/)\n * Copyright 2014 Wang Shenwei.\n * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE)\n */\n\n;(function(){\n\tvar $ = window.jQuery,\n\t\t$win = $(window),\n\t\t$doc = $(document),\n\t\t$body;\n\n\t// Can I use inline svg ?\n\tvar svgNS = 'http://www.w3.org/2000/svg',\n\t\tsvgSupported = 'SVGAngle' in window && (function(){\n\t\t\tvar supported,\n\t\t\t\tel = document.createElement('div');\n\t\t\tel.innerHTML = '<svg/>';\n\t\t\tsupported = (el.firstChild && el.firstChild.namespaceURI) == svgNS;\n\t\t\tel.innerHTML = '';\n\t\t\treturn supported;\n\t\t})();\n\n\t// Can I use transition ?\n\tvar transitionSupported = (function(){\n\t\tvar style = document.createElement('div').style;\n\t\treturn 'transition' in style ||\n\t\t\t'WebkitTransition' in style ||\n\t\t\t'MozTransition' in style ||\n\t\t\t'msTransition' in style ||\n\t\t\t'OTransition' in style;\n\t})();\n\n\t// Listen touch events in touch screen device, instead of mouse events in desktop.\n\tvar touchSupported = 'ontouchstart' in window,\n\t\tmousedownEvent = 'mousedown' + ( touchSupported ? ' touchstart' : ''),\n\t\tmousemoveEvent = 'mousemove.clockpicker' + ( touchSupported ? ' touchmove.clockpicker' : ''),\n\t\tmouseupEvent = 'mouseup.clockpicker' + ( touchSupported ? ' touchend.clockpicker' : '');\n\n\t// Vibrate the device if supported\n\tvar vibrate = navigator.vibrate ? 'vibrate' : navigator.webkitVibrate ? 'webkitVibrate' : null;\n\n\tfunction createSvgElement(name) {\n\t\treturn document.createElementNS(svgNS, name);\n\t}\n\n\tfunction leadingZero(num) {\n\t\treturn (num < 10 ? '0' : '') + num;\n\t}\n\n\t// Get a unique id\n\tvar idCounter = 0;\n\tfunction uniqueId(prefix) {\n\t\tvar id = ++idCounter + '';\n\t\treturn prefix ? prefix + id : id;\n\t}\n\n\t// Clock size\n\tvar dialRadius = 100,\n\t\touterRadius = 80,\n\t\t// innerRadius = 80 on 12 hour clock\n\t\tinnerRadius = 54,\n\t\ttickRadius = 13,\n\t\tdiameter = dialRadius * 2,\n\t\tduration = transitionSupported ? 350 : 1;\n\n\t// Popover template\n\tvar tpl = [\n\t\t'<div class=\"popover clockpicker-popover\">',\n\t\t\t'<div class=\"arrow\"></div>',\n\t\t\t'<div class=\"popover-title\">',\n\t\t\t\t'<span class=\"clockpicker-span-hours text-primary\"></span>',\n\t\t\t\t' : ',\n\t\t\t\t'<span class=\"clockpicker-span-minutes\"></span>',\n\t\t\t\t'<span class=\"clockpicker-span-am-pm\"></span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"popover-content\">',\n\t\t\t\t'<div class=\"clockpicker-plate\">',\n\t\t\t\t\t'<div class=\"clockpicker-canvas\"></div>',\n\t\t\t\t\t'<div class=\"clockpicker-dial clockpicker-hours\"></div>',\n\t\t\t\t\t'<div class=\"clockpicker-dial clockpicker-minutes clockpicker-dial-out\"></div>',\n\t\t\t\t'</div>',\n\t\t\t\t'<span class=\"clockpicker-am-pm-block\">',\n\t\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t'</div>'\n\t].join('');\n\n\t// ClockPicker\n\tfunction ClockPicker(element, options) {\n\t\tvar popover = $(tpl),\n\t\t\tplate = popover.find('.clockpicker-plate'),\n\t\t\thoursView = popover.find('.clockpicker-hours'),\n\t\t\tminutesView = popover.find('.clockpicker-minutes'),\n\t\t\tamPmBlock = popover.find('.clockpicker-am-pm-block'),\n\t\t\tisInput = element.prop('tagName') === 'INPUT',\n\t\t\tinput = isInput ? element : element.find('input'),\n\t\t\taddon = element.find('.input-group-addon'),\n\t\t\tself = this,\n\t\t\ttimer;\n\n\t\tthis.id = uniqueId('cp');\n\t\tthis.element = element;\n\t\tthis.options = options;\n\t\tthis.isAppended = false;\n\t\tthis.isShown = false;\n\t\tthis.currentView = 'hours';\n\t\tthis.isInput = isInput;\n\t\tthis.input = input;\n\t\tthis.addon = addon;\n\t\tthis.popover = popover;\n\t\tthis.plate = plate;\n\t\tthis.hoursView = hoursView;\n\t\tthis.minutesView = minutesView;\n\t\tthis.amPmBlock = amPmBlock;\n\t\tthis.spanHours = popover.find('.clockpicker-span-hours');\n\t\tthis.spanMinutes = popover.find('.clockpicker-span-minutes');\n\t\tthis.spanAmPm = popover.find('.clockpicker-span-am-pm');\n\t\tthis.amOrPm = \"PM\";\n\n\t\t// Setup for for 12 hour clock if option is selected\n\t\tif (options.twelvehour) {\n\n\t\t\tvar  amPmButtonsTemplate = ['<div class=\"clockpicker-am-pm-block\">',\n\t\t\t\t'<button type=\"button\" class=\"btn btn-sm btn-default clockpicker-button clockpicker-am-button\">',\n\t\t\t\t'AM</button>',\n\t\t\t\t'<button type=\"button\" class=\"btn btn-sm btn-default clockpicker-button clockpicker-pm-button\">',\n\t\t\t\t'PM</button>',\n\t\t\t\t'</div>'].join('');\n\n\t\t\tvar amPmButtons = $(amPmButtonsTemplate);\n\t\t\t//amPmButtons.appendTo(plate);\n\n\t\t\t////Not working b/c they are not shown when this runs\n\t\t\t//$('clockpicker-am-button')\n\t\t\t//    .on(\"click\", function() {\n\t\t\t//        self.amOrPm = \"AM\";\n\t\t\t//        $('.clockpicker-span-am-pm').empty().append('AM');\n\t\t\t//    });\n\t\t\t//\n\t\t\t//$('clockpicker-pm-button')\n\t\t\t//    .on(\"click\", function() {\n\t\t\t//         self.amOrPm = \"PM\";\n\t\t\t//        $('.clockpicker-span-am-pm').empty().append('PM');\n\t\t\t//    });\n\n\t\t\t$('<button type=\"button\" class=\"btn btn-sm btn-default clockpicker-button am-button\">' + \"AM\" + '</button>')\n\t\t\t\t.on(\"click\", function() {\n\t\t\t\t\tself.amOrPm = \"AM\";\n\t\t\t\t\t$('.clockpicker-span-am-pm').empty().append('AM');\n\t\t\t\t}).appendTo(this.amPmBlock);\n\n\n\t\t\t$('<button type=\"button\" class=\"btn btn-sm btn-default clockpicker-button pm-button\">' + \"PM\" + '</button>')\n\t\t\t\t.on(\"click\", function() {\n\t\t\t\t\tself.amOrPm = 'PM';\n\t\t\t\t\t$('.clockpicker-span-am-pm').empty().append('PM');\n\t\t\t\t}).appendTo(this.amPmBlock);\n\n\t\t}\n\n\t\tif (! options.autoclose) {\n\t\t\t// If autoclose is not setted, append a button\n\t\t\t$('<button type=\"button\" class=\"btn btn-sm btn-default btn-block clockpicker-button\">' + options.donetext + '</button>')\n\t\t\t\t.click($.proxy(this.done, this))\n\t\t\t\t.appendTo(popover);\n\t\t}\n\n\t\t// Placement and arrow align - make sure they make sense.\n\t\tif ((options.placement === 'top' || options.placement === 'bottom') && (options.align === 'top' || options.align === 'bottom')) options.align = 'left';\n\t\tif ((options.placement === 'left' || options.placement === 'right') && (options.align === 'left' || options.align === 'right')) options.align = 'top';\n\n\t\tpopover.addClass(options.placement);\n\t\tpopover.addClass('clockpicker-align-' + options.align);\n\n\t\tthis.spanHours.click($.proxy(this.toggleView, this, 'hours'));\n\t\tthis.spanMinutes.click($.proxy(this.toggleView, this, 'minutes'));\n\n\t\t// Show or toggle\n\t\tinput.on('focus.clockpicker click.clockpicker', $.proxy(this.show, this));\n\t\taddon.on('click.clockpicker', $.proxy(this.toggle, this));\n\n\t\t// Build ticks\n\t\tvar tickTpl = $('<div class=\"clockpicker-tick\"></div>'),\n\t\t\ti, tick, radian, radius;\n\n\t\t// Hours view\n\t\tif (options.twelvehour) {\n\t\t\tfor (i = 1; i < 13; i += 1) {\n\t\t\t\ttick = tickTpl.clone();\n\t\t\t\tradian = i / 6 * Math.PI;\n\t\t\t\tradius = outerRadius;\n\t\t\t\ttick.css('font-size', '120%');\n\t\t\t\ttick.css({\n\t\t\t\t\tleft: dialRadius + Math.sin(radian) * radius - tickRadius,\n\t\t\t\t\ttop: dialRadius - Math.cos(radian) * radius - tickRadius\n\t\t\t\t});\n\t\t\t\ttick.html(i === 0 ? '00' : i);\n\t\t\t\thoursView.append(tick);\n\t\t\t\ttick.on(mousedownEvent, mousedown);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (i = 0; i < 24; i += 1) {\n\t\t\t\ttick = tickTpl.clone();\n\t\t\t\tradian = i / 6 * Math.PI;\n\t\t\t\tvar inner = i > 0 && i < 13;\n\t\t\t\tradius = inner ? innerRadius : outerRadius;\n\t\t\t\ttick.css({\n\t\t\t\t\tleft: dialRadius + Math.sin(radian) * radius - tickRadius,\n\t\t\t\t\ttop: dialRadius - Math.cos(radian) * radius - tickRadius\n\t\t\t\t});\n\t\t\t\tif (inner) {\n\t\t\t\t\ttick.css('font-size', '120%');\n\t\t\t\t}\n\t\t\t\ttick.html(i === 0 ? '00' : i);\n\t\t\t\thoursView.append(tick);\n\t\t\t\ttick.on(mousedownEvent, mousedown);\n\t\t\t}\n\t\t}\n\n\t\t// Minutes view\n\t\tfor (i = 0; i < 60; i += 5) {\n\t\t\ttick = tickTpl.clone();\n\t\t\tradian = i / 30 * Math.PI;\n\t\t\ttick.css({\n\t\t\t\tleft: dialRadius + Math.sin(radian) * outerRadius - tickRadius,\n\t\t\t\ttop: dialRadius - Math.cos(radian) * outerRadius - tickRadius\n\t\t\t});\n\t\t\ttick.css('font-size', '120%');\n\t\t\ttick.html(leadingZero(i));\n\t\t\tminutesView.append(tick);\n\t\t\ttick.on(mousedownEvent, mousedown);\n\t\t}\n\n\t\t// Clicking on minutes view space\n\t\tplate.on(mousedownEvent, function(e){\n\t\t\tif ($(e.target).closest('.clockpicker-tick').length === 0) {\n\t\t\t\tmousedown(e, true);\n\t\t\t}\n\t\t});\n\n\t\t// Mousedown or touchstart\n\t\tfunction mousedown(e, space) {\n\t\t\tvar offset = plate.offset(),\n\t\t\t\tisTouch = /^touch/.test(e.type),\n\t\t\t\tx0 = offset.left + dialRadius,\n\t\t\t\ty0 = offset.top + dialRadius,\n\t\t\t\tdx = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,\n\t\t\t\tdy = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0,\n\t\t\t\tz = Math.sqrt(dx * dx + dy * dy),\n\t\t\t\tmoved = false;\n\n\t\t\t// When clicking on minutes view space, check the mouse position\n\t\t\tif (space && (z < outerRadius - tickRadius || z > outerRadius + tickRadius)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\te.preventDefault();\n\n\t\t\t// Set cursor style of body after 200ms\n\t\t\tvar movingTimer = setTimeout(function(){\n\t\t\t\t$body.addClass('clockpicker-moving');\n\t\t\t}, 200);\n\n\t\t\t// Place the canvas to top\n\t\t\tif (svgSupported) {\n\t\t\t\tplate.append(self.canvas);\n\t\t\t}\n\n\t\t\t// Clock\n\t\t\tself.setHand(dx, dy, ! space, true);\n\n\t\t\t// Mousemove on document\n\t\t\t$doc.off(mousemoveEvent).on(mousemoveEvent, function(e){\n\t\t\t\te.preventDefault();\n\t\t\t\tvar isTouch = /^touch/.test(e.type),\n\t\t\t\t\tx = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,\n\t\t\t\t\ty = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0;\n\t\t\t\tif (! moved && x === dx && y === dy) {\n\t\t\t\t\t// Clicking in chrome on windows will trigger a mousemove event\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmoved = true;\n\t\t\t\tself.setHand(x, y, false, true);\n\t\t\t});\n\n\t\t\t// Mouseup on document\n\t\t\t$doc.off(mouseupEvent).on(mouseupEvent, function(e){\n\t\t\t\t$doc.off(mouseupEvent);\n\t\t\t\te.preventDefault();\n\t\t\t\tvar isTouch = /^touch/.test(e.type),\n\t\t\t\t\tx = (isTouch ? e.originalEvent.changedTouches[0] : e).pageX - x0,\n\t\t\t\t\ty = (isTouch ? e.originalEvent.changedTouches[0] : e).pageY - y0;\n\t\t\t\tif ((space || moved) && x === dx && y === dy) {\n\t\t\t\t\tself.setHand(x, y);\n\t\t\t\t}\n\t\t\t\tif (self.currentView === 'hours') {\n\t\t\t\t\tself.toggleView('minutes', duration / 2);\n\t\t\t\t} else {\n\t\t\t\t\tif (options.autoclose) {\n\t\t\t\t\t\tself.minutesView.addClass('clockpicker-dial-out');\n\t\t\t\t\t\tsetTimeout(function(){\n\t\t\t\t\t\t\tself.done();\n\t\t\t\t\t\t}, duration / 2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tplate.prepend(canvas);\n\n\t\t\t\t// Reset cursor style of body\n\t\t\t\tclearTimeout(movingTimer);\n\t\t\t\t$body.removeClass('clockpicker-moving');\n\n\t\t\t\t// Unbind mousemove event\n\t\t\t\t$doc.off(mousemoveEvent);\n\t\t\t});\n\t\t}\n\n\t\tif (svgSupported) {\n\t\t\t// Draw clock hands and others\n\t\t\tvar canvas = popover.find('.clockpicker-canvas'),\n\t\t\t\tsvg = createSvgElement('svg');\n\t\t\tsvg.setAttribute('class', 'clockpicker-svg');\n\t\t\tsvg.setAttribute('width', diameter);\n\t\t\tsvg.setAttribute('height', diameter);\n\t\t\tvar g = createSvgElement('g');\n\t\t\tg.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');\n\t\t\tvar bearing = createSvgElement('circle');\n\t\t\tbearing.setAttribute('class', 'clockpicker-canvas-bearing');\n\t\t\tbearing.setAttribute('cx', 0);\n\t\t\tbearing.setAttribute('cy', 0);\n\t\t\tbearing.setAttribute('r', 2);\n\t\t\tvar hand = createSvgElement('line');\n\t\t\thand.setAttribute('x1', 0);\n\t\t\thand.setAttribute('y1', 0);\n\t\t\tvar bg = createSvgElement('circle');\n\t\t\tbg.setAttribute('class', 'clockpicker-canvas-bg');\n\t\t\tbg.setAttribute('r', tickRadius);\n\t\t\tvar fg = createSvgElement('circle');\n\t\t\tfg.setAttribute('class', 'clockpicker-canvas-fg');\n\t\t\tfg.setAttribute('r', 3.5);\n\t\t\tg.appendChild(hand);\n\t\t\tg.appendChild(bg);\n\t\t\tg.appendChild(fg);\n\t\t\tg.appendChild(bearing);\n\t\t\tsvg.appendChild(g);\n\t\t\tcanvas.append(svg);\n\n\t\t\tthis.hand = hand;\n\t\t\tthis.bg = bg;\n\t\t\tthis.fg = fg;\n\t\t\tthis.bearing = bearing;\n\t\t\tthis.g = g;\n\t\t\tthis.canvas = canvas;\n\t\t}\n\n\t\traiseCallback(this.options.init);\n\t}\n\n\tfunction raiseCallback(callbackFunction) {\n\t\tif (callbackFunction && typeof callbackFunction === \"function\") {\n\t\t\tcallbackFunction();\n\t\t}\n\t}\n\n\t// Default options\n\tClockPicker.DEFAULTS = {\n\t\t'default': '',       // default time, 'now' or '13:14' e.g.\n\t\tfromnow: 0,          // set default time to * milliseconds from now (using with default = 'now')\n\t\tplacement: 'bottom', // clock popover placement\n\t\talign: 'left',       // popover arrow align\n\t\tdonetext: '完成',    // done button text\n\t\tautoclose: false,    // auto close when minute is selected\n\t\ttwelvehour: false, // change to 12 hour AM/PM clock from 24 hour\n\t\tvibrate: true        // vibrate the device when dragging clock hand\n\t};\n\n\t// Show or hide popover\n\tClockPicker.prototype.toggle = function(){\n\t\tthis[this.isShown ? 'hide' : 'show']();\n\t};\n\n\t// Set popover position\n\tClockPicker.prototype.locate = function(){\n\t\tvar element = this.element,\n\t\t\tpopover = this.popover,\n\t\t\toffset = element.offset(),\n\t\t\twidth = element.outerWidth(),\n\t\t\theight = element.outerHeight(),\n\t\t\tplacement = this.options.placement,\n\t\t\talign = this.options.align,\n\t\t\tstyles = {},\n\t\t\tself = this;\n\n\t\tpopover.show();\n\n\t\t// Place the popover\n\t\tswitch (placement) {\n\t\t\tcase 'bottom':\n\t\t\t\tstyles.top = offset.top + height;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstyles.left = offset.left + width;\n\t\t\t\tbreak;\n\t\t\tcase 'top':\n\t\t\t\tstyles.top = offset.top - popover.outerHeight();\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstyles.left = offset.left - popover.outerWidth();\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Align the popover arrow\n\t\tswitch (align) {\n\t\t\tcase 'left':\n\t\t\t\tstyles.left = offset.left;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstyles.left = offset.left + width - popover.outerWidth();\n\t\t\t\tbreak;\n\t\t\tcase 'top':\n\t\t\t\tstyles.top = offset.top;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstyles.top = offset.top + height - popover.outerHeight();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tpopover.css(styles);\n\t};\n\n\t// Show popover\n\tClockPicker.prototype.show = function(e){\n\t\t// Not show again\n\t\tif (this.isShown) {\n\t\t\treturn;\n\t\t}\n\n\t\traiseCallback(this.options.beforeShow);\n\n\t\tvar self = this;\n\n\t\t// Initialize\n\t\tif (! this.isAppended) {\n\t\t\t// Append popover to body\n\t\t\t$body = $(document.body).append(this.popover);\n\n\t\t\t// Reset position when resize\n\t\t\t$win.on('resize.clockpicker' + this.id, function(){\n\t\t\t\tif (self.isShown) {\n\t\t\t\t\tself.locate();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.isAppended = true;\n\t\t}\n\n\t\t// Get the time\n\t\tvar value = ((this.input.prop('value') || this.options['default'] || '') + '').split(':');\n\t\tif (value[0] === 'now') {\n\t\t\tvar now = new Date(+ new Date() + this.options.fromnow);\n\t\t\tvalue = [\n\t\t\t\tnow.getHours(),\n\t\t\t\tnow.getMinutes()\n\t\t\t];\n\t\t}\n\t\tthis.hours = + value[0] || 0;\n\t\tthis.minutes = + value[1] || 0;\n\t\tthis.spanHours.html(leadingZero(this.hours));\n\t\tthis.spanMinutes.html(leadingZero(this.minutes));\n\n\t\t// Toggle to hours view\n\t\tthis.toggleView('hours');\n\n\t\t// Set position\n\t\tthis.locate();\n\n\t\tthis.isShown = true;\n\n\t\t// Hide when clicking or tabbing on any element except the clock, input and addon\n\t\t$doc.on('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id, function(e){\n\t\t\tvar target = $(e.target);\n\t\t\tif (target.closest(self.popover).length === 0 &&\n\t\t\t\t\ttarget.closest(self.addon).length === 0 &&\n\t\t\t\t\ttarget.closest(self.input).length === 0) {\n\t\t\t\tself.hide();\n\t\t\t}\n\t\t});\n\n\t\t// Hide when ESC is pressed\n\t\t$doc.on('keyup.clockpicker.' + this.id, function(e){\n\t\t\tif (e.keyCode === 27) {\n\t\t\t\tself.hide();\n\t\t\t}\n\t\t});\n\n\t\traiseCallback(this.options.afterShow);\n\t};\n\n\t// Hide popover\n\tClockPicker.prototype.hide = function(){\n\t\traiseCallback(this.options.beforeHide);\n\n\t\tthis.isShown = false;\n\n\t\t// Unbinding events on document\n\t\t$doc.off('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id);\n\t\t$doc.off('keyup.clockpicker.' + this.id);\n\n\t\tthis.popover.hide();\n\n\t\traiseCallback(this.options.afterHide);\n\t};\n\n\t// Toggle to hours or minutes view\n\tClockPicker.prototype.toggleView = function(view, delay){\n\t\tvar raiseAfterHourSelect = false;\n\t\tif (view === 'minutes' && $(this.hoursView).css(\"visibility\") === \"visible\") {\n\t\t\traiseCallback(this.options.beforeHourSelect);\n\t\t\traiseAfterHourSelect = true;\n\t\t}\n\t\tvar isHours = view === 'hours',\n\t\t\tnextView = isHours ? this.hoursView : this.minutesView,\n\t\t\thideView = isHours ? this.minutesView : this.hoursView;\n\n\t\tthis.currentView = view;\n\n\t\tthis.spanHours.toggleClass('text-primary', isHours);\n\t\tthis.spanMinutes.toggleClass('text-primary', ! isHours);\n\n\t\t// Let's make transitions\n\t\thideView.addClass('clockpicker-dial-out');\n\t\tnextView.css('visibility', 'visible').removeClass('clockpicker-dial-out');\n\n\t\t// Reset clock hand\n\t\tthis.resetClock(delay);\n\n\t\t// After transitions ended\n\t\tclearTimeout(this.toggleViewTimer);\n\t\tthis.toggleViewTimer = setTimeout(function(){\n\t\t\thideView.css('visibility', 'hidden');\n\t\t}, duration);\n\n\t\tif (raiseAfterHourSelect) {\n\t\t\traiseCallback(this.options.afterHourSelect);\n\t\t}\n\t};\n\n\t// Reset clock hand\n\tClockPicker.prototype.resetClock = function(delay){\n\t\tvar view = this.currentView,\n\t\t\tvalue = this[view],\n\t\t\tisHours = view === 'hours',\n\t\t\tunit = Math.PI / (isHours ? 6 : 30),\n\t\t\tradian = value * unit,\n\t\t\tradius = isHours && value > 0 && value < 13 ? innerRadius : outerRadius,\n\t\t\tx = Math.sin(radian) * radius,\n\t\t\ty = - Math.cos(radian) * radius,\n\t\t\tself = this;\n\t\tif (svgSupported && delay) {\n\t\t\tself.canvas.addClass('clockpicker-canvas-out');\n\t\t\tsetTimeout(function(){\n\t\t\t\tself.canvas.removeClass('clockpicker-canvas-out');\n\t\t\t\tself.setHand(x, y);\n\t\t\t}, delay);\n\t\t} else {\n\t\t\tthis.setHand(x, y);\n\t\t}\n\t};\n\n\t// Set clock hand to (x, y)\n\tClockPicker.prototype.setHand = function(x, y, roundBy5, dragging){\n\t\tvar radian = Math.atan2(x, - y),\n\t\t\tisHours = this.currentView === 'hours',\n\t\t\tunit = Math.PI / (isHours || roundBy5 ? 6 : 30),\n\t\t\tz = Math.sqrt(x * x + y * y),\n\t\t\toptions = this.options,\n\t\t\tinner = isHours && z < (outerRadius + innerRadius) / 2,\n\t\t\tradius = inner ? innerRadius : outerRadius,\n\t\t\tvalue;\n\n\t\t\tif (options.twelvehour) {\n\t\t\t\tradius = outerRadius;\n\t\t\t}\n\n\t\t// Radian should in range [0, 2PI]\n\t\tif (radian < 0) {\n\t\t\tradian = Math.PI * 2 + radian;\n\t\t}\n\n\t\t// Get the round value\n\t\tvalue = Math.round(radian / unit);\n\n\t\t// Get the round radian\n\t\tradian = value * unit;\n\n\t\t// Correct the hours or minutes\n\t\tif (options.twelvehour) {\n\t\t\tif (isHours) {\n\t\t\t\tif (value === 0) {\n\t\t\t\t\tvalue = 12;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (roundBy5) {\n\t\t\t\t\tvalue *= 5;\n\t\t\t\t}\n\t\t\t\tif (value === 60) {\n\t\t\t\t\tvalue = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (isHours) {\n\t\t\t\tif (value === 12) {\n\t\t\t\t\tvalue = 0;\n\t\t\t\t}\n\t\t\t\tvalue = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;\n\t\t\t} else {\n\t\t\t\tif (roundBy5) {\n\t\t\t\t\tvalue *= 5;\n\t\t\t\t}\n\t\t\t\tif (value === 60) {\n\t\t\t\t\tvalue = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Once hours or minutes changed, vibrate the device\n\t\tif (this[this.currentView] !== value) {\n\t\t\tif (vibrate && this.options.vibrate) {\n\t\t\t\t// Do not vibrate too frequently\n\t\t\t\tif (! this.vibrateTimer) {\n\t\t\t\t\tnavigator[vibrate](10);\n\t\t\t\t\tthis.vibrateTimer = setTimeout($.proxy(function(){\n\t\t\t\t\t\tthis.vibrateTimer = null;\n\t\t\t\t\t}, this), 100);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis[this.currentView] = value;\n\t\tthis[isHours ? 'spanHours' : 'spanMinutes'].html(leadingZero(value));\n\n\t\t// If svg is not supported, just add an active class to the tick\n\t\tif (! svgSupported) {\n\t\t\tthis[isHours ? 'hoursView' : 'minutesView'].find('.clockpicker-tick').each(function(){\n\t\t\t\tvar tick = $(this);\n\t\t\t\ttick.toggleClass('active', value === + tick.html());\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Place clock hand at the top when dragging\n\t\tif (dragging || (! isHours && value % 5)) {\n\t\t\tthis.g.insertBefore(this.hand, this.bearing);\n\t\t\tthis.g.insertBefore(this.bg, this.fg);\n\t\t\tthis.bg.setAttribute('class', 'clockpicker-canvas-bg clockpicker-canvas-bg-trans');\n\t\t} else {\n\t\t\t// Or place it at the bottom\n\t\t\tthis.g.insertBefore(this.hand, this.bg);\n\t\t\tthis.g.insertBefore(this.fg, this.bg);\n\t\t\tthis.bg.setAttribute('class', 'clockpicker-canvas-bg');\n\t\t}\n\n\t\t// Set clock hand and others' position\n\t\tvar cx = Math.sin(radian) * radius,\n\t\t\tcy = - Math.cos(radian) * radius;\n\t\tthis.hand.setAttribute('x2', cx);\n\t\tthis.hand.setAttribute('y2', cy);\n\t\tthis.bg.setAttribute('cx', cx);\n\t\tthis.bg.setAttribute('cy', cy);\n\t\tthis.fg.setAttribute('cx', cx);\n\t\tthis.fg.setAttribute('cy', cy);\n\t};\n\n\t// Hours and minutes are selected\n\tClockPicker.prototype.done = function() {\n\t\traiseCallback(this.options.beforeDone);\n\t\tthis.hide();\n\t\tvar last = this.input.prop('value'),\n\t\t\tvalue = leadingZero(this.hours) + ':' + leadingZero(this.minutes);\n\t\tif  (this.options.twelvehour) {\n\t\t\tvalue = value + this.amOrPm;\n\t\t}\n\n\t\tthis.input.prop('value', value);\n\t\tif (value !== last) {\n\t\t\tthis.input.triggerHandler('change');\n\t\t\tif (! this.isInput) {\n\t\t\t\tthis.element.trigger('change');\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.autoclose) {\n\t\t\tthis.input.trigger('blur');\n\t\t}\n\n\t\traiseCallback(this.options.afterDone);\n\t};\n\n\t// Remove clockpicker from input\n\tClockPicker.prototype.remove = function() {\n\t\tthis.element.removeData('clockpicker');\n\t\tthis.input.off('focus.clockpicker click.clockpicker');\n\t\tthis.addon.off('click.clockpicker');\n\t\tif (this.isShown) {\n\t\t\tthis.hide();\n\t\t}\n\t\tif (this.isAppended) {\n\t\t\t$win.off('resize.clockpicker' + this.id);\n\t\t\tthis.popover.remove();\n\t\t}\n\t};\n\n\t// Extends $.fn.clockpicker\n\t$.fn.clockpicker = function(option){\n\t\tvar args = Array.prototype.slice.call(arguments, 1);\n\t\treturn this.each(function(){\n\t\t\tvar $this = $(this),\n\t\t\t\tdata = $this.data('clockpicker');\n\t\t\tif (! data) {\n\t\t\t\tvar options = $.extend({}, ClockPicker.DEFAULTS, $this.data(), typeof option == 'object' && option);\n\t\t\t\t$this.data('clockpicker', new ClockPicker($this, options));\n\t\t\t} else {\n\t\t\t\t// Manual operatsions. show, hide, remove, e.g.\n\t\t\t\tif (typeof data[option] === 'function') {\n\t\t\t\t\tdata[option].apply(data, args);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n}());\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/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.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\n  var gecko = /gecko\\/\\d/i.test(navigator.userAgent);\n  // ie_uptoN means Internet Explorer version N or lower\n  var ie_upto10 = /MSIE \\d/.test(navigator.userAgent);\n  var ie_11up = /Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(navigator.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(navigator.userAgent);\n  var qtwebkit = webkit && /Qt\\/\\d+\\.\\d+/.test(navigator.userAgent);\n  var chrome = /Chrome\\//.test(navigator.userAgent);\n  var presto = /Opera\\//.test(navigator.userAgent);\n  var safari = /Apple Computer/.test(navigator.vendor);\n  var khtml = /KHTML\\//.test(navigator.userAgent);\n  var mac_geMountainLion = /Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(navigator.userAgent);\n  var phantom = /PhantomJS/.test(navigator.userAgent);\n\n  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\\/\\w+/.test(navigator.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(navigator.userAgent);\n  var mac = ios || /Mac/.test(navigator.platform);\n  var windows = /win/i.test(navigator.platform);\n\n  var presto_version = presto && navigator.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);\n    this.doc = doc;\n\n    var display = this.display = new Display(place, doc);\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) focusInput(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, 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 readInput\n      draggingText: false,\n      highlight: new Delayed() // stores highlight worker timeout\n    };\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(bind(resetInput, this, 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) || activeElt() == display.input)\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    for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);\n    endOperation(this);\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) {\n    var d = this;\n\n    // The semihidden textarea that is focused when the editor is\n    // focused, and receives input.\n    var input = d.input = elt(\"textarea\", null, null, \"position: absolute; padding: 0; width: 1px; height: 1em; outline: none\");\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) input.style.width = \"1000px\";\n    else input.setAttribute(\"wrap\", \"off\");\n    // If border: 0; -- iOS fails to open keyboard (issue #1287)\n    if (ios) input.style.border = \"1px solid black\";\n    input.setAttribute(\"autocorrect\", \"off\"); input.setAttribute(\"autocapitalize\", \"off\"); input.setAttribute(\"spellcheck\", \"false\");\n\n    // Wraps and hides input textarea\n    d.inputDiv = elt(\"div\", [input], null, \"overflow: hidden; position: relative; width: 3px; height: 0px;\");\n    // The fake scrollbar elements.\n    d.scrollbarH = elt(\"div\", [elt(\"div\", null, null, \"height: 100%; min-height: 1px\")], \"CodeMirror-hscrollbar\");\n    d.scrollbarV = elt(\"div\", [elt(\"div\", null, null, \"min-width: 1px\")], \"CodeMirror-vscrollbar\");\n    // Covers bottom-right square when both scrollbars are present.\n    d.scrollbarFiller = elt(\"div\", null, \"CodeMirror-scrollbar-filler\");\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    // 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    // 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: \" + scrollerCutOff + \"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.inputDiv, d.scrollbarH, d.scrollbarV,\n                            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    // Needed to hide big blue blinking cursor on Mobile Safari\n    if (ios) input.style.width = \"0px\";\n    if (!webkit) d.scroller.draggable = true;\n    // Needed to handle Tab key in KHTML\n    if (khtml) { d.inputDiv.style.height = \"1px\"; d.inputDiv.style.position = \"absolute\"; }\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) d.scrollbarH.style.minHeight = d.scrollbarV.style.minWidth = \"18px\";\n\n    if (place.appendChild) place.appendChild(d.wrapper);\n    else place(d.wrapper);\n\n    // Current rendered range (may be bigger than the view window).\n    d.viewFrom = d.viewTo = doc.first;\n    // Information about the rendered lines.\n    d.view = [];\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.lastSizeC = 0;\n    d.updateLineNumbers = null;\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    // See readInput and resetInput\n    d.prevInput = \"\";\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    // 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    d.pollingFast = false;\n    // Self-resetting timeout for the poller\n    d.poll = new Delayed();\n\n    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n\n    // Tracks when resetInput has punted to just putting a short\n    // string into the textarea instead of the full selection.\n    d.inaccurateSelection = false;\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\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    } 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 keyMapChanged(cm) {\n    var map = keyMap[cm.options.keyMap], style = map.style;\n    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-keymap-\\S+/g, \"\") +\n      (style ? \" cm-keymap-\" + style : \"\");\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    cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + \"px\" : 0;\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  function hScrollbarTakesSpace(cm) {\n    return cm.display.scroller.clientHeight - cm.display.wrapper.clientHeight < scrollerCutOff - 3;\n  }\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 scroll = cm.display.scroller;\n    return {\n      clientHeight: scroll.clientHeight,\n      barHeight: cm.display.scrollbarV.clientHeight,\n      scrollWidth: scroll.scrollWidth, clientWidth: scroll.clientWidth,\n      hScrollbarTakesSpace: hScrollbarTakesSpace(cm),\n      barWidth: cm.display.scrollbarH.clientWidth,\n      docHeight: Math.round(cm.doc.height + paddingVert(cm.display))\n    };\n  }\n\n  // Re-synchronize the fake scrollbars with the actual size of the\n  // content.\n  function updateScrollbars(cm, measure) {\n    if (!measure) measure = measureForScrollbars(cm);\n    var d = cm.display, sWidth = scrollbarWidth(d.measure);\n    var scrollHeight = measure.docHeight + scrollerCutOff;\n    var needsH = measure.scrollWidth > measure.clientWidth;\n    if (needsH && measure.scrollWidth <= measure.clientWidth + 1 &&\n        sWidth > 0 && !measure.hScrollbarTakesSpace)\n      needsH = false; // (Issue #2562)\n    var needsV = scrollHeight > measure.clientHeight;\n\n    if (needsV) {\n      d.scrollbarV.style.display = \"block\";\n      d.scrollbarV.style.bottom = needsH ? sWidth + \"px\" : \"0\";\n      // A bug in IE8 can cause this value to be negative, so guard it.\n      d.scrollbarV.firstChild.style.height =\n        Math.max(0, scrollHeight - measure.clientHeight + (measure.barHeight || d.scrollbarV.clientHeight)) + \"px\";\n    } else {\n      d.scrollbarV.style.display = \"\";\n      d.scrollbarV.firstChild.style.height = \"0\";\n    }\n    if (needsH) {\n      d.scrollbarH.style.display = \"block\";\n      d.scrollbarH.style.right = needsV ? sWidth + \"px\" : \"0\";\n      d.scrollbarH.firstChild.style.width =\n        (measure.scrollWidth - measure.clientWidth + (measure.barWidth || d.scrollbarH.clientWidth)) + \"px\";\n    } else {\n      d.scrollbarH.style.display = \"\";\n      d.scrollbarH.firstChild.style.width = \"0\";\n    }\n    if (needsH && needsV) {\n      d.scrollbarFiller.style.display = \"block\";\n      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = sWidth + \"px\";\n    } else d.scrollbarFiller.style.display = \"\";\n    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n      d.gutterFiller.style.display = \"block\";\n      d.gutterFiller.style.height = sWidth + \"px\";\n      d.gutterFiller.style.width = d.gutters.offsetWidth + \"px\";\n    } else d.gutterFiller.style.display = \"\";\n\n    if (!cm.state.checkedOverlayScrollbar && measure.clientHeight > 0) {\n      if (sWidth === 0) {\n        var w = mac && !mac_geMountainLion ? \"12px\" : \"18px\";\n        d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = w;\n        var barMouseDown = function(e) {\n          if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)\n            operation(cm, onMouseDown)(e);\n        };\n        on(d.scrollbarV, \"mousedown\", barMouseDown);\n        on(d.scrollbarH, \"mousedown\", barMouseDown);\n      }\n      cm.state.checkedOverlayScrollbar = true;\n    }\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        return {from: ensureFrom,\n                to: lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)};\n      if (Math.min(ensureTo, doc.lastLine()) >= to)\n        return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),\n                to: ensureTo};\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);\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.oldViewFrom = display.viewFrom; this.oldViewTo = display.viewTo;\n    this.oldScrollerWidth = display.scroller.clientWidth;\n    this.force = force;\n    this.dims = getDimensions(cm);\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    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        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.lastSizeC != update.wrapperHeight;\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 &&\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    // 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.\n    removeChildren(display.cursorDiv);\n    removeChildren(display.selectionDiv);\n\n    if (different) {\n      display.lastSizeC = update.wrapperHeight;\n      startWorker(cm, 400);\n    }\n\n    display.updateLineNumbers = null;\n\n    return true;\n  }\n\n  function postUpdateDisplay(cm, update) {\n    var force = update.force, viewport = update.viewport;\n    for (var first = true;; first = false) {\n      if (first && cm.options.lineWrapping && update.oldScrollerWidth != cm.display.scroller.clientWidth) {\n        force = true;\n      } else {\n        force = false;\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) - scrollerCutOff -\n                                    cm.display.scroller.clientHeight, 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      setDocumentHeight(cm, barMeasure);\n      updateScrollbars(cm, barMeasure);\n    }\n\n    signalLater(cm, \"update\", cm);\n    if (cm.display.viewFrom != update.oldViewFrom || cm.display.viewTo != update.oldViewTo)\n      signalLater(cm, \"viewportChange\", cm, cm.display.viewFrom, cm.display.viewTo);\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      setDocumentHeight(cm, barMeasure);\n      updateScrollbars(cm, barMeasure);\n    }\n  }\n\n  function setDocumentHeight(cm, measure) {\n    cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + \"px\";\n    cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + \"px\";\n  }\n\n  function checkForWebkitWidthBug(cm, measure) {\n    // Work around Webkit bug where it sometimes reserves space for a\n    // non-existing phantom scrollbar in the scroller (Issue #2420)\n    if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) {\n      cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = \"0px\";\n      cm.display.gutters.style.height = measure.docHeight + \"px\";\n    }\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.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) { // 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(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    var markers = lineView.line.gutterMarkers;\n    if (cm.options.lineNumbers || markers) {\n      var wrap = ensureLineWrapped(lineView);\n      var gutterWrap = lineView.gutter =\n        wrap.insertBefore(elt(\"div\", null, \"CodeMirror-gutter-wrapper\", \"position: absolute; left: \" +\n                              (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + \"px\"),\n                          lineView.text);\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(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(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(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(lineView, dims) {\n    insertLineWidgetsFor(lineView.line, lineView, dims, true);\n    if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)\n      insertLineWidgetsFor(lineView.rest[i], lineView, dims, false);\n  }\n\n  function insertLineWidgetsFor(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.ignoreEvents = true;\n      positionLineWidget(widget, node, lineView, dims);\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  // 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) {\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    };\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);\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 newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);\n      var newHead = skipAtomic(doc, range.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  // Ensure a given position is not inside an atomic range.\n  function skipAtomic(doc, pos, bias, mayClear) {\n    var flipped = false, curPos = pos;\n    var dir = bias || 1;\n    doc.cantEdit = false;\n    search: for (;;) {\n      var line = getLine(doc, curPos.line);\n      if (line.markedSpans) {\n        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 <= curPos.ch : sp.from < curPos.ch)) &&\n              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.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            var newPos = m.find(dir < 0 ? -1 : 1);\n            if (cmp(newPos, curPos) == 0) {\n              newPos.ch += dir;\n              if (newPos.ch < 0) {\n                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));\n                else newPos = null;\n              } else if (newPos.ch > line.text.length) {\n                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);\n                else newPos = null;\n              }\n              if (!newPos) {\n                if (flipped) {\n                  // Driven in a corner -- no valid cursor position found at all\n                  // -- try again *with* clearing, if we didn't already\n                  if (!mayClear) return skipAtomic(doc, pos, bias, true);\n                  // Otherwise, turn off editing until further notice, and return the start of the doc\n                  doc.cantEdit = true;\n                  return Pos(doc.first, 0);\n                }\n                flipped = true; newPos = pos; dir = -dir;\n              }\n            }\n            curPos = newPos;\n            continue search;\n          }\n        }\n      }\n      return curPos;\n    }\n  }\n\n  // SELECTION DRAWING\n\n  // Redraw the selection and/or cursor\n  function drawSelection(cm) {\n    var display = cm.display, 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      var range = doc.sel.ranges[i];\n      var collapsed = range.empty();\n      if (collapsed || cm.options.showCursorWhenSelecting)\n        drawSelectionCursor(cm, range, curFragment);\n      if (!collapsed)\n        drawSelectionRange(cm, range, selFragment);\n    }\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  function showSelection(cm, drawn) {\n    removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors);\n    removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection);\n    if (drawn.teTop != null) {\n      cm.display.inputDiv.style.top = drawn.teTop + \"px\";\n      cm.display.inputDiv.style.left = drawn.teLeft + \"px\";\n    }\n  }\n\n  function updateSelection(cm) {\n    showSelection(cm, drawSelection(cm));\n  }\n\n  // Draws a cursor for the given range\n  function drawSelectionCursor(cm, range, output) {\n    var pos = cursorCoords(cm, range.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, rightSide = display.lineSpace.offsetWidth - 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;\n        var highlighted = highlightLine(cm, line, 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 = copyState(doc.mode, state);\n      } else {\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  // 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 && cm.display.scroller.clientWidth;\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    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 measureCharInner(cm, prepared, ch, bias) {\n    var map = prepared.map;\n\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\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(mStart + start))) --start;\n        while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;\n        if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) {\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), 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      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]();\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++](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    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      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo +\n                                  scrollerCutOff - display.scroller.clientWidth);\n    }\n\n    if (op.updatedDisplay || op.selectionChanged)\n      op.newSelectionNodes = drawSelection(cm);\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.newSelectionNodes)\n      showSelection(cm, op.newSelectionNodes);\n    if (op.updatedDisplay)\n      setDocumentHeight(cm, op.barMeasure);\n    if (op.updatedDisplay || op.startHeight != cm.doc.height)\n      updateScrollbars(cm, op.barMeasure);\n\n    if (op.selectionChanged) restartBlink(cm);\n\n    if (cm.state.focused && op.updateInput)\n      resetInput(cm, op.typing);\n  }\n\n  function endOperation_finish(op) {\n    var cm = op.cm, display = cm.display, doc = cm.doc;\n\n    if (op.adjustWidthTo != null && Math.abs(op.barMeasure.scrollWidth - cm.display.scroller.scrollWidth) > 1)\n      updateScrollbars(cm);\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      var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));\n      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;\n    }\n    if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {\n      var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));\n      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;\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    // Apply workaround for two webkit bugs\n    if (op.updatedDisplay && webkit) {\n      if (cm.options.lineWrapping)\n        checkForWebkitWidthBug(cm, op.barMeasure); // (Issue #2420)\n      if (op.barMeasure.scrollWidth > op.barMeasure.clientWidth &&\n          op.barMeasure.scrollWidth < op.barMeasure.clientWidth + 1 &&\n          !hScrollbarTakesSpace(cm))\n        updateScrollbars(cm); // (Issue #2562)\n    }\n\n    // Fire change events, and delayed event handlers\n    if (op.changeObjs)\n      signal(cm, \"changes\", cm, op.changeObjs);\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  // INPUT HANDLING\n\n  // Poll for input changes, using the normal rate of polling. This\n  // runs as long as the editor is focused.\n  function slowPoll(cm) {\n    if (cm.display.pollingFast) return;\n    cm.display.poll.set(cm.options.pollInterval, function() {\n      readInput(cm);\n      if (cm.state.focused) slowPoll(cm);\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  function fastPoll(cm) {\n    var missed = false;\n    cm.display.pollingFast = true;\n    function p() {\n      var changed = readInput(cm);\n      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}\n      else {cm.display.pollingFast = false; slowPoll(cm);}\n    }\n    cm.display.poll.set(20, p);\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  // 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  function readInput(cm) {\n    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc;\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 (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput)\n      return false;\n    // See paste handler for more on the fakedLastChar kludge\n    if (cm.state.pasteIncoming && cm.state.fakedLastChar) {\n      input.value = input.value.substring(0, input.value.length - 1);\n      cm.state.fakedLastChar = 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 && cm.display.inputHasSelection === text ||\n        mac && /[\\uf700-\\uf7ff]/.test(text)) {\n      resetInput(cm);\n      return false;\n    }\n\n    var withOp = !cm.curOp;\n    if (withOp) startOperation(cm);\n    cm.display.shift = false;\n\n    if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput)\n      prevInput = \"\\u200b\";\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    var inserted = text.slice(same), textLines = splitLines(inserted);\n\n    // When pasing N lines into N selections, insert one line per selection\n    var multiPaste = null;\n    if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) {\n      if (lastCopied && lastCopied.join(\"\\n\") == inserted)\n        multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);\n      else if (textLines.length == doc.sel.ranges.length)\n        multiPaste = map(textLines, function(l) { return [l]; });\n    }\n\n    // Normal behavior is to insert the new text into every selection\n    for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {\n      var range = doc.sel.ranges[i];\n      var from = range.from(), to = range.to();\n      // Handle deletion\n      if (same < prevInput.length)\n        from = Pos(from.line, from.ch - (prevInput.length - same));\n      // Handle overwrite\n      else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)\n        to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));\n      var updateInput = cm.curOp.updateInput;\n      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,\n                         origin: cm.state.pasteIncoming ? \"paste\" : cm.state.cutIncoming ? \"cut\" : \"+input\"};\n      makeChange(cm.doc, changeEvent);\n      signalLater(cm, \"inputRead\", cm, changeEvent);\n      // When an 'electric' character is inserted, immediately trigger a reindent\n      if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&\n          cm.options.smartIndent && range.head.ch < 100 &&\n          (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {\n        var mode = cm.getModeAt(range.head);\n        var end = changeEnd(changeEvent);\n        if (mode.electricChars) {\n          for (var j = 0; j < mode.electricChars.length; j++)\n            if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {\n              indentLine(cm, end.line, \"smart\");\n              break;\n            }\n        } else if (mode.electricInput) {\n          if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))\n            indentLine(cm, end.line, \"smart\");\n        }\n      }\n    }\n    ensureCursorVisible(cm);\n    cm.curOp.updateInput = updateInput;\n    cm.curOp.typing = true;\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 = cm.display.prevInput = \"\";\n    else cm.display.prevInput = text;\n    if (withOp) endOperation(cm);\n    cm.state.pasteIncoming = cm.state.cutIncoming = false;\n    return true;\n  }\n\n  // Reset the input to correspond to the selection (or to be empty,\n  // when not typing and nothing is selected)\n  function resetInput(cm, typing) {\n    var minimal, selected, doc = cm.doc;\n    if (cm.somethingSelected()) {\n      cm.display.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      cm.display.input.value = content;\n      if (cm.state.focused) selectInput(cm.display.input);\n      if (ie && ie_version >= 9) cm.display.inputHasSelection = content;\n    } else if (!typing) {\n      cm.display.prevInput = cm.display.input.value = \"\";\n      if (ie && ie_version >= 9) cm.display.inputHasSelection = null;\n    }\n    cm.display.inaccurateSelection = minimal;\n  }\n\n  function focusInput(cm) {\n    if (cm.options.readOnly != \"nocursor\" && (!mobile || activeElt() != cm.display.input))\n      cm.display.input.focus();\n  }\n\n  function ensureFocus(cm) {\n    if (!cm.state.focused) { focusInput(cm); onFocus(cm); }\n  }\n\n  function isReadOnly(cm) {\n    return cm.options.readOnly || cm.doc.cantEdit;\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    // Prevent normal selection in the editor (we handle our own)\n    on(d.lineSpace, \"selectstart\", function(e) {\n      if (!eventInWidget(d, e)) e_preventDefault(e);\n    });\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    // 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    on(d.scrollbarV, \"scroll\", function() {\n      if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);\n    });\n    on(d.scrollbarH, \"scroll\", function() {\n      if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);\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 clicks in the scrollbars from killing focus\n    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }\n    on(d.scrollbarH, \"mousedown\", reFocus);\n    on(d.scrollbarV, \"mousedown\", reFocus);\n    // Prevent wrapper from ever scrolling\n    on(d.wrapper, \"scroll\", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });\n\n    on(d.input, \"keyup\", function(e) { onKeyUp.call(cm, e); });\n    on(d.input, \"input\", function() {\n      if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;\n      fastPoll(cm);\n    });\n    on(d.input, \"keydown\", operation(cm, onKeyDown));\n    on(d.input, \"keypress\", operation(cm, onKeyPress));\n    on(d.input, \"focus\", bind(onFocus, cm));\n    on(d.input, \"blur\", bind(onBlur, cm));\n\n    function drag_(e) {\n      if (!signalDOMEvent(cm, e)) e_stop(e);\n    }\n    if (cm.options.dragDrop) {\n      on(d.scroller, \"dragstart\", function(e){onDragStart(cm, e);});\n      on(d.scroller, \"dragenter\", drag_);\n      on(d.scroller, \"dragover\", drag_);\n      on(d.scroller, \"drop\", operation(cm, onDrop));\n    }\n    on(d.scroller, \"paste\", function(e) {\n      if (eventInWidget(d, e)) return;\n      cm.state.pasteIncoming = true;\n      focusInput(cm);\n      fastPoll(cm);\n    });\n    on(d.input, \"paste\", function() {\n      // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206\n      // Add a char to the end of textarea before paste occur so that\n      // selection doesn't span to the end of textarea.\n      if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {\n        var start = d.input.selectionStart, end = d.input.selectionEnd;\n        d.input.value += \"$\";\n        // The selection end needs to be set before the start, otherwise there\n        // can be an intermediate non-empty selection between the two, which\n        // can override the middle-click paste buffer on linux and cause the\n        // wrong thing to get pasted.\n        d.input.selectionEnd = end;\n        d.input.selectionStart = start;\n        cm.state.fakedLastChar = true;\n      }\n      cm.state.pasteIncoming = true;\n      fastPoll(cm);\n    });\n\n    function prepareCopyCut(e) {\n      if (cm.somethingSelected()) {\n        lastCopied = cm.getSelections();\n        if (d.inaccurateSelection) {\n          d.prevInput = \"\";\n          d.inaccurateSelection = false;\n          d.input.value = lastCopied.join(\"\\n\");\n          selectInput(d.input);\n        }\n      } else {\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        if (e.type == \"cut\") {\n          cm.setSelections(ranges, null, sel_dontScroll);\n        } else {\n          d.prevInput = \"\";\n          d.input.value = text.join(\"\\n\");\n          selectInput(d.input);\n        }\n        lastCopied = text;\n      }\n      if (e.type == \"cut\") cm.state.cutIncoming = true;\n    }\n    on(d.input, \"cut\", prepareCopyCut);\n    on(d.input, \"copy\", prepareCopyCut);\n\n    // Needed to handle Tab key in KHTML\n    if (khtml) on(d.sizer, \"mouseup\", function() {\n      if (activeElt() == d.input) d.input.blur();\n      focusInput(cm);\n    });\n  }\n\n  // Called when the window resizes\n  function onResize(cm) {\n    // Might be a text scaling operation, clear size caches.\n    var d = cm.display;\n    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\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.ignoreEvents || n.parentNode == display.sizer && n != display.mover) 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) {\n      var target = e_target(e);\n      if (target == display.scrollbarH || target == display.scrollbarV ||\n          target == display.scrollbarFiller || target == display.gutterFiller) 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    if (signalDOMEvent(this, e)) return;\n    var cm = this, display = cm.display;\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      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(bind(focusInput, cm), 20);\n      e_preventDefault(e);\n      break;\n    case 3:\n      if (captureRightClick) onContextMenu(cm, e);\n      break;\n    }\n  }\n\n  var lastClick, lastDoubleClick;\n  function leftButtonDown(cm, e, start) {\n    setTimeout(bind(ensureFocus, cm), 0);\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;\n    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&\n        type == \"single\" && sel.contains(start) > -1 && sel.somethingSelected())\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;\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)\n          extendSelection(cm.doc, start);\n        focusInput(cm);\n        // Work around unexplainable focus problem in IE9 (#2127)\n        if (ie && ie_version == 9)\n          setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);\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;\n    if (addNew && !e.shiftKey) {\n      ourIndex = doc.sel.contains(start);\n      if (ourIndex > -1)\n        ourRange = doc.sel.ranges[ourIndex];\n      else\n        ourRange = new Range(start, start);\n    } else {\n      ourRange = doc.sel.primary();\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      replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);\n    } else {\n      ourIndex = doc.sel.ranges.length;\n      setSelection(doc, normalizeSelection(doc.sel.ranges.concat([ourRange]), ourIndex),\n                   {scroll: false, origin: \"*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        ensureFocus(cm);\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      counter = Infinity;\n      e_preventDefault(e);\n      focusInput(cm);\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    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, signalfn) {\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        signalfn(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, signalLater);\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    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 || isReadOnly(cm)) 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        var reader = new FileReader;\n        reader.onload = operation(cm, function() {\n          text[i] = reader.result;\n          if (++read == n) {\n            pos = clipPos(cm.doc, pos);\n            var change = {from: pos, to: pos, text: splitLines(text.join(\"\\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(bind(focusInput, cm), 20);\n        return;\n      }\n      try {\n        var text = e.dataTransfer.getData(\"Text\");\n        if (text) {\n          if (cm.state.draggingText && !(mac ? e.metaKey : 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          focusInput(cm);\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  // 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    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = 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    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = 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  function onScrollWheel(cm, 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\n    var display = cm.display, scroll = display.scroller;\n    // Quit if there's nothing to scroll here\n    if (!(dx && scroll.scrollWidth > scroll.clientWidth ||\n          dy && scroll.scrollHeight > scroll.clientHeight)) 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)\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      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    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;\n    var prevShift = cm.display.shift, done = false;\n    try {\n      if (isReadOnly(cm)) 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  // Collect the currently active keymaps.\n  function allKeyMaps(cm) {\n    var maps = cm.state.keyMaps.slice(0);\n    if (cm.options.extraKeys) maps.push(cm.options.extraKeys);\n    maps.push(cm.options.keyMap);\n    return maps;\n  }\n\n  var maybeTransition;\n  // Handle a key from the keydown event.\n  function handleKeyBinding(cm, e) {\n    // Handle automatic keymap transitions\n    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;\n    clearTimeout(maybeTransition);\n    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {\n      if (getKeyMap(cm.options.keyMap) == startMap) {\n        cm.options.keyMap = (next.call ? next.call(null, cm) : next);\n        keyMapChanged(cm);\n      }\n    }, 50);\n\n    var name = keyName(e, true), handled = false;\n    if (!name) return false;\n    var keymaps = allKeyMaps(cm);\n\n    if (e.shiftKey) {\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      handled = lookupKey(\"Shift-\" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})\n             || lookupKey(name, keymaps, function(b) {\n                  if (typeof b == \"string\" ? /^go[A-Z]/.test(b) : b.motion)\n                    return doHandleBinding(cm, b);\n                });\n    } else {\n      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });\n    }\n\n    if (handled) {\n      e_preventDefault(e);\n      restartBlink(cm);\n      signalLater(cm, \"keyHandled\", cm, name, e);\n    }\n    return handled;\n  }\n\n  // Handle a key from the keypress event\n  function handleCharBinding(cm, e, ch) {\n    var handled = lookupKey(\"'\" + ch + \"'\", allKeyMaps(cm),\n                            function(b) { return doHandleBinding(cm, b, true); });\n    if (handled) {\n      e_preventDefault(e);\n      restartBlink(cm);\n      signalLater(cm, \"keyHandled\", cm, \"'\" + ch + \"'\", e);\n    }\n    return handled;\n  }\n\n  var lastStoppedKey = null;\n  function onKeyDown(e) {\n    var cm = this;\n    ensureFocus(cm);\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 (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)) || khtml) && handleKeyBinding(cm, e)) return;\n    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n    if (handleCharBinding(cm, e, ch)) return;\n    if (ie && ie_version >= 9) cm.display.inputHasSelection = null;\n    fastPoll(cm);\n  }\n\n  // FOCUS/BLUR EVENTS\n\n  function onFocus(cm) {\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      // The prevInput test prevents this from firing when a context\n      // menu is closed (since the resetInput would kill the\n      // select-all detection hack)\n      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {\n        resetInput(cm);\n        if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730\n      }\n    }\n    slowPoll(cm);\n    restartBlink(cm);\n  }\n  function onBlur(cm) {\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 (signalDOMEvent(cm, e, \"contextmenu\")) return;\n    var display = cm.display;\n    if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;\n\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 = display.input.style.cssText;\n    display.inputDiv.style.position = \"absolute\";\n    display.input.style.cssText = \"position: fixed; width: 30px; height: 30px; top: \" + (e.clientY - 5) +\n      \"px; left: \" + (e.clientX - 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    focusInput(cm);\n    if (webkit) window.scrollTo(null, oldScrollY);\n    resetInput(cm);\n    // Adds \"Select all\" to context menu in FF\n    if (!cm.somethingSelected()) display.input.value = display.prevInput = \" \";\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 (display.input.selectionStart != null) {\n        var selected = cm.somethingSelected();\n        var extval = display.input.value = \"\\u200b\" + (selected ? display.input.value : \"\");\n        display.prevInput = selected ? \"\" : \"\\u200b\";\n        display.input.selectionStart = 1; display.input.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      display.inputDiv.style.position = \"relative\";\n      display.input.style.cssText = oldCSS;\n      if (ie && ie_version < 9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;\n      slowPoll(cm);\n\n      // Try to detect the user choosing select-all\n      if (display.input.selectionStart != null) {\n        if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();\n        var i = 0, poll = function() {\n          if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0)\n            operation(cm, commands.selectAll)(cm);\n          else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);\n          else resetInput(cm);\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  function contextMenuInGutter(cm, e) {\n    if (!hasHandler(cm, \"gutterContextMenu\")) return false;\n    return gutterEvent(cm, e, \"gutterContextMenu\", false, signal);\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 (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 = 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    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 + scrollerCutOff) + \"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) return coords;\n    }\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 = display.scroller.clientHeight - scrollerCutOff, 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 = display.scroller.clientWidth - scrollerCutOff - display.gutters.offsetWidth;\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\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    } 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    line.stateAfter = null;\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    var possible = true;\n    function findNextLine() {\n      var l = line + dir;\n      if (l < doc.first || l >= doc.first + doc.size) return (possible = 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 (possible = false);\n      } else ch = next;\n      return true;\n    }\n\n    if (unit == \"char\") moveOnce();\n    else if (unit == \"column\") 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), origDir, true);\n    if (!possible) 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(); focusInput(this); fastPoll(this);},\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\"](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 || (typeof maps[i] != \"string\" && 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      var doc = this.doc;\n      pos = clipPos(doc, pos);\n      var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;\n      var line = getLine(doc, pos.line);\n      var stream = new StringStream(line.text, this.options.tabSize);\n      while (stream.pos < pos.ch && !stream.eol()) {\n        stream.start = stream.pos;\n        var style = readToken(mode, stream, state);\n      }\n      return {start: stream.start,\n              end: stream.pos,\n              string: stream.current(),\n              type: style || null,\n              state: state};\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 helpers;\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, 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      var lineObj = getLine(this.doc, line);\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    addLineWidget: methodOp(function(handle, node, options) {\n      return addLineWidget(this, handle, node, options);\n    }),\n\n    removeLineWidget: function(widget) { widget.clear(); },\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      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](this);\n    },\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 activeElt() == this.display.input; },\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, co = scrollerCutOff;\n      return {left: scroller.scrollLeft, top: scroller.scrollTop,\n              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,\n              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};\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      resetInput(this);\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;},\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(\"specialChars\", /[\\t\\u0000-\\u0019\\u00ad\\u200b-\\u200f\\u2028\\u2029\\ufeff]/g, function(cm, val) {\n    cm.options.specialChars = new RegExp(val.source + (val.test(\"\\t\") ? \"\" : \"|\\t\"), \"g\");\n    cm.refresh();\n  }, true);\n  option(\"specialCharPlaceholder\", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);\n  option(\"electricChars\", 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\", keyMapChanged);\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, updateScrollbars, 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\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      if (!val) resetInput(cm);\n    }\n  });\n  option(\"disableInput\", false, function(cm, val) {if (!val) resetInput(cm);}, true);\n  option(\"dragDrop\", true);\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.inputDiv.style.top = cm.display.inputDiv.style.left = 0;\n  });\n\n  option(\"tabindex\", null, function(cm, val) {\n    cm.display.input.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) + \"\\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(\"\\n\", range.anchor, range.head, \"+input\");\n          cm.indentLine(range.from().line + 1, null, true);\n          ensureCursorVisible(cm);\n        }\n      });\n    },\n    toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n  };\n\n  // STANDARD KEYMAPS\n\n  var keyMap = CodeMirror.keyMap = {};\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  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  // 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[\"default\"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n\n  // KEYMAP DISPATCH\n\n  function getKeyMap(val) {\n    if (typeof val == \"string\") return keyMap[val];\n    else return val;\n  }\n\n  // Given an array of keymaps and a key name, call handle on any\n  // bindings found, until that returns a truthy value, at which point\n  // we consider the key handled. Implements things like binding a key\n  // to false stopping further handling and keymap fallthrough.\n  var lookupKey = CodeMirror.lookupKey = function(name, maps, handle) {\n    function lookup(map) {\n      map = getKeyMap(map);\n      var found = map[name];\n      if (found === false) return \"stop\";\n      if (found != null && handle(found)) return true;\n      if (map.nofallthrough) return \"stop\";\n\n      var fallthrough = map.fallthrough;\n      if (fallthrough == null) return false;\n      if (Object.prototype.toString.call(fallthrough) != \"[object Array]\")\n        return lookup(fallthrough);\n      for (var i = 0; i < fallthrough.length; ++i) {\n        var done = lookup(fallthrough[i]);\n        if (done) return done;\n      }\n      return false;\n    }\n\n    for (var i = 0; i < maps.length; ++i) {\n      var done = lookup(maps[i]);\n      if (done) return done != \"stop\";\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(event) {\n    var name = keyNames[event.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 name = keyNames[event.keyCode];\n    if (name == null || event.altGraphKey) return false;\n    if (event.altKey) name = \"Alt-\" + name;\n    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = \"Ctrl-\" + name;\n    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = \"Cmd-\" + name;\n    if (!noShift && event.shiftKey) name = \"Shift-\" + name;\n    return name;\n  };\n\n  // FROMTEXTAREA\n\n  CodeMirror.fromTextArea = function(textarea, options) {\n    if (!options) 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    textarea.style.display = \"none\";\n    var cm = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\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    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 TextMarker = CodeMirror.TextMarker = function(doc, type) {\n    this.lines = [];\n    this.type = type;\n    this.doc = doc;\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.ignoreEvents = 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)\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    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(cm, node, options) {\n    if (options) for (var opt in options) if (options.hasOwnProperty(opt))\n      this[opt] = options[opt];\n    this.cm = cm;\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.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    runInOp(cm, function() {\n      adjustScrollWhenAboveVisible(cm, line, -height);\n      regLineChange(cm, no, \"widget\");\n      updateLineHeight(line, Math.max(0, line.height - height));\n    });\n  };\n  LineWidget.prototype.changed = function() {\n    var oldH = this.height, cm = this.cm, line = this.line;\n    this.height = null;\n    var diff = widgetHeight(this) - oldH;\n    if (!diff) return;\n    runInOp(cm, function() {\n      cm.curOp.forceUpdate = true;\n      adjustScrollWhenAboveVisible(cm, line, diff);\n      updateLineHeight(line, line.height + diff);\n    });\n  };\n\n  function widgetHeight(widget) {\n    if (widget.height != null) return widget.height;\n    if (!contains(document.body, widget.node)) {\n      var parentStyle = \"position: relative;\";\n      if (widget.coverGutter)\n        parentStyle += \"margin-left: -\" + widget.cm.getGutterElement().offsetWidth + \"px;\";\n      removeChildrenAndAdd(widget.cm.display.measure, elt(\"div\", [widget.node], null, parentStyle));\n    }\n    return widget.height = widget.node.offsetHeight;\n  }\n\n  function addLineWidget(cm, handle, node, options) {\n    var widget = new LineWidget(cm, node, options);\n    if (widget.noHScroll) cm.display.alignWidgets = true;\n    changeLine(cm.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 (!lineIsHidden(cm.doc, line)) {\n        var aboveVisible = heightAtLine(line) < cm.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) {\n    for (var i = 0; i < 10; i++) {\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  // 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    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), lineClasses);\n      }\n      if (cm.options.addModeClass) {\n        var mName = CodeMirror.innerMode(mode, state).mode.name;\n        if (mName) style = \"m-\" + (style ? mName + \" \" + style : mName);\n      }\n      if (!flattenSpans || curStyle != style) {\n        if (curStart < stream.start) f(stream.start, curStyle);\n        curStart = stream.start; 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) {\n    if (!line.styles || line.styles[0] != cm.state.modeGen) {\n      var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));\n      line.styles = result.styles;\n      if (result.classes) line.styleClasses = result.classes;\n      else if (line.styleClasses) line.styleClasses = null;\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() && stream.pos <= cm.options.maxHighlightLength) {\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]), content: content, col: 0, pos: 0, cm: cm};\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 ((ie || webkit) && cm.getOption(\"lineWrapping\"))\n        builder.addToken = buildTokenSplitSpaces(builder.addToken);\n      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))\n        builder.addToken = buildTokenBadBidi(builder.addToken, order);\n      builder.map = [];\n      insertLineContent(line, builder, getLineStyles(cm, line));\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    signal(cm, \"renderLine\", cm, lineView.line, builder.pre);\n    if (builder.pre.className)\n      builder.textClass = joinClasses(builder.pre.className, builder.textClass || \"\");\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    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) {\n    if (!text) return;\n    var special = builder.cm.options.specialChars, mustWrap = false;\n    if (!special.test(text)) {\n      builder.col += text.length;\n      var content = document.createTextNode(text);\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(text.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          builder.col += tabWidth;\n        } else {\n          var txt = builder.cm.options.specialCharPlaceholder(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) {\n      var fullStyle = style || \"\";\n      if (startStyle) fullStyle += startStyle;\n      if (endStyle) fullStyle += endStyle;\n      var token = elt(\"span\", [content], fullStyle);\n      if (title) token.title = title;\n      return builder.content.appendChild(token);\n    }\n    builder.content.appendChild(content);\n  }\n\n  function buildTokenSplitSpaces(inner) {\n    function split(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    return function(builder, text, style, startStyle, endStyle, title) {\n      inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);\n    };\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) {\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);\n        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);\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) {\n      builder.map.push(builder.pos, builder.pos + size, 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;\n    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;\n    for (;;) {\n      if (nextChange == pos) { // Update current marker set\n        spanStyle = spanEndStyle = spanStartStyle = title = \"\";\n        collapsed = null; nextChange = Infinity;\n        var foundBookmarks = [];\n        for (var j = 0; j < spans.length; ++j) {\n          var sp = spans[j], m = sp.marker;\n          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {\n            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = \"\"; }\n            if (m.className) spanStyle += \" \" + m.className;\n            if (m.startStyle && sp.from == pos) spanStartStyle += \" \" + m.startStyle;\n            if (m.endStyle && sp.to == nextChange) spanEndStyle += \" \" + m.endStyle;\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          if (m.type == \"bookmark\" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);\n        }\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        }\n        if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)\n          buildCollapsedSpan(builder, 0, foundBookmarks[j]);\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);\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\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 (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      for (var i = 0, added = []; i < text.length - 1; ++i)\n        added.push(new Line(text[i], spansFor(i), estimateHeight));\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        for (var added = [], i = 1; i < text.length - 1; ++i)\n          added.push(new Line(text[i], spansFor(i), estimateHeight));\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      for (var i = 1, added = []; i < text.length - 1; ++i)\n        added.push(new Line(text[i], spansFor(i), estimateHeight));\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) {\n    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);\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\n    if (typeof text == \"string\") text = 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 || \"\\n\");\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: splitLines(code), origin: \"setValue\"}, 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 || \"\\n\");\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      extendSelections(this, map(this.sel.ranges, f), 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 || \"\\n\");\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 || \"\\n\");\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: 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, \"class\", function(line) {\n        var prop = where == \"text\" ? \"textClass\" : where == \"background\" ? \"bgClass\" : \"wrapClass\";\n        if (!line[prop]) line[prop] = cls;\n        else if (new RegExp(\"(?:^|\\\\s)\" + cls + \"(?:$|\\\\s)\").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, \"class\", function(line) {\n        var prop = where == \"text\" ? \"textClass\" : where == \"background\" ? \"bgClass\" : \"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(new RegExp(\"(?:^|\\\\s+)\" + cls + \"(?:$|\\\\s+)\"));\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    markText: function(from, to, options) {\n      return markText(this, clipPos(this, from), clipPos(this, to), options, \"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      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 (!(lineNo == from.line && from.ch > span.to ||\n                span.from == null && lineNo != from.line||\n                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), this.modeOption, this.first);\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);\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\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\".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 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 arr = emitter._handlers && emitter._handlers[type];\n      if (!arr) return;\n      for (var i = 0; i < arr.length; ++i)\n        if (arr[i] == f) { arr.splice(i, 1); break; }\n    }\n  };\n\n  var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {\n    var arr = emitter._handlers && emitter._handlers[type];\n    if (!arr) return;\n    var args = Array.prototype.slice.call(arguments, 2);\n    for (var i = 0; i < arr.length; ++i) arr[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 = emitter._handlers && emitter._handlers[type];\n    if (!arr) 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    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    var arr = emitter._handlers && emitter._handlers[type];\n    return arr && arr.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 scrollerCutOff = 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  function findColumn(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  if ([].indexOf) indexOf = function(array, elt) { return array.indexOf(elt); };\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  if ([].map) map = function(array, f) { return array.map(f); };\n\n  function createObj(base, props) {\n    var inst;\n    if (Object.create) {\n      inst = Object.create(base);\n    } else {\n      var ctor = function() {};\n      ctor.prototype = base;\n      inst = new ctor();\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\\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) {\n    var r = document.createRange();\n    r.setEnd(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    r.moveToElementText(node.parentNode);\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  function contains(parent, child) {\n    if (parent.contains)\n      return parent.contains(child);\n    while (child = child.parentNode)\n      if (child == parent) return true;\n  }\n\n  function activeElt() { return document.activeElement; }\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(\"\\\\b\" + cls + \"\\\\b\\\\s*\"); }\n  function rmClass(node, cls) {\n    var test = classTest(cls);\n    if (test.test(node.className)) node.className = node.className.replace(test, \"\");\n  }\n  function addClass(node, cls) {\n    if (!classTest(cls).test(node.className)) node.className += \" \" + 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        knownScrollbarWidth = 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 knownScrollbarWidth;\n  function scrollbarWidth(measure) {\n    if (knownScrollbarWidth != null) return knownScrollbarWidth;\n    var test = elt(\"div\", null, null, \"width: 50px; height: 50px; overflow-x: scroll\");\n    removeChildrenAndAdd(measure, test);\n    if (test.offsetWidth)\n      knownScrollbarWidth = test.offsetHeight - test.clientHeight;\n    return knownScrollbarWidth || 0;\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    if (zwspSupported) return elt(\"span\", \"\\u200b\");\n    else return elt(\"span\", \"\\u00a0\", null, \"display: inline-block; width: 1px; margin-right: -1px\");\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 splitLines = 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 = {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\", 107: \"=\", 109: \"-\", 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  CodeMirror.keyNames = keyNames;\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 != 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 = \"4.7.0\";\n\n  return CodeMirror;\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/apl/apl.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(\"apl\", function() {\n  var builtInOps = {\n    \".\": \"innerProduct\",\n    \"\\\\\": \"scan\",\n    \"/\": \"reduce\",\n    \"⌿\": \"reduce1Axis\",\n    \"⍀\": \"scan1Axis\",\n    \"¨\": \"each\",\n    \"⍣\": \"power\"\n  };\n  var builtInFuncs = {\n    \"+\": [\"conjugate\", \"add\"],\n    \"−\": [\"negate\", \"subtract\"],\n    \"×\": [\"signOf\", \"multiply\"],\n    \"÷\": [\"reciprocal\", \"divide\"],\n    \"⌈\": [\"ceiling\", \"greaterOf\"],\n    \"⌊\": [\"floor\", \"lesserOf\"],\n    \"∣\": [\"absolute\", \"residue\"],\n    \"⍳\": [\"indexGenerate\", \"indexOf\"],\n    \"?\": [\"roll\", \"deal\"],\n    \"⋆\": [\"exponentiate\", \"toThePowerOf\"],\n    \"⍟\": [\"naturalLog\", \"logToTheBase\"],\n    \"○\": [\"piTimes\", \"circularFuncs\"],\n    \"!\": [\"factorial\", \"binomial\"],\n    \"⌹\": [\"matrixInverse\", \"matrixDivide\"],\n    \"<\": [null, \"lessThan\"],\n    \"≤\": [null, \"lessThanOrEqual\"],\n    \"=\": [null, \"equals\"],\n    \">\": [null, \"greaterThan\"],\n    \"≥\": [null, \"greaterThanOrEqual\"],\n    \"≠\": [null, \"notEqual\"],\n    \"≡\": [\"depth\", \"match\"],\n    \"≢\": [null, \"notMatch\"],\n    \"∈\": [\"enlist\", \"membership\"],\n    \"⍷\": [null, \"find\"],\n    \"∪\": [\"unique\", \"union\"],\n    \"∩\": [null, \"intersection\"],\n    \"∼\": [\"not\", \"without\"],\n    \"∨\": [null, \"or\"],\n    \"∧\": [null, \"and\"],\n    \"⍱\": [null, \"nor\"],\n    \"⍲\": [null, \"nand\"],\n    \"⍴\": [\"shapeOf\", \"reshape\"],\n    \",\": [\"ravel\", \"catenate\"],\n    \"⍪\": [null, \"firstAxisCatenate\"],\n    \"⌽\": [\"reverse\", \"rotate\"],\n    \"⊖\": [\"axis1Reverse\", \"axis1Rotate\"],\n    \"⍉\": [\"transpose\", null],\n    \"↑\": [\"first\", \"take\"],\n    \"↓\": [null, \"drop\"],\n    \"⊂\": [\"enclose\", \"partitionWithAxis\"],\n    \"⊃\": [\"diclose\", \"pick\"],\n    \"⌷\": [null, \"index\"],\n    \"⍋\": [\"gradeUp\", null],\n    \"⍒\": [\"gradeDown\", null],\n    \"⊤\": [\"encode\", null],\n    \"⊥\": [\"decode\", null],\n    \"⍕\": [\"format\", \"formatByExample\"],\n    \"⍎\": [\"execute\", null],\n    \"⊣\": [\"stop\", \"left\"],\n    \"⊢\": [\"pass\", \"right\"]\n  };\n\n  var isOperator = /[\\.\\/⌿⍀¨⍣]/;\n  var isNiladic = /⍬/;\n  var isFunction = /[\\+−×÷⌈⌊∣⍳\\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;\n  var isArrow = /←/;\n  var isComment = /[⍝#].*$/;\n\n  var stringEater = function(type) {\n    var prev;\n    prev = false;\n    return function(c) {\n      prev = c;\n      if (c === type) {\n        return prev === \"\\\\\";\n      }\n      return true;\n    };\n  };\n  return {\n    startState: function() {\n      return {\n        prev: false,\n        func: false,\n        op: false,\n        string: false,\n        escape: false\n      };\n    },\n    token: function(stream, state) {\n      var ch, funcName, word;\n      if (stream.eatSpace()) {\n        return null;\n      }\n      ch = stream.next();\n      if (ch === '\"' || ch === \"'\") {\n        stream.eatWhile(stringEater(ch));\n        stream.next();\n        state.prev = true;\n        return \"string\";\n      }\n      if (/[\\[{\\(]/.test(ch)) {\n        state.prev = false;\n        return null;\n      }\n      if (/[\\]}\\)]/.test(ch)) {\n        state.prev = true;\n        return null;\n      }\n      if (isNiladic.test(ch)) {\n        state.prev = false;\n        return \"niladic\";\n      }\n      if (/[¯\\d]/.test(ch)) {\n        if (state.func) {\n          state.func = false;\n          state.prev = false;\n        } else {\n          state.prev = true;\n        }\n        stream.eatWhile(/[\\w\\.]/);\n        return \"number\";\n      }\n      if (isOperator.test(ch)) {\n        return \"operator apl-\" + builtInOps[ch];\n      }\n      if (isArrow.test(ch)) {\n        return \"apl-arrow\";\n      }\n      if (isFunction.test(ch)) {\n        funcName = \"apl-\";\n        if (builtInFuncs[ch] != null) {\n          if (state.prev) {\n            funcName += builtInFuncs[ch][1];\n          } else {\n            funcName += builtInFuncs[ch][0];\n          }\n        }\n        state.func = true;\n        state.prev = false;\n        return \"function \" + funcName;\n      }\n      if (isComment.test(ch)) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      if (ch === \"∘\" && stream.peek() === \".\") {\n        stream.next();\n        return \"function jot-dot\";\n      }\n      stream.eatWhile(/[\\w\\$_]/);\n      word = stream.current();\n      state.prev = true;\n      return \"keyword\";\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/apl\", \"apl\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/apl/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: APL mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"./apl.js\"></script>\n<style>\n\t.CodeMirror { border: 2px inset #dee; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">APL</a>\n  </ul>\n</div>\n\n<article>\n<h2>APL mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n⍝ Conway's game of life\n\n⍝ This example was inspired by the impressive demo at\n⍝ http://www.youtube.com/watch?v=a9xAKttWgP4\n\n⍝ Create a matrix:\n⍝     0 1 1\n⍝     1 1 0\n⍝     0 1 0\ncreature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7   ⍝ Original creature from demo\ncreature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8   ⍝ Glider\n\n⍝ Place the creature on a larger board, near the centre\nboard ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature\n\n⍝ A function to move from one generation to the next\nlife ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}\n\n⍝ Compute n-th generation and format it as a\n⍝ character matrix\ngen ← {' #'[(life ⍣ ⍵) board]}\n\n⍝ Show first three generations\n(gen 1) (gen 2) (gen 3)\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/apl\"\n      });\n    </script>\n\n    <p>Simple mode that tries to handle APL as well as it can.</p>\n    <p>It attempts to label functions/operators based upon\n    monadic/dyadic usage (but this is far from fully fleshed out).\n    This means there are meaningful classnames so hover states can\n    have popups etc.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/asterisk/asterisk.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\n * =====================================================================================\n *\n *       Filename:  mode/asterisk/asterisk.js\n *\n *    Description:  CodeMirror mode for Asterisk dialplan\n *\n *        Created:  05/17/2012 09:20:25 PM\n *       Revision:  none\n *\n *         Author:  Stas Kobzar (stas@modulis.ca),\n *        Company:  Modulis.ca Inc.\n *\n * =====================================================================================\n */\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(\"asterisk\", function() {\n  var atoms    = [\"exten\", \"same\", \"include\",\"ignorepat\",\"switch\"],\n      dpcmd    = [\"#include\",\"#exec\"],\n      apps     = [\n                  \"addqueuemember\",\"adsiprog\",\"aelsub\",\"agentlogin\",\"agentmonitoroutgoing\",\"agi\",\n                  \"alarmreceiver\",\"amd\",\"answer\",\"authenticate\",\"background\",\"backgrounddetect\",\n                  \"bridge\",\"busy\",\"callcompletioncancel\",\"callcompletionrequest\",\"celgenuserevent\",\n                  \"changemonitor\",\"chanisavail\",\"channelredirect\",\"chanspy\",\"clearhash\",\"confbridge\",\n                  \"congestion\",\"continuewhile\",\"controlplayback\",\"dahdiacceptr2call\",\"dahdibarge\",\n                  \"dahdiras\",\"dahdiscan\",\"dahdisendcallreroutingfacility\",\"dahdisendkeypadfacility\",\n                  \"datetime\",\"dbdel\",\"dbdeltree\",\"deadagi\",\"dial\",\"dictate\",\"directory\",\"disa\",\n                  \"dumpchan\",\"eagi\",\"echo\",\"endwhile\",\"exec\",\"execif\",\"execiftime\",\"exitwhile\",\"extenspy\",\n                  \"externalivr\",\"festival\",\"flash\",\"followme\",\"forkcdr\",\"getcpeid\",\"gosub\",\"gosubif\",\n                  \"goto\",\"gotoif\",\"gotoiftime\",\"hangup\",\"iax2provision\",\"ices\",\"importvar\",\"incomplete\",\n                  \"ivrdemo\",\"jabberjoin\",\"jabberleave\",\"jabbersend\",\"jabbersendgroup\",\"jabberstatus\",\n                  \"jack\",\"log\",\"macro\",\"macroexclusive\",\"macroexit\",\"macroif\",\"mailboxexists\",\"meetme\",\n                  \"meetmeadmin\",\"meetmechanneladmin\",\"meetmecount\",\"milliwatt\",\"minivmaccmess\",\"minivmdelete\",\n                  \"minivmgreet\",\"minivmmwi\",\"minivmnotify\",\"minivmrecord\",\"mixmonitor\",\"monitor\",\"morsecode\",\n                  \"mp3player\",\"mset\",\"musiconhold\",\"nbscat\",\"nocdr\",\"noop\",\"odbc\",\"odbc\",\"odbcfinish\",\n                  \"originate\",\"ospauth\",\"ospfinish\",\"osplookup\",\"ospnext\",\"page\",\"park\",\"parkandannounce\",\n                  \"parkedcall\",\"pausemonitor\",\"pausequeuemember\",\"pickup\",\"pickupchan\",\"playback\",\"playtones\",\n                  \"privacymanager\",\"proceeding\",\"progress\",\"queue\",\"queuelog\",\"raiseexception\",\"read\",\"readexten\",\n                  \"readfile\",\"receivefax\",\"receivefax\",\"receivefax\",\"record\",\"removequeuemember\",\n                  \"resetcdr\",\"retrydial\",\"return\",\"ringing\",\"sayalpha\",\"saycountedadj\",\"saycountednoun\",\n                  \"saycountpl\",\"saydigits\",\"saynumber\",\"sayphonetic\",\"sayunixtime\",\"senddtmf\",\"sendfax\",\n                  \"sendfax\",\"sendfax\",\"sendimage\",\"sendtext\",\"sendurl\",\"set\",\"setamaflags\",\n                  \"setcallerpres\",\"setmusiconhold\",\"sipaddheader\",\"sipdtmfmode\",\"sipremoveheader\",\"skel\",\n                  \"slastation\",\"slatrunk\",\"sms\",\"softhangup\",\"speechactivategrammar\",\"speechbackground\",\n                  \"speechcreate\",\"speechdeactivategrammar\",\"speechdestroy\",\"speechloadgrammar\",\"speechprocessingsound\",\n                  \"speechstart\",\"speechunloadgrammar\",\"stackpop\",\"startmusiconhold\",\"stopmixmonitor\",\"stopmonitor\",\n                  \"stopmusiconhold\",\"stopplaytones\",\"system\",\"testclient\",\"testserver\",\"transfer\",\"tryexec\",\n                  \"trysystem\",\"unpausemonitor\",\"unpausequeuemember\",\"userevent\",\"verbose\",\"vmauthenticate\",\n                  \"vmsayname\",\"voicemail\",\"voicemailmain\",\"wait\",\"waitexten\",\"waitfornoise\",\"waitforring\",\n                  \"waitforsilence\",\"waitmusiconhold\",\"waituntil\",\"while\",\"zapateller\"\n                 ];\n\n  function basicToken(stream,state){\n    var cur = '';\n    var ch  = '';\n    ch = stream.next();\n    // comment\n    if(ch == \";\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    // context\n    if(ch == '[') {\n      stream.skipTo(']');\n      stream.eat(']');\n      return \"header\";\n    }\n    // string\n    if(ch == '\"') {\n      stream.skipTo('\"');\n      return \"string\";\n    }\n    if(ch == \"'\") {\n      stream.skipTo(\"'\");\n      return \"string-2\";\n    }\n    // dialplan commands\n    if(ch == '#') {\n      stream.eatWhile(/\\w/);\n      cur = stream.current();\n      if(dpcmd.indexOf(cur) !== -1) {\n        stream.skipToEnd();\n        return \"strong\";\n      }\n    }\n    // application args\n    if(ch == '$'){\n      var ch1 = stream.peek();\n      if(ch1 == '{'){\n        stream.skipTo('}');\n        stream.eat('}');\n        return \"variable-3\";\n      }\n    }\n    // extension\n    stream.eatWhile(/\\w/);\n    cur = stream.current();\n    if(atoms.indexOf(cur) !== -1) {\n      state.extenStart = true;\n      switch(cur) {\n        case 'same': state.extenSame = true; break;\n        case 'include':\n        case 'switch':\n        case 'ignorepat':\n          state.extenInclude = true;break;\n        default:break;\n      }\n      return \"atom\";\n    }\n  }\n\n  return {\n    startState: function() {\n      return {\n        extenStart: false,\n        extenSame:  false,\n        extenInclude: false,\n        extenExten: false,\n        extenPriority: false,\n        extenApplication: false\n      };\n    },\n    token: function(stream, state) {\n\n      var cur = '';\n      var ch  = '';\n      if(stream.eatSpace()) return null;\n      // extension started\n      if(state.extenStart){\n        stream.eatWhile(/[^\\s]/);\n        cur = stream.current();\n        if(/^=>?$/.test(cur)){\n          state.extenExten = true;\n          state.extenStart = false;\n          return \"strong\";\n        } else {\n          state.extenStart = false;\n          stream.skipToEnd();\n          return \"error\";\n        }\n      } else if(state.extenExten) {\n        // set exten and priority\n        state.extenExten = false;\n        state.extenPriority = true;\n        stream.eatWhile(/[^,]/);\n        if(state.extenInclude) {\n          stream.skipToEnd();\n          state.extenPriority = false;\n          state.extenInclude = false;\n        }\n        if(state.extenSame) {\n          state.extenPriority = false;\n          state.extenSame = false;\n          state.extenApplication = true;\n        }\n        return \"tag\";\n      } else if(state.extenPriority) {\n        state.extenPriority = false;\n        state.extenApplication = true;\n        ch = stream.next(); // get comma\n        if(state.extenSame) return null;\n        stream.eatWhile(/[^,]/);\n        return \"number\";\n      } else if(state.extenApplication) {\n        stream.eatWhile(/,/);\n        cur = stream.current();\n        if(cur === ',') return null;\n        stream.eatWhile(/\\w/);\n        cur = stream.current().toLowerCase();\n        state.extenApplication = false;\n        if(apps.indexOf(cur) !== -1){\n          return \"def strong\";\n        }\n      } else{\n        return basicToken(stream,state);\n      }\n\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-asterisk\", \"asterisk\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/asterisk/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Asterisk dialplan mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"asterisk.js\"></script>\n<style>\n      .CodeMirror {border: 1px solid #999;}\n      .cm-s-default span.cm-arrow { color: red; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Asterisk dialplan</a>\n  </ul>\n</div>\n\n<article>\n<h2>Asterisk dialplan mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n; extensions.conf - the Asterisk dial plan\n;\n\n[general]\n;\n; If static is set to no, or omitted, then the pbx_config will rewrite\n; this file when extensions are modified.  Remember that all comments\n; made in the file will be lost when that happens.\nstatic=yes\n\n#include \"/etc/asterisk/additional_general.conf\n\n[iaxprovider]\nswitch => IAX2/user:[key]@myserver/mycontext\n\n[dynamic]\n#exec /usr/bin/dynamic-peers.pl\n\n[trunkint]\n;\n; International long distance through trunk\n;\nexten => _9011.,1,Macro(dundi-e164,${EXTEN:4})\nexten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})\n\n[local]\n;\n; Master context for local, toll-free, and iaxtel calls only\n;\nignorepat => 9\ninclude => default\n\n[demo]\ninclude => stdexten\n;\n; We start with what to do when a call first comes in.\n;\nexten => s,1,Wait(1)\t\t\t; Wait a second, just for fun\nsame  => n,Answer\t\t\t; Answer the line\nsame  => n,Set(TIMEOUT(digit)=5)\t; Set Digit Timeout to 5 seconds\nsame  => n,Set(TIMEOUT(response)=10)\t; Set Response Timeout to 10 seconds\nsame  => n(restart),BackGround(demo-congrats)\t; Play a congratulatory message\nsame  => n(instruct),BackGround(demo-instruct)\t; Play some instructions\nsame  => n,WaitExten\t\t\t; Wait for an extension to be dialed.\n\nexten => 2,1,BackGround(demo-moreinfo)\t; Give some more information.\nexten => 2,n,Goto(s,instruct)\n\nexten => 3,1,Set(LANGUAGE()=fr)\t\t; Set language to french\nexten => 3,n,Goto(s,restart)\t\t; Start with the congratulations\n\nexten => 1000,1,Goto(default,s,1)\n;\n; We also create an example user, 1234, who is on the console and has\n; voicemail, etc.\n;\nexten => 1234,1,Playback(transfer,skip)\t\t; \"Please hold while...\"\n\t\t\t\t\t; (but skip if channel is not up)\nexten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))\nexten => 1234,n,Goto(default,s,1)\t\t; exited Voicemail\n\nexten => 1235,1,Voicemail(1234,u)\t\t; Right to voicemail\n\nexten => 1236,1,Dial(Console/dsp)\t\t; Ring forever\nexten => 1236,n,Voicemail(1234,b)\t\t; Unless busy\n\n;\n; # for when they're done with the demo\n;\nexten => #,1,Playback(demo-thanks)\t; \"Thanks for trying the demo\"\nexten => #,n,Hangup\t\t\t; Hang them up.\n\n;\n; A timeout and \"invalid extension rule\"\n;\nexten => t,1,Goto(#,1)\t\t\t; If they take too long, give up\nexten => i,1,Playback(invalid)\t\t; \"That's not valid, try again\"\n\n;\n; Create an extension, 500, for dialing the\n; Asterisk demo.\n;\nexten => 500,1,Playback(demo-abouttotry); Let them know what's going on\nexten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default)\t; Call the Asterisk demo\nexten => 500,n,Playback(demo-nogo)\t; Couldn't connect to the demo site\nexten => 500,n,Goto(s,6)\t\t; Return to the start over message.\n\n;\n; Create an extension, 600, for evaluating echo latency.\n;\nexten => 600,1,Playback(demo-echotest)\t; Let them know what's going on\nexten => 600,n,Echo\t\t\t; Do the echo test\nexten => 600,n,Playback(demo-echodone)\t; Let them know it's over\nexten => 600,n,Goto(s,6)\t\t; Start over\n\n;\n;\tYou can use the Macro Page to intercom a individual user\nexten => 76245,1,Macro(page,SIP/Grandstream1)\n; or if your peernames are the same as extensions\nexten => _7XXX,1,Macro(page,SIP/${EXTEN})\n;\n;\n; System Wide Page at extension 7999\n;\nexten => 7999,1,Set(TIMEOUT(absolute)=60)\nexten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)\n\n; Give voicemail at extension 8500\n;\nexten => 8500,1,VoicemailMain\nexten => 8500,n,Goto(s,6)\n\n    </textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-asterisk\",\n        matchBrackets: true,\n        lineNumber: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-asterisk</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/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\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      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings,\n      indentStatements = parserConfig.indentStatements !== false;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\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 (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\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      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (atoms.propertyIsEnumerable(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  function 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  }\n  function pushContext(state, col, type) {\n    var indent = state.indented;\n    if (state.context && state.context.type == \"statement\")\n      indent = state.context.indented;\n    return state.context = new Context(indent, col, type, null, state.context);\n  }\n  function 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\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      };\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 = 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 ((curPunc == \";\" || curPunc == \":\" || curPunc == \",\") && ctx.type == \"statement\") 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 (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (indentStatements &&\n               (((ctx.type == \"}\" || ctx.type == \"top\") && curPunc != ';') ||\n                (ctx.type == \"statement\" && curPunc == \"newstatement\")))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\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 (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit);\n      else if (ctx.align && (!dontAlignCalls || ctx.type != \")\")) return ctx.column + (closing ? 0 : 1);\n      else if (ctx.type == \")\" && !closing) return ctx.indented + statementIndentUnit;\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\",\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  var cKeywords = \"auto if break int case long char register continue return default short do sizeof \" +\n    \"double static else struct entry switch extern typedef float union for unsigned \" +\n    \"goto while enum void const signed volatile\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false;\n    for (;;) {\n      if (stream.skipTo(\"\\\\\")) {\n        stream.next();\n        if (stream.eol()) {\n          state.tokenize = cppHook;\n          break;\n        }\n      } else {\n        stream.skipToEnd();\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"meta\";\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  // 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.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    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null\"),\n    hooks: {\"#\": cppHook},\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 bool 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                    \"wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final \" +\n                    \"static_assert override\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"#\": cppHook,\n      \"u\": cpp11StringHook,\n      \"U\": cpp11StringHook,\n      \"L\": cpp11StringHook,\n      \"R\": cpp11StringHook\n    },\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert boolean break byte case catch char class const continue default \" +\n                    \"do double else enum extends final finally float for goto if implements import \" +\n                    \"instanceof int interface long native new package private protected public \" +\n                    \"return short static strictfp super switch synchronized this throw throws transient \" +\n                    \"try void volatile while\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    atoms: words(\"true false null\"),\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 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    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    builtin: words(\"Boolean Byte Char DateTime DateTimeOffset Decimal Double\" +\n                    \" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32\" +\n                    \" UInt64 bool byte char decimal double short int long object\"  +\n                    \" sbyte float string ushort uint ulong\"),\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 false 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 trye 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      \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n      \"Enumeration Equiv Error Exception Fractional Function IndexedSeq 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    atoms: words(\"true false null\"),\n    indentStatements: 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    }\n  });\n\n  def([\"x-shader/x-vertex\", \"x-shader/x-fragment\"], {\n    name: \"clike\",\n    keywords: words(\"float int bool void \" +\n                    \"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 \" +\n                    \"mat2 mat3 mat4 \" +\n                    \"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    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    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    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null\"),\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    atoms: words(\"YES NO NULL NILL ON OFF\"),\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$]/);\n        return \"keyword\";\n      },\n      \"#\": cppHook\n    },\n    modeProps: {fold: \"brace\"}\n  });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/clike/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: C-like mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<link rel=\"stylesheet\" href=\"../../addon/hint/show-hint.css\">\n<script src=\"../../addon/hint/show-hint.js\"></script>\n<script src=\"clike.js\"></script>\n<style>.CodeMirror {border: 2px inset #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">C-like</a>\n  </ul>\n</div>\n\n<article>\n<h2>C-like mode</h2>\n\n<div><textarea id=\"c-code\">\n/* C demo code */\n\n#include <zmq.h>\n#include <pthread.h>\n#include <semaphore.h>\n#include <time.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <malloc.h>\n\ntypedef struct {\n  void* arg_socket;\n  zmq_msg_t* arg_msg;\n  char* arg_string;\n  unsigned long arg_len;\n  int arg_int, arg_command;\n\n  int signal_fd;\n  int pad;\n  void* context;\n  sem_t sem;\n} acl_zmq_context;\n\n#define p(X) (context->arg_##X)\n\nvoid* zmq_thread(void* context_pointer) {\n  acl_zmq_context* context = (acl_zmq_context*)context_pointer;\n  char ok = 'K', err = 'X';\n  int res;\n\n  while (1) {\n    while ((res = sem_wait(&amp;context->sem)) == EINTR);\n    if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}\n    switch(p(command)) {\n    case 0: goto cleanup;\n    case 1: p(socket) = zmq_socket(context->context, p(int)); break;\n    case 2: p(int) = zmq_close(p(socket)); break;\n    case 3: p(int) = zmq_bind(p(socket), p(string)); break;\n    case 4: p(int) = zmq_connect(p(socket), p(string)); break;\n    case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;\n    case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;\n    case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;\n    case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;\n    case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;\n    }\n    p(command) = errno;\n    write(context->signal_fd, &amp;ok, 1);\n  }\n cleanup:\n  close(context->signal_fd);\n  free(context_pointer);\n  return 0;\n}\n\nvoid* zmq_thread_init(void* zmq_context, int signal_fd) {\n  acl_zmq_context* context = malloc(sizeof(acl_zmq_context));\n  pthread_t thread;\n\n  context->context = zmq_context;\n  context->signal_fd = signal_fd;\n  sem_init(&amp;context->sem, 1, 0);\n  pthread_create(&amp;thread, 0, &amp;zmq_thread, context);\n  pthread_detach(thread);\n  return context;\n}\n</textarea></div>\n\n<h2>C++ example</h2>\n\n<div><textarea id=\"cpp-code\">\n#include <iostream>\n#include \"mystuff/util.h\"\n\nnamespace {\nenum Enum {\n  VAL1, VAL2, VAL3\n};\n\nchar32_t unicode_string = U\"\\U0010FFFF\";\nstring raw_string = R\"delim(anything\nyou\nwant)delim\";\n\nint Helper(const MyType& param) {\n  return 0;\n}\n} // namespace\n\nclass ForwardDec;\n\ntemplate <class T, class V>\nclass Class : public BaseClass {\n  const MyType<T, V> member_;\n\n public:\n  const MyType<T, V>& Method() const {\n    return member_;\n  }\n\n  void Method2(MyType<T, V>* value);\n}\n\ntemplate <class T, class V>\nvoid Class::Method2(MyType<T, V>* value) {\n  std::out << 1 >> method();\n  value->Method3(member_);\n  member_ = value;\n}\n</textarea></div>\n\n<h2>Objective-C example</h2>\n\n<div><textarea id=\"objectivec-code\">\n/*\nThis is a longer comment\nThat spans two lines\n*/\n\n#import <Test/Test.h>\n@implementation YourAppDelegate\n\n// This is a one-line comment\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{\n  char myString[] = \"This is a C character array\";\n  int test = 5;\n  return YES;\n}\n</textarea></div>\n\n<h2>Java example</h2>\n\n<div><textarea id=\"java-code\">\nimport com.demo.util.MyType;\nimport com.demo.util.MyInterface;\n\npublic enum Enum {\n  VAL1, VAL2, VAL3\n}\n\npublic class Class<T, V> implements MyInterface {\n  public static final MyType<T, V> member;\n\n  private class InnerClass {\n    public int zero() {\n      return 0;\n    }\n  }\n\n  @Override\n  public MyType method() {\n    return member;\n  }\n\n  public void method2(MyType<T, V> value) {\n    method();\n    value.method3();\n    member = value;\n  }\n}\n</textarea></div>\n\n<h2>Scala example</h2>\n\n<div><textarea id=\"scala-code\">\nobject FilterTest extends App {\n  def filter(xs: List[Int], threshold: Int) = {\n    def process(ys: List[Int]): List[Int] =\n      if (ys.isEmpty) ys\n      else if (ys.head < threshold) ys.head :: process(ys.tail)\n      else process(ys.tail)\n    process(xs)\n  }\n  println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))\n}\n</textarea></div>\n\n    <script>\n      var cEditor = CodeMirror.fromTextArea(document.getElementById(\"c-code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-csrc\"\n      });\n      var cppEditor = CodeMirror.fromTextArea(document.getElementById(\"cpp-code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-c++src\"\n      });\n      var javaEditor = CodeMirror.fromTextArea(document.getElementById(\"java-code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-java\"\n      });\n      var objectivecEditor = CodeMirror.fromTextArea(document.getElementById(\"objectivec-code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-objectivec\"\n      });\n      var scalaEditor = CodeMirror.fromTextArea(document.getElementById(\"scala-code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-scala\"\n      });\n      var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;\n      CodeMirror.keyMap.default[(mac ? \"Cmd\" : \"Ctrl\") + \"-Space\"] = \"autocomplete\";\n    </script>\n\n    <p>Simple mode that tries to handle C-like languages as well as it\n    can. Takes two configuration parameters: <code>keywords</code>, an\n    object whose property names are the keywords in the language,\n    and <code>useCPP</code>, which determines whether C preprocessor\n    directives are recognized.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>\n    (C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>\n    (Java), <code>text/x-csharp</code> (C#),\n    <code>text/x-objectivec</code> (Objective-C),\n    <code>text/x-scala</code> (Scala), <code>text/x-vertex</code>\n    and <code>x-shader/x-fragment</code> (shader programs).</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/clike/scala.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Scala mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/ambiance.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"clike.js\"></script>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Scala</a>\n  </ul>\n</div>\n\n<article>\n<h2>Scala mode</h2>\n<form>\n<textarea id=\"code\" name=\"code\">\n\n  /*                     __                                               *\\\n  **     ________ ___   / /  ___     Scala API                            **\n  **    / __/ __// _ | / /  / _ |    (c) 2003-2011, LAMP/EPFL             **\n  **  __\\ \\/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **\n  ** /____/\\___/_/ |_/____/_/ | |                                         **\n  **                          |/                                          **\n  \\*                                                                      */\n\n  package scala.collection\n\n  import generic._\n  import mutable.{ Builder, ListBuffer }\n  import annotation.{tailrec, migration, bridge}\n  import annotation.unchecked.{ uncheckedVariance => uV }\n  import parallel.ParIterable\n\n  /** A template trait for traversable collections of type `Traversable[A]`.\n   *\n   *  $traversableInfo\n   *  @define mutability\n   *  @define traversableInfo\n   *  This is a base trait of all kinds of $mutability Scala collections. It\n   *  implements the behavior common to all collections, in terms of a method\n   *  `foreach` with signature:\n   * {{{\n   *     def foreach[U](f: Elem => U): Unit\n   * }}}\n   *  Collection classes mixing in this trait provide a concrete\n   *  `foreach` method which traverses all the\n   *  elements contained in the collection, applying a given function to each.\n   *  They also need to provide a method `newBuilder`\n   *  which creates a builder for collections of the same kind.\n   *\n   *  A traversable class might or might not have two properties: strictness\n   *  and orderedness. Neither is represented as a type.\n   *\n   *  The instances of a strict collection class have all their elements\n   *  computed before they can be used as values. By contrast, instances of\n   *  a non-strict collection class may defer computation of some of their\n   *  elements until after the instance is available as a value.\n   *  A typical example of a non-strict collection class is a\n   *  <a href=\"../immutable/Stream.html\" target=\"ContentFrame\">\n   *  `scala.collection.immutable.Stream`</a>.\n   *  A more general class of examples are `TraversableViews`.\n   *\n   *  If a collection is an instance of an ordered collection class, traversing\n   *  its elements with `foreach` will always visit elements in the\n   *  same order, even for different runs of the program. If the class is not\n   *  ordered, `foreach` can visit elements in different orders for\n   *  different runs (but it will keep the same order in the same run).'\n   *\n   *  A typical example of a collection class which is not ordered is a\n   *  `HashMap` of objects. The traversal order for hash maps will\n   *  depend on the hash codes of its elements, and these hash codes might\n   *  differ from one run to the next. By contrast, a `LinkedHashMap`\n   *  is ordered because it's `foreach` method visits elements in the\n   *  order they were inserted into the `HashMap`.\n   *\n   *  @author 郑保乐\n   *  @version 2.8\n   *  @since   2.8\n   *  @tparam A    the element type of the collection\n   *  @tparam Repr the type of the actual collection containing the elements.\n   *\n   *  @define Coll Traversable\n   *  @define coll traversable collection\n   */\n  trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]\n                                      with FilterMonadic[A, Repr]\n                                      with TraversableOnce[A]\n                                      with GenTraversableLike[A, Repr]\n                                      with Parallelizable[A, ParIterable[A]]\n  {\n    self =>\n\n    import Traversable.breaks._\n\n    /** The type implementing this traversable */\n    protected type Self = Repr\n\n    /** The collection of type $coll underlying this `TraversableLike` object.\n     *  By default this is implemented as the `TraversableLike` object itself,\n     *  but this can be overridden.\n     */\n    def repr: Repr = this.asInstanceOf[Repr]\n\n    /** The underlying collection seen as an instance of `$Coll`.\n     *  By default this is implemented as the current collection object itself,\n     *  but this can be overridden.\n     */\n    protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]\n\n    /** A conversion from collections of type `Repr` to `$Coll` objects.\n     *  By default this is implemented as just a cast, but this can be overridden.\n     */\n    protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]\n\n    /** Creates a new builder for this collection type.\n     */\n    protected[this] def newBuilder: Builder[A, Repr]\n\n    protected[this] def parCombiner = ParIterable.newCombiner[A]\n\n    /** Applies a function `f` to all elements of this $coll.\n     *\n     *    Note: this method underlies the implementation of most other bulk operations.\n     *    It's important to implement this method in an efficient way.\n     *\n     *\n     *  @param  f   the function that is applied for its side-effect to every element.\n     *              The result of function `f` is discarded.\n     *\n     *  @tparam  U  the type parameter describing the result of function `f`.\n     *              This result will always be ignored. Typically `U` is `Unit`,\n     *              but this is not necessary.\n     *\n     *  @usecase def foreach(f: A => Unit): Unit\n     */\n    def foreach[U](f: A => U): Unit\n\n    /** Tests whether this $coll is empty.\n     *\n     *  @return    `true` if the $coll contain no elements, `false` otherwise.\n     */\n    def isEmpty: Boolean = {\n      var result = true\n      breakable {\n        for (x <- this) {\n          result = false\n          break\n        }\n      }\n      result\n    }\n\n    /** Tests whether this $coll is known to have a finite size.\n     *  All strict collections are known to have finite size. For a non-strict collection\n     *  such as `Stream`, the predicate returns `true` if all elements have been computed.\n     *  It returns `false` if the stream is not yet evaluated to the end.\n     *\n     *  Note: many collection methods will not work on collections of infinite sizes.\n     *\n     *  @return  `true` if this collection is known to have finite size, `false` otherwise.\n     */\n    def hasDefiniteSize = true\n\n    def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)\n      b ++= thisCollection\n      b ++= that.seq\n      b.result\n    }\n\n    @bridge\n    def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =\n      ++(that: GenTraversableOnce[B])(bf)\n\n    /** Concatenates this $coll with the elements of a traversable collection.\n     *  It differs from ++ in that the right operand determines the type of the\n     *  resulting collection rather than the left one.\n     *\n     *  @param that   the traversable to append.\n     *  @tparam B     the element type of the returned collection.\n     *  @tparam That  $thatinfo\n     *  @param bf     $bfinfo\n     *  @return       a new collection of type `That` which contains all elements\n     *                of this $coll followed by all elements of `that`.\n     *\n     *  @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]\n     *\n     *  @return       a new $coll which contains all elements of this $coll\n     *                followed by all elements of `that`.\n     */\n    def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)\n      b ++= that\n      b ++= thisCollection\n      b.result\n    }\n\n    /** This overload exists because: for the implementation of ++: we should reuse\n     *  that of ++ because many collections override it with more efficient versions.\n     *  Since TraversableOnce has no '++' method, we have to implement that directly,\n     *  but Traversable and down can use the overload.\n     */\n    def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =\n      (that ++ seq)(breakOut)\n\n    def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      b.sizeHint(this)\n      for (x <- this) b += f(x)\n      b.result\n    }\n\n    def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      for (x <- this) b ++= f(x).seq\n      b.result\n    }\n\n    /** Selects all elements of this $coll which satisfy a predicate.\n     *\n     *  @param p     the predicate used to test elements.\n     *  @return      a new $coll consisting of all elements of this $coll that satisfy the given\n     *               predicate `p`. The order of the elements is preserved.\n     */\n    def filter(p: A => Boolean): Repr = {\n      val b = newBuilder\n      for (x <- this)\n        if (p(x)) b += x\n      b.result\n    }\n\n    /** Selects all elements of this $coll which do not satisfy a predicate.\n     *\n     *  @param p     the predicate used to test elements.\n     *  @return      a new $coll consisting of all elements of this $coll that do not satisfy the given\n     *               predicate `p`. The order of the elements is preserved.\n     */\n    def filterNot(p: A => Boolean): Repr = filter(!p(_))\n\n    def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)\n      b.result\n    }\n\n    /** Builds a new collection by applying an option-valued function to all\n     *  elements of this $coll on which the function is defined.\n     *\n     *  @param f      the option-valued function which filters and maps the $coll.\n     *  @tparam B     the element type of the returned collection.\n     *  @tparam That  $thatinfo\n     *  @param bf     $bfinfo\n     *  @return       a new collection of type `That` resulting from applying the option-valued function\n     *                `f` to each element and collecting all defined results.\n     *                The order of the elements is preserved.\n     *\n     *  @usecase def filterMap[B](f: A => Option[B]): $Coll[B]\n     *\n     *  @param pf     the partial function which filters and maps the $coll.\n     *  @return       a new $coll resulting from applying the given option-valued function\n     *                `f` to each element and collecting all defined results.\n     *                The order of the elements is preserved.\n    def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      for (x <- this)\n        f(x) match {\n          case Some(y) => b += y\n          case _ =>\n        }\n      b.result\n    }\n     */\n\n    /** Partitions this $coll in two ${coll}s according to a predicate.\n     *\n     *  @param p the predicate on which to partition.\n     *  @return  a pair of ${coll}s: the first $coll consists of all elements that\n     *           satisfy the predicate `p` and the second $coll consists of all elements\n     *           that don't. The relative order of the elements in the resulting ${coll}s\n     *           is the same as in the original $coll.\n     */\n    def partition(p: A => Boolean): (Repr, Repr) = {\n      val l, r = newBuilder\n      for (x <- this) (if (p(x)) l else r) += x\n      (l.result, r.result)\n    }\n\n    def groupBy[K](f: A => K): immutable.Map[K, Repr] = {\n      val m = mutable.Map.empty[K, Builder[A, Repr]]\n      for (elem <- this) {\n        val key = f(elem)\n        val bldr = m.getOrElseUpdate(key, newBuilder)\n        bldr += elem\n      }\n      val b = immutable.Map.newBuilder[K, Repr]\n      for ((k, v) <- m)\n        b += ((k, v.result))\n\n      b.result\n    }\n\n    /** Tests whether a predicate holds for all elements of this $coll.\n     *\n     *  $mayNotTerminateInf\n     *\n     *  @param   p     the predicate used to test elements.\n     *  @return        `true` if the given predicate `p` holds for all elements\n     *                 of this $coll, otherwise `false`.\n     */\n    def forall(p: A => Boolean): Boolean = {\n      var result = true\n      breakable {\n        for (x <- this)\n          if (!p(x)) { result = false; break }\n      }\n      result\n    }\n\n    /** Tests whether a predicate holds for some of the elements of this $coll.\n     *\n     *  $mayNotTerminateInf\n     *\n     *  @param   p     the predicate used to test elements.\n     *  @return        `true` if the given predicate `p` holds for some of the\n     *                 elements of this $coll, otherwise `false`.\n     */\n    def exists(p: A => Boolean): Boolean = {\n      var result = false\n      breakable {\n        for (x <- this)\n          if (p(x)) { result = true; break }\n      }\n      result\n    }\n\n    /** Finds the first element of the $coll satisfying a predicate, if any.\n     *\n     *  $mayNotTerminateInf\n     *  $orderDependent\n     *\n     *  @param p    the predicate used to test elements.\n     *  @return     an option value containing the first element in the $coll\n     *              that satisfies `p`, or `None` if none exists.\n     */\n    def find(p: A => Boolean): Option[A] = {\n      var result: Option[A] = None\n      breakable {\n        for (x <- this)\n          if (p(x)) { result = Some(x); break }\n      }\n      result\n    }\n\n    def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)\n\n    def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      val b = bf(repr)\n      b.sizeHint(this, 1)\n      var acc = z\n      b += acc\n      for (x <- this) { acc = op(acc, x); b += acc }\n      b.result\n    }\n\n    @migration(2, 9,\n      \"This scanRight definition has changed in 2.9.\\n\" +\n      \"The previous behavior can be reproduced with scanRight.reverse.\"\n    )\n    def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n      var scanned = List(z)\n      var acc = z\n      for (x <- reversed) {\n        acc = op(x, acc)\n        scanned ::= acc\n      }\n      val b = bf(repr)\n      for (elem <- scanned) b += elem\n      b.result\n    }\n\n    /** Selects the first element of this $coll.\n     *  $orderDependent\n     *  @return  the first element of this $coll.\n     *  @throws `NoSuchElementException` if the $coll is empty.\n     */\n    def head: A = {\n      var result: () => A = () => throw new NoSuchElementException\n      breakable {\n        for (x <- this) {\n          result = () => x\n          break\n        }\n      }\n      result()\n    }\n\n    /** Optionally selects the first element.\n     *  $orderDependent\n     *  @return  the first element of this $coll if it is nonempty, `None` if it is empty.\n     */\n    def headOption: Option[A] = if (isEmpty) None else Some(head)\n\n    /** Selects all elements except the first.\n     *  $orderDependent\n     *  @return  a $coll consisting of all elements of this $coll\n     *           except the first one.\n     *  @throws `UnsupportedOperationException` if the $coll is empty.\n     */\n    override def tail: Repr = {\n      if (isEmpty) throw new UnsupportedOperationException(\"empty.tail\")\n      drop(1)\n    }\n\n    /** Selects the last element.\n      * $orderDependent\n      * @return The last element of this $coll.\n      * @throws NoSuchElementException If the $coll is empty.\n      */\n    def last: A = {\n      var lst = head\n      for (x <- this)\n        lst = x\n      lst\n    }\n\n    /** Optionally selects the last element.\n     *  $orderDependent\n     *  @return  the last element of this $coll$ if it is nonempty, `None` if it is empty.\n     */\n    def lastOption: Option[A] = if (isEmpty) None else Some(last)\n\n    /** Selects all elements except the last.\n     *  $orderDependent\n     *  @return  a $coll consisting of all elements of this $coll\n     *           except the last one.\n     *  @throws `UnsupportedOperationException` if the $coll is empty.\n     */\n    def init: Repr = {\n      if (isEmpty) throw new UnsupportedOperationException(\"empty.init\")\n      var lst = head\n      var follow = false\n      val b = newBuilder\n      b.sizeHint(this, -1)\n      for (x <- this.seq) {\n        if (follow) b += lst\n        else follow = true\n        lst = x\n      }\n      b.result\n    }\n\n    def take(n: Int): Repr = slice(0, n)\n\n    def drop(n: Int): Repr =\n      if (n <= 0) {\n        val b = newBuilder\n        b.sizeHint(this)\n        b ++= thisCollection result\n      }\n      else sliceWithKnownDelta(n, Int.MaxValue, -n)\n\n    def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)\n\n    // Precondition: from >= 0, until > 0, builder already configured for building.\n    private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {\n      var i = 0\n      breakable {\n        for (x <- this.seq) {\n          if (i >= from) b += x\n          i += 1\n          if (i >= until) break\n        }\n      }\n      b.result\n    }\n    // Precondition: from >= 0\n    private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {\n      val b = newBuilder\n      if (until <= from) b.result\n      else {\n        b.sizeHint(this, delta)\n        sliceInternal(from, until, b)\n      }\n    }\n    // Precondition: from >= 0\n    private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {\n      val b = newBuilder\n      if (until <= from) b.result\n      else {\n        b.sizeHintBounded(until - from, this)\n        sliceInternal(from, until, b)\n      }\n    }\n\n    def takeWhile(p: A => Boolean): Repr = {\n      val b = newBuilder\n      breakable {\n        for (x <- this) {\n          if (!p(x)) break\n          b += x\n        }\n      }\n      b.result\n    }\n\n    def dropWhile(p: A => Boolean): Repr = {\n      val b = newBuilder\n      var go = false\n      for (x <- this) {\n        if (!p(x)) go = true\n        if (go) b += x\n      }\n      b.result\n    }\n\n    def span(p: A => Boolean): (Repr, Repr) = {\n      val l, r = newBuilder\n      var toLeft = true\n      for (x <- this) {\n        toLeft = toLeft && p(x)\n        (if (toLeft) l else r) += x\n      }\n      (l.result, r.result)\n    }\n\n    def splitAt(n: Int): (Repr, Repr) = {\n      val l, r = newBuilder\n      l.sizeHintBounded(n, this)\n      if (n >= 0) r.sizeHint(this, -n)\n      var i = 0\n      for (x <- this) {\n        (if (i < n) l else r) += x\n        i += 1\n      }\n      (l.result, r.result)\n    }\n\n    /** Iterates over the tails of this $coll. The first value will be this\n     *  $coll and the final one will be an empty $coll, with the intervening\n     *  values the results of successive applications of `tail`.\n     *\n     *  @return   an iterator over all the tails of this $coll\n     *  @example  `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`\n     */\n    def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)\n\n    /** Iterates over the inits of this $coll. The first value will be this\n     *  $coll and the final one will be an empty $coll, with the intervening\n     *  values the results of successive applications of `init`.\n     *\n     *  @return  an iterator over all the inits of this $coll\n     *  @example  `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`\n     */\n    def inits: Iterator[Repr] = iterateUntilEmpty(_.init)\n\n    /** Copies elements of this $coll to an array.\n     *  Fills the given array `xs` with at most `len` elements of\n     *  this $coll, starting at position `start`.\n     *  Copying will stop once either the end of the current $coll is reached,\n     *  or the end of the array is reached, or `len` elements have been copied.\n     *\n     *  $willNotTerminateInf\n     *\n     *  @param  xs     the array to fill.\n     *  @param  start  the starting index.\n     *  @param  len    the maximal number of elements to copy.\n     *  @tparam B      the type of the elements of the array.\n     *\n     *\n     *  @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit\n     */\n    def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {\n      var i = start\n      val end = (start + len) min xs.length\n      breakable {\n        for (x <- this) {\n          if (i >= end) break\n          xs(i) = x\n          i += 1\n        }\n      }\n    }\n\n    def toTraversable: Traversable[A] = thisCollection\n    def toIterator: Iterator[A] = toStream.iterator\n    def toStream: Stream[A] = toBuffer.toStream\n\n    /** Converts this $coll to a string.\n     *\n     *  @return   a string representation of this collection. By default this\n     *            string consists of the `stringPrefix` of this $coll,\n     *            followed by all elements separated by commas and enclosed in parentheses.\n     */\n    override def toString = mkString(stringPrefix + \"(\", \", \", \")\")\n\n    /** Defines the prefix of this object's `toString` representation.\n     *\n     *  @return  a string representation which starts the result of `toString`\n     *           applied to this $coll. By default the string prefix is the\n     *           simple name of the collection class $coll.\n     */\n    def stringPrefix : String = {\n      var string = repr.asInstanceOf[AnyRef].getClass.getName\n      val idx1 = string.lastIndexOf('.' : Int)\n      if (idx1 != -1) string = string.substring(idx1 + 1)\n      val idx2 = string.indexOf('$')\n      if (idx2 != -1) string = string.substring(0, idx2)\n      string\n    }\n\n    /** Creates a non-strict view of this $coll.\n     *\n     *  @return a non-strict view of this $coll.\n     */\n    def view = new TraversableView[A, Repr] {\n      protected lazy val underlying = self.repr\n      override def foreach[U](f: A => U) = self foreach f\n    }\n\n    /** Creates a non-strict view of a slice of this $coll.\n     *\n     *  Note: the difference between `view` and `slice` is that `view` produces\n     *        a view of the current $coll, whereas `slice` produces a new $coll.\n     *\n     *  Note: `view(from, to)` is equivalent to `view.slice(from, to)`\n     *  $orderDependent\n     *\n     *  @param from   the index of the first element of the view\n     *  @param until  the index of the element following the view\n     *  @return a non-strict view of a slice of this $coll, starting at index `from`\n     *  and extending up to (but not including) index `until`.\n     */\n    def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)\n\n    /** Creates a non-strict filter of this $coll.\n     *\n     *  Note: the difference between `c filter p` and `c withFilter p` is that\n     *        the former creates a new collection, whereas the latter only\n     *        restricts the domain of subsequent `map`, `flatMap`, `foreach`,\n     *        and `withFilter` operations.\n     *  $orderDependent\n     *\n     *  @param p   the predicate used to test elements.\n     *  @return    an object of class `WithFilter`, which supports\n     *             `map`, `flatMap`, `foreach`, and `withFilter` operations.\n     *             All these operations apply to those elements of this $coll which\n     *             satisfy the predicate `p`.\n     */\n    def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)\n\n    /** A class supporting filtered operations. Instances of this class are\n     *  returned by method `withFilter`.\n     */\n    class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {\n\n      /** Builds a new collection by applying a function to all elements of the\n       *  outer $coll containing this `WithFilter` instance that satisfy predicate `p`.\n       *\n       *  @param f      the function to apply to each element.\n       *  @tparam B     the element type of the returned collection.\n       *  @tparam That  $thatinfo\n       *  @param bf     $bfinfo\n       *  @return       a new collection of type `That` resulting from applying\n       *                the given function `f` to each element of the outer $coll\n       *                that satisfies predicate `p` and collecting the results.\n       *\n       *  @usecase def map[B](f: A => B): $Coll[B]\n       *\n       *  @return       a new $coll resulting from applying the given function\n       *                `f` to each element of the outer $coll that satisfies\n       *                predicate `p` and collecting the results.\n       */\n      def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n        val b = bf(repr)\n        for (x <- self)\n          if (p(x)) b += f(x)\n        b.result\n      }\n\n      /** Builds a new collection by applying a function to all elements of the\n       *  outer $coll containing this `WithFilter` instance that satisfy\n       *  predicate `p` and concatenating the results.\n       *\n       *  @param f      the function to apply to each element.\n       *  @tparam B     the element type of the returned collection.\n       *  @tparam That  $thatinfo\n       *  @param bf     $bfinfo\n       *  @return       a new collection of type `That` resulting from applying\n       *                the given collection-valued function `f` to each element\n       *                of the outer $coll that satisfies predicate `p` and\n       *                concatenating the results.\n       *\n       *  @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]\n       *\n       *  @return       a new $coll resulting from applying the given collection-valued function\n       *                `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.\n       */\n      def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {\n        val b = bf(repr)\n        for (x <- self)\n          if (p(x)) b ++= f(x).seq\n        b.result\n      }\n\n      /** Applies a function `f` to all elements of the outer $coll containing\n       *  this `WithFilter` instance that satisfy predicate `p`.\n       *\n       *  @param  f   the function that is applied for its side-effect to every element.\n       *              The result of function `f` is discarded.\n       *\n       *  @tparam  U  the type parameter describing the result of function `f`.\n       *              This result will always be ignored. Typically `U` is `Unit`,\n       *              but this is not necessary.\n       *\n       *  @usecase def foreach(f: A => Unit): Unit\n       */\n      def foreach[U](f: A => U): Unit =\n        for (x <- self)\n          if (p(x)) f(x)\n\n      /** Further refines the filter for this $coll.\n       *\n       *  @param q   the predicate used to test elements.\n       *  @return    an object of class `WithFilter`, which supports\n       *             `map`, `flatMap`, `foreach`, and `withFilter` operations.\n       *             All these operations apply to those elements of this $coll which\n       *             satisfy the predicate `q` in addition to the predicate `p`.\n       */\n      def withFilter(q: A => Boolean): WithFilter =\n        new WithFilter(x => p(x) && q(x))\n    }\n\n    // A helper for tails and inits.\n    private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {\n      val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)\n      it ++ Iterator(Nil) map (newBuilder ++= _ result)\n    }\n  }\n\n\n</textarea>\n</form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"ambiance\",\n        mode: \"text/x-scala\"\n      });\n    </script>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/clojure/clojure.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Author: Hans Engel\n * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)\n */\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(\"clojure\", function (options) {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\", CHARACTER = \"string-2\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\", KEYWORD = \"keyword\", VAR = \"variable\";\n    var INDENT_WORD_SKIP = options.indentUnit || 2;\n    var NORMAL_INDENT_UNIT = options.indentUnit || 2;\n\n    function makeKeywords(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\n    var atoms = makeKeywords(\"true false nil\");\n\n    var keywords = makeKeywords(\n      \"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle\");\n\n    var builtins = makeKeywords(\n        \"* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>\");\n\n    var indentKeys = makeKeywords(\n        // Built-ins\n        \"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch \" +\n\n        // Binding forms\n        \"let letfn binding loop for doseq dotimes when-let if-let \" +\n\n        // Data structures\n        \"defstruct struct-map assoc \" +\n\n        // clojure.test\n        \"testing deftest \" +\n\n        // contrib\n        \"handler-case handle dotrace deftrace\");\n\n    var tests = {\n        digit: /\\d/,\n        digit_or_colon: /[\\d:]/,\n        hex: /[0-9a-f]/i,\n        sign: /[+-]/,\n        exponent: /e/i,\n        keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n        symbol: /[\\w*+!\\-\\._?:<>\\/\\xa1-\\uffff]/\n    };\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    function isNumber(ch, stream){\n        // hex\n        if ( ch === '0' && stream.eat(/x/i) ) {\n            stream.eatWhile(tests.hex);\n            return true;\n        }\n\n        // leading sign\n        if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {\n          stream.eat(tests.sign);\n          ch = stream.next();\n        }\n\n        if ( tests.digit.test(ch) ) {\n            stream.eat(ch);\n            stream.eatWhile(tests.digit);\n\n            if ( '.' == stream.peek() ) {\n                stream.eat('.');\n                stream.eatWhile(tests.digit);\n            }\n\n            if ( stream.eat(tests.exponent) ) {\n                stream.eat(tests.sign);\n                stream.eatWhile(tests.digit);\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    // Eat character that starts after backslash \\\n    function eatCharacter(stream) {\n        var first = stream.next();\n        // Read special literals: backspace, newline, space, return.\n        // Just read all lowercase letters.\n        if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {\n            return;\n        }\n        // Read unicode character: \\u1000 \\uA0a1\n        if (first === \"u\") {\n            stream.match(/[0-9a-z]{4}/i, true);\n        }\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in string mode\n                    break;\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n                    } else if (ch == \"\\\\\") {\n                        eatCharacter(stream);\n                        returnType = CHARACTER;\n                    } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n                        returnType = ATOM;\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (isNumber(ch,stream)){\n                        returnType = NUMBER;\n                    } else if (ch == \"(\" || ch == \"[\" || ch == \"{\" ) {\n                        var keyWord = '', indentTemp = stream.column(), letter;\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        if (ch == \"(\") while ((letter = stream.eat(tests.keyword_char)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||\n                                                   /^(?:def|with)/.test(keyWord))) { // indent-word\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation the user defined spaces after\n                                pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\" || ch == \"}\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : (ch == \"]\" ? \"[\" :\"{\"))) {\n                            popStack(state);\n                        }\n                    } else if ( ch == \":\" ) {\n                        stream.eatWhile(tests.symbol);\n                        return ATOM;\n                    } else {\n                        stream.eatWhile(tests.symbol);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = KEYWORD;\n                        } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {\n                            returnType = ATOM;\n                        } else {\n                          returnType = VAR;\n                        }\n                    }\n            }\n\n            return returnType;\n        },\n\n        indent: function (state) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        },\n\n        lineComment: \";;\"\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-clojure\", \"clojure\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/clojure/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Clojure mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"clojure.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Clojure</a>\n  </ul>\n</div>\n\n<article>\n<h2>Clojure mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n; Conway's Game of Life, based on the work of:\n;; Laurent Petit https://gist.github.com/1200343\n;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life\n\n(ns ^{:doc \"Conway's Game of Life.\"}\n game-of-life)\n\n;; Core game of life's algorithm functions\n\n(defn neighbours\n  \"Given a cell's coordinates, returns the coordinates of its neighbours.\"\n  [[x y]]\n  (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]\n    [(+ dx x) (+ dy y)]))\n\n(defn step\n  \"Given a set of living cells, computes the new set of living cells.\"\n  [cells]\n  (set (for [[cell n] (frequencies (mapcat neighbours cells))\n             :when (or (= n 3) (and (= n 2) (cells cell)))]\n         cell)))\n\n;; Utility methods for displaying game on a text terminal\n\n(defn print-board\n  \"Prints a board on *out*, representing a step in the game.\"\n  [board w h]\n  (doseq [x (range (inc w)) y (range (inc h))]\n    (if (= y 0) (print \"\\n\"))\n    (print (if (board [x y]) \"[X]\" \" . \"))))\n\n(defn display-grids\n  \"Prints a squence of boards on *out*, representing several steps.\"\n  [grids w h]\n  (doseq [board grids]\n    (print-board board w h)\n    (print \"\\n\")))\n\n;; Launches an example board\n\n(def\n  ^{:doc \"board represents the initial set of living cells\"}\n   board #{[2 1] [2 2] [2 3]})\n\n(display-grids (take 3 (iterate step board)) 5 5)\n\n;; Let's play with characters\n(println \\1 \\a \\# \\\\\n         \\\" \\( \\newline\n         \\} \\\" \\space\n         \\tab \\return \\backspace\n         \\u1000 \\uAaAa \\u9F9F)\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/cobol/cobol.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Author: Gautam Mehta\n * Branched from CodeMirror's Scheme mode\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(\"cobol\", function () {\n  var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\",\n      ATOM = \"atom\", NUMBER = \"number\", KEYWORD = \"keyword\", MODTAG = \"header\",\n      COBOLLINENUM = \"def\", PERIOD = \"link\";\n  function makeKeywords(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  var atoms = makeKeywords(\"TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES \");\n  var keywords = makeKeywords(\n      \"ACCEPT ACCESS ACQUIRE ADD ADDRESS \" +\n      \"ADVANCING AFTER ALIAS ALL ALPHABET \" +\n      \"ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED \" +\n      \"ALSO ALTER ALTERNATE AND ANY \" +\n      \"ARE AREA AREAS ARITHMETIC ASCENDING \" +\n      \"ASSIGN AT ATTRIBUTE AUTHOR AUTO \" +\n      \"AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS \" +\n      \"B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP \" +\n      \"BEFORE BELL BINARY BIT BITS \" +\n      \"BLANK BLINK BLOCK BOOLEAN BOTTOM \" +\n      \"BY CALL CANCEL CD CF \" +\n      \"CH CHARACTER CHARACTERS CLASS CLOCK-UNITS \" +\n      \"CLOSE COBOL CODE CODE-SET COL \" +\n      \"COLLATING COLUMN COMMA COMMIT COMMITMENT \" +\n      \"COMMON COMMUNICATION COMP COMP-0 COMP-1 \" +\n      \"COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 \" +\n      \"COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 \" +\n      \"COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 \" +\n      \"COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE \" +\n      \"CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS \" +\n      \"CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS \" +\n      \"CONVERTING COPY CORR CORRESPONDING COUNT \" +\n      \"CRT CRT-UNDER CURRENCY CURRENT CURSOR \" +\n      \"DATA DATE DATE-COMPILED DATE-WRITTEN DAY \" +\n      \"DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION \" +\n      \"DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS \" +\n      \"DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE \" +\n      \"DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING \" +\n      \"DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED \" +\n      \"DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION \" +\n      \"DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 \" +\n      \"DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 \" +\n      \"DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION \" +\n      \"DOWN DROP DUPLICATE DUPLICATES DYNAMIC \" +\n      \"EBCDIC EGI EJECT ELSE EMI \" +\n      \"EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. \" +\n      \"END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY \" +\n      \"END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY \" +\n      \"END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN \" +\n      \"END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT \" +\n      \"END-UNSTRING END-WRITE END-XML ENTER ENTRY \" +\n      \"ENVIRONMENT EOP EQUAL EQUALS ERASE \" +\n      \"ERROR ESI EVALUATE EVERY EXCEEDS \" +\n      \"EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL \" +\n      \"EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL \" +\n      \"FILE-STREAM FILES FILLER FINAL FIND \" +\n      \"FINISH FIRST FOOTING FOR FOREGROUND-COLOR \" +\n      \"FOREGROUND-COLOUR FORMAT FREE FROM FULL \" +\n      \"FUNCTION GENERATE GET GIVING GLOBAL \" +\n      \"GO GOBACK GREATER GROUP HEADING \" +\n      \"HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL \" +\n      \"ID IDENTIFICATION IF IN INDEX \" +\n      \"INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 \" +\n      \"INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED \" +\n      \"INDIC INDICATE INDICATOR INDICATORS INITIAL \" +\n      \"INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT \" +\n      \"INSTALLATION INTO INVALID INVOKE IS \" +\n      \"JUST JUSTIFIED KANJI KEEP KEY \" +\n      \"LABEL LAST LD LEADING LEFT \" +\n      \"LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY \" +\n      \"LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER \" +\n      \"LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE \" +\n      \"LOCALE LOCALLY LOCK \" +\n      \"MEMBER MEMORY MERGE MESSAGE METACLASS \" +\n      \"MODE MODIFIED MODIFY MODULES MOVE \" +\n      \"MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE \" +\n      \"NEXT NO NO-ECHO NONE NOT \" +\n      \"NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER \" +\n      \"NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS \" +\n      \"OF OFF OMITTED ON ONLY \" +\n      \"OPEN OPTIONAL OR ORDER ORGANIZATION \" +\n      \"OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL \" +\n      \"PADDING PAGE PAGE-COUNTER PARSE PERFORM \" +\n      \"PF PH PIC PICTURE PLUS \" +\n      \"POINTER POSITION POSITIVE PREFIX PRESENT \" +\n      \"PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES \" +\n      \"PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID \" +\n      \"PROMPT PROTECTED PURGE QUEUE QUOTE \" +\n      \"QUOTES RANDOM RD READ READY \" +\n      \"REALM RECEIVE RECONNECT RECORD RECORD-NAME \" +\n      \"RECORDS RECURSIVE REDEFINES REEL REFERENCE \" +\n      \"REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE \" +\n      \"REMAINDER REMOVAL RENAMES REPEATED REPLACE \" +\n      \"REPLACING REPORT REPORTING REPORTS REPOSITORY \" +\n      \"REQUIRED RERUN RESERVE RESET RETAINING \" +\n      \"RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO \" +\n      \"REVERSED REWIND REWRITE RF RH \" +\n      \"RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED \" +\n      \"RUN SAME SCREEN SD SEARCH \" +\n      \"SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT \" +\n      \"SELECT SEND SENTENCE SEPARATE SEQUENCE \" +\n      \"SEQUENTIAL SET SHARED SIGN SIZE \" +\n      \"SKIP1 SKIP2 SKIP3 SORT SORT-MERGE \" +\n      \"SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL \" +\n      \"SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 \" +\n      \"START STARTING STATUS STOP STORE \" +\n      \"STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA \" +\n      \"SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS \" +\n      \"SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT \" +\n      \"TABLE TALLYING TAPE TENANT TERMINAL \" +\n      \"TERMINATE TEST TEXT THAN THEN \" +\n      \"THROUGH THRU TIME TIMES TITLE \" +\n      \"TO TOP TRAILING TRAILING-SIGN TRANSACTION \" +\n      \"TYPE TYPEDEF UNDERLINE UNEQUAL UNIT \" +\n      \"UNSTRING UNTIL UP UPDATE UPON \" +\n      \"USAGE USAGE-MODE USE USING VALID \" +\n      \"VALIDATE VALUE VALUES VARYING VLR \" +\n      \"WAIT WHEN WHEN-COMPILED WITH WITHIN \" +\n      \"WORDS WORKING-STORAGE WRITE XML XML-CODE \" +\n      \"XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL \" );\n\n  var builtins = makeKeywords(\"- * ** / + < <= = > >= \");\n  var tests = {\n    digit: /\\d/,\n    digit_or_colon: /[\\d:]/,\n    hex: /[0-9a-f]/i,\n    sign: /[+-]/,\n    exponent: /e/i,\n    keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n    symbol: /[\\w*+\\-]/\n  };\n  function isNumber(ch, stream){\n    // hex\n    if ( ch === '0' && stream.eat(/x/i) ) {\n      stream.eatWhile(tests.hex);\n      return true;\n    }\n    // leading sign\n    if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {\n      stream.eat(tests.sign);\n      ch = stream.next();\n    }\n    if ( tests.digit.test(ch) ) {\n      stream.eat(ch);\n      stream.eatWhile(tests.digit);\n      if ( '.' == stream.peek()) {\n        stream.eat('.');\n        stream.eatWhile(tests.digit);\n      }\n      if ( stream.eat(tests.exponent) ) {\n        stream.eat(tests.sign);\n        stream.eatWhile(tests.digit);\n      }\n      return true;\n    }\n    return false;\n  }\n  return {\n    startState: function () {\n      return {\n        indentStack: null,\n        indentation: 0,\n        mode: false\n      };\n    },\n    token: function (stream, state) {\n      if (state.indentStack == null && stream.sol()) {\n        // update indentation, but only if indentStack is empty\n        state.indentation = 6 ; //stream.indentation();\n      }\n      // skip spaces\n      if (stream.eatSpace()) {\n        return null;\n      }\n      var returnType = null;\n      switch(state.mode){\n      case \"string\": // multi-line string parsing mode\n        var next = false;\n        while ((next = stream.next()) != null) {\n          if (next == \"\\\"\" || next == \"\\'\") {\n            state.mode = false;\n            break;\n          }\n        }\n        returnType = STRING; // continue on in string mode\n        break;\n      default: // default parsing mode\n        var ch = stream.next();\n        var col = stream.column();\n        if (col >= 0 && col <= 5) {\n          returnType = COBOLLINENUM;\n        } else if (col >= 72 && col <= 79) {\n          stream.skipToEnd();\n          returnType = MODTAG;\n        } else if (ch == \"*\" && col == 6) { // comment\n          stream.skipToEnd(); // rest of the line is a comment\n          returnType = COMMENT;\n        } else if (ch == \"\\\"\" || ch == \"\\'\") {\n          state.mode = \"string\";\n          returnType = STRING;\n        } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n          returnType = ATOM;\n        } else if (ch == \".\") {\n          returnType = PERIOD;\n        } else if (isNumber(ch,stream)){\n          returnType = NUMBER;\n        } else {\n          if (stream.current().match(tests.symbol)) {\n            while (col < 71) {\n              if (stream.eat(tests.symbol) === undefined) {\n                break;\n              } else {\n                col++;\n              }\n            }\n          }\n          if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {\n            returnType = KEYWORD;\n          } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {\n            returnType = BUILTIN;\n          } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {\n            returnType = ATOM;\n          } else returnType = null;\n        }\n      }\n      return returnType;\n    },\n    indent: function (state) {\n      if (state.indentStack == null) return state.indentation;\n      return state.indentStack.indent;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-cobol\", \"cobol\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/cobol/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: COBOL mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/neat.css\">\n<link rel=\"stylesheet\" href=\"../../theme/elegant.css\">\n<link rel=\"stylesheet\" href=\"../../theme/erlang-dark.css\">\n<link rel=\"stylesheet\" href=\"../../theme/night.css\">\n<link rel=\"stylesheet\" href=\"../../theme/monokai.css\">\n<link rel=\"stylesheet\" href=\"../../theme/cobalt.css\">\n<link rel=\"stylesheet\" href=\"../../theme/eclipse.css\">\n<link rel=\"stylesheet\" href=\"../../theme/rubyblue.css\">\n<link rel=\"stylesheet\" href=\"../../theme/lesser-dark.css\">\n<link rel=\"stylesheet\" href=\"../../theme/xq-dark.css\">\n<link rel=\"stylesheet\" href=\"../../theme/xq-light.css\">\n<link rel=\"stylesheet\" href=\"../../theme/ambiance.css\">\n<link rel=\"stylesheet\" href=\"../../theme/blackboard.css\">\n<link rel=\"stylesheet\" href=\"../../theme/vibrant-ink.css\">\n<link rel=\"stylesheet\" href=\"../../theme/solarized.css\">\n<link rel=\"stylesheet\" href=\"../../theme/twilight.css\">\n<link rel=\"stylesheet\" href=\"../../theme/midnight.css\">\n<link rel=\"stylesheet\" href=\"../../addon/dialog/dialog.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"cobol.js\"></script>\n<script src=\"../../addon/selection/active-line.js\"></script>\n<script src=\"../../addon/search/search.js\"></script>\n<script src=\"../../addon/dialog/dialog.js\"></script>\n<script src=\"../../addon/search/searchcursor.js\"></script>\n<style>\n        .CodeMirror {\n          border: 1px solid #eee;\n          font-size : 20px;\n          height : auto !important;\n        }\n        .CodeMirror-activeline-background {background: #555555 !important;}\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">COBOL</a>\n  </ul>\n</div>\n\n<article>\n<h2>COBOL mode</h2>\n\n    <p> Select Theme <select onchange=\"selectTheme()\" id=\"selectTheme\">\n        <option>default</option>\n        <option>ambiance</option>\n        <option>blackboard</option>\n        <option>cobalt</option>\n        <option>eclipse</option>\n        <option>elegant</option>\n        <option>erlang-dark</option>\n        <option>lesser-dark</option>\n        <option>midnight</option>\n        <option>monokai</option>\n        <option>neat</option>\n        <option>night</option>\n        <option>rubyblue</option>\n        <option>solarized dark</option>\n        <option>solarized light</option>\n        <option selected>twilight</option>\n        <option>vibrant-ink</option>\n        <option>xq-dark</option>\n        <option>xq-light</option>\n    </select>    Select Font Size <select onchange=\"selectFontsize()\" id=\"selectFontSize\">\n          <option value=\"13px\">13px</option>\n          <option value=\"14px\">14px</option>\n          <option value=\"16px\">16px</option>\n          <option value=\"18px\">18px</option>\n          <option value=\"20px\" selected=\"selected\">20px</option>\n          <option value=\"24px\">24px</option>\n          <option value=\"26px\">26px</option>\n          <option value=\"28px\">28px</option>\n          <option value=\"30px\">30px</option>\n          <option value=\"32px\">32px</option>\n          <option value=\"34px\">34px</option>\n          <option value=\"36px\">36px</option>\n        </select>\n<label for=\"checkBoxReadOnly\">Read-only</label>\n<input type=\"checkbox\" id=\"checkBoxReadOnly\" onchange=\"selectReadOnly()\">\n<label for=\"id_tabToIndentSpace\">Insert Spaces on Tab</label>\n<input type=\"checkbox\" id=\"id_tabToIndentSpace\" onchange=\"tabToIndentSpace()\">\n</p>\n<textarea id=\"code\" name=\"code\">\n---------1---------2---------3---------4---------5---------6---------7---------8\n12345678911234567892123456789312345678941234567895123456789612345678971234567898\n000010 IDENTIFICATION DIVISION.                                        MODTGHERE\n000020 PROGRAM-ID.       SAMPLE.\n000030 AUTHOR.           TEST SAM.\n000040 DATE-WRITTEN.     5 February 2013\n000041\n000042* A sample program just to show the form.\n000043* The program copies its input to the output,\n000044* and counts the number of records.\n000045* At the end this number is printed.\n000046\n000050 ENVIRONMENT DIVISION.\n000060 INPUT-OUTPUT SECTION.\n000070 FILE-CONTROL.\n000080     SELECT STUDENT-FILE     ASSIGN TO SYSIN\n000090         ORGANIZATION IS LINE SEQUENTIAL.\n000100     SELECT PRINT-FILE       ASSIGN TO SYSOUT\n000110         ORGANIZATION IS LINE SEQUENTIAL.\n000120\n000130 DATA DIVISION.\n000140 FILE SECTION.\n000150 FD  STUDENT-FILE\n000160     RECORD CONTAINS 43 CHARACTERS\n000170     DATA RECORD IS STUDENT-IN.\n000180 01  STUDENT-IN              PIC X(43).\n000190\n000200 FD  PRINT-FILE\n000210     RECORD CONTAINS 80 CHARACTERS\n000220     DATA RECORD IS PRINT-LINE.\n000230 01  PRINT-LINE              PIC X(80).\n000240\n000250 WORKING-STORAGE SECTION.\n000260 01  DATA-REMAINS-SWITCH     PIC X(2)      VALUE SPACES.\n000261 01  RECORDS-WRITTEN         PIC 99.\n000270\n000280 01  DETAIL-LINE.\n000290     05  FILLER              PIC X(7)      VALUE SPACES.\n000300     05  RECORD-IMAGE        PIC X(43).\n000310     05  FILLER              PIC X(30)     VALUE SPACES.\n000311\n000312 01  SUMMARY-LINE.\n000313     05  FILLER              PIC X(7)      VALUE SPACES.\n000314     05  TOTAL-READ          PIC 99.\n000315     05  FILLER              PIC X         VALUE SPACE.\n000316     05  FILLER              PIC X(17)\n000317                 VALUE  'Records were read'.\n000318     05  FILLER              PIC X(53)     VALUE SPACES.\n000319\n000320 PROCEDURE DIVISION.\n000321\n000330 PREPARE-SENIOR-REPORT.\n000340     OPEN INPUT  STUDENT-FILE\n000350          OUTPUT PRINT-FILE.\n000351     MOVE ZERO TO RECORDS-WRITTEN.\n000360     READ STUDENT-FILE\n000370         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH\n000380     END-READ.\n000390     PERFORM PROCESS-RECORDS\n000410         UNTIL DATA-REMAINS-SWITCH = 'NO'.\n000411     PERFORM PRINT-SUMMARY.\n000420     CLOSE STUDENT-FILE\n000430           PRINT-FILE.\n000440     STOP RUN.\n000450\n000460 PROCESS-RECORDS.\n000470     MOVE STUDENT-IN TO RECORD-IMAGE.\n000480     MOVE DETAIL-LINE TO PRINT-LINE.\n000490     WRITE PRINT-LINE.\n000500     ADD 1 TO RECORDS-WRITTEN.\n000510     READ STUDENT-FILE\n000520         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH\n000530     END-READ.\n000540\n000550 PRINT-SUMMARY.\n000560     MOVE RECORDS-WRITTEN TO TOTAL-READ.\n000570     MOVE SUMMARY-LINE TO PRINT-LINE.\n000571     WRITE PRINT-LINE.\n000572\n000580\n</textarea>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-cobol\",\n        theme : \"twilight\",\n        styleActiveLine: true,\n        showCursorWhenSelecting : true,\n      });\n      function selectTheme() {\n        var themeInput = document.getElementById(\"selectTheme\");\n        var theme = themeInput.options[themeInput.selectedIndex].innerHTML;\n        editor.setOption(\"theme\", theme);\n      }\n      function selectFontsize() {\n        var fontSizeInput = document.getElementById(\"selectFontSize\");\n        var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;\n        editor.getWrapperElement().style.fontSize = fontSize;\n        editor.refresh();\n      }\n      function selectReadOnly() {\n        editor.setOption(\"readOnly\", document.getElementById(\"checkBoxReadOnly\").checked);\n      }\n      function tabToIndentSpace() {\n        if (document.getElementById(\"id_tabToIndentSpace\").checked) {\n            editor.setOption(\"extraKeys\", {Tab: function(cm) { cm.replaceSelection(\"    \", \"end\"); }});\n        } else {\n            editor.setOption(\"extraKeys\", {Tab: function(cm) { cm.replaceSelection(\"    \", \"end\"); }});\n        }\n      }\n    </script>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/coffeescript/coffeescript.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Link to the project's GitHub page:\n * https://github.com/pickhardt/coffeescript-codemirror-mode\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(\"coffeescript\", function(conf, parserConf) {\n  var ERRORCLASS = \"error\";\n\n  function wordRegexp(words) {\n    return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n  }\n\n  var operators = /^(?:->|=>|\\+[+=]?|-[\\-=]?|\\*[\\*=]?|\\/[\\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\\|=?|\\^=?|\\~|!|\\?|(or|and|\\|\\||&&|\\?)=)/;\n  var delimiters = /^(?:[()\\[\\]{},:`=;]|\\.\\.?\\.?)/;\n  var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;\n  var properties = /^(@|this\\.)[_A-Za-z$][_A-Za-z$0-9]*/;\n\n  var wordOperators = wordRegexp([\"and\", \"or\", \"not\",\n                                  \"is\", \"isnt\", \"in\",\n                                  \"instanceof\", \"typeof\"]);\n  var indentKeywords = [\"for\", \"while\", \"loop\", \"if\", \"unless\", \"else\",\n                        \"switch\", \"try\", \"catch\", \"finally\", \"class\"];\n  var commonKeywords = [\"break\", \"by\", \"continue\", \"debugger\", \"delete\",\n                        \"do\", \"in\", \"of\", \"new\", \"return\", \"then\",\n                        \"this\", \"@\", \"throw\", \"when\", \"until\", \"extends\"];\n\n  var keywords = wordRegexp(indentKeywords.concat(commonKeywords));\n\n  indentKeywords = wordRegexp(indentKeywords);\n\n\n  var stringPrefixes = /^('{3}|\\\"{3}|['\\\"])/;\n  var regexPrefixes = /^(\\/{3}|\\/)/;\n  var commonConstants = [\"Infinity\", \"NaN\", \"undefined\", \"null\", \"true\", \"false\", \"on\", \"off\", \"yes\", \"no\"];\n  var constants = wordRegexp(commonConstants);\n\n  // Tokenizers\n  function tokenBase(stream, state) {\n    // Handle scope changes\n    if (stream.sol()) {\n      if (state.scope.align === null) state.scope.align = false;\n      var scopeOffset = state.scope.offset;\n      if (stream.eatSpace()) {\n        var lineOffset = stream.indentation();\n        if (lineOffset > scopeOffset && state.scope.type == \"coffee\") {\n          return \"indent\";\n        } else if (lineOffset < scopeOffset) {\n          return \"dedent\";\n        }\n        return null;\n      } else {\n        if (scopeOffset > 0) {\n          dedent(stream, state);\n        }\n      }\n    }\n    if (stream.eatSpace()) {\n      return null;\n    }\n\n    var ch = stream.peek();\n\n    // Handle docco title comment (single line)\n    if (stream.match(\"####\")) {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n\n    // Handle multi line comments\n    if (stream.match(\"###\")) {\n      state.tokenize = longComment;\n      return state.tokenize(stream, state);\n    }\n\n    // Single line comment\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)) {\n        floatLiteral = true;\n      }\n      if (stream.match(/^-?\\d+\\.\\d*/)) {\n        floatLiteral = true;\n      }\n      if (stream.match(/^-?\\.\\d+/)) {\n        floatLiteral = true;\n      }\n\n      if (floatLiteral) {\n        // prevent from getting extra . on 1..\n        if (stream.peek() == \".\"){\n          stream.backUp(1);\n        }\n        return \"number\";\n      }\n      // Integers\n      var intLiteral = false;\n      // Hex\n      if (stream.match(/^-?0x[0-9a-f]+/i)) {\n        intLiteral = true;\n      }\n      // Decimal\n      if (stream.match(/^-?[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n        intLiteral = true;\n      }\n      // Zero by itself with no other piece of number.\n      if (stream.match(/^-?0(?![\\dx])/i)) {\n        intLiteral = true;\n      }\n      if (intLiteral) {\n        return \"number\";\n      }\n    }\n\n    // Handle strings\n    if (stream.match(stringPrefixes)) {\n      state.tokenize = tokenFactory(stream.current(), false, \"string\");\n      return state.tokenize(stream, state);\n    }\n    // Handle regex literals\n    if (stream.match(regexPrefixes)) {\n      if (stream.current() != \"/\" || stream.match(/^.*\\//, false)) { // prevent highlight of division\n        state.tokenize = tokenFactory(stream.current(), true, \"string-2\");\n        return state.tokenize(stream, state);\n      } else {\n        stream.backUp(1);\n      }\n    }\n\n    // Handle operators and delimiters\n    if (stream.match(operators) || stream.match(wordOperators)) {\n      return \"operator\";\n    }\n    if (stream.match(delimiters)) {\n      return \"punctuation\";\n    }\n\n    if (stream.match(constants)) {\n      return \"atom\";\n    }\n\n    if (stream.match(keywords)) {\n      return \"keyword\";\n    }\n\n    if (stream.match(identifiers)) {\n      return \"variable\";\n    }\n\n    if (stream.match(properties)) {\n      return \"property\";\n    }\n\n    // Handle non-detected items\n    stream.next();\n    return ERRORCLASS;\n  }\n\n  function tokenFactory(delimiter, singleline, outclass) {\n    return function(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          }\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          outclass = ERRORCLASS;\n        } else {\n          state.tokenize = tokenBase;\n        }\n      }\n      return outclass;\n    };\n  }\n\n  function longComment(stream, state) {\n    while (!stream.eol()) {\n      stream.eatWhile(/[^#]/);\n      if (stream.match(\"###\")) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      stream.eatWhile(\"#\");\n    }\n    return \"comment\";\n  }\n\n  function indent(stream, state, type) {\n    type = type || \"coffee\";\n    var offset = 0, align = false, alignOffset = null;\n    for (var scope = state.scope; scope; scope = scope.prev) {\n      if (scope.type === \"coffee\" || scope.type == \"}\") {\n        offset = scope.offset + conf.indentUnit;\n        break;\n      }\n    }\n    if (type !== \"coffee\") {\n      align = null;\n      alignOffset = stream.column() + stream.current().length;\n    } else if (state.scope.align) {\n      state.scope.align = false;\n    }\n    state.scope = {\n      offset: offset,\n      type: type,\n      prev: state.scope,\n      align: align,\n      alignOffset: alignOffset\n    };\n  }\n\n  function dedent(stream, state) {\n    if (!state.scope.prev) return;\n    if (state.scope.type === \"coffee\") {\n      var _indent = stream.indentation();\n      var matched = false;\n      for (var scope = state.scope; scope; scope = scope.prev) {\n        if (_indent === scope.offset) {\n          matched = true;\n          break;\n        }\n      }\n      if (!matched) {\n        return true;\n      }\n      while (state.scope.prev && state.scope.offset !== _indent) {\n        state.scope = state.scope.prev;\n      }\n      return false;\n    } else {\n      state.scope = state.scope.prev;\n      return false;\n    }\n  }\n\n  function tokenLexer(stream, state) {\n    var style = state.tokenize(stream, state);\n    var current = stream.current();\n\n    // Handle \".\" connected identifiers\n    if (current === \".\") {\n      style = state.tokenize(stream, state);\n      current = stream.current();\n      if (/^\\.[\\w$]+$/.test(current)) {\n        return \"variable\";\n      } else {\n        return ERRORCLASS;\n      }\n    }\n\n    // Handle scope changes.\n    if (current === \"return\") {\n      state.dedent = true;\n    }\n    if (((current === \"->\" || current === \"=>\") &&\n         !state.lambda &&\n         !stream.peek())\n        || style === \"indent\") {\n      indent(stream, state);\n    }\n    var delimiter_index = \"[({\".indexOf(current);\n    if (delimiter_index !== -1) {\n      indent(stream, state, \"])}\".slice(delimiter_index, delimiter_index+1));\n    }\n    if (indentKeywords.exec(current)){\n      indent(stream, state);\n    }\n    if (current == \"then\"){\n      dedent(stream, state);\n    }\n\n\n    if (style === \"dedent\") {\n      if (dedent(stream, state)) {\n        return ERRORCLASS;\n      }\n    }\n    delimiter_index = \"])}\".indexOf(current);\n    if (delimiter_index !== -1) {\n      while (state.scope.type == \"coffee\" && state.scope.prev)\n        state.scope = state.scope.prev;\n      if (state.scope.type == current)\n        state.scope = state.scope.prev;\n    }\n    if (state.dedent && stream.eol()) {\n      if (state.scope.type == \"coffee\" && state.scope.prev)\n        state.scope = state.scope.prev;\n      state.dedent = false;\n    }\n\n    return style;\n  }\n\n  var external = {\n    startState: function(basecolumn) {\n      return {\n        tokenize: tokenBase,\n        scope: {offset:basecolumn || 0, type:\"coffee\", prev: null, align: false},\n        lastToken: null,\n        lambda: false,\n        dedent: 0\n      };\n    },\n\n    token: function(stream, state) {\n      var fillAlign = state.scope.align === null && state.scope;\n      if (fillAlign && stream.sol()) fillAlign.align = false;\n\n      var style = tokenLexer(stream, state);\n      if (fillAlign && style && style != \"comment\") fillAlign.align = true;\n\n      state.lastToken = {style:style, content: stream.current()};\n\n      if (stream.eol() && stream.lambda) {\n        state.lambda = false;\n      }\n\n      return style;\n    },\n\n    indent: function(state, text) {\n      if (state.tokenize != tokenBase) return 0;\n      var scope = state.scope;\n      var closer = text && \"])}\".indexOf(text.charAt(0)) > -1;\n      if (closer) while (scope.type == \"coffee\" && scope.prev) scope = scope.prev;\n      var closes = closer && scope.type === text.charAt(0);\n      if (scope.align)\n        return scope.alignOffset - (closes ? 1 : 0);\n      else\n        return (closes ? scope.prev : scope).offset;\n    },\n\n    lineComment: \"#\",\n    fold: \"indent\"\n  };\n  return external;\n});\n\nCodeMirror.defineMIME(\"text/x-coffeescript\", \"coffeescript\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/coffeescript/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: CoffeeScript mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"coffeescript.js\"></script>\n<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">CoffeeScript</a>\n  </ul>\n</div>\n\n<article>\n<h2>CoffeeScript mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# CoffeeScript mode for CodeMirror\n# Copyright (c) 2011 Jeff Pickhardt, released under\n# the MIT License.\n#\n# Modified from the Python CodeMirror mode, which also is\n# under the MIT License Copyright (c) 2010 Timothy Farrell.\n#\n# The following script, Underscore.coffee, is used to\n# demonstrate CoffeeScript mode for CodeMirror.\n#\n# To download CoffeeScript mode for CodeMirror, go to:\n# https://github.com/pickhardt/coffeescript-codemirror-mode\n\n# **Underscore.coffee\n# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**\n# Underscore is freely distributable under the terms of the\n# [MIT license](http://en.wikipedia.org/wiki/MIT_License).\n# Portions of Underscore are inspired by or borrowed from\n# [Prototype.js](http://prototypejs.org/api), Oliver Steele's\n# [Functional](http://osteele.com), and John Resig's\n# [Micro-Templating](http://ejohn.org).\n# For all details and documentation:\n# http://documentcloud.github.com/underscore/\n\n\n# Baseline setup\n# --------------\n\n# Establish the root object, `window` in the browser, or `global` on the server.\nroot = this\n\n\n# Save the previous value of the `_` variable.\npreviousUnderscore = root._\n\n### Multiline\n    comment\n###\n\n# Establish the object that gets thrown to break out of a loop iteration.\n# `StopIteration` is SOP on Mozilla.\nbreaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration\n\n\n#### Docco style single line comment (title)\n\n\n# Helper function to escape **RegExp** contents, because JS doesn't have one.\nescapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\\]\\/\\\\])/g, '\\\\$1')\n\n\n# Save bytes in the minified (but not gzipped) version:\nArrayProto = Array.prototype\nObjProto = Object.prototype\n\n\n# Create quick reference variables for speed access to core prototypes.\nslice = ArrayProto.slice\nunshift = ArrayProto.unshift\ntoString = ObjProto.toString\nhasOwnProperty = ObjProto.hasOwnProperty\npropertyIsEnumerable = ObjProto.propertyIsEnumerable\n\n\n# All **ECMA5** native implementations we hope to use are declared here.\nnativeForEach = ArrayProto.forEach\nnativeMap = ArrayProto.map\nnativeReduce = ArrayProto.reduce\nnativeReduceRight = ArrayProto.reduceRight\nnativeFilter = ArrayProto.filter\nnativeEvery = ArrayProto.every\nnativeSome = ArrayProto.some\nnativeIndexOf = ArrayProto.indexOf\nnativeLastIndexOf = ArrayProto.lastIndexOf\nnativeIsArray = Array.isArray\nnativeKeys = Object.keys\n\n\n# Create a safe reference to the Underscore object for use below.\n_ = (obj) -> new wrapper(obj)\n\n\n# Export the Underscore object for **CommonJS**.\nif typeof(exports) != 'undefined' then exports._ = _\n\n\n# Export Underscore to global scope.\nroot._ = _\n\n\n# Current version.\n_.VERSION = '1.1.0'\n\n\n# Collection Functions\n# --------------------\n\n# The cornerstone, an **each** implementation.\n# Handles objects implementing **forEach**, arrays, and raw objects.\n_.each = (obj, iterator, context) ->\n  try\n    if nativeForEach and obj.forEach is nativeForEach\n      obj.forEach iterator, context\n    else if _.isNumber obj.length\n      iterator.call context, obj[i], i, obj for i in [0...obj.length]\n    else\n      iterator.call context, val, key, obj for own key, val of obj\n  catch e\n    throw e if e isnt breaker\n  obj\n\n\n# Return the results of applying the iterator to each element. Use JavaScript\n# 1.6's version of **map**, if possible.\n_.map = (obj, iterator, context) ->\n  return obj.map(iterator, context) if nativeMap and obj.map is nativeMap\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push iterator.call context, value, index, list\n  results\n\n\n# **Reduce** builds up a single result from a list of values. Also known as\n# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.\n_.reduce = (obj, iterator, memo, context) ->\n  if nativeReduce and obj.reduce is nativeReduce\n    iterator = _.bind iterator, context if context\n    return obj.reduce iterator, memo\n  _.each obj, (value, index, list) ->\n    memo = iterator.call context, memo, value, index, list\n  memo\n\n\n# The right-associative version of **reduce**, also known as **foldr**. Uses\n# JavaScript 1.8's version of **reduceRight**, if available.\n_.reduceRight = (obj, iterator, memo, context) ->\n  if nativeReduceRight and obj.reduceRight is nativeReduceRight\n    iterator = _.bind iterator, context if context\n    return obj.reduceRight iterator, memo\n  reversed = _.clone(_.toArray(obj)).reverse()\n  _.reduce reversed, iterator, memo, context\n\n\n# Return the first value which passes a truth test.\n_.detect = (obj, iterator, context) ->\n  result = null\n  _.each obj, (value, index, list) ->\n    if iterator.call context, value, index, list\n      result = value\n      _.breakLoop()\n  result\n\n\n# Return all the elements that pass a truth test. Use JavaScript 1.6's\n# **filter**, if it exists.\n_.filter = (obj, iterator, context) ->\n  return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push value if iterator.call context, value, index, list\n  results\n\n\n# Return all the elements for which a truth test fails.\n_.reject = (obj, iterator, context) ->\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push value if not iterator.call context, value, index, list\n  results\n\n\n# Determine whether all of the elements match a truth test. Delegate to\n# JavaScript 1.6's **every**, if it is present.\n_.every = (obj, iterator, context) ->\n  iterator ||= _.identity\n  return obj.every iterator, context if nativeEvery and obj.every is nativeEvery\n  result = true\n  _.each obj, (value, index, list) ->\n    _.breakLoop() unless (result = result and iterator.call(context, value, index, list))\n  result\n\n\n# Determine if at least one element in the object matches a truth test. Use\n# JavaScript 1.6's **some**, if it exists.\n_.some = (obj, iterator, context) ->\n  iterator ||= _.identity\n  return obj.some iterator, context if nativeSome and obj.some is nativeSome\n  result = false\n  _.each obj, (value, index, list) ->\n    _.breakLoop() if (result = iterator.call(context, value, index, list))\n  result\n\n\n# Determine if a given value is included in the array or object,\n# based on `===`.\n_.include = (obj, target) ->\n  return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf\n  return true for own key, val of obj when val is target\n  false\n\n\n# Invoke a method with arguments on every item in a collection.\n_.invoke = (obj, method) ->\n  args = _.rest arguments, 2\n  (if method then val[method] else val).apply(val, args) for val in obj\n\n\n# Convenience version of a common use case of **map**: fetching a property.\n_.pluck = (obj, key) ->\n  _.map(obj, (val) -> val[key])\n\n\n# Return the maximum item or (item-based computation).\n_.max = (obj, iterator, context) ->\n  return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)\n  result = computed: -Infinity\n  _.each obj, (value, index, list) ->\n    computed = if iterator then iterator.call(context, value, index, list) else value\n    computed >= result.computed and (result = {value: value, computed: computed})\n  result.value\n\n\n# Return the minimum element (or element-based computation).\n_.min = (obj, iterator, context) ->\n  return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)\n  result = computed: Infinity\n  _.each obj, (value, index, list) ->\n    computed = if iterator then iterator.call(context, value, index, list) else value\n    computed < result.computed and (result = {value: value, computed: computed})\n  result.value\n\n\n# Sort the object's values by a criterion produced by an iterator.\n_.sortBy = (obj, iterator, context) ->\n  _.pluck(((_.map obj, (value, index, list) ->\n    {value: value, criteria: iterator.call(context, value, index, list)}\n  ).sort((left, right) ->\n    a = left.criteria; b = right.criteria\n    if a < b then -1 else if a > b then 1 else 0\n  )), 'value')\n\n\n# Use a comparator function to figure out at what index an object should\n# be inserted so as to maintain order. Uses binary search.\n_.sortedIndex = (array, obj, iterator) ->\n  iterator ||= _.identity\n  low = 0\n  high = array.length\n  while low < high\n    mid = (low + high) >> 1\n    if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid\n  low\n\n\n# Convert anything iterable into a real, live array.\n_.toArray = (iterable) ->\n  return [] if (!iterable)\n  return iterable.toArray() if (iterable.toArray)\n  return iterable if (_.isArray(iterable))\n  return slice.call(iterable) if (_.isArguments(iterable))\n  _.values(iterable)\n\n\n# Return the number of elements in an object.\n_.size = (obj) -> _.toArray(obj).length\n\n\n# Array Functions\n# ---------------\n\n# Get the first element of an array. Passing `n` will return the first N\n# values in the array. Aliased as **head**. The `guard` check allows it to work\n# with **map**.\n_.first = (array, n, guard) ->\n  if n and not guard then slice.call(array, 0, n) else array[0]\n\n\n# Returns everything but the first entry of the array. Aliased as **tail**.\n# Especially useful on the arguments object. Passing an `index` will return\n# the rest of the values in the array from that index onward. The `guard`\n# check allows it to work with **map**.\n_.rest = (array, index, guard) ->\n  slice.call(array, if _.isUndefined(index) or guard then 1 else index)\n\n\n# Get the last element of an array.\n_.last = (array) -> array[array.length - 1]\n\n\n# Trim out all falsy values from an array.\n_.compact = (array) -> item for item in array when item\n\n\n# Return a completely flattened version of an array.\n_.flatten = (array) ->\n  _.reduce array, (memo, value) ->\n    return memo.concat(_.flatten(value)) if _.isArray value\n    memo.push value\n    memo\n  , []\n\n\n# Return a version of the array that does not contain the specified value(s).\n_.without = (array) ->\n  values = _.rest arguments\n  val for val in _.toArray(array) when not _.include values, val\n\n\n# Produce a duplicate-free version of the array. If the array has already\n# been sorted, you have the option of using a faster algorithm.\n_.uniq = (array, isSorted) ->\n  memo = []\n  for el, i in _.toArray array\n    memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))\n  memo\n\n\n# Produce an array that contains every item shared between all the\n# passed-in arrays.\n_.intersect = (array) ->\n  rest = _.rest arguments\n  _.select _.uniq(array), (item) ->\n    _.all rest, (other) ->\n      _.indexOf(other, item) >= 0\n\n\n# Zip together multiple lists into a single array -- elements that share\n# an index go together.\n_.zip = ->\n  length = _.max _.pluck arguments, 'length'\n  results = new Array length\n  for i in [0...length]\n    results[i] = _.pluck arguments, String i\n  results\n\n\n# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),\n# we need this function. Return the position of the first occurrence of an\n# item in an array, or -1 if the item is not included in the array.\n_.indexOf = (array, item) ->\n  return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf\n  i = 0; l = array.length\n  while l - i\n    if array[i] is item then return i else i++\n  -1\n\n\n# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,\n# if possible.\n_.lastIndexOf = (array, item) ->\n  return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf\n  i = array.length\n  while i\n    if array[i] is item then return i else i--\n  -1\n\n\n# Generate an integer Array containing an arithmetic progression. A port of\n# [the native Python **range** function](http://docs.python.org/library/functions.html#range).\n_.range = (start, stop, step) ->\n  a = arguments\n  solo = a.length <= 1\n  i = start = if solo then 0 else a[0]\n  stop = if solo then a[0] else a[1]\n  step = a[2] or 1\n  len = Math.ceil((stop - start) / step)\n  return [] if len <= 0\n  range = new Array len\n  idx = 0\n  loop\n    return range if (if step > 0 then i - stop else stop - i) >= 0\n    range[idx] = i\n    idx++\n    i+= step\n\n\n# Function Functions\n# ------------------\n\n# Create a function bound to a given object (assigning `this`, and arguments,\n# optionally). Binding with arguments is also known as **curry**.\n_.bind = (func, obj) ->\n  args = _.rest arguments, 2\n  -> func.apply obj or root, args.concat arguments\n\n\n# Bind all of an object's methods to that object. Useful for ensuring that\n# all callbacks defined on an object belong to it.\n_.bindAll = (obj) ->\n  funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)\n  _.each funcs, (f) -> obj[f] = _.bind obj[f], obj\n  obj\n\n\n# Delays a function for the given number of milliseconds, and then calls\n# it with the arguments supplied.\n_.delay = (func, wait) ->\n  args = _.rest arguments, 2\n  setTimeout((-> func.apply(func, args)), wait)\n\n\n# Memoize an expensive function by storing its results.\n_.memoize = (func, hasher) ->\n  memo = {}\n  hasher or= _.identity\n  ->\n    key = hasher.apply this, arguments\n    return memo[key] if key of memo\n    memo[key] = func.apply this, arguments\n\n\n# Defers a function, scheduling it to run after the current call stack has\n# cleared.\n_.defer = (func) ->\n  _.delay.apply _, [func, 1].concat _.rest arguments\n\n\n# Returns the first function passed as an argument to the second,\n# allowing you to adjust arguments, run code before and after, and\n# conditionally execute the original function.\n_.wrap = (func, wrapper) ->\n  -> wrapper.apply wrapper, [func].concat arguments\n\n\n# Returns a function that is the composition of a list of functions, each\n# consuming the return value of the function that follows.\n_.compose = ->\n  funcs = arguments\n  ->\n    args = arguments\n    for i in [funcs.length - 1..0] by -1\n      args = [funcs[i].apply(this, args)]\n    args[0]\n\n\n# Object Functions\n# ----------------\n\n# Retrieve the names of an object's properties.\n_.keys = nativeKeys or (obj) ->\n  return _.range 0, obj.length if _.isArray(obj)\n  key for key, val of obj\n\n\n# Retrieve the values of an object's properties.\n_.values = (obj) ->\n  _.map obj, _.identity\n\n\n# Return a sorted list of the function names available in Underscore.\n_.functions = (obj) ->\n  _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()\n\n\n# Extend a given object with all of the properties in a source object.\n_.extend = (obj) ->\n  for source in _.rest(arguments)\n    obj[key] = val for key, val of source\n  obj\n\n\n# Create a (shallow-cloned) duplicate of an object.\n_.clone = (obj) ->\n  return obj.slice 0 if _.isArray obj\n  _.extend {}, obj\n\n\n# Invokes interceptor with the obj, and then returns obj.\n# The primary purpose of this method is to \"tap into\" a method chain,\n# in order to perform operations on intermediate results within\n the chain.\n_.tap = (obj, interceptor) ->\n  interceptor obj\n  obj\n\n\n# Perform a deep comparison to check if two objects are equal.\n_.isEqual = (a, b) ->\n  # Check object identity.\n  return true if a is b\n  # Different types?\n  atype = typeof(a); btype = typeof(b)\n  return false if atype isnt btype\n  # Basic equality test (watch out for coercions).\n  return true if `a == b`\n  # One is falsy and the other truthy.\n  return false if (!a and b) or (a and !b)\n  # One of them implements an `isEqual()`?\n  return a.isEqual(b) if a.isEqual\n  # Check dates' integer values.\n  return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)\n  # Both are NaN?\n  return false if _.isNaN(a) and _.isNaN(b)\n  # Compare regular expressions.\n  if _.isRegExp(a) and _.isRegExp(b)\n    return a.source is b.source and\n           a.global is b.global and\n           a.ignoreCase is b.ignoreCase and\n           a.multiline is b.multiline\n  # If a is not an object by this point, we can't handle it.\n  return false if atype isnt 'object'\n  # Check for different array lengths before comparing contents.\n  return false if a.length and (a.length isnt b.length)\n  # Nothing else worked, deep compare the contents.\n  aKeys = _.keys(a); bKeys = _.keys(b)\n  # Different object sizes?\n  return false if aKeys.length isnt bKeys.length\n  # Recursive comparison of contents.\n  return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])\n  true\n\n\n# Is a given array or object empty?\n_.isEmpty = (obj) ->\n  return obj.length is 0 if _.isArray(obj) or _.isString(obj)\n  return false for own key of obj\n  true\n\n\n# Is a given value a DOM element?\n_.isElement = (obj) -> obj and obj.nodeType is 1\n\n\n# Is a given value an array?\n_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)\n\n\n# Is a given variable an arguments object?\n_.isArguments = (obj) -> obj and obj.callee\n\n\n# Is the given value a function?\n_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)\n\n\n# Is the given value a string?\n_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))\n\n\n# Is a given value a number?\n_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'\n\n\n# Is a given value a boolean?\n_.isBoolean = (obj) -> obj is true or obj is false\n\n\n# Is a given value a Date?\n_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)\n\n\n# Is the given value a regular expression?\n_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))\n\n\n# Is the given value NaN -- this one is interesting. `NaN != NaN`, and\n# `isNaN(undefined) == true`, so we make sure it's a number first.\n_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)\n\n\n# Is a given value equal to null?\n_.isNull = (obj) -> obj is null\n\n\n# Is a given variable undefined?\n_.isUndefined = (obj) -> typeof obj is 'undefined'\n\n\n# Utility Functions\n# -----------------\n\n# Run Underscore.js in noConflict mode, returning the `_` variable to its\n# previous owner. Returns a reference to the Underscore object.\n_.noConflict = ->\n  root._ = previousUnderscore\n  this\n\n\n# Keep the identity function around for default iterators.\n_.identity = (value) -> value\n\n\n# Run a function `n` times.\n_.times = (n, iterator, context) ->\n  iterator.call context, i for i in [0...n]\n\n\n# Break out of the middle of an iteration.\n_.breakLoop = -> throw breaker\n\n\n# Add your own custom functions to the Underscore object, ensuring that\n# they're correctly added to the OOP wrapper as well.\n_.mixin = (obj) ->\n  for name in _.functions(obj)\n    addToWrapper name, _[name] = obj[name]\n\n\n# Generate a unique integer id (unique within the entire client session).\n# Useful for temporary DOM ids.\nidCounter = 0\n_.uniqueId = (prefix) ->\n  (prefix or '') + idCounter++\n\n\n# By default, Underscore uses **ERB**-style template delimiters, change the\n# following template settings to use alternative delimiters.\n_.templateSettings = {\n  start: '<%'\n  end: '%>'\n  interpolate: /<%=(.+?)%>/g\n}\n\n\n# JavaScript templating a-la **ERB**, pilfered from John Resig's\n# *Secrets of the JavaScript Ninja*, page 83.\n# Single-quote fix from Rick Strahl.\n# With alterations for arbitrary delimiters, and to preserve whitespace.\n_.template = (str, data) ->\n  c = _.templateSettings\n  endMatch = new RegExp(\"'(?=[^\"+c.end.substr(0, 1)+\"]*\"+escapeRegExp(c.end)+\")\",\"g\")\n  fn = new Function 'obj',\n    'var p=[],print=function(){p.push.apply(p,arguments);};' +\n    'with(obj||{}){p.push(\\'' +\n    str.replace(/\\r/g, '\\\\r')\n       .replace(/\\n/g, '\\\\n')\n       .replace(/\\t/g, '\\\\t')\n       .replace(endMatch,\"���\")\n       .split(\"'\").join(\"\\\\'\")\n       .split(\"���\").join(\"'\")\n       .replace(c.interpolate, \"',$1,'\")\n       .split(c.start).join(\"');\")\n       .split(c.end).join(\"p.push('\") +\n       \"');}return p.join('');\"\n  if data then fn(data) else fn\n\n\n# Aliases\n# -------\n\n_.forEach = _.each\n_.foldl = _.inject = _.reduce\n_.foldr = _.reduceRight\n_.select = _.filter\n_.all = _.every\n_.any = _.some\n_.contains = _.include\n_.head = _.first\n_.tail = _.rest\n_.methods = _.functions\n\n\n# Setup the OOP Wrapper\n# ---------------------\n\n# If Underscore is called as a function, it returns a wrapped object that\n# can be used OO-style. This wrapper holds altered versions of all the\n# underscore functions. Wrapped objects may be chained.\nwrapper = (obj) ->\n  this._wrapped = obj\n  this\n\n\n# Helper function to continue chaining intermediate results.\nresult = (obj, chain) ->\n  if chain then _(obj).chain() else obj\n\n\n# A method to easily add functions to the OOP wrapper.\naddToWrapper = (name, func) ->\n  wrapper.prototype[name] = ->\n    args = _.toArray arguments\n    unshift.call args, this._wrapped\n    result func.apply(_, args), this._chain\n\n\n# Add all ofthe Underscore functions to the wrapper object.\n_.mixin _\n\n\n# Add all mutator Array functions to the wrapper.\n_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->\n  method = Array.prototype[name]\n  wrapper.prototype[name] = ->\n    method.apply(this._wrapped, arguments)\n    result(this._wrapped, this._chain)\n\n\n# Add all accessor Array functions to the wrapper.\n_.each ['concat', 'join', 'slice'], (name) ->\n  method = Array.prototype[name]\n  wrapper.prototype[name] = ->\n    result(method.apply(this._wrapped, arguments), this._chain)\n\n\n# Start chaining a wrapped Underscore object.\nwrapper::chain = ->\n  this._chain = true\n  this\n\n\n# Extracts the result from a wrapped and chained object.\nwrapper::value = -> this._wrapped\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>\n\n    <p>The CoffeeScript mode was written by Jeff Pickhardt.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/commonlisp/commonlisp.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(\"commonlisp\", function (config) {\n  var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;\n  var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;\n  var numLiteral = /^(?:[+\\-]?(?:\\d+|\\d*\\.\\d+)(?:[efd][+\\-]?\\d+)?|[+\\-]?\\d+(?:\\/[+\\-]?\\d+)?|#b[+\\-]?[01]+|#o[+\\-]?[0-7]+|#x[+\\-]?[\\da-f]+)/;\n  var symbol = /[^\\s'`,@()\\[\\]\";]/;\n  var type;\n\n  function readSym(stream) {\n    var ch;\n    while (ch = stream.next()) {\n      if (ch == \"\\\\\") stream.next();\n      else if (!symbol.test(ch)) { stream.backUp(1); break; }\n    }\n    return stream.current();\n  }\n\n  function base(stream, state) {\n    if (stream.eatSpace()) {type = \"ws\"; return null;}\n    if (stream.match(numLiteral)) return \"number\";\n    var ch = stream.next();\n    if (ch == \"\\\\\") ch = stream.next();\n\n    if (ch == '\"') return (state.tokenize = inString)(stream, state);\n    else if (ch == \"(\") { type = \"open\"; return \"bracket\"; }\n    else if (ch == \")\" || ch == \"]\") { type = \"close\"; return \"bracket\"; }\n    else if (ch == \";\") { stream.skipToEnd(); type = \"ws\"; return \"comment\"; }\n    else if (/['`,@]/.test(ch)) return null;\n    else if (ch == \"|\") {\n      if (stream.skipTo(\"|\")) { stream.next(); return \"symbol\"; }\n      else { stream.skipToEnd(); return \"error\"; }\n    } else if (ch == \"#\") {\n      var ch = stream.next();\n      if (ch == \"[\") { type = \"open\"; return \"bracket\"; }\n      else if (/[+\\-=\\.']/.test(ch)) return null;\n      else if (/\\d/.test(ch) && stream.match(/^\\d*#/)) return null;\n      else if (ch == \"|\") return (state.tokenize = inComment)(stream, state);\n      else if (ch == \":\") { readSym(stream); return \"meta\"; }\n      else return \"error\";\n    } else {\n      var name = readSym(stream);\n      if (name == \".\") return null;\n      type = \"symbol\";\n      if (name == \"nil\" || name == \"t\" || name.charAt(0) == \":\") return \"atom\";\n      if (state.lastType == \"open\" && (specialForm.test(name) || assumeBody.test(name))) return \"keyword\";\n      if (name.charAt(0) == \"&\") return \"variable-2\";\n      return \"variable\";\n    }\n  }\n\n  function inString(stream, state) {\n    var escaped = false, next;\n    while (next = stream.next()) {\n      if (next == '\"' && !escaped) { state.tokenize = base; break; }\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return \"string\";\n  }\n\n  function inComment(stream, state) {\n    var next, last;\n    while (next = stream.next()) {\n      if (next == \"#\" && last == \"|\") { state.tokenize = base; break; }\n      last = next;\n    }\n    type = \"ws\";\n    return \"comment\";\n  }\n\n  return {\n    startState: function () {\n      return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};\n    },\n\n    token: function (stream, state) {\n      if (stream.sol() && typeof state.ctx.indentTo != \"number\")\n        state.ctx.indentTo = state.ctx.start + 1;\n\n      type = null;\n      var style = state.tokenize(stream, state);\n      if (type != \"ws\") {\n        if (state.ctx.indentTo == null) {\n          if (type == \"symbol\" && assumeBody.test(stream.current()))\n            state.ctx.indentTo = state.ctx.start + config.indentUnit;\n          else\n            state.ctx.indentTo = \"next\";\n        } else if (state.ctx.indentTo == \"next\") {\n          state.ctx.indentTo = stream.column();\n        }\n        state.lastType = type;\n      }\n      if (type == \"open\") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};\n      else if (type == \"close\") state.ctx = state.ctx.prev || state.ctx;\n      return style;\n    },\n\n    indent: function (state, _textAfter) {\n      var i = state.ctx.indentTo;\n      return typeof i == \"number\" ? i : state.ctx.start + 1;\n    },\n\n    lineComment: \";;\",\n    blockCommentStart: \"#|\",\n    blockCommentEnd: \"|#\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-common-lisp\", \"commonlisp\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/commonlisp/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Common Lisp mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"commonlisp.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Common Lisp</a>\n  </ul>\n</div>\n\n<article>\n<h2>Common Lisp mode</h2>\n<form><textarea id=\"code\" name=\"code\">(in-package :cl-postgres)\n\n;; These are used to synthesize reader and writer names for integer\n;; reading/writing functions when the amount of bytes and the\n;; signedness is known. Both the macro that creates the functions and\n;; some macros that use them create names this way.\n(eval-when (:compile-toplevel :load-toplevel :execute)\n  (defun integer-reader-name (bytes signed)\n    (intern (with-standard-io-syntax\n              (format nil \"~a~a~a~a\" '#:read- (if signed \"\" '#:u) '#:int bytes))))\n  (defun integer-writer-name (bytes signed)\n    (intern (with-standard-io-syntax\n              (format nil \"~a~a~a~a\" '#:write- (if signed \"\" '#:u) '#:int bytes)))))\n\n(defmacro integer-reader (bytes)\n  \"Create a function to read integers from a binary stream.\"\n  (let ((bits (* bytes 8)))\n    (labels ((return-form (signed)\n               (if signed\n                   `(if (logbitp ,(1- bits) result)\n                        (dpb result (byte ,(1- bits) 0) -1)\n                        result)\n                   `result))\n             (generate-reader (signed)\n               `(defun ,(integer-reader-name bytes signed) (socket)\n                  (declare (type stream socket)\n                           #.*optimize*)\n                  ,(if (= bytes 1)\n                       `(let ((result (the (unsigned-byte 8) (read-byte socket))))\n                          (declare (type (unsigned-byte 8) result))\n                          ,(return-form signed))\n                       `(let ((result 0))\n                          (declare (type (unsigned-byte ,bits) result))\n                          ,@(loop :for byte :from (1- bytes) :downto 0\n                                   :collect `(setf (ldb (byte 8 ,(* 8 byte)) result)\n                                                   (the (unsigned-byte 8) (read-byte socket))))\n                          ,(return-form signed))))))\n      `(progn\n;; This causes weird errors on SBCL in some circumstances. Disabled for now.\n;;         (declaim (inline ,(integer-reader-name bytes t)\n;;                          ,(integer-reader-name bytes nil)))\n         (declaim (ftype (function (t) (signed-byte ,bits))\n                         ,(integer-reader-name bytes t)))\n         ,(generate-reader t)\n         (declaim (ftype (function (t) (unsigned-byte ,bits))\n                         ,(integer-reader-name bytes nil)))\n         ,(generate-reader nil)))))\n\n(defmacro integer-writer (bytes)\n  \"Create a function to write integers to a binary stream.\"\n  (let ((bits (* 8 bytes)))\n    `(progn\n      (declaim (inline ,(integer-writer-name bytes t)\n                       ,(integer-writer-name bytes nil)))\n      (defun ,(integer-writer-name bytes nil) (socket value)\n        (declare (type stream socket)\n                 (type (unsigned-byte ,bits) value)\n                 #.*optimize*)\n        ,@(if (= bytes 1)\n              `((write-byte value socket))\n              (loop :for byte :from (1- bytes) :downto 0\n                    :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)\n                               socket)))\n        (values))\n      (defun ,(integer-writer-name bytes t) (socket value)\n        (declare (type stream socket)\n                 (type (signed-byte ,bits) value)\n                 #.*optimize*)\n        ,@(if (= bytes 1)\n              `((write-byte (ldb (byte 8 0) value) socket))\n              (loop :for byte :from (1- bytes) :downto 0\n                    :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)\n                               socket)))\n        (values)))))\n\n;; All the instances of the above that we need.\n\n(integer-reader 1)\n(integer-reader 2)\n(integer-reader 4)\n(integer-reader 8)\n\n(integer-writer 1)\n(integer-writer 2)\n(integer-writer 4)\n\n(defun write-bytes (socket bytes)\n  \"Write a byte-array to a stream.\"\n  (declare (type stream socket)\n           (type (simple-array (unsigned-byte 8)) bytes)\n           #.*optimize*)\n  (write-sequence bytes socket))\n\n(defun write-str (socket string)\n  \"Write a null-terminated string to a stream \\(encoding it when UTF-8\nsupport is enabled.).\"\n  (declare (type stream socket)\n           (type string string)\n           #.*optimize*)\n  (enc-write-string string socket)\n  (write-uint1 socket 0))\n\n(declaim (ftype (function (t unsigned-byte)\n                          (simple-array (unsigned-byte 8) (*)))\n                read-bytes))\n(defun read-bytes (socket length)\n  \"Read a byte array of the given length from a stream.\"\n  (declare (type stream socket)\n           (type fixnum length)\n           #.*optimize*)\n  (let ((result (make-array length :element-type '(unsigned-byte 8))))\n    (read-sequence result socket)\n    result))\n\n(declaim (ftype (function (t) string) read-str))\n(defun read-str (socket)\n  \"Read a null-terminated string from a stream. Takes care of encoding\nwhen UTF-8 support is enabled.\"\n  (declare (type stream socket)\n           #.*optimize*)\n  (enc-read-string socket :null-terminated t))\n\n(defun skip-bytes (socket length)\n  \"Skip a given number of bytes in a binary stream.\"\n  (declare (type stream socket)\n           (type (unsigned-byte 32) length)\n           #.*optimize*)\n  (dotimes (i length)\n    (read-byte socket)))\n\n(defun skip-str (socket)\n  \"Skip a null-terminated string.\"\n  (declare (type stream socket)\n           #.*optimize*)\n  (loop :for char :of-type fixnum = (read-byte socket)\n        :until (zerop char)))\n\n(defun ensure-socket-is-closed (socket &amp;key abort)\n  (when (open-stream-p socket)\n    (handler-case\n        (close socket :abort abort)\n      (error (error)\n        (warn \"Ignoring the error which happened while trying to close PostgreSQL socket: ~A\" error)))))\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {lineNumbers: true});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-common-lisp</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/css.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(\"css\", function(config, parserConfig) {\n  if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode(\"text/css\");\n\n  var indentUnit = config.indentUnit,\n      tokenHooks = parserConfig.tokenHooks,\n      mediaTypes = parserConfig.mediaTypes || {},\n      mediaFeatures = parserConfig.mediaFeatures || {},\n      propertyKeywords = parserConfig.propertyKeywords || {},\n      nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},\n      colorKeywords = parserConfig.colorKeywords || {},\n      valueKeywords = parserConfig.valueKeywords || {},\n      fontProperties = parserConfig.fontProperties || {},\n      allowNested = parserConfig.allowNested;\n\n  var type, override;\n  function ret(style, tp) { type = tp; return style; }\n\n  // Tokenizers\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (tokenHooks[ch]) {\n      var result = tokenHooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == \"@\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"def\", stream.current());\n    } else if (ch == \"=\" || (ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) {\n      return ret(null, \"compare\");\n    } else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    } else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    } else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    } else if (/\\d/.test(ch) || ch == \".\" && stream.eat(/\\d/)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    } else if (ch === \"-\") {\n      if (/[\\d.]/.test(stream.peek())) {\n        stream.eatWhile(/[\\w.%]/);\n        return ret(\"number\", \"unit\");\n      } else if (stream.match(/^\\w+-/)) {\n        return ret(\"meta\", \"meta\");\n      }\n    } else if (/[,+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    } else if (ch == \".\" && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {\n      return ret(\"qualifier\", \"qualifier\");\n    } else if (/[:;{}\\[\\]\\(\\)]/.test(ch)) {\n      return ret(null, ch);\n    } else if (ch == \"u\" && stream.match(\"rl(\")) {\n      stream.backUp(1);\n      state.tokenize = tokenParenthesized;\n      return ret(\"property\", \"word\");\n    } else if (/[\\w\\\\\\-]/.test(ch)) {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"property\", \"word\");\n    } else {\n      return ret(null, null);\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          if (quote == \")\") stream.backUp(1);\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (ch == quote || !escaped && quote != \")\") state.tokenize = null;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function tokenParenthesized(stream, state) {\n    stream.next(); // Must be '('\n    if (!stream.match(/\\s*[\\\"\\')]/, false))\n      state.tokenize = tokenString(\")\");\n    else\n      state.tokenize = null;\n    return ret(null, \"(\");\n  }\n\n  // Context management\n\n  function Context(type, indent, prev) {\n    this.type = type;\n    this.indent = indent;\n    this.prev = prev;\n  }\n\n  function pushContext(state, stream, type) {\n    state.context = new Context(type, stream.indentation() + indentUnit, state.context);\n    return type;\n  }\n\n  function popContext(state) {\n    state.context = state.context.prev;\n    return state.context.type;\n  }\n\n  function pass(type, stream, state) {\n    return states[state.context.type](type, stream, state);\n  }\n  function popAndPass(type, stream, state, n) {\n    for (var i = n || 1; i > 0; i--)\n      state.context = state.context.prev;\n    return pass(type, stream, state);\n  }\n\n  // Parser\n\n  function wordAsValue(stream) {\n    var word = stream.current().toLowerCase();\n    if (valueKeywords.hasOwnProperty(word))\n      override = \"atom\";\n    else if (colorKeywords.hasOwnProperty(word))\n      override = \"keyword\";\n    else\n      override = \"variable\";\n  }\n\n  var states = {};\n\n  states.top = function(type, stream, state) {\n    if (type == \"{\") {\n      return pushContext(state, stream, \"block\");\n    } else if (type == \"}\" && state.context.prev) {\n      return popContext(state);\n    } else if (type == \"@media\") {\n      return pushContext(state, stream, \"media\");\n    } else if (type == \"@font-face\") {\n      return \"font_face_before\";\n    } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {\n      return \"keyframes\";\n    } else if (type && type.charAt(0) == \"@\") {\n      return pushContext(state, stream, \"at\");\n    } else if (type == \"hash\") {\n      override = \"builtin\";\n    } else if (type == \"word\") {\n      override = \"tag\";\n    } else if (type == \"variable-definition\") {\n      return \"maybeprop\";\n    } else if (type == \"interpolation\") {\n      return pushContext(state, stream, \"interpolation\");\n    } else if (type == \":\") {\n      return \"pseudo\";\n    } else if (allowNested && type == \"(\") {\n      return pushContext(state, stream, \"parens\");\n    }\n    return state.context.type;\n  };\n\n  states.block = function(type, stream, state) {\n    if (type == \"word\") {\n      var word = stream.current().toLowerCase();\n      if (propertyKeywords.hasOwnProperty(word)) {\n        override = \"property\";\n        return \"maybeprop\";\n      } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {\n        override = \"string-2\";\n        return \"maybeprop\";\n      } else if (allowNested) {\n        override = stream.match(/^\\s*:(?:\\s|$)/, false) ? \"property\" : \"tag\";\n        return \"block\";\n      } else {\n        override += \" error\";\n        return \"maybeprop\";\n      }\n    } else if (type == \"meta\") {\n      return \"block\";\n    } else if (!allowNested && (type == \"hash\" || type == \"qualifier\")) {\n      override = \"error\";\n      return \"block\";\n    } else {\n      return states.top(type, stream, state);\n    }\n  };\n\n  states.maybeprop = function(type, stream, state) {\n    if (type == \":\") return pushContext(state, stream, \"prop\");\n    return pass(type, stream, state);\n  };\n\n  states.prop = function(type, stream, state) {\n    if (type == \";\") return popContext(state);\n    if (type == \"{\" && allowNested) return pushContext(state, stream, \"propBlock\");\n    if (type == \"}\" || type == \"{\") return popAndPass(type, stream, state);\n    if (type == \"(\") return pushContext(state, stream, \"parens\");\n\n    if (type == \"hash\" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {\n      override += \" error\";\n    } else if (type == \"word\") {\n      wordAsValue(stream);\n    } else if (type == \"interpolation\") {\n      return pushContext(state, stream, \"interpolation\");\n    }\n    return \"prop\";\n  };\n\n  states.propBlock = function(type, _stream, state) {\n    if (type == \"}\") return popContext(state);\n    if (type == \"word\") { override = \"property\"; return \"maybeprop\"; }\n    return state.context.type;\n  };\n\n  states.parens = function(type, stream, state) {\n    if (type == \"{\" || type == \"}\") return popAndPass(type, stream, state);\n    if (type == \")\") return popContext(state);\n    if (type == \"(\") return pushContext(state, stream, \"parens\");\n    if (type == \"word\") wordAsValue(stream);\n    return \"parens\";\n  };\n\n  states.pseudo = function(type, stream, state) {\n    if (type == \"word\") {\n      override = \"variable-3\";\n      return state.context.type;\n    }\n    return pass(type, stream, state);\n  };\n\n  states.media = function(type, stream, state) {\n    if (type == \"(\") return pushContext(state, stream, \"media_parens\");\n    if (type == \"}\") return popAndPass(type, stream, state);\n    if (type == \"{\") return popContext(state) && pushContext(state, stream, allowNested ? \"block\" : \"top\");\n\n    if (type == \"word\") {\n      var word = stream.current().toLowerCase();\n      if (word == \"only\" || word == \"not\" || word == \"and\")\n        override = \"keyword\";\n      else if (mediaTypes.hasOwnProperty(word))\n        override = \"attribute\";\n      else if (mediaFeatures.hasOwnProperty(word))\n        override = \"property\";\n      else\n        override = \"error\";\n    }\n    return state.context.type;\n  };\n\n  states.media_parens = function(type, stream, state) {\n    if (type == \")\") return popContext(state);\n    if (type == \"{\" || type == \"}\") return popAndPass(type, stream, state, 2);\n    return states.media(type, stream, state);\n  };\n\n  states.font_face_before = function(type, stream, state) {\n    if (type == \"{\")\n      return pushContext(state, stream, \"font_face\");\n    return pass(type, stream, state);\n  };\n\n  states.font_face = function(type, stream, state) {\n    if (type == \"}\") return popContext(state);\n    if (type == \"word\") {\n      if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))\n        override = \"error\";\n      else\n        override = \"property\";\n      return \"maybeprop\";\n    }\n    return \"font_face\";\n  };\n\n  states.keyframes = function(type, stream, state) {\n    if (type == \"word\") { override = \"variable\"; return \"keyframes\"; }\n    if (type == \"{\") return pushContext(state, stream, \"top\");\n    return pass(type, stream, state);\n  };\n\n  states.at = function(type, stream, state) {\n    if (type == \";\") return popContext(state);\n    if (type == \"{\" || type == \"}\") return popAndPass(type, stream, state);\n    if (type == \"word\") override = \"tag\";\n    else if (type == \"hash\") override = \"builtin\";\n    return \"at\";\n  };\n\n  states.interpolation = function(type, stream, state) {\n    if (type == \"}\") return popContext(state);\n    if (type == \"{\" || type == \";\") return popAndPass(type, stream, state);\n    if (type != \"variable\") override = \"error\";\n    return \"interpolation\";\n  };\n\n  return {\n    startState: function(base) {\n      return {tokenize: null,\n              state: \"top\",\n              context: new Context(\"top\", base || 0, null)};\n    },\n\n    token: function(stream, state) {\n      if (!state.tokenize && stream.eatSpace()) return null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style && typeof style == \"object\") {\n        type = style[1];\n        style = style[0];\n      }\n      override = style;\n      state.state = states[state.state](type, stream, state);\n      return override;\n    },\n\n    indent: function(state, textAfter) {\n      var cx = state.context, ch = textAfter && textAfter.charAt(0);\n      var indent = cx.indent;\n      if (cx.type == \"prop\" && (ch == \"}\" || ch == \")\")) cx = cx.prev;\n      if (cx.prev &&\n          (ch == \"}\" && (cx.type == \"block\" || cx.type == \"top\" || cx.type == \"interpolation\" || cx.type == \"font_face\") ||\n           ch == \")\" && (cx.type == \"parens\" || cx.type == \"media_parens\") ||\n           ch == \"{\" && (cx.type == \"at\" || cx.type == \"media\"))) {\n        indent = cx.indent - indentUnit;\n        cx = cx.prev;\n      }\n      return indent;\n    },\n\n    electricChars: \"}\",\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    fold: \"brace\"\n  };\n});\n\n  function keySet(array) {\n    var keys = {};\n    for (var i = 0; i < array.length; ++i) {\n      keys[array[i]] = true;\n    }\n    return keys;\n  }\n\n  var mediaTypes_ = [\n    \"all\", \"aural\", \"braille\", \"handheld\", \"print\", \"projection\", \"screen\",\n    \"tty\", \"tv\", \"embossed\"\n  ], mediaTypes = keySet(mediaTypes_);\n\n  var mediaFeatures_ = [\n    \"width\", \"min-width\", \"max-width\", \"height\", \"min-height\", \"max-height\",\n    \"device-width\", \"min-device-width\", \"max-device-width\", \"device-height\",\n    \"min-device-height\", \"max-device-height\", \"aspect-ratio\",\n    \"min-aspect-ratio\", \"max-aspect-ratio\", \"device-aspect-ratio\",\n    \"min-device-aspect-ratio\", \"max-device-aspect-ratio\", \"color\", \"min-color\",\n    \"max-color\", \"color-index\", \"min-color-index\", \"max-color-index\",\n    \"monochrome\", \"min-monochrome\", \"max-monochrome\", \"resolution\",\n    \"min-resolution\", \"max-resolution\", \"scan\", \"grid\"\n  ], mediaFeatures = keySet(mediaFeatures_);\n\n  var propertyKeywords_ = [\n    \"align-content\", \"align-items\", \"align-self\", \"alignment-adjust\",\n    \"alignment-baseline\", \"anchor-point\", \"animation\", \"animation-delay\",\n    \"animation-direction\", \"animation-duration\", \"animation-fill-mode\",\n    \"animation-iteration-count\", \"animation-name\", \"animation-play-state\",\n    \"animation-timing-function\", \"appearance\", \"azimuth\", \"backface-visibility\",\n    \"background\", \"background-attachment\", \"background-clip\", \"background-color\",\n    \"background-image\", \"background-origin\", \"background-position\",\n    \"background-repeat\", \"background-size\", \"baseline-shift\", \"binding\",\n    \"bleed\", \"bookmark-label\", \"bookmark-level\", \"bookmark-state\",\n    \"bookmark-target\", \"border\", \"border-bottom\", \"border-bottom-color\",\n    \"border-bottom-left-radius\", \"border-bottom-right-radius\",\n    \"border-bottom-style\", \"border-bottom-width\", \"border-collapse\",\n    \"border-color\", \"border-image\", \"border-image-outset\",\n    \"border-image-repeat\", \"border-image-slice\", \"border-image-source\",\n    \"border-image-width\", \"border-left\", \"border-left-color\",\n    \"border-left-style\", \"border-left-width\", \"border-radius\", \"border-right\",\n    \"border-right-color\", \"border-right-style\", \"border-right-width\",\n    \"border-spacing\", \"border-style\", \"border-top\", \"border-top-color\",\n    \"border-top-left-radius\", \"border-top-right-radius\", \"border-top-style\",\n    \"border-top-width\", \"border-width\", \"bottom\", \"box-decoration-break\",\n    \"box-shadow\", \"box-sizing\", \"break-after\", \"break-before\", \"break-inside\",\n    \"caption-side\", \"clear\", \"clip\", \"color\", \"color-profile\", \"column-count\",\n    \"column-fill\", \"column-gap\", \"column-rule\", \"column-rule-color\",\n    \"column-rule-style\", \"column-rule-width\", \"column-span\", \"column-width\",\n    \"columns\", \"content\", \"counter-increment\", \"counter-reset\", \"crop\", \"cue\",\n    \"cue-after\", \"cue-before\", \"cursor\", \"direction\", \"display\",\n    \"dominant-baseline\", \"drop-initial-after-adjust\",\n    \"drop-initial-after-align\", \"drop-initial-before-adjust\",\n    \"drop-initial-before-align\", \"drop-initial-size\", \"drop-initial-value\",\n    \"elevation\", \"empty-cells\", \"fit\", \"fit-position\", \"flex\", \"flex-basis\",\n    \"flex-direction\", \"flex-flow\", \"flex-grow\", \"flex-shrink\", \"flex-wrap\",\n    \"float\", \"float-offset\", \"flow-from\", \"flow-into\", \"font\", \"font-feature-settings\",\n    \"font-family\", \"font-kerning\", \"font-language-override\", \"font-size\", \"font-size-adjust\",\n    \"font-stretch\", \"font-style\", \"font-synthesis\", \"font-variant\",\n    \"font-variant-alternates\", \"font-variant-caps\", \"font-variant-east-asian\",\n    \"font-variant-ligatures\", \"font-variant-numeric\", \"font-variant-position\",\n    \"font-weight\", \"grid\", \"grid-area\", \"grid-auto-columns\", \"grid-auto-flow\",\n    \"grid-auto-position\", \"grid-auto-rows\", \"grid-column\", \"grid-column-end\",\n    \"grid-column-start\", \"grid-row\", \"grid-row-end\", \"grid-row-start\",\n    \"grid-template\", \"grid-template-areas\", \"grid-template-columns\",\n    \"grid-template-rows\", \"hanging-punctuation\", \"height\", \"hyphens\",\n    \"icon\", \"image-orientation\", \"image-rendering\", \"image-resolution\",\n    \"inline-box-align\", \"justify-content\", \"left\", \"letter-spacing\",\n    \"line-break\", \"line-height\", \"line-stacking\", \"line-stacking-ruby\",\n    \"line-stacking-shift\", \"line-stacking-strategy\", \"list-style\",\n    \"list-style-image\", \"list-style-position\", \"list-style-type\", \"margin\",\n    \"margin-bottom\", \"margin-left\", \"margin-right\", \"margin-top\",\n    \"marker-offset\", \"marks\", \"marquee-direction\", \"marquee-loop\",\n    \"marquee-play-count\", \"marquee-speed\", \"marquee-style\", \"max-height\",\n    \"max-width\", \"min-height\", \"min-width\", \"move-to\", \"nav-down\", \"nav-index\",\n    \"nav-left\", \"nav-right\", \"nav-up\", \"object-fit\", \"object-position\",\n    \"opacity\", \"order\", \"orphans\", \"outline\",\n    \"outline-color\", \"outline-offset\", \"outline-style\", \"outline-width\",\n    \"overflow\", \"overflow-style\", \"overflow-wrap\", \"overflow-x\", \"overflow-y\",\n    \"padding\", \"padding-bottom\", \"padding-left\", \"padding-right\", \"padding-top\",\n    \"page\", \"page-break-after\", \"page-break-before\", \"page-break-inside\",\n    \"page-policy\", \"pause\", \"pause-after\", \"pause-before\", \"perspective\",\n    \"perspective-origin\", \"pitch\", \"pitch-range\", \"play-during\", \"position\",\n    \"presentation-level\", \"punctuation-trim\", \"quotes\", \"region-break-after\",\n    \"region-break-before\", \"region-break-inside\", \"region-fragment\",\n    \"rendering-intent\", \"resize\", \"rest\", \"rest-after\", \"rest-before\", \"richness\",\n    \"right\", \"rotation\", \"rotation-point\", \"ruby-align\", \"ruby-overhang\",\n    \"ruby-position\", \"ruby-span\", \"shape-image-threshold\", \"shape-inside\", \"shape-margin\",\n    \"shape-outside\", \"size\", \"speak\", \"speak-as\", \"speak-header\",\n    \"speak-numeral\", \"speak-punctuation\", \"speech-rate\", \"stress\", \"string-set\",\n    \"tab-size\", \"table-layout\", \"target\", \"target-name\", \"target-new\",\n    \"target-position\", \"text-align\", \"text-align-last\", \"text-decoration\",\n    \"text-decoration-color\", \"text-decoration-line\", \"text-decoration-skip\",\n    \"text-decoration-style\", \"text-emphasis\", \"text-emphasis-color\",\n    \"text-emphasis-position\", \"text-emphasis-style\", \"text-height\",\n    \"text-indent\", \"text-justify\", \"text-outline\", \"text-overflow\", \"text-shadow\",\n    \"text-size-adjust\", \"text-space-collapse\", \"text-transform\", \"text-underline-position\",\n    \"text-wrap\", \"top\", \"transform\", \"transform-origin\", \"transform-style\",\n    \"transition\", \"transition-delay\", \"transition-duration\",\n    \"transition-property\", \"transition-timing-function\", \"unicode-bidi\",\n    \"vertical-align\", \"visibility\", \"voice-balance\", \"voice-duration\",\n    \"voice-family\", \"voice-pitch\", \"voice-range\", \"voice-rate\", \"voice-stress\",\n    \"voice-volume\", \"volume\", \"white-space\", \"widows\", \"width\", \"word-break\",\n    \"word-spacing\", \"word-wrap\", \"z-index\",\n    // SVG-specific\n    \"clip-path\", \"clip-rule\", \"mask\", \"enable-background\", \"filter\", \"flood-color\",\n    \"flood-opacity\", \"lighting-color\", \"stop-color\", \"stop-opacity\", \"pointer-events\",\n    \"color-interpolation\", \"color-interpolation-filters\",\n    \"color-rendering\", \"fill\", \"fill-opacity\", \"fill-rule\", \"image-rendering\",\n    \"marker\", \"marker-end\", \"marker-mid\", \"marker-start\", \"shape-rendering\", \"stroke\",\n    \"stroke-dasharray\", \"stroke-dashoffset\", \"stroke-linecap\", \"stroke-linejoin\",\n    \"stroke-miterlimit\", \"stroke-opacity\", \"stroke-width\", \"text-rendering\",\n    \"baseline-shift\", \"dominant-baseline\", \"glyph-orientation-horizontal\",\n    \"glyph-orientation-vertical\", \"text-anchor\", \"writing-mode\"\n  ], propertyKeywords = keySet(propertyKeywords_);\n\n  var nonStandardPropertyKeywords_ = [\n    \"scrollbar-arrow-color\", \"scrollbar-base-color\", \"scrollbar-dark-shadow-color\",\n    \"scrollbar-face-color\", \"scrollbar-highlight-color\", \"scrollbar-shadow-color\",\n    \"scrollbar-3d-light-color\", \"scrollbar-track-color\", \"shape-inside\",\n    \"searchfield-cancel-button\", \"searchfield-decoration\", \"searchfield-results-button\",\n    \"searchfield-results-decoration\", \"zoom\"\n  ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);\n\n  var colorKeywords_ = [\n    \"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\",\n    \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\",\n    \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\", \"cornflowerblue\",\n    \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\", \"darkcyan\", \"darkgoldenrod\",\n    \"darkgray\", \"darkgreen\", \"darkkhaki\", \"darkmagenta\", \"darkolivegreen\",\n    \"darkorange\", \"darkorchid\", \"darkred\", \"darksalmon\", \"darkseagreen\",\n    \"darkslateblue\", \"darkslategray\", \"darkturquoise\", \"darkviolet\",\n    \"deeppink\", \"deepskyblue\", \"dimgray\", \"dodgerblue\", \"firebrick\",\n    \"floralwhite\", \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\",\n    \"gold\", \"goldenrod\", \"gray\", \"grey\", \"green\", \"greenyellow\", \"honeydew\",\n    \"hotpink\", \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\",\n    \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\", \"lightcoral\",\n    \"lightcyan\", \"lightgoldenrodyellow\", \"lightgray\", \"lightgreen\", \"lightpink\",\n    \"lightsalmon\", \"lightseagreen\", \"lightskyblue\", \"lightslategray\",\n    \"lightsteelblue\", \"lightyellow\", \"lime\", \"limegreen\", \"linen\", \"magenta\",\n    \"maroon\", \"mediumaquamarine\", \"mediumblue\", \"mediumorchid\", \"mediumpurple\",\n    \"mediumseagreen\", \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\",\n    \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\", \"moccasin\",\n    \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\", \"orange\", \"orangered\",\n    \"orchid\", \"palegoldenrod\", \"palegreen\", \"paleturquoise\", \"palevioletred\",\n    \"papayawhip\", \"peachpuff\", \"peru\", \"pink\", \"plum\", \"powderblue\",\n    \"purple\", \"rebeccapurple\", \"red\", \"rosybrown\", \"royalblue\", \"saddlebrown\",\n    \"salmon\", \"sandybrown\", \"seagreen\", \"seashell\", \"sienna\", \"silver\", \"skyblue\",\n    \"slateblue\", \"slategray\", \"snow\", \"springgreen\", \"steelblue\", \"tan\",\n    \"teal\", \"thistle\", \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\",\n    \"whitesmoke\", \"yellow\", \"yellowgreen\"\n  ], colorKeywords = keySet(colorKeywords_);\n\n  var valueKeywords_ = [\n    \"above\", \"absolute\", \"activeborder\", \"activecaption\", \"afar\",\n    \"after-white-space\", \"ahead\", \"alias\", \"all\", \"all-scroll\", \"alternate\",\n    \"always\", \"amharic\", \"amharic-abegede\", \"antialiased\", \"appworkspace\",\n    \"arabic-indic\", \"armenian\", \"asterisks\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\",\n    \"avoid-region\", \"background\", \"backwards\", \"baseline\", \"below\", \"bidi-override\", \"binary\",\n    \"bengali\", \"blink\", \"block\", \"block-axis\", \"bold\", \"bolder\", \"border\", \"border-box\",\n    \"both\", \"bottom\", \"break\", \"break-all\", \"break-word\", \"button\", \"button-bevel\",\n    \"buttonface\", \"buttonhighlight\", \"buttonshadow\", \"buttontext\", \"cambodian\",\n    \"capitalize\", \"caps-lock-indicator\", \"caption\", \"captiontext\", \"caret\",\n    \"cell\", \"center\", \"checkbox\", \"circle\", \"cjk-earthly-branch\",\n    \"cjk-heavenly-stem\", \"cjk-ideographic\", \"clear\", \"clip\", \"close-quote\",\n    \"col-resize\", \"collapse\", \"column\", \"compact\", \"condensed\", \"contain\", \"content\",\n    \"content-box\", \"context-menu\", \"continuous\", \"copy\", \"cover\", \"crop\",\n    \"cross\", \"crosshair\", \"currentcolor\", \"cursive\", \"dashed\", \"decimal\",\n    \"decimal-leading-zero\", \"default\", \"default-button\", \"destination-atop\",\n    \"destination-in\", \"destination-out\", \"destination-over\", \"devanagari\",\n    \"disc\", \"discard\", \"document\", \"dot-dash\", \"dot-dot-dash\", \"dotted\",\n    \"double\", \"down\", \"e-resize\", \"ease\", \"ease-in\", \"ease-in-out\", \"ease-out\",\n    \"element\", \"ellipse\", \"ellipsis\", \"embed\", \"end\", \"ethiopic\", \"ethiopic-abegede\",\n    \"ethiopic-abegede-am-et\", \"ethiopic-abegede-gez\", \"ethiopic-abegede-ti-er\",\n    \"ethiopic-abegede-ti-et\", \"ethiopic-halehame-aa-er\",\n    \"ethiopic-halehame-aa-et\", \"ethiopic-halehame-am-et\",\n    \"ethiopic-halehame-gez\", \"ethiopic-halehame-om-et\",\n    \"ethiopic-halehame-sid-et\", \"ethiopic-halehame-so-et\",\n    \"ethiopic-halehame-ti-er\", \"ethiopic-halehame-ti-et\",\n    \"ethiopic-halehame-tig\", \"ew-resize\", \"expanded\", \"extra-condensed\",\n    \"extra-expanded\", \"fantasy\", \"fast\", \"fill\", \"fixed\", \"flat\", \"flex\", \"footnotes\",\n    \"forwards\", \"from\", \"geometricPrecision\", \"georgian\", \"graytext\", \"groove\",\n    \"gujarati\", \"gurmukhi\", \"hand\", \"hangul\", \"hangul-consonant\", \"hebrew\",\n    \"help\", \"hidden\", \"hide\", \"higher\", \"highlight\", \"highlighttext\",\n    \"hiragana\", \"hiragana-iroha\", \"horizontal\", \"hsl\", \"hsla\", \"icon\", \"ignore\",\n    \"inactiveborder\", \"inactivecaption\", \"inactivecaptiontext\", \"infinite\",\n    \"infobackground\", \"infotext\", \"inherit\", \"initial\", \"inline\", \"inline-axis\",\n    \"inline-block\", \"inline-flex\", \"inline-table\", \"inset\", \"inside\", \"intrinsic\", \"invert\",\n    \"italic\", \"justify\", \"kannada\", \"katakana\", \"katakana-iroha\", \"keep-all\", \"khmer\",\n    \"landscape\", \"lao\", \"large\", \"larger\", \"left\", \"level\", \"lighter\",\n    \"line-through\", \"linear\", \"lines\", \"list-item\", \"listbox\", \"listitem\",\n    \"local\", \"logical\", \"loud\", \"lower\", \"lower-alpha\", \"lower-armenian\",\n    \"lower-greek\", \"lower-hexadecimal\", \"lower-latin\", \"lower-norwegian\",\n    \"lower-roman\", \"lowercase\", \"ltr\", \"malayalam\", \"match\",\n    \"media-controls-background\", \"media-current-time-display\",\n    \"media-fullscreen-button\", \"media-mute-button\", \"media-play-button\",\n    \"media-return-to-realtime-button\", \"media-rewind-button\",\n    \"media-seek-back-button\", \"media-seek-forward-button\", \"media-slider\",\n    \"media-sliderthumb\", \"media-time-remaining-display\", \"media-volume-slider\",\n    \"media-volume-slider-container\", \"media-volume-sliderthumb\", \"medium\",\n    \"menu\", \"menulist\", \"menulist-button\", \"menulist-text\",\n    \"menulist-textfield\", \"menutext\", \"message-box\", \"middle\", \"min-intrinsic\",\n    \"mix\", \"mongolian\", \"monospace\", \"move\", \"multiple\", \"myanmar\", \"n-resize\",\n    \"narrower\", \"ne-resize\", \"nesw-resize\", \"no-close-quote\", \"no-drop\",\n    \"no-open-quote\", \"no-repeat\", \"none\", \"normal\", \"not-allowed\", \"nowrap\",\n    \"ns-resize\", \"nw-resize\", \"nwse-resize\", \"oblique\", \"octal\", \"open-quote\",\n    \"optimizeLegibility\", \"optimizeSpeed\", \"oriya\", \"oromo\", \"outset\",\n    \"outside\", \"outside-shape\", \"overlay\", \"overline\", \"padding\", \"padding-box\",\n    \"painted\", \"page\", \"paused\", \"persian\", \"plus-darker\", \"plus-lighter\", \"pointer\",\n    \"polygon\", \"portrait\", \"pre\", \"pre-line\", \"pre-wrap\", \"preserve-3d\", \"progress\", \"push-button\",\n    \"radio\", \"read-only\", \"read-write\", \"read-write-plaintext-only\", \"rectangle\", \"region\",\n    \"relative\", \"repeat\", \"repeat-x\", \"repeat-y\", \"reset\", \"reverse\", \"rgb\", \"rgba\",\n    \"ridge\", \"right\", \"round\", \"row-resize\", \"rtl\", \"run-in\", \"running\",\n    \"s-resize\", \"sans-serif\", \"scroll\", \"scrollbar\", \"se-resize\", \"searchfield\",\n    \"searchfield-cancel-button\", \"searchfield-decoration\",\n    \"searchfield-results-button\", \"searchfield-results-decoration\",\n    \"semi-condensed\", \"semi-expanded\", \"separate\", \"serif\", \"show\", \"sidama\",\n    \"single\", \"skip-white-space\", \"slide\", \"slider-horizontal\",\n    \"slider-vertical\", \"sliderthumb-horizontal\", \"sliderthumb-vertical\", \"slow\",\n    \"small\", \"small-caps\", \"small-caption\", \"smaller\", \"solid\", \"somali\",\n    \"source-atop\", \"source-in\", \"source-out\", \"source-over\", \"space\", \"square\",\n    \"square-button\", \"start\", \"static\", \"status-bar\", \"stretch\", \"stroke\",\n    \"sub\", \"subpixel-antialiased\", \"super\", \"sw-resize\", \"table\",\n    \"table-caption\", \"table-cell\", \"table-column\", \"table-column-group\",\n    \"table-footer-group\", \"table-header-group\", \"table-row\", \"table-row-group\",\n    \"telugu\", \"text\", \"text-bottom\", \"text-top\", \"textarea\", \"textfield\", \"thai\",\n    \"thick\", \"thin\", \"threeddarkshadow\", \"threedface\", \"threedhighlight\",\n    \"threedlightshadow\", \"threedshadow\", \"tibetan\", \"tigre\", \"tigrinya-er\",\n    \"tigrinya-er-abegede\", \"tigrinya-et\", \"tigrinya-et-abegede\", \"to\", \"top\",\n    \"transparent\", \"ultra-condensed\", \"ultra-expanded\", \"underline\", \"up\",\n    \"upper-alpha\", \"upper-armenian\", \"upper-greek\", \"upper-hexadecimal\",\n    \"upper-latin\", \"upper-norwegian\", \"upper-roman\", \"uppercase\", \"urdu\", \"url\",\n    \"vertical\", \"vertical-text\", \"visible\", \"visibleFill\", \"visiblePainted\",\n    \"visibleStroke\", \"visual\", \"w-resize\", \"wait\", \"wave\", \"wider\",\n    \"window\", \"windowframe\", \"windowtext\", \"x-large\", \"x-small\", \"xor\",\n    \"xx-large\", \"xx-small\"\n  ], valueKeywords = keySet(valueKeywords_);\n\n  var fontProperties_ = [\n    \"font-family\", \"src\", \"unicode-range\", \"font-variant\", \"font-feature-settings\",\n    \"font-stretch\", \"font-weight\", \"font-style\"\n  ], fontProperties = keySet(fontProperties_);\n\n  var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)\n    .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);\n  CodeMirror.registerHelper(\"hintWords\", \"css\", allWords);\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return [\"comment\", \"comment\"];\n  }\n\n  function tokenSGMLComment(stream, state) {\n    if (stream.skipTo(\"-->\")) {\n      stream.match(\"-->\");\n      state.tokenize = null;\n    } else {\n      stream.skipToEnd();\n    }\n    return [\"comment\", \"comment\"];\n  }\n\n  CodeMirror.defineMIME(\"text/css\", {\n    mediaTypes: mediaTypes,\n    mediaFeatures: mediaFeatures,\n    propertyKeywords: propertyKeywords,\n    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n    colorKeywords: colorKeywords,\n    valueKeywords: valueKeywords,\n    fontProperties: fontProperties,\n    tokenHooks: {\n      \"<\": function(stream, state) {\n        if (!stream.match(\"!--\")) return false;\n        state.tokenize = tokenSGMLComment;\n        return tokenSGMLComment(stream, state);\n      },\n      \"/\": function(stream, state) {\n        if (!stream.eat(\"*\")) return false;\n        state.tokenize = tokenCComment;\n        return tokenCComment(stream, state);\n      }\n    },\n    name: \"css\"\n  });\n\n  CodeMirror.defineMIME(\"text/x-scss\", {\n    mediaTypes: mediaTypes,\n    mediaFeatures: mediaFeatures,\n    propertyKeywords: propertyKeywords,\n    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n    colorKeywords: colorKeywords,\n    valueKeywords: valueKeywords,\n    fontProperties: fontProperties,\n    allowNested: true,\n    tokenHooks: {\n      \"/\": function(stream, state) {\n        if (stream.eat(\"/\")) {\n          stream.skipToEnd();\n          return [\"comment\", \"comment\"];\n        } else if (stream.eat(\"*\")) {\n          state.tokenize = tokenCComment;\n          return tokenCComment(stream, state);\n        } else {\n          return [\"operator\", \"operator\"];\n        }\n      },\n      \":\": function(stream) {\n        if (stream.match(/\\s*\\{/))\n          return [null, \"{\"];\n        return false;\n      },\n      \"$\": function(stream) {\n        stream.match(/^[\\w-]+/);\n        if (stream.match(/^\\s*:/, false))\n          return [\"variable-2\", \"variable-definition\"];\n        return [\"variable-2\", \"variable\"];\n      },\n      \"#\": function(stream) {\n        if (!stream.eat(\"{\")) return false;\n        return [null, \"interpolation\"];\n      }\n    },\n    name: \"css\",\n    helperType: \"scss\"\n  });\n\n  CodeMirror.defineMIME(\"text/x-less\", {\n    mediaTypes: mediaTypes,\n    mediaFeatures: mediaFeatures,\n    propertyKeywords: propertyKeywords,\n    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n    colorKeywords: colorKeywords,\n    valueKeywords: valueKeywords,\n    fontProperties: fontProperties,\n    allowNested: true,\n    tokenHooks: {\n      \"/\": function(stream, state) {\n        if (stream.eat(\"/\")) {\n          stream.skipToEnd();\n          return [\"comment\", \"comment\"];\n        } else if (stream.eat(\"*\")) {\n          state.tokenize = tokenCComment;\n          return tokenCComment(stream, state);\n        } else {\n          return [\"operator\", \"operator\"];\n        }\n      },\n      \"@\": function(stream) {\n        if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\\b/, false)) return false;\n        stream.eatWhile(/[\\w\\\\\\-]/);\n        if (stream.match(/^\\s*:/, false))\n          return [\"variable-2\", \"variable-definition\"];\n        return [\"variable-2\", \"variable\"];\n      },\n      \"&\": function() {\n        return [\"atom\", \"atom\"];\n      }\n    },\n    name: \"css\",\n    helperType: \"less\"\n  });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: CSS mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../addon/hint/show-hint.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"css.js\"></script>\n<script src=\"../../addon/hint/show-hint.js\"></script>\n<script src=\"../../addon/hint/css-hint.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">CSS</a>\n  </ul>\n</div>\n\n<article>\n<h2>CSS mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n/* Some example CSS */\n\n@import url(\"something.css\");\n\nbody {\n  margin: 0;\n  padding: 3em 6em;\n  font-family: tahoma, arial, sans-serif;\n  color: #000;\n}\n\n#navigation a {\n  font-weight: bold;\n  text-decoration: none !important;\n}\n\nh1 {\n  font-size: 2.5em;\n}\n\nh2 {\n  font-size: 1.7em;\n}\n\nh1:before, h2:before {\n  content: \"::\";\n}\n\ncode {\n  font-family: courier, monospace;\n  font-size: 80%;\n  color: #418A8A;\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        extraKeys: {\"Ctrl-Space\": \"autocomplete\"},\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href=\"scss.html\">demo</a>), <code>text/x-less</code> (<a href=\"less.html\">demo</a>).</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#css_*\">normal</a>,  <a href=\"../../test/index.html#verbose,css_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/less.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: LESS mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"css.js\"></script>\n<style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">LESS</a>\n  </ul>\n</div>\n\n<article>\n<h2>LESS mode</h2>\n<form><textarea id=\"code\" name=\"code\">@media screen and (device-aspect-ratio: 16/9) { … }\n@media screen and (device-aspect-ratio: 1280/720) { … }\n@media screen and (device-aspect-ratio: 2560/1440) { … }\n\nhtml:lang(fr-be)\n\ntr:nth-child(2n+1) /* represents every odd row of an HTML table */\n\nimg:nth-of-type(2n+1) { float: right; }\nimg:nth-of-type(2n) { float: left; }\n\nbody > h2:not(:first-of-type):not(:last-of-type)\n\nhtml|*:not(:link):not(:visited)\n*|*:not(:hover)\np::first-line { text-transform: uppercase }\n\n@namespace foo url(http://www.example.com);\nfoo|h1 { color: blue }  /* first rule */\n\nspan[hello=\"Ocean\"][goodbye=\"Land\"]\n\nE[foo]{\n  padding:65px;\n}\n\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner { // Inner padding and border oddities in FF3/4\n  padding: 0;\n  border: 0;\n}\n.btn {\n  // reset here as of 2.0.3 due to Recess property order\n  border-color: #ccc;\n  border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);\n}\nfieldset span button, fieldset span input[type=\"file\"] {\n  font-size:12px;\n\tfont-family:Arial, Helvetica, sans-serif;\n}\n\n.rounded-corners (@radius: 5px) {\n  border-radius: @radius;\n  -webkit-border-radius: @radius;\n  -moz-border-radius: @radius;\n}\n\n@import url(\"something.css\");\n\n@light-blue:   hsl(190, 50%, 65%);\n\n#menu {\n  position: absolute;\n  width: 100%;\n  z-index: 3;\n  clear: both;\n  display: block;\n  background-color: @blue;\n  height: 42px;\n  border-top: 2px solid lighten(@alpha-blue, 20%);\n  border-bottom: 2px solid darken(@alpha-blue, 25%);\n  .box-shadow(0, 1px, 8px, 0.6);\n  -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.\n\n  &.docked {\n    background-color: hsla(210, 60%, 40%, 0.4);\n  }\n  &:hover {\n    background-color: @blue;\n  }\n\n  #dropdown {\n    margin: 0 0 0 117px;\n    padding: 0;\n    padding-top: 5px;\n    display: none;\n    width: 190px;\n    border-top: 2px solid @medium;\n    color: @highlight;\n    border: 2px solid darken(@medium, 25%);\n    border-left-color: darken(@medium, 15%);\n    border-right-color: darken(@medium, 15%);\n    border-top-width: 0;\n    background-color: darken(@medium, 10%);\n    ul {\n      padding: 0px;\n    }\n    li {\n      font-size: 14px;\n      display: block;\n      text-align: left;\n      padding: 0;\n      border: 0;\n      a {\n        display: block;\n        padding: 0px 15px;\n        text-decoration: none;\n        color: white;\n        &:hover {\n          background-color: darken(@medium, 15%);\n          text-decoration: none;\n        }\n      }\n    }\n    .border-radius(5px, bottom);\n    .box-shadow(0, 6px, 8px, 0.5);\n  }\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers : true,\n        matchBrackets : true,\n        mode: \"text/x-less\"\n      });\n    </script>\n\n    <p>The LESS mode is a sub-mode of the <a href=\"index.html\">CSS mode</a> (defined in <code>css.js</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#less_*\">normal</a>,  <a href=\"../../test/index.html#verbose,less_*\">verbose</a>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/less_test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  \"use strict\";\n\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"text/x-less\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), \"less\"); }\n\n  MT(\"variable\",\n     \"[variable-2 @base]: [atom #f04615];\",\n     \"[qualifier .class] {\",\n     \"  [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]\",\n     \"  [property color]: [variable saturate]([variable-2 @base], [number 5%]);\",\n     \"}\");\n\n  MT(\"amp\",\n     \"[qualifier .child], [qualifier .sibling] {\",\n     \"  [qualifier .parent] [atom &] {\",\n     \"    [property color]: [keyword black];\",\n     \"  }\",\n     \"  [atom &] + [atom &] {\",\n     \"    [property color]: [keyword red];\",\n     \"  }\",\n     \"}\");\n\n  MT(\"mixin\",\n     \"[qualifier .mixin] ([variable dark]; [variable-2 @color]) {\",\n     \"  [property color]: [variable darken]([variable-2 @color], [number 10%]);\",\n     \"}\",\n     \"[qualifier .mixin] ([variable light]; [variable-2 @color]) {\",\n     \"  [property color]: [variable lighten]([variable-2 @color], [number 10%]);\",\n     \"}\",\n     \"[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {\",\n     \"  [property display]: [atom block];\",\n     \"}\",\n     \"[variable-2 @switch]: [variable light];\",\n     \"[qualifier .class] {\",\n     \"  [qualifier .mixin]([variable-2 @switch]; [atom #888]);\",\n     \"}\");\n\n  MT(\"nest\",\n     \"[qualifier .one] {\",\n     \"  [def @media] ([property width]: [number 400px]) {\",\n     \"    [property font-size]: [number 1.2em];\",\n     \"    [def @media] [attribute print] [keyword and] [property color] {\",\n     \"      [property color]: [keyword blue];\",\n     \"    }\",\n     \"  }\",\n     \"}\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/scss.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: SCSS mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"css.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">SCSS</a>\n  </ul>\n</div>\n\n<article>\n<h2>SCSS mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n/* Some example SCSS */\n\n@import \"compass/css3\";\n$variable: #333;\n\n$blue: #3bbfce;\n$margin: 16px;\n\n.content-navigation {\n  #nested {\n    background-color: black;\n  }\n  border-color: $blue;\n  color:\n    darken($blue, 9%);\n}\n\n.border {\n  padding: $margin / 2;\n  margin: $margin / 2;\n  border-color: $blue;\n}\n\n@mixin table-base {\n  th {\n    text-align: center;\n    font-weight: bold;\n  }\n  td, th {padding: 2px}\n}\n\ntable.hl {\n  margin: 2em 0;\n  td.ln {\n    text-align: right;\n  }\n}\n\nli {\n  font: {\n    family: serif;\n    weight: bold;\n    size: 1.2em;\n  }\n}\n\n@mixin left($dist) {\n  float: left;\n  margin-left: $dist;\n}\n\n#data {\n  @include left(10px);\n  @include table-base;\n}\n\n.source {\n  @include flow-into(target);\n  border: 10px solid green;\n  margin: 20px;\n  width: 200px; }\n\n.new-container {\n  @include flow-from(target);\n  border: 10px solid red;\n  margin: 20px;\n  width: 200px; }\n\nbody {\n  margin: 0;\n  padding: 3em 6em;\n  font-family: tahoma, arial, sans-serif;\n  color: #000;\n}\n\n@mixin yellow() {\n  background: yellow;\n}\n\n.big {\n  font-size: 14px;\n}\n\n.nested {\n  @include border-radius(3px);\n  @extend .big;\n  p {\n    background: whitesmoke;\n    a {\n      color: red;\n    }\n  }\n}\n\n#navigation a {\n  font-weight: bold;\n  text-decoration: none !important;\n}\n\nh1 {\n  font-size: 2.5em;\n}\n\nh2 {\n  font-size: 1.7em;\n}\n\nh1:before, h2:before {\n  content: \"::\";\n}\n\ncode {\n  font-family: courier, monospace;\n  font-size: 80%;\n  color: #418A8A;\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-scss\"\n      });\n    </script>\n\n    <p>The SCSS mode is a sub-mode of the <a href=\"index.html\">CSS mode</a> (defined in <code>css.js</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#scss_*\">normal</a>,  <a href=\"../../test/index.html#verbose,scss_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/scss_test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"text/x-scss\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), \"scss\"); }\n\n  MT('url_with_quotation',\n    \"[tag foo] { [property background]:[atom url]([string test.jpg]) }\");\n\n  MT('url_with_double_quotes',\n    \"[tag foo] { [property background]:[atom url]([string \\\"test.jpg\\\"]) }\");\n\n  MT('url_with_single_quotes',\n    \"[tag foo] { [property background]:[atom url]([string \\'test.jpg\\']) }\");\n\n  MT('string',\n    \"[def @import] [string \\\"compass/css3\\\"]\");\n\n  MT('important_keyword',\n    \"[tag foo] { [property background]:[atom url]([string \\'test.jpg\\']) [keyword !important] }\");\n\n  MT('variable',\n    \"[variable-2 $blue]:[atom #333]\");\n\n  MT('variable_as_attribute',\n    \"[tag foo] { [property color]:[variable-2 $blue] }\");\n\n  MT('numbers',\n    \"[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }\");\n\n  MT('number_percentage',\n    \"[tag foo] { [property width]:[number 80%] }\");\n\n  MT('selector',\n    \"[builtin #hello][qualifier .world]{}\");\n\n  MT('singleline_comment',\n    \"[comment // this is a comment]\");\n\n  MT('multiline_comment',\n    \"[comment /*foobar*/]\");\n\n  MT('attribute_with_hyphen',\n    \"[tag foo] { [property font-size]:[number 10px] }\");\n\n  MT('string_after_attribute',\n    \"[tag foo] { [property content]:[string \\\"::\\\"] }\");\n\n  MT('directives',\n    \"[def @include] [qualifier .mixin]\");\n\n  MT('basic_structure',\n    \"[tag p] { [property background]:[keyword red]; }\");\n\n  MT('nested_structure',\n    \"[tag p] { [tag a] { [property color]:[keyword red]; } }\");\n\n  MT('mixin',\n    \"[def @mixin] [tag table-base] {}\");\n\n  MT('number_without_semicolon',\n    \"[tag p] {[property width]:[number 12]}\",\n    \"[tag a] {[property color]:[keyword red];}\");\n\n  MT('atom_in_nested_block',\n    \"[tag p] { [tag a] { [property color]:[atom #000]; } }\");\n\n  MT('interpolation_in_property',\n    \"[tag foo] { #{[variable-2 $hello]}:[number 2]; }\");\n\n  MT('interpolation_in_selector',\n    \"[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }\");\n\n  MT('interpolation_error',\n    \"[tag foo]#{[error foo]} { [property color]:[atom #000]; }\");\n\n  MT(\"divide_operator\",\n    \"[tag foo] { [property width]:[number 4] [operator /] [number 2] }\");\n\n  MT('nested_structure_with_id_selector',\n    \"[tag p] { [builtin #hello] { [property color]:[keyword red]; } }\");\n\n  MT('indent_mixin',\n     \"[def @mixin] [tag container] (\",\n     \"  [variable-2 $a]: [number 10],\",\n     \"  [variable-2 $b]: [number 10])\",\n     \"{}\");\n\n  MT('indent_nested',\n     \"[tag foo] {\",\n     \"  [tag bar] {\",\n     \"  }\",\n     \"}\");\n\n  MT('indent_parentheses',\n     \"[tag foo] {\",\n     \"  [property color]: [variable darken]([variable-2 $blue],\",\n     \"    [number 9%]);\",\n     \"}\");\n\n  MT('indent_vardef',\n     \"[variable-2 $name]:\",\n     \"  [string 'val'];\",\n     \"[tag tag] {\",\n     \"  [tag inner] {\",\n     \"    [property margin]: [number 3px];\",\n     \"  }\",\n     \"}\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/css/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"css\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  // Error, because \"foobarhello\" is neither a known type or property, but\n  // property was expected (after \"and\"), and it should be in parenthese.\n  MT(\"atMediaUnknownType\",\n     \"[def @media] [attribute screen] [keyword and] [error foobarhello] { }\");\n\n  // Soft error, because \"foobarhello\" is not a known property or type.\n  MT(\"atMediaUnknownProperty\",\n     \"[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }\");\n\n  // Make sure nesting works with media queries\n  MT(\"atMediaMaxWidthNested\",\n     \"[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }\");\n\n  MT(\"tagSelector\",\n     \"[tag foo] { }\");\n\n  MT(\"classSelector\",\n     \"[qualifier .foo-bar_hello] { }\");\n\n  MT(\"idSelector\",\n     \"[builtin #foo] { [error #foo] }\");\n\n  MT(\"tagSelectorUnclosed\",\n     \"[tag foo] { [property margin]: [number 0] } [tag bar] { }\");\n\n  MT(\"tagStringNoQuotes\",\n     \"[tag foo] { [property font-family]: [variable hello] [variable world]; }\");\n\n  MT(\"tagStringDouble\",\n     \"[tag foo] { [property font-family]: [string \\\"hello world\\\"]; }\");\n\n  MT(\"tagStringSingle\",\n     \"[tag foo] { [property font-family]: [string 'hello world']; }\");\n\n  MT(\"tagColorKeyword\",\n     \"[tag foo] {\",\n     \"  [property color]: [keyword black];\",\n     \"  [property color]: [keyword navy];\",\n     \"  [property color]: [keyword yellow];\",\n     \"}\");\n\n  MT(\"tagColorHex3\",\n     \"[tag foo] { [property background]: [atom #fff]; }\");\n\n  MT(\"tagColorHex6\",\n     \"[tag foo] { [property background]: [atom #ffffff]; }\");\n\n  MT(\"tagColorHex4\",\n     \"[tag foo] { [property background]: [atom&error #ffff]; }\");\n\n  MT(\"tagColorHexInvalid\",\n     \"[tag foo] { [property background]: [atom&error #ffg]; }\");\n\n  MT(\"tagNegativeNumber\",\n     \"[tag foo] { [property margin]: [number -5px]; }\");\n\n  MT(\"tagPositiveNumber\",\n     \"[tag foo] { [property padding]: [number 5px]; }\");\n\n  MT(\"tagVendor\",\n     \"[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }\");\n\n  MT(\"tagBogusProperty\",\n     \"[tag foo] { [property&error barhelloworld]: [number 0]; }\");\n\n  MT(\"tagTwoProperties\",\n     \"[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }\");\n\n  MT(\"tagTwoPropertiesURL\",\n     \"[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }\");\n\n  MT(\"commentSGML\",\n     \"[comment <!--comment-->]\");\n\n  MT(\"commentSGML2\",\n     \"[comment <!--comment]\",\n     \"[comment -->] [tag div] {}\");\n\n  MT(\"indent_tagSelector\",\n     \"[tag strong], [tag em] {\",\n     \"  [property background]: [atom rgba](\",\n     \"    [number 255], [number 255], [number 0], [number .2]\",\n     \"  );\",\n     \"}\");\n\n  MT(\"indent_atMedia\",\n     \"[def @media] {\",\n     \"  [tag foo] {\",\n     \"    [property color]:\",\n     \"      [keyword yellow];\",\n     \"  }\",\n     \"}\");\n\n  MT(\"indent_comma\",\n     \"[tag foo] {\",\n     \"  [property font-family]: [variable verdana],\",\n     \"    [atom sans-serif];\",\n     \"}\");\n\n  MT(\"indent_parentheses\",\n     \"[tag foo]:[variable-3 before] {\",\n     \"  [property background]: [atom url](\",\n     \"[string     blahblah]\",\n     \"[string     etc]\",\n     \"[string   ]) [keyword !important];\",\n     \"}\");\n\n  MT(\"font_face\",\n     \"[def @font-face] {\",\n     \"  [property font-family]: [string 'myfont'];\",\n     \"  [error nonsense]: [string 'abc'];\",\n     \"  [property src]: [atom url]([string http://blah]),\",\n     \"    [atom url]([string http://foo]);\",\n     \"}\");\n\n  MT(\"empty_url\",\n     \"[def @import] [tag url]() [tag screen];\");\n\n  MT(\"parens\",\n     \"[qualifier .foo] {\",\n     \"  [property background-image]: [variable fade]([atom #000], [number 20%]);\",\n     \"  [property border-image]: [variable linear-gradient](\",\n     \"    [atom to] [atom bottom],\",\n     \"    [variable fade]([atom #000], [number 20%]) [number 0%],\",\n     \"    [variable fade]([atom #000], [number 20%]) [number 100%]\",\n     \"  );\",\n     \"}\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/cypher/cypher.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// By the Neo4j Team and contributors.\n// https://github.com/neo4j-contrib/CodeMirror\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  var wordRegexp = function(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  };\n\n  CodeMirror.defineMode(\"cypher\", function(config) {\n    var tokenBase = function(stream/*, state*/) {\n      var ch = stream.next(), curPunc = null;\n      if (ch === \"\\\"\" || ch === \"'\") {\n        stream.match(/.+?[\"']/);\n        return \"string\";\n      }\n      if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n        curPunc = ch;\n        return \"node\";\n      } else if (ch === \"/\" && stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (operatorChars.test(ch)) {\n        stream.eatWhile(operatorChars);\n        return null;\n      } else {\n        stream.eatWhile(/[_\\w\\d]/);\n        if (stream.eat(\":\")) {\n          stream.eatWhile(/[\\w\\d_\\-]/);\n          return \"atom\";\n        }\n        var word = stream.current();\n        if (funcs.test(word)) return \"builtin\";\n        if (preds.test(word)) return \"def\";\n        if (keywords.test(word)) return \"keyword\";\n        return \"variable\";\n      }\n    };\n    var pushContext = function(state, type, col) {\n      return state.context = {\n        prev: state.context,\n        indent: state.indent,\n        col: col,\n        type: type\n      };\n    };\n    var popContext = function(state) {\n      state.indent = state.context.indent;\n      return state.context = state.context.prev;\n    };\n    var indentUnit = config.indentUnit;\n    var curPunc;\n    var funcs = wordRegexp([\"abs\", \"acos\", \"allShortestPaths\", \"asin\", \"atan\", \"atan2\", \"avg\", \"ceil\", \"coalesce\", \"collect\", \"cos\", \"cot\", \"count\", \"degrees\", \"e\", \"endnode\", \"exp\", \"extract\", \"filter\", \"floor\", \"haversin\", \"head\", \"id\", \"labels\", \"last\", \"left\", \"length\", \"log\", \"log10\", \"lower\", \"ltrim\", \"max\", \"min\", \"node\", \"nodes\", \"percentileCont\", \"percentileDisc\", \"pi\", \"radians\", \"rand\", \"range\", \"reduce\", \"rel\", \"relationship\", \"relationships\", \"replace\", \"right\", \"round\", \"rtrim\", \"shortestPath\", \"sign\", \"sin\", \"split\", \"sqrt\", \"startnode\", \"stdev\", \"stdevp\", \"str\", \"substring\", \"sum\", \"tail\", \"tan\", \"timestamp\", \"toFloat\", \"toInt\", \"trim\", \"type\", \"upper\"]);\n    var preds = wordRegexp([\"all\", \"and\", \"any\", \"has\", \"in\", \"none\", \"not\", \"or\", \"single\", \"xor\"]);\n    var keywords = wordRegexp([\"as\", \"asc\", \"ascending\", \"assert\", \"by\", \"case\", \"commit\", \"constraint\", \"create\", \"csv\", \"cypher\", \"delete\", \"desc\", \"descending\", \"distinct\", \"drop\", \"else\", \"end\", \"explain\", \"false\", \"fieldterminator\", \"foreach\", \"from\", \"headers\", \"in\", \"index\", \"is\", \"limit\", \"load\", \"match\", \"merge\", \"null\", \"on\", \"optional\", \"order\", \"periodic\", \"profile\", \"remove\", \"return\", \"scan\", \"set\", \"skip\", \"start\", \"then\", \"true\", \"union\", \"unique\", \"unwind\", \"using\", \"when\", \"where\", \"with\"]);\n    var operatorChars = /[*+\\-<>=&|~%^]/;\n\n    return {\n      startState: function(/*base*/) {\n        return {\n          tokenize: tokenBase,\n          context: null,\n          indent: 0,\n          col: 0\n        };\n      },\n      token: function(stream, state) {\n        if (stream.sol()) {\n          if (state.context && (state.context.align == null)) {\n            state.context.align = false;\n          }\n          state.indent = stream.indentation();\n        }\n        if (stream.eatSpace()) {\n          return null;\n        }\n        var style = state.tokenize(stream, state);\n        if (style !== \"comment\" && state.context && (state.context.align == null) && state.context.type !== \"pattern\") {\n          state.context.align = true;\n        }\n        if (curPunc === \"(\") {\n          pushContext(state, \")\", stream.column());\n        } else if (curPunc === \"[\") {\n          pushContext(state, \"]\", stream.column());\n        } else if (curPunc === \"{\") {\n          pushContext(state, \"}\", stream.column());\n        } else if (/[\\]\\}\\)]/.test(curPunc)) {\n          while (state.context && state.context.type === \"pattern\") {\n            popContext(state);\n          }\n          if (state.context && curPunc === state.context.type) {\n            popContext(state);\n          }\n        } else if (curPunc === \".\" && state.context && state.context.type === \"pattern\") {\n          popContext(state);\n        } else if (/atom|string|variable/.test(style) && state.context) {\n          if (/[\\}\\]]/.test(state.context.type)) {\n            pushContext(state, \"pattern\", stream.column());\n          } else if (state.context.type === \"pattern\" && !state.context.align) {\n            state.context.align = true;\n            state.context.col = stream.column();\n          }\n        }\n        return style;\n      },\n      indent: function(state, textAfter) {\n        var firstChar = textAfter && textAfter.charAt(0);\n        var context = state.context;\n        if (/[\\]\\}]/.test(firstChar)) {\n          while (context && context.type === \"pattern\") {\n            context = context.prev;\n          }\n        }\n        var closing = context && firstChar === context.type;\n        if (!context) return 0;\n        if (context.type === \"keywords\") return CodeMirror.commands.newlineAndIndent;\n        if (context.align) return context.col + (closing ? 0 : 1);\n        return context.indent + (closing ? 0 : indentUnit);\n      }\n    };\n  });\n\n  CodeMirror.modeExtensions[\"cypher\"] = {\n    autoFormatLineBreaks: function(text) {\n      var i, lines, reProcessedPortion;\n      var lines = text.split(\"\\n\");\n      var reProcessedPortion = /\\s+\\b(return|where|order by|match|with|skip|limit|create|delete|set)\\b\\s/g;\n      for (var i = 0; i < lines.length; i++)\n        lines[i] = lines[i].replace(reProcessedPortion, \" \\n$1 \").trim();\n      return lines.join(\"\\n\");\n    }\n  };\n\n  CodeMirror.defineMIME(\"application/x-cypher-query\", \"cypher\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/cypher/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Cypher Mode for CodeMirror</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\" />\n<link rel=\"stylesheet\" href=\"../../theme/neo.css\" />\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"cypher.js\"></script>\n<style>\n.CodeMirror {\n    border-top: 1px solid black;\n    border-bottom: 1px solid black;\n}\n        </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Cypher Mode for CodeMirror</a>\n  </ul>\n</div>\n\n<article>\n<h2>Cypher Mode for CodeMirror</h2>\n<form>\n            <textarea id=\"code\" name=\"code\">// Cypher Mode for CodeMirror, using the neo theme\nMATCH (joe { name: 'Joe' })-[:knows*2..2]-(friend_of_friend)\nWHERE NOT (joe)-[:knows]-(friend_of_friend)\nRETURN friend_of_friend.name, COUNT(*)\nORDER BY COUNT(*) DESC , friend_of_friend.name\n</textarea>\n            </form>\n            <p><strong>MIME types defined:</strong>\n            <code><a href=\"?mime=application/x-cypher-query\">application/x-cypher-query</a></code>\n        </p>\n<script>\nwindow.onload = function() {\n  var mime = 'application/x-cypher-query';\n  // get mime type\n  if (window.location.href.indexOf('mime=') > -1) {\n    mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);\n  }\n  window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {\n    mode: mime,\n    indentWithTabs: true,\n    smartIndent: true,\n    lineNumbers: true,\n    matchBrackets : true,\n    autofocus: true,\n    theme: 'neo'\n  });\n};\n</script>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/d/d.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(\"d\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n      keywords = parserConfig.keywords || {},\n      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\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 == \"'\" || ch == \"`\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"+\")) {\n        state.tokenize = tokenComment;\n        return tokenNestedComment(stream, state);\n      }\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      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (atoms.propertyIsEnumerable(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  function tokenNestedComment(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  function 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  }\n  function pushContext(state, col, type) {\n    var indent = state.indented;\n    if (state.context && state.context.type == \"statement\")\n      indent = state.context.indented;\n    return state.context = new Context(indent, col, type, null, state.context);\n  }\n  function 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\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      };\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 = 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 ((curPunc == \";\" || curPunc == \":\" || curPunc == \",\") && ctx.type == \"statement\") 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 (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (((ctx.type == \"}\" || ctx.type == \"top\") && curPunc != ';') || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\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 (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\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\n  var blockKeywords = \"body catch class do else enum for foreach foreach_reverse if in interface mixin \" +\n                      \"out scope struct switch try union unittest version while with\";\n\n  CodeMirror.defineMIME(\"text/x-d\", {\n    name: \"d\",\n    keywords: words(\"abstract alias align asm assert auto break case cast cdouble cent cfloat const continue \" +\n                    \"debug default delegate delete deprecated export extern final finally function goto immutable \" +\n                    \"import inout invariant is lazy macro module new nothrow override package pragma private \" +\n                    \"protected public pure ref return shared short static super synchronized template this \" +\n                    \"throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters \" +\n                    blockKeywords),\n    blockKeywords: words(blockKeywords),\n    builtin: words(\"bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte \" +\n                   \"ucent uint ulong ushort wchar wstring void size_t sizediff_t\"),\n    atoms: words(\"exit failure success true false null\"),\n    hooks: {\n      \"@\": function(stream, _state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/d/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: D mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"d.js\"></script>\n<style>.CodeMirror {border: 2px inset #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">D</a>\n  </ul>\n</div>\n\n<article>\n<h2>D mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n/* D demo code // copied from phobos/sd/metastrings.d */\n// Written in the D programming language.\n\n/**\nTemplates with which to do compile-time manipulation of strings.\n\nMacros:\n WIKI = Phobos/StdMetastrings\n\nCopyright: Copyright Digital Mars 2007 - 2009.\nLicense:   <a href=\"http://www.boost.org/LICENSE_1_0.txt\">Boost License 1.0</a>.\nAuthors:   $(WEB digitalmars.com, Walter Bright),\n           Don Clugston\nSource:    $(PHOBOSSRC std/_metastrings.d)\n*/\n/*\n         Copyright Digital Mars 2007 - 2009.\nDistributed under the Boost Software License, Version 1.0.\n   (See accompanying file LICENSE_1_0.txt or copy at\n         http://www.boost.org/LICENSE_1_0.txt)\n */\nmodule std.metastrings;\n\n/**\nFormats constants into a string at compile time.  Analogous to $(XREF\nstring,format).\n\nParameters:\n\nA = tuple of constants, which can be strings, characters, or integral\n    values.\n\nFormats:\n *    The formats supported are %s for strings, and %%\n *    for the % character.\nExample:\n---\nimport std.metastrings;\nimport std.stdio;\n\nvoid main()\n{\n  string s = Format!(\"Arg %s = %s\", \"foo\", 27);\n  writefln(s); // \"Arg foo = 27\"\n}\n * ---\n */\n\ntemplate Format(A...)\n{\n    static if (A.length == 0)\n        enum Format = \"\";\n    else static if (is(typeof(A[0]) : const(char)[]))\n        enum Format = FormatString!(A[0], A[1..$]);\n    else\n        enum Format = toStringNow!(A[0]) ~ Format!(A[1..$]);\n}\n\ntemplate FormatString(const(char)[] F, A...)\n{\n    static if (F.length == 0)\n        enum FormatString = Format!(A);\n    else static if (F.length == 1)\n        enum FormatString = F[0] ~ Format!(A);\n    else static if (F[0..2] == \"%s\")\n        enum FormatString\n            = toStringNow!(A[0]) ~ FormatString!(F[2..$],A[1..$]);\n    else static if (F[0..2] == \"%%\")\n        enum FormatString = \"%\" ~ FormatString!(F[2..$],A);\n    else\n    {\n        static assert(F[0] != '%', \"unrecognized format %\" ~ F[1]);\n        enum FormatString = F[0] ~ FormatString!(F[1..$],A);\n    }\n}\n\nunittest\n{\n    auto s = Format!(\"hel%slo\", \"world\", -138, 'c', true);\n    assert(s == \"helworldlo-138ctrue\", \"[\" ~ s ~ \"]\");\n}\n\n/**\n * Convert constant argument to a string.\n */\n\ntemplate toStringNow(ulong v)\n{\n    static if (v < 10)\n        enum toStringNow = \"\" ~ cast(char)(v + '0');\n    else\n        enum toStringNow = toStringNow!(v / 10) ~ toStringNow!(v % 10);\n}\n\nunittest\n{\n    static assert(toStringNow!(1uL << 62) == \"4611686018427387904\");\n}\n\n/// ditto\ntemplate toStringNow(long v)\n{\n    static if (v < 0)\n        enum toStringNow = \"-\" ~ toStringNow!(cast(ulong) -v);\n    else\n        enum toStringNow = toStringNow!(cast(ulong) v);\n}\n\nunittest\n{\n    static assert(toStringNow!(0x100000000) == \"4294967296\");\n    static assert(toStringNow!(-138L) == \"-138\");\n}\n\n/// ditto\ntemplate toStringNow(uint U)\n{\n    enum toStringNow = toStringNow!(cast(ulong)U);\n}\n\n/// ditto\ntemplate toStringNow(int I)\n{\n    enum toStringNow = toStringNow!(cast(long)I);\n}\n\n/// ditto\ntemplate toStringNow(bool B)\n{\n    enum toStringNow = B ? \"true\" : \"false\";\n}\n\n/// ditto\ntemplate toStringNow(string S)\n{\n    enum toStringNow = S;\n}\n\n/// ditto\ntemplate toStringNow(char C)\n{\n    enum toStringNow = \"\" ~ C;\n}\n\n\n/********\n * Parse unsigned integer literal from the start of string s.\n * returns:\n *    .value = the integer literal as a string,\n *    .rest = the string following the integer literal\n * Otherwise:\n *    .value = null,\n *    .rest = s\n */\n\ntemplate parseUinteger(const(char)[] s)\n{\n    static if (s.length == 0)\n    {\n        enum value = \"\";\n        enum rest = \"\";\n    }\n    else static if (s[0] >= '0' && s[0] <= '9')\n    {\n        enum value = s[0] ~ parseUinteger!(s[1..$]).value;\n        enum rest = parseUinteger!(s[1..$]).rest;\n    }\n    else\n    {\n        enum value = \"\";\n        enum rest = s;\n    }\n}\n\n/********\nParse integer literal optionally preceded by $(D '-') from the start\nof string $(D s).\n\nReturns:\n   .value = the integer literal as a string,\n   .rest = the string following the integer literal\n\nOtherwise:\n   .value = null,\n   .rest = s\n*/\n\ntemplate parseInteger(const(char)[] s)\n{\n    static if (s.length == 0)\n    {\n        enum value = \"\";\n        enum rest = \"\";\n    }\n    else static if (s[0] >= '0' && s[0] <= '9')\n    {\n        enum value = s[0] ~ parseUinteger!(s[1..$]).value;\n        enum rest = parseUinteger!(s[1..$]).rest;\n    }\n    else static if (s.length >= 2 &&\n            s[0] == '-' && s[1] >= '0' && s[1] <= '9')\n    {\n        enum value = s[0..2] ~ parseUinteger!(s[2..$]).value;\n        enum rest = parseUinteger!(s[2..$]).rest;\n    }\n    else\n    {\n        enum value = \"\";\n        enum rest = s;\n    }\n}\n\nunittest\n{\n    assert(parseUinteger!(\"1234abc\").value == \"1234\");\n    assert(parseUinteger!(\"1234abc\").rest == \"abc\");\n    assert(parseInteger!(\"-1234abc\").value == \"-1234\");\n    assert(parseInteger!(\"-1234abc\").rest == \"abc\");\n}\n\n/**\nDeprecated aliases held for backward compatibility.\n*/\ndeprecated alias toStringNow ToString;\n/// Ditto\ndeprecated alias parseUinteger ParseUinteger;\n/// Ditto\ndeprecated alias parseUinteger ParseInteger;\n\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        indentUnit: 4,\n        mode: \"text/x-d\"\n      });\n    </script>\n\n    <p>Simple mode that handle D-Syntax (<a href=\"http://www.dlang.org\">DLang Homepage</a>).</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-d</code>\n    .</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dart/dart.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\"), require(\"../clike/clike\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../clike/clike\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  var keywords = (\"this super static final const abstract class extends external factory \" +\n    \"implements get native operator set typedef with enum throw rethrow \" +\n    \"assert break case continue default in return new deferred async await \" +\n    \"try catch finally do else for if switch while import library export \" +\n    \"part of show hide is\").split(\" \");\n  var blockKeywords = \"try catch finally do else for if switch while\".split(\" \");\n  var atoms = \"true false null\".split(\" \");\n  var builtins = \"void bool num int double dynamic var String\".split(\" \");\n\n  function set(words) {\n    var obj = {};\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n\n  CodeMirror.defineMIME(\"application/dart\", {\n    name: \"clike\",\n    keywords: set(keywords),\n    multiLineStrings: true,\n    blockKeywords: set(blockKeywords),\n    builtin: set(builtins),\n    atoms: set(atoms),\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n\n  CodeMirror.registerHelper(\"hintWords\", \"application/dart\", keywords.concat(atoms).concat(builtins));\n\n  // This is needed to make loading through meta.js work.\n  CodeMirror.defineMode(\"dart\", function(conf) {\n    return CodeMirror.getMode(conf, \"application/dart\");\n  }, \"clike\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dart/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Dart mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../clike/clike.js\"></script>\n<script src=\"dart.js\"></script>\n<style>.CodeMirror {border: 1px solid #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Dart</a>\n  </ul>\n</div>\n\n<article>\n<h2>Dart mode</h2>\n<form>\n<textarea id=\"code\" name=\"code\">\nimport 'dart:math' show Random;\n\nvoid main() {\n  print(new Die(n: 12).roll());\n}\n\n// Define a class.\nclass Die {\n  // Define a class variable.\n  static Random shaker = new Random();\n\n  // Define instance variables.\n  int sides, value;\n\n  // Define a method using shorthand syntax.\n  String toString() => '$value';\n\n  // Define a constructor.\n  Die({int n: 6}) {\n    if (4 <= n && n <= 20) {\n      sides = n;\n    } else {\n      // Support for errors and exceptions.\n      throw new ArgumentError(/* */);\n    }\n  }\n\n  // Define an instance method.\n  int roll() {\n    return value = shaker.nextInt(sides) + 1;\n  }\n}\n</textarea>\n</form>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n    lineNumbers: true,\n    mode: \"application/dart\"\n  });\n</script>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/diff/diff.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(\"diff\", function() {\n\n  var TOKEN_NAMES = {\n    '+': 'positive',\n    '-': 'negative',\n    '@': 'meta'\n  };\n\n  return {\n    token: function(stream) {\n      var tw_pos = stream.string.search(/[\\t ]+?$/);\n\n      if (!stream.sol() || tw_pos === 0) {\n        stream.skipToEnd();\n        return (\"error \" + (\n          TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');\n      }\n\n      var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();\n\n      if (tw_pos === -1) {\n        stream.skipToEnd();\n      } else {\n        stream.pos = tw_pos;\n      }\n\n      return token_name;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-diff\", \"diff\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/diff/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Diff mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"diff.js\"></script>\n<style>\n      .CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}\n      span.cm-meta {color: #a0b !important;}\n      span.cm-error { background-color: black; opacity: 0.4;}\n      span.cm-error.cm-string { background-color: red; }\n      span.cm-error.cm-tag { background-color: #2b2; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Diff</a>\n  </ul>\n</div>\n\n<article>\n<h2>Diff mode</h2>\n<form><textarea id=\"code\" name=\"code\">\ndiff --git a/index.html b/index.html\nindex c1d9156..7764744 100644\n--- a/index.html\n+++ b/index.html\n@@ -95,7 +95,8 @@ StringStream.prototype = {\n     <script>\n       var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n         lineNumbers: true,\n-        autoMatchBrackets: true\n+        autoMatchBrackets: true,\n+      onGutterClick: function(x){console.log(x);}\n       });\n     </script>\n   </body>\ndiff --git a/lib/codemirror.js b/lib/codemirror.js\nindex 04646a9..9a39cc7 100644\n--- a/lib/codemirror.js\n+++ b/lib/codemirror.js\n@@ -399,10 +399,16 @@ var CodeMirror = (function() {\n     }\n\n     function onMouseDown(e) {\n-      var start = posFromMouse(e), last = start;\n+      var start = posFromMouse(e), last = start, target = e.target();\n       if (!start) return;\n       setCursor(start.line, start.ch, false);\n       if (e.button() != 1) return;\n+      if (target.parentNode == gutter) {\n+        if (options.onGutterClick)\n+          options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);\n+        return;\n+      }\n+\n       if (!focused) onFocus();\n\n       e.stop();\n@@ -808,7 +814,7 @@ var CodeMirror = (function() {\n       for (var i = showingFrom; i < showingTo; ++i) {\n         var marker = lines[i].gutterMarker;\n         if (marker) html.push('<div class=\"' + marker.style + '\">' + htmlEscape(marker.text) + '</div>');\n-        else html.push(\"<div>\" + (options.lineNumbers ? i + 1 : \"\\u00a0\") + \"</div>\");\n+        else html.push(\"<div>\" + (options.lineNumbers ? i + options.firstLineNumber : \"\\u00a0\") + \"</div>\");\n       }\n       gutter.style.display = \"none\"; // TODO test whether this actually helps\n       gutter.innerHTML = html.join(\"\");\n@@ -1371,10 +1377,8 @@ var CodeMirror = (function() {\n         if (option == \"parser\") setParser(value);\n         else if (option === \"lineNumbers\") setLineNumbers(value);\n         else if (option === \"gutter\") setGutter(value);\n-        else if (option === \"readOnly\") options.readOnly = value;\n-        else if (option === \"indentUnit\") {options.indentUnit = indentUnit = value; setParser(options.parser);}\n-        else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;\n-        else throw new Error(\"Can't set option \" + option);\n+        else if (option === \"indentUnit\") {options.indentUnit = value; setParser(options.parser);}\n+        else options[option] = value;\n       },\n       cursorCoords: cursorCoords,\n       undo: operation(undo),\n@@ -1402,7 +1406,8 @@ var CodeMirror = (function() {\n       replaceRange: operation(replaceRange),\n\n       operation: function(f){return operation(f)();},\n-      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}\n+      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},\n+      getInputField: function(){return input;}\n     };\n     return instance;\n   }\n@@ -1420,6 +1425,7 @@ var CodeMirror = (function() {\n     readOnly: false,\n     onChange: null,\n     onCursorActivity: null,\n+    onGutterClick: null,\n     autoMatchBrackets: false,\n     workTime: 200,\n     workDelay: 300,\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/django/django.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\"), require(\"../htmlmixed/htmlmixed\"),\n        require(\"../../addon/mode/overlay\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\",\n            \"../../addon/mode/overlay\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  CodeMirror.defineMode(\"django:inner\", function() {\n    var keywords = [\"block\", \"endblock\", \"for\", \"endfor\", \"in\", \"true\", \"false\",\n                    \"loop\", \"none\", \"self\", \"super\", \"if\", \"endif\", \"as\", \"not\", \"and\",\n                    \"else\", \"import\", \"with\", \"endwith\", \"without\", \"context\", \"ifequal\", \"endifequal\",\n                    \"ifnotequal\", \"endifnotequal\", \"extends\", \"include\", \"load\", \"length\", \"comment\",\n                    \"endcomment\", \"empty\"];\n    keywords = new RegExp(\"^((\" + keywords.join(\")|(\") + \"))\\\\b\");\n\n    function tokenBase (stream, state) {\n      stream.eatWhile(/[^\\{]/);\n      var ch = stream.next();\n      if (ch == \"{\") {\n        if (ch = stream.eat(/\\{|%|#/)) {\n          state.tokenize = inTag(ch);\n          return \"tag\";\n        }\n      }\n    }\n    function inTag (close) {\n      if (close == \"{\") {\n        close = \"}\";\n      }\n      return function (stream, state) {\n        var ch = stream.next();\n        if ((ch == close) && stream.eat(\"}\")) {\n          state.tokenize = tokenBase;\n          return \"tag\";\n        }\n        if (stream.match(keywords)) {\n          return \"keyword\";\n        }\n        return close == \"#\" ? \"comment\" : \"string\";\n      };\n    }\n    return {\n      startState: function () {\n        return {tokenize: tokenBase};\n      },\n      token: function (stream, state) {\n        return state.tokenize(stream, state);\n      }\n    };\n  });\n\n  CodeMirror.defineMode(\"django\", function(config) {\n    var htmlBase = CodeMirror.getMode(config, \"text/html\");\n    var djangoInner = CodeMirror.getMode(config, \"django:inner\");\n    return CodeMirror.overlayMode(htmlBase, djangoInner);\n  });\n\n  CodeMirror.defineMIME(\"text/x-django\", \"django\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/django/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Django template mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/mode/overlay.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"django.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Django</a>\n  </ul>\n</div>\n\n<article>\n<h2>Django template mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n<!doctype html>\n<html>\n    <head>\n        <title>My Django web application</title>\n    </head>\n    <body class=\"gray-bg\">\n        <h1>\n            {{ page.title }}\n        </h1>\n        <ul class=\"my-list\">\n            {% for item in items %}\n                <li>{% item.name %}</li>\n            {% empty %}\n                <li>You have no items in your list.</li>\n            {% endfor %}\n        </ul>\n    </body>\n</html>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"django\",\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n    </script>\n\n    <p>Mode for HTML with embedded Django template markup.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-django</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dockerfile/dockerfile.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\"), require(\"../../addon/mode/simple\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../../addon/mode/simple\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  // Collect all Dockerfile directives\n  var instructions = [\"from\", \"maintainer\", \"run\", \"cmd\", \"expose\", \"env\",\n                      \"add\", \"copy\", \"entrypoint\", \"volume\", \"user\",\n                      \"workdir\", \"onbuild\"],\n      instructionRegex = \"(\" + instructions.join('|') + \")\",\n      instructionOnlyLine = new RegExp(instructionRegex + \"\\\\s*$\", \"i\"),\n      instructionWithArguments = new RegExp(instructionRegex + \"(\\\\s+)\", \"i\");\n\n  CodeMirror.defineSimpleMode(\"dockerfile\", {\n    start: [\n      // Block comment: This is a line starting with a comment\n      {\n        regex: /#.*$/,\n        token: \"comment\"\n      },\n      // Highlight an instruction without any arguments (for convenience)\n      {\n        regex: instructionOnlyLine,\n        token: \"variable-2\"\n      },\n      // Highlight an instruction followed by arguments\n      {\n        regex: instructionWithArguments,\n        token: [\"variable-2\", null],\n        next: \"arguments\"\n      },\n      {\n        regex: /./,\n        token: null\n      }\n    ],\n    arguments: [\n      {\n        // Line comment without instruction arguments is an error\n        regex: /#.*$/,\n        token: \"error\",\n        next: \"start\"\n      },\n      {\n        regex: /[^#]+\\\\$/,\n        token: null\n      },\n      {\n        // Match everything except for the inline comment\n        regex: /[^#]+/,\n        token: null,\n        next: \"start\"\n      },\n      {\n        regex: /$/,\n        token: null,\n        next: \"start\"\n      },\n      // Fail safe return to start\n      {\n        token: null,\n        next: \"start\"\n      }\n    ]\n  });\n\n  CodeMirror.defineMIME(\"text/x-dockerfile\", \"dockerfile\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dockerfile/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Dockerfile mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/mode/simple.js\"></script>\n<script src=\"dockerfile.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Dockerfile</a>\n  </ul>\n</div>\n\n<article>\n<h2>Dockerfile mode</h2>\n<form><textarea id=\"code\" name=\"code\"># Install Ghost blogging platform and run development environment\n#\n# VERSION 1.0.0\n\nFROM ubuntu:12.10\nMAINTAINER Amer Grgic \"amer@livebyt.es\"\nWORKDIR /data/ghost\n\n# Install dependencies for nginx installation\nRUN apt-get update\nRUN apt-get install -y python g++ make software-properties-common --force-yes\nRUN add-apt-repository ppa:chris-lea/node.js\nRUN apt-get update\n# Install unzip\nRUN apt-get install -y unzip\n# Install curl\nRUN apt-get install -y curl\n# Install nodejs & npm\nRUN apt-get install -y rlwrap\nRUN apt-get install -y nodejs\n# Download Ghost v0.4.1\nRUN curl -L https://ghost.org/zip/ghost-latest.zip -o /tmp/ghost.zip\n# Unzip Ghost zip to /data/ghost\nRUN unzip -uo /tmp/ghost.zip -d /data/ghost\n# Add custom config js to /data/ghost\nADD ./config.example.js /data/ghost/config.js\n# Install Ghost with NPM\nRUN cd /data/ghost/ && npm install --production\n# Expose port 2368\nEXPOSE 2368\n# Run Ghost\nCMD [\"npm\",\"start\"]\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"dockerfile\"\n      });\n    </script>\n\n    <p>Dockerfile syntax highlighting for CodeMirror. Depends on\n    the <a href=\"../../demo/simplemode.html\">simplemode</a> addon.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-dockerfile</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dtd/dtd.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\n  DTD mode\n  Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>\n  Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n  GitHub: @peterkroon\n*/\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(\"dtd\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n    if (ch == \"<\" && stream.eat(\"!\") ) {\n      if (stream.eatWhile(/[\\-]/)) {\n        state.tokenize = tokenSGMLComment;\n        return tokenSGMLComment(stream, state);\n      } else if (stream.eatWhile(/[\\w]/)) return ret(\"keyword\", \"doindent\");\n    } else if (ch == \"<\" && stream.eat(\"?\")) { //xml declaration\n      state.tokenize = inBlock(\"meta\", \"?>\");\n      return ret(\"meta\", ch);\n    } else if (ch == \"#\" && stream.eatWhile(/[\\w]/)) return ret(\"atom\", \"tag\");\n    else if (ch == \"|\") return ret(\"keyword\", \"seperator\");\n    else if (ch.match(/[\\(\\)\\[\\]\\-\\.,\\+\\?>]/)) return ret(null, ch);//if(ch === \">\") return ret(null, \"endtag\"); else\n    else if (ch.match(/[\\[\\]]/)) return ret(\"rule\", ch);\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    } else if (stream.eatWhile(/[a-zA-Z\\?\\+\\d]/)) {\n      var sc = stream.current();\n      if( sc.substr(sc.length-1,sc.length).match(/\\?|\\+/) !== null )stream.backUp(1);\n      return ret(\"tag\", \"tag\");\n    } else if (ch == \"%\" || ch == \"*\" ) return ret(\"number\", \"number\");\n    else {\n      stream.eatWhile(/[\\w\\\\\\-_%.{,]/);\n      return ret(null, null);\n    }\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return ret(\"string\", \"tag\");\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (stream.current() == \"[\" || type === \"doindent\" || type == \"[\") state.stack.push(\"rule\");\n      else if (type === \"endtag\") state.stack[state.stack.length-1] = \"endtag\";\n      else if (stream.current() == \"]\" || type == \"]\" || (type == \">\" && context == \"rule\")) state.stack.pop();\n      else if (type == \"[\") state.stack.push(\"[\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n\n      if( textAfter.match(/\\]\\s+|\\]/) )n=n-1;\n      else if(textAfter.substr(textAfter.length-1, textAfter.length) === \">\"){\n        if(textAfter.substr(0,1) === \"<\")n;\n        else if( type == \"doindent\" && textAfter.length > 1 )n;\n        else if( type == \"doindent\")n--;\n        else if( type == \">\" && textAfter.length > 1)n;\n        else if( type == \"tag\" && textAfter !== \">\")n;\n        else if( type == \"tag\" && state.stack[state.stack.length-1] == \"rule\")n--;\n        else if( type == \"tag\")n++;\n        else if( textAfter === \">\" && state.stack[state.stack.length-1] == \"rule\" && type === \">\")n--;\n        else if( textAfter === \">\" && state.stack[state.stack.length-1] == \"rule\")n;\n        else if( textAfter.substr(0,1) !== \"<\" && textAfter.substr(0,1) === \">\" )n=n-1;\n        else if( textAfter === \">\")n;\n        else n=n-1;\n        //over rule them all\n        if(type == null || type == \"]\")n--;\n      }\n\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"]>\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml-dtd\", \"dtd\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dtd/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: DTD mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"dtd.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">DTD</a>\n  </ul>\n</div>\n\n<article>\n<h2>DTD mode</h2>\n<form><textarea id=\"code\" name=\"code\"><?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!ATTLIST title\n  xmlns\tCDATA\t#FIXED\t\"http://docbook.org/ns/docbook\"\n  role\tCDATA\t#IMPLIED\n  %db.common.attributes;\n  %db.common.linking.attributes;\n>\n\n<!--\n  Try: http://docbook.org/xml/5.0/dtd/docbook.dtd\n-->\n\n<!DOCTYPE xsl:stylesheet\n  [\n    <!ENTITY nbsp   \"&amp;#160;\">\n    <!ENTITY copy   \"&amp;#169;\">\n    <!ENTITY reg    \"&amp;#174;\">\n    <!ENTITY trade  \"&amp;#8482;\">\n    <!ENTITY mdash  \"&amp;#8212;\">\n    <!ENTITY ldquo  \"&amp;#8220;\">\n    <!ENTITY rdquo  \"&amp;#8221;\">\n    <!ENTITY pound  \"&amp;#163;\">\n    <!ENTITY yen    \"&amp;#165;\">\n    <!ENTITY euro   \"&amp;#8364;\">\n    <!ENTITY mathml \"http://www.w3.org/1998/Math/MathML\">\n  ]\n>\n\n<!ELEMENT title (#PCDATA|inlinemediaobject|remark|superscript|subscript|xref|link|olink|anchor|biblioref|alt|annotation|indexterm|abbrev|acronym|date|emphasis|footnote|footnoteref|foreignphrase|phrase|quote|wordasword|firstterm|glossterm|coref|trademark|productnumber|productname|database|application|hardware|citation|citerefentry|citetitle|citebiblioid|author|person|personname|org|orgname|editor|jobtitle|replaceable|package|parameter|termdef|nonterminal|systemitem|option|optional|property|inlineequation|tag|markup|token|symbol|literal|code|constant|email|uri|guiicon|guibutton|guimenuitem|guimenu|guisubmenu|guilabel|menuchoice|mousebutton|keycombo|keycap|keycode|keysym|shortcut|accel|prompt|envar|filename|command|computeroutput|userinput|function|varname|returnvalue|type|classname|exceptionname|interfacename|methodname|modifier|initializer|ooclass|ooexception|oointerface|errorcode|errortext|errorname|errortype)*>\n\n<!ENTITY % db.common.attributes \"\n  xml:id\tID\t#IMPLIED\n  version\tCDATA\t#IMPLIED\n  xml:lang\tCDATA\t#IMPLIED\n  xml:base\tCDATA\t#IMPLIED\n  remap\tCDATA\t#IMPLIED\n  xreflabel\tCDATA\t#IMPLIED\n  revisionflag\t(changed|added|deleted|off)\t#IMPLIED\n  dir\t(ltr|rtl|lro|rlo)\t#IMPLIED\n  arch\tCDATA\t#IMPLIED\n  audience\tCDATA\t#IMPLIED\n  condition\tCDATA\t#IMPLIED\n  conformance\tCDATA\t#IMPLIED\n  os\tCDATA\t#IMPLIED\n  revision\tCDATA\t#IMPLIED\n  security\tCDATA\t#IMPLIED\n  userlevel\tCDATA\t#IMPLIED\n  vendor\tCDATA\t#IMPLIED\n  wordsize\tCDATA\t#IMPLIED\n  annotations\tCDATA\t#IMPLIED\n\n\"></textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"dtd\", alignCDATA: true},\n        lineNumbers: true,\n        lineWrapping: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>application/xml-dtd</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dylan/dylan.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(\"dylan\", function(_config) {\n  // Words\n  var words = {\n    // Words that introduce unnamed definitions like \"define interface\"\n    unnamedDefinition: [\"interface\"],\n\n    // Words that introduce simple named definitions like \"define library\"\n    namedDefinition: [\"module\", \"library\", \"macro\",\n                      \"C-struct\", \"C-union\",\n                      \"C-function\", \"C-callable-wrapper\"\n                     ],\n\n    // Words that introduce type definitions like \"define class\".\n    // These are also parameterized like \"define method\" and are\n    // appended to otherParameterizedDefinitionWords\n    typeParameterizedDefinition: [\"class\", \"C-subtype\", \"C-mapped-subtype\"],\n\n    // Words that introduce trickier definitions like \"define method\".\n    // These require special definitions to be added to startExpressions\n    otherParameterizedDefinition: [\"method\", \"function\",\n                                   \"C-variable\", \"C-address\"\n                                  ],\n\n    // Words that introduce module constant definitions.\n    // These must also be simple definitions and are\n    // appended to otherSimpleDefinitionWords\n    constantSimpleDefinition: [\"constant\"],\n\n    // Words that introduce module variable definitions.\n    // These must also be simple definitions and are\n    // appended to otherSimpleDefinitionWords\n    variableSimpleDefinition: [\"variable\"],\n\n    // Other words that introduce simple definitions\n    // (without implicit bodies).\n    otherSimpleDefinition: [\"generic\", \"domain\",\n                            \"C-pointer-type\",\n                            \"table\"\n                           ],\n\n    // Words that begin statements with implicit bodies.\n    statement: [\"if\", \"block\", \"begin\", \"method\", \"case\",\n                \"for\", \"select\", \"when\", \"unless\", \"until\",\n                \"while\", \"iterate\", \"profiling\", \"dynamic-bind\"\n               ],\n\n    // Patterns that act as separators in compound statements.\n    // This may include any general pattern that must be indented\n    // specially.\n    separator: [\"finally\", \"exception\", \"cleanup\", \"else\",\n                \"elseif\", \"afterwards\"\n               ],\n\n    // Keywords that do not require special indentation handling,\n    // but which should be highlighted\n    other: [\"above\", \"below\", \"by\", \"from\", \"handler\", \"in\",\n            \"instance\", \"let\", \"local\", \"otherwise\", \"slot\",\n            \"subclass\", \"then\", \"to\", \"keyed-by\", \"virtual\"\n           ],\n\n    // Condition signaling function calls\n    signalingCalls: [\"signal\", \"error\", \"cerror\",\n                     \"break\", \"check-type\", \"abort\"\n                    ]\n  };\n\n  words[\"otherDefinition\"] =\n    words[\"unnamedDefinition\"]\n    .concat(words[\"namedDefinition\"])\n    .concat(words[\"otherParameterizedDefinition\"]);\n\n  words[\"definition\"] =\n    words[\"typeParameterizedDefinition\"]\n    .concat(words[\"otherDefinition\"]);\n\n  words[\"parameterizedDefinition\"] =\n    words[\"typeParameterizedDefinition\"]\n    .concat(words[\"otherParameterizedDefinition\"]);\n\n  words[\"simpleDefinition\"] =\n    words[\"constantSimpleDefinition\"]\n    .concat(words[\"variableSimpleDefinition\"])\n    .concat(words[\"otherSimpleDefinition\"]);\n\n  words[\"keyword\"] =\n    words[\"statement\"]\n    .concat(words[\"separator\"])\n    .concat(words[\"other\"]);\n\n  // Patterns\n  var symbolPattern = \"[-_a-zA-Z?!*@<>$%]+\";\n  var symbol = new RegExp(\"^\" + symbolPattern);\n  var patterns = {\n    // Symbols with special syntax\n    symbolKeyword: symbolPattern + \":\",\n    symbolClass: \"<\" + symbolPattern + \">\",\n    symbolGlobal: \"\\\\*\" + symbolPattern + \"\\\\*\",\n    symbolConstant: \"\\\\$\" + symbolPattern\n  };\n  var patternStyles = {\n    symbolKeyword: \"atom\",\n    symbolClass: \"tag\",\n    symbolGlobal: \"variable-2\",\n    symbolConstant: \"variable-3\"\n  };\n\n  // Compile all patterns to regular expressions\n  for (var patternName in patterns)\n    if (patterns.hasOwnProperty(patternName))\n      patterns[patternName] = new RegExp(\"^\" + patterns[patternName]);\n\n  // Names beginning \"with-\" and \"without-\" are commonly\n  // used as statement macro\n  patterns[\"keyword\"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];\n\n  var styles = {};\n  styles[\"keyword\"] = \"keyword\";\n  styles[\"definition\"] = \"def\";\n  styles[\"simpleDefinition\"] = \"def\";\n  styles[\"signalingCalls\"] = \"builtin\";\n\n  // protected words lookup table\n  var wordLookup = {};\n  var styleLookup = {};\n\n  [\n    \"keyword\",\n    \"definition\",\n    \"simpleDefinition\",\n    \"signalingCalls\"\n  ].forEach(function(type) {\n    words[type].forEach(function(word) {\n      wordLookup[word] = type;\n      styleLookup[word] = styles[type];\n    });\n  });\n\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  var type, content;\n\n  function ret(_type, style, _content) {\n    type = _type;\n    content = _content;\n    return style;\n  }\n\n  function tokenBase(stream, state) {\n    // String\n    var ch = stream.peek();\n    if (ch == \"'\" || ch == '\"') {\n      stream.next();\n      return chain(stream, state, tokenString(ch, \"string\", \"string\"));\n    }\n    // Comment\n    else if (ch == \"/\") {\n      stream.next();\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, tokenComment);\n      } else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      } else {\n        stream.skipTo(\" \");\n        return ret(\"operator\", \"operator\");\n      }\n    }\n    // Decimal\n    else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:e[+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    // Hash\n    else if (ch == \"#\") {\n      stream.next();\n      // Symbol with string syntax\n      ch = stream.peek();\n      if (ch == '\"') {\n        stream.next();\n        return chain(stream, state, tokenString('\"', \"symbol\", \"string-2\"));\n      }\n      // Binary number\n      else if (ch == \"b\") {\n        stream.next();\n        stream.eatWhile(/[01]/);\n        return ret(\"number\", \"number\");\n      }\n      // Hex number\n      else if (ch == \"x\") {\n        stream.next();\n        stream.eatWhile(/[\\da-f]/i);\n        return ret(\"number\", \"number\");\n      }\n      // Octal number\n      else if (ch == \"o\") {\n        stream.next();\n        stream.eatWhile(/[0-7]/);\n        return ret(\"number\", \"number\");\n      }\n      // Hash symbol\n      else {\n        stream.eatWhile(/[-a-zA-Z]/);\n        return ret(\"hash\", \"keyword\");\n      }\n    } else if (stream.match(\"end\")) {\n      return ret(\"end\", \"keyword\");\n    }\n    for (var name in patterns) {\n      if (patterns.hasOwnProperty(name)) {\n        var pattern = patterns[name];\n        if ((pattern instanceof Array && pattern.some(function(p) {\n          return stream.match(p);\n        })) || stream.match(pattern))\n          return ret(name, patternStyles[name], stream.current());\n      }\n    }\n    if (stream.match(\"define\")) {\n      return ret(\"definition\", \"def\");\n    } else {\n      stream.eatWhile(/[\\w\\-]/);\n      // Keyword\n      if (wordLookup[stream.current()]) {\n        return ret(wordLookup[stream.current()], styleLookup[stream.current()], stream.current());\n      } else if (stream.current().match(symbol)) {\n        return ret(\"variable\", \"variable\");\n      } else {\n        stream.next();\n        return ret(\"other\", \"variable-2\");\n      }\n    }\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false,\n    ch;\n    while ((ch = stream.next())) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote, type, style) {\n    return function(stream, state) {\n      var next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote) {\n          end = true;\n          break;\n        }\n      }\n      if (end)\n        state.tokenize = tokenBase;\n      return ret(type, style);\n    };\n  }\n\n  // Interface\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        currentIndent: 0\n      };\n    },\n    token: function(stream, state) {\n      if (stream.eatSpace())\n        return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    },\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-dylan\", \"dylan\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/dylan/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Dylan mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../../addon/comment/continuecomment.js\"></script>\n<script src=\"../../addon/comment/comment.js\"></script>\n<script src=\"dylan.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Dylan</a>\n  </ul>\n</div>\n\n<article>\n<h2>Dylan mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\nModule:       locators-internals\nSynopsis:     Abstract modeling of locations\nAuthor:       Andy Armstrong\nCopyright:    Original Code is Copyright (c) 1995-2004 Functional Objects, Inc.\n              All rights reserved.\nLicense:      See License.txt in this distribution for details.\nWarranty:     Distributed WITHOUT WARRANTY OF ANY KIND\n\ndefine open generic locator-server\n    (locator :: <locator>) => (server :: false-or(<server-locator>));\ndefine open generic locator-host\n    (locator :: <locator>) => (host :: false-or(<string>));\ndefine open generic locator-volume\n    (locator :: <locator>) => (volume :: false-or(<string>));\ndefine open generic locator-directory\n    (locator :: <locator>) => (directory :: false-or(<directory-locator>));\ndefine open generic locator-relative?\n    (locator :: <locator>) => (relative? :: <boolean>);\ndefine open generic locator-path\n    (locator :: <locator>) => (path :: <sequence>);\ndefine open generic locator-base\n    (locator :: <locator>) => (base :: false-or(<string>));\ndefine open generic locator-extension\n    (locator :: <locator>) => (extension :: false-or(<string>));\n\n/// Locator classes\n\ndefine open abstract class <directory-locator> (<physical-locator>)\nend class <directory-locator>;\n\ndefine open abstract class <file-locator> (<physical-locator>)\nend class <file-locator>;\n\ndefine method as\n    (class == <directory-locator>, string :: <string>)\n => (locator :: <directory-locator>)\n  as(<native-directory-locator>, string)\nend method as;\n\ndefine method make\n    (class == <directory-locator>,\n     #key server :: false-or(<server-locator>) = #f,\n          path :: <sequence> = #[],\n          relative? :: <boolean> = #f,\n          name :: false-or(<string>) = #f)\n => (locator :: <directory-locator>)\n  make(<native-directory-locator>,\n       server:    server,\n       path:      path,\n       relative?: relative?,\n       name:      name)\nend method make;\n\ndefine method as\n    (class == <file-locator>, string :: <string>)\n => (locator :: <file-locator>)\n  as(<native-file-locator>, string)\nend method as;\n\ndefine method make\n    (class == <file-locator>,\n     #key directory :: false-or(<directory-locator>) = #f,\n          base :: false-or(<string>) = #f,\n          extension :: false-or(<string>) = #f,\n          name :: false-or(<string>) = #f)\n => (locator :: <file-locator>)\n  make(<native-file-locator>,\n       directory: directory,\n       base:      base,\n       extension: extension,\n       name:      name)\nend method make;\n\n/// Locator coercion\n\n//---*** andrewa: This caching scheme doesn't work yet, so disable it.\ndefine constant $cache-locators?        = #f;\ndefine constant $cache-locator-strings? = #f;\n\ndefine constant $locator-to-string-cache = make(<object-table>, weak: #\"key\");\ndefine constant $string-to-locator-cache = make(<string-table>, weak: #\"value\");\n\ndefine open generic locator-as-string\n    (class :: subclass(<string>), locator :: <locator>)\n => (string :: <string>);\n\ndefine open generic string-as-locator\n    (class :: subclass(<locator>), string :: <string>)\n => (locator :: <locator>);\n\ndefine sealed sideways method as\n    (class :: subclass(<string>), locator :: <locator>)\n => (string :: <string>)\n  let string = element($locator-to-string-cache, locator, default: #f);\n  if (string)\n    as(class, string)\n  else\n    let string = locator-as-string(class, locator);\n    if ($cache-locator-strings?)\n      element($locator-to-string-cache, locator) := string;\n    else\n      string\n    end\n  end\nend method as;\n\ndefine sealed sideways method as\n    (class :: subclass(<locator>), string :: <string>)\n => (locator :: <locator>)\n  let locator = element($string-to-locator-cache, string, default: #f);\n  if (instance?(locator, class))\n    locator\n  else\n    let locator = string-as-locator(class, string);\n    if ($cache-locators?)\n      element($string-to-locator-cache, string) := locator;\n    else\n      locator\n    end\n  end\nend method as;\n\n/// Locator conditions\n\ndefine class <locator-error> (<format-string-condition>, <error>)\nend class <locator-error>;\n\ndefine function locator-error\n    (format-string :: <string>, #rest format-arguments)\n  error(make(<locator-error>,\n             format-string:    format-string,\n             format-arguments: format-arguments))\nend function locator-error;\n\n/// Useful locator protocols\n\ndefine open generic locator-test\n    (locator :: <directory-locator>) => (test :: <function>);\n\ndefine method locator-test\n    (locator :: <directory-locator>) => (test :: <function>)\n  \\=\nend method locator-test;\n\ndefine open generic locator-might-have-links?\n    (locator :: <directory-locator>) => (links? :: <boolean>);\n\ndefine method locator-might-have-links?\n    (locator :: <directory-locator>) => (links? :: singleton(#f))\n  #f\nend method locator-might-have-links?;\n\ndefine method locator-relative?\n    (locator :: <file-locator>) => (relative? :: <boolean>)\n  let directory = locator.locator-directory;\n  ~directory | directory.locator-relative?\nend method locator-relative?;\n\ndefine method current-directory-locator?\n    (locator :: <directory-locator>) => (current-directory? :: <boolean>)\n  locator.locator-relative?\n    & locator.locator-path = #[#\"self\"]\nend method current-directory-locator?;\n\ndefine method locator-directory\n    (locator :: <directory-locator>) => (parent :: false-or(<directory-locator>))\n  let path = locator.locator-path;\n  unless (empty?(path))\n    make(object-class(locator),\n         server:    locator.locator-server,\n         path:      copy-sequence(path, end: path.size - 1),\n         relative?: locator.locator-relative?)\n  end\nend method locator-directory;\n\n/// Simplify locator\n\ndefine open generic simplify-locator\n    (locator :: <physical-locator>)\n => (simplified-locator :: <physical-locator>);\n\ndefine method simplify-locator\n    (locator :: <directory-locator>)\n => (simplified-locator :: <directory-locator>)\n  let path = locator.locator-path;\n  let relative? = locator.locator-relative?;\n  let resolve-parent? = ~locator.locator-might-have-links?;\n  let simplified-path\n    = simplify-path(path,\n                    resolve-parent?: resolve-parent?,\n                    relative?: relative?);\n  if (path ~= simplified-path)\n    make(object-class(locator),\n         server:    locator.locator-server,\n         path:      simplified-path,\n         relative?: locator.locator-relative?)\n  else\n    locator\n  end\nend method simplify-locator;\n\ndefine method simplify-locator\n    (locator :: <file-locator>) => (simplified-locator :: <file-locator>)\n  let directory = locator.locator-directory;\n  let simplified-directory = directory & simplify-locator(directory);\n  if (directory ~= simplified-directory)\n    make(object-class(locator),\n         directory: simplified-directory,\n         base:      locator.locator-base,\n         extension: locator.locator-extension)\n  else\n    locator\n  end\nend method simplify-locator;\n\n/// Subdirectory locator\n\ndefine open generic subdirectory-locator\n    (locator :: <directory-locator>, #rest sub-path)\n => (subdirectory :: <directory-locator>);\n\ndefine method subdirectory-locator\n    (locator :: <directory-locator>, #rest sub-path)\n => (subdirectory :: <directory-locator>)\n  let old-path = locator.locator-path;\n  let new-path = concatenate-as(<simple-object-vector>, old-path, sub-path);\n  make(object-class(locator),\n       server:    locator.locator-server,\n       path:      new-path,\n       relative?: locator.locator-relative?)\nend method subdirectory-locator;\n\n/// Relative locator\n\ndefine open generic relative-locator\n    (locator :: <physical-locator>, from-locator :: <physical-locator>)\n => (relative-locator :: <physical-locator>);\n\ndefine method relative-locator\n    (locator :: <directory-locator>, from-locator :: <directory-locator>)\n => (relative-locator :: <directory-locator>)\n  let path = locator.locator-path;\n  let from-path = from-locator.locator-path;\n  case\n    ~locator.locator-relative? & from-locator.locator-relative? =>\n      locator-error\n        (\"Cannot find relative path of absolute locator %= from relative locator %=\",\n         locator, from-locator);\n    locator.locator-server ~= from-locator.locator-server =>\n      locator;\n    path = from-path =>\n      make(object-class(locator),\n           path: vector(#\"self\"),\n           relative?: #t);\n    otherwise =>\n      make(object-class(locator),\n           path: relative-path(path, from-path, test: locator.locator-test),\n           relative?: #t);\n  end\nend method relative-locator;\n\ndefine method relative-locator\n    (locator :: <file-locator>, from-directory :: <directory-locator>)\n => (relative-locator :: <file-locator>)\n  let directory = locator.locator-directory;\n  let relative-directory = directory & relative-locator(directory, from-directory);\n  if (relative-directory ~= directory)\n    simplify-locator\n      (make(object-class(locator),\n            directory: relative-directory,\n            base:      locator.locator-base,\n            extension: locator.locator-extension))\n  else\n    locator\n  end\nend method relative-locator;\n\ndefine method relative-locator\n    (locator :: <physical-locator>, from-locator :: <file-locator>)\n => (relative-locator :: <physical-locator>)\n  let from-directory = from-locator.locator-directory;\n  case\n    from-directory =>\n      relative-locator(locator, from-directory);\n    ~locator.locator-relative? =>\n      locator-error\n        (\"Cannot find relative path of absolute locator %= from relative locator %=\",\n         locator, from-locator);\n    otherwise =>\n      locator;\n  end\nend method relative-locator;\n\n/// Merge locators\n\ndefine open generic merge-locators\n    (locator :: <physical-locator>, from-locator :: <physical-locator>)\n => (merged-locator :: <physical-locator>);\n\n/// Merge locators\n\ndefine method merge-locators\n    (locator :: <directory-locator>, from-locator :: <directory-locator>)\n => (merged-locator :: <directory-locator>)\n  if (locator.locator-relative?)\n    let path = concatenate(from-locator.locator-path, locator.locator-path);\n    simplify-locator\n      (make(object-class(locator),\n            server:    from-locator.locator-server,\n            path:      path,\n            relative?: from-locator.locator-relative?))\n  else\n    locator\n  end\nend method merge-locators;\n\ndefine method merge-locators\n    (locator :: <file-locator>, from-locator :: <directory-locator>)\n => (merged-locator :: <file-locator>)\n  let directory = locator.locator-directory;\n  let merged-directory\n    = if (directory)\n        merge-locators(directory, from-locator)\n      else\n        simplify-locator(from-locator)\n      end;\n  if (merged-directory ~= directory)\n    make(object-class(locator),\n         directory: merged-directory,\n         base:      locator.locator-base,\n         extension: locator.locator-extension)\n  else\n    locator\n  end\nend method merge-locators;\n\ndefine method merge-locators\n    (locator :: <physical-locator>, from-locator :: <file-locator>)\n => (merged-locator :: <physical-locator>)\n  let from-directory = from-locator.locator-directory;\n  if (from-directory)\n    merge-locators(locator, from-directory)\n  else\n    locator\n  end\nend method merge-locators;\n\n/// Locator protocols\n\ndefine sideways method supports-open-locator?\n    (locator :: <file-locator>) => (openable? :: <boolean>)\n  ~locator.locator-relative?\nend method supports-open-locator?;\n\ndefine sideways method open-locator\n    (locator :: <file-locator>, #rest keywords, #key, #all-keys)\n => (stream :: <stream>)\n  apply(open-file-stream, locator, keywords)\nend method open-locator;\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-dylan\",\n        lineNumbers: true,\n        matchBrackets: true,\n        continueComments: \"Enter\",\n        extraKeys: {\"Ctrl-Q\": \"toggleComment\"},\n        tabMode: \"indent\",\n        indentUnit: 2\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-dylan</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ebnf/ebnf.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  CodeMirror.defineMode(\"ebnf\", function (config) {\n    var commentType = {slash: 0, parenthesis: 1};\n    var stateType = {comment: 0, _string: 1, characterClass: 2};\n    var bracesMode = null;\n\n    if (config.bracesMode)\n      bracesMode = CodeMirror.getMode(config, config.bracesMode);\n\n    return {\n      startState: function () {\n        return {\n          stringType: null,\n          commentType: null,\n          braced: 0,\n          lhs: true,\n          localState: null,\n          stack: [],\n          inDefinition: false\n        };\n      },\n      token: function (stream, state) {\n        if (!stream) return;\n\n        //check for state changes\n        if (state.stack.length === 0) {\n          //strings\n          if ((stream.peek() == '\"') || (stream.peek() == \"'\")) {\n            state.stringType = stream.peek();\n            stream.next(); // Skip quote\n            state.stack.unshift(stateType._string);\n          } else if (stream.match(/^\\/\\*/)) { //comments starting with /*\n            state.stack.unshift(stateType.comment);\n            state.commentType = commentType.slash;\n          } else if (stream.match(/^\\(\\*/)) { //comments starting with (*\n            state.stack.unshift(stateType.comment);\n            state.commentType = commentType.parenthesis;\n          }\n        }\n\n        //return state\n        //stack has\n        switch (state.stack[0]) {\n        case stateType._string:\n          while (state.stack[0] === stateType._string && !stream.eol()) {\n            if (stream.peek() === state.stringType) {\n              stream.next(); // Skip quote\n              state.stack.shift(); // Clear flag\n            } else if (stream.peek() === \"\\\\\") {\n              stream.next();\n              stream.next();\n            } else {\n              stream.match(/^.[^\\\\\\\"\\']*/);\n            }\n          }\n          return state.lhs ? \"property string\" : \"string\"; // Token style\n\n        case stateType.comment:\n          while (state.stack[0] === stateType.comment && !stream.eol()) {\n            if (state.commentType === commentType.slash && stream.match(/\\*\\//)) {\n              state.stack.shift(); // Clear flag\n              state.commentType = null;\n            } else if (state.commentType === commentType.parenthesis && stream.match(/\\*\\)/)) {\n              state.stack.shift(); // Clear flag\n              state.commentType = null;\n            } else {\n              stream.match(/^.[^\\*]*/);\n            }\n          }\n          return \"comment\";\n\n        case stateType.characterClass:\n          while (state.stack[0] === stateType.characterClass && !stream.eol()) {\n            if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./))) {\n              state.stack.shift();\n            }\n          }\n          return \"operator\";\n        }\n\n        var peek = stream.peek();\n\n        if (bracesMode !== null && (state.braced || peek === \"{\")) {\n          if (state.localState === null)\n            state.localState = bracesMode.startState();\n\n          var token = bracesMode.token(stream, state.localState),\n          text = stream.current();\n\n          if (!token) {\n            for (var i = 0; i < text.length; i++) {\n              if (text[i] === \"{\") {\n                if (state.braced === 0) {\n                  token = \"matchingbracket\";\n                }\n                state.braced++;\n              } else if (text[i] === \"}\") {\n                state.braced--;\n                if (state.braced === 0) {\n                  token = \"matchingbracket\";\n                }\n              }\n            }\n          }\n          return token;\n        }\n\n        //no stack\n        switch (peek) {\n        case \"[\":\n          stream.next();\n          state.stack.unshift(stateType.characterClass);\n          return \"bracket\";\n        case \":\":\n        case \"|\":\n        case \";\":\n          stream.next();\n          return \"operator\";\n        case \"%\":\n          if (stream.match(\"%%\")) {\n            return \"header\";\n          } else if (stream.match(/[%][A-Za-z]+/)) {\n            return \"keyword\";\n          } else if (stream.match(/[%][}]/)) {\n            return \"matchingbracket\";\n          }\n          break;\n        case \"/\":\n          if (stream.match(/[\\/][A-Za-z]+/)) {\n          return \"keyword\";\n        }\n        case \"\\\\\":\n          if (stream.match(/[\\][a-z]+/)) {\n            return \"string-2\";\n          }\n        case \".\":\n          if (stream.match(\".\")) {\n            return \"atom\";\n          }\n        case \"*\":\n        case \"-\":\n        case \"+\":\n        case \"^\":\n          if (stream.match(peek)) {\n            return \"atom\";\n          }\n        case \"$\":\n          if (stream.match(\"$$\")) {\n            return \"builtin\";\n          } else if (stream.match(/[$][0-9]+/)) {\n            return \"variable-3\";\n          }\n        case \"<\":\n          if (stream.match(/<<[a-zA-Z_]+>>/)) {\n            return \"builtin\";\n          }\n        }\n\n        if (stream.match(/^\\/\\//)) {\n          stream.skipToEnd();\n          return \"comment\";\n        } else if (stream.match(/return/)) {\n          return \"operator\";\n        } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {\n          if (stream.match(/(?=[\\(.])/)) {\n            return \"variable\";\n          } else if (stream.match(/(?=[\\s\\n]*[:=])/)) {\n            return \"def\";\n          }\n          return \"variable-2\";\n        } else if ([\"[\", \"]\", \"(\", \")\"].indexOf(stream.peek()) != -1) {\n          stream.next();\n          return \"bracket\";\n        } else if (!stream.eatSpace()) {\n          stream.next();\n        }\n        return null;\n      }\n    };\n  });\n\n  CodeMirror.defineMIME(\"text/x-ebnf\", \"ebnf\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ebnf/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: EBNF Mode</title>\n    <meta charset=\"utf-8\"/>\n    <link rel=stylesheet href=\"../../doc/docs.css\">\n\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <script src=\"ebnf.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body class=\"gray-bg\">\n    <div id=nav>\n      <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n      <ul>\n        <li><a href=\"../../index.html\">Home</a>\n        <li><a href=\"../../doc/manual.html\">Manual</a>\n        <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n      </ul>\n      <ul>\n        <li><a href=\"../index.html\">Language modes</a>\n        <li><a class=active href=\"#\">EBNF Mode</a>\n      </ul>\n    </div>\n\n    <article>\n      <h2>EBNF Mode (bracesMode setting = \"javascript\")</h2>\n      <form><textarea id=\"code\" name=\"code\">\n/* description: Parses end executes mathematical expressions. */\n\n/* lexical grammar */\n%lex\n\n%%\n\\s+                   /* skip whitespace */\n[0-9]+(\".\"[0-9]+)?\\b  return 'NUMBER';\n\"*\"                   return '*';\n\"/\"                   return '/';\n\"-\"                   return '-';\n\"+\"                   return '+';\n\"^\"                   return '^';\n\"(\"                   return '(';\n\")\"                   return ')';\n\"PI\"                  return 'PI';\n\"E\"                   return 'E';\n&lt;&lt;EOF&gt;&gt;               return 'EOF';\n\n/lex\n\n/* operator associations and precedence */\n\n%left '+' '-'\n%left '*' '/'\n%left '^'\n%left UMINUS\n\n%start expressions\n\n%% /* language grammar */\n\nexpressions\n: e EOF\n{print($1); return $1;}\n;\n\ne\n: e '+' e\n{$$ = $1+$3;}\n| e '-' e\n{$$ = $1-$3;}\n| e '*' e\n{$$ = $1*$3;}\n| e '/' e\n{$$ = $1/$3;}\n| e '^' e\n{$$ = Math.pow($1, $3);}\n| '-' e %prec UMINUS\n{$$ = -$2;}\n| '(' e ')'\n{$$ = $2;}\n| NUMBER\n{$$ = Number(yytext);}\n| E\n{$$ = Math.E;}\n| PI\n{$$ = Math.PI;}\n;</textarea></form>\n      <script>\n        var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n          mode: {name: \"ebnf\"},\n          lineNumbers: true,\n          bracesMode: 'javascript'\n        });\n      </script>\n      <h3>The EBNF Mode</h3>\n      <p> Created by <a href=\"https://github.com/robertleeplummerjr\">Robert Plummer</a></p>\n    </article>\n  </body>\n</html>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ecl/ecl.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(\"ecl\", function(config) {\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\n  function metaHook(stream, state) {\n    if (!state.startOfLine) return false;\n    stream.skipToEnd();\n    return \"meta\";\n  }\n\n  var indentUnit = config.indentUnit;\n  var keyword = words(\"abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode\");\n  var variable = words(\"apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait\");\n  var variable_2 = words(\"__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath\");\n  var variable_3 = words(\"ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode\");\n  var builtin = words(\"checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when\");\n  var blockKeywords = words(\"catch class do else finally for if switch try while\");\n  var atoms = words(\"true false null\");\n  var hooks = {\"#\": metaHook};\n  var multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\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 (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\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      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current().toLowerCase();\n    if (keyword.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    } else if (variable.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable\";\n    } else if (variable_2.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable-2\";\n    } else if (variable_3.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable-3\";\n    } else if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    } else { //Data types are of from KEYWORD##\n                var i = cur.length - 1;\n                while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))\n                        --i;\n\n                if (i > 0) {\n                        var cur2 = cur.substr(0, i + 1);\n                if (variable_3.propertyIsEnumerable(cur2)) {\n                        if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = \"newstatement\";\n                        return \"variable-3\";\n                }\n            }\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return null;\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 = tokenBase;\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 = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function 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  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function 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\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      };\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 = 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 ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") 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 (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ecl\", \"ecl\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ecl/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: ECL mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"ecl.js\"></script>\n<style>.CodeMirror {border: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">ECL</a>\n  </ul>\n</div>\n\n<article>\n<h2>ECL mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n/*\nsample useless code to demonstrate ecl syntax highlighting\nthis is a multiline comment!\n*/\n\n//  this is a singleline comment!\n\nimport ut;\nr :=\n  record\n   string22 s1 := '123';\n   integer4 i1 := 123;\n  end;\n#option('tmp', true);\nd := dataset('tmp::qb', r, thor);\noutput(d);\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p>Based on CodeMirror's clike mode.  For more information see <a href=\"http://hpccsystems.com\">HPCC Systems</a> web site.</p>\n    <p><strong>MIME types defined:</strong> <code>text/x-ecl</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/eiffel/eiffel.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(\"eiffel\", function() {\n  function wordObj(words) {\n    var o = {};\n    for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n    return o;\n  }\n  var keywords = wordObj([\n    'note',\n    'across',\n    'when',\n    'variant',\n    'until',\n    'unique',\n    'undefine',\n    'then',\n    'strip',\n    'select',\n    'retry',\n    'rescue',\n    'require',\n    'rename',\n    'reference',\n    'redefine',\n    'prefix',\n    'once',\n    'old',\n    'obsolete',\n    'loop',\n    'local',\n    'like',\n    'is',\n    'inspect',\n    'infix',\n    'include',\n    'if',\n    'frozen',\n    'from',\n    'external',\n    'export',\n    'ensure',\n    'end',\n    'elseif',\n    'else',\n    'do',\n    'creation',\n    'create',\n    'check',\n    'alias',\n    'agent',\n    'separate',\n    'invariant',\n    'inherit',\n    'indexing',\n    'feature',\n    'expanded',\n    'deferred',\n    'class',\n    'Void',\n    'True',\n    'Result',\n    'Precursor',\n    'False',\n    'Current',\n    'create',\n    'attached',\n    'detachable',\n    'as',\n    'and',\n    'implies',\n    'not',\n    'or'\n  ]);\n  var operators = wordObj([\":=\", \"and then\",\"and\", \"or\",\"<<\",\">>\"]);\n  var curPunc;\n\n  function chain(newtok, stream, state) {\n    state.tokenize.push(newtok);\n    return newtok(stream, state);\n  }\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    if (stream.eatSpace()) return null;\n    var ch = stream.next();\n    if (ch == '\"'||ch == \"'\") {\n      return chain(readQuoted(ch, \"string\"), stream, state);\n    } else if (ch == \"-\"&&stream.eat(\"-\")) {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \":\"&&stream.eat(\"=\")) {\n      return \"operator\";\n    } else if (/[0-9]/.test(ch)) {\n      stream.eatWhile(/[xXbBCc0-9\\.]/);\n      stream.eat(/[\\?\\!]/);\n      return \"ident\";\n    } else if (/[a-zA-Z_0-9]/.test(ch)) {\n      stream.eatWhile(/[a-zA-Z_0-9]/);\n      stream.eat(/[\\?\\!]/);\n      return \"ident\";\n    } else if (/[=+\\-\\/*^%<>~]/.test(ch)) {\n      stream.eatWhile(/[=+\\-\\/*^%<>~]/);\n      return \"operator\";\n    } else {\n      return null;\n    }\n  }\n\n  function readQuoted(quote, style,  unescaped) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && (unescaped || !escaped)) {\n          state.tokenize.pop();\n          break;\n        }\n        escaped = !escaped && ch == \"%\";\n      }\n      return style;\n    };\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: [tokenBase]};\n    },\n\n    token: function(stream, state) {\n      var style = state.tokenize[state.tokenize.length-1](stream, state);\n      if (style == \"ident\") {\n        var word = stream.current();\n        style = keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n          : operators.propertyIsEnumerable(stream.current()) ? \"operator\"\n          : /^[A-Z][A-Z_0-9]*$/g.test(word) ? \"tag\"\n          : /^0[bB][0-1]+$/g.test(word) ? \"number\"\n          : /^0[cC][0-7]+$/g.test(word) ? \"number\"\n          : /^0[xX][a-fA-F0-9]+$/g.test(word) ? \"number\"\n          : /^([0-9]+\\.[0-9]*)|([0-9]*\\.[0-9]+)$/g.test(word) ? \"number\"\n          : /^[0-9]+$/g.test(word) ? \"number\"\n          : \"variable\";\n      }\n      return style;\n    },\n    lineComment: \"--\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-eiffel\", \"eiffel\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/eiffel/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Eiffel mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/neat.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"eiffel.js\"></script>\n<style>\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .cm-s-default span.cm-arrow { color: red; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Eiffel</a>\n  </ul>\n</div>\n\n<article>\n<h2>Eiffel mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nnote\n    description: \"[\n        Project-wide universal properties.\n        This class is an ancestor to all developer-written classes.\n        ANY may be customized for individual projects or teams.\n        ]\"\n\n    library: \"Free implementation of ELKS library\"\n    status: \"See notice at end of class.\"\n    legal: \"See notice at end of class.\"\n    date: \"$Date: 2013-01-25 11:49:00 -0800 (Fri, 25 Jan 2013) $\"\n    revision: \"$Revision: 712 $\"\n\nclass\n    ANY\n\nfeature -- Customization\n\nfeature -- Access\n\n    generator: STRING\n            -- Name of current object's generating class\n            -- (base class of the type of which it is a direct instance)\n        external\n            \"built_in\"\n        ensure\n            generator_not_void: Result /= Void\n            generator_not_empty: not Result.is_empty\n        end\n\n    generating_type: TYPE [detachable like Current]\n            -- Type of current object\n            -- (type of which it is a direct instance)\n        do\n            Result := {detachable like Current}\n        ensure\n            generating_type_not_void: Result /= Void\n        end\n\nfeature -- Status report\n\n    conforms_to (other: ANY): BOOLEAN\n            -- Does type of current object conform to type\n            -- of `other' (as per Eiffel: The Language, chapter 13)?\n        require\n            other_not_void: other /= Void\n        external\n            \"built_in\"\n        end\n\n    same_type (other: ANY): BOOLEAN\n            -- Is type of current object identical to type of `other'?\n        require\n            other_not_void: other /= Void\n        external\n            \"built_in\"\n        ensure\n            definition: Result = (conforms_to (other) and\n                                        other.conforms_to (Current))\n        end\n\nfeature -- Comparison\n\n    is_equal (other: like Current): BOOLEAN\n            -- Is `other' attached to an object considered\n            -- equal to current object?\n        require\n            other_not_void: other /= Void\n        external\n            \"built_in\"\n        ensure\n            symmetric: Result implies other ~ Current\n            consistent: standard_is_equal (other) implies Result\n        end\n\n    frozen standard_is_equal (other: like Current): BOOLEAN\n            -- Is `other' attached to an object of the same type\n            -- as current object, and field-by-field identical to it?\n        require\n            other_not_void: other /= Void\n        external\n            \"built_in\"\n        ensure\n            same_type: Result implies same_type (other)\n            symmetric: Result implies other.standard_is_equal (Current)\n        end\n\n    frozen equal (a: detachable ANY; b: like a): BOOLEAN\n            -- Are `a' and `b' either both void or attached\n            -- to objects considered equal?\n        do\n            if a = Void then\n                Result := b = Void\n            else\n                Result := b /= Void and then\n                            a.is_equal (b)\n            end\n        ensure\n            definition: Result = (a = Void and b = Void) or else\n                        ((a /= Void and b /= Void) and then\n                        a.is_equal (b))\n        end\n\n    frozen standard_equal (a: detachable ANY; b: like a): BOOLEAN\n            -- Are `a' and `b' either both void or attached to\n            -- field-by-field identical objects of the same type?\n            -- Always uses default object comparison criterion.\n        do\n            if a = Void then\n                Result := b = Void\n            else\n                Result := b /= Void and then\n                            a.standard_is_equal (b)\n            end\n        ensure\n            definition: Result = (a = Void and b = Void) or else\n                        ((a /= Void and b /= Void) and then\n                        a.standard_is_equal (b))\n        end\n\n    frozen is_deep_equal (other: like Current): BOOLEAN\n            -- Are `Current' and `other' attached to isomorphic object structures?\n        require\n            other_not_void: other /= Void\n        external\n            \"built_in\"\n        ensure\n            shallow_implies_deep: standard_is_equal (other) implies Result\n            same_type: Result implies same_type (other)\n            symmetric: Result implies other.is_deep_equal (Current)\n        end\n\n    frozen deep_equal (a: detachable ANY; b: like a): BOOLEAN\n            -- Are `a' and `b' either both void\n            -- or attached to isomorphic object structures?\n        do\n            if a = Void then\n                Result := b = Void\n            else\n                Result := b /= Void and then a.is_deep_equal (b)\n            end\n        ensure\n            shallow_implies_deep: standard_equal (a, b) implies Result\n            both_or_none_void: (a = Void) implies (Result = (b = Void))\n            same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))\n            symmetric: Result implies deep_equal (b, a)\n        end\n\nfeature -- Duplication\n\n    frozen twin: like Current\n            -- New object equal to `Current'\n            -- `twin' calls `copy'; to change copying/twinning semantics, redefine `copy'.\n        external\n            \"built_in\"\n        ensure\n            twin_not_void: Result /= Void\n            is_equal: Result ~ Current\n        end\n\n    copy (other: like Current)\n            -- Update current object using fields of object attached\n            -- to `other', so as to yield equal objects.\n        require\n            other_not_void: other /= Void\n            type_identity: same_type (other)\n        external\n            \"built_in\"\n        ensure\n            is_equal: Current ~ other\n        end\n\n    frozen standard_copy (other: like Current)\n            -- Copy every field of `other' onto corresponding field\n            -- of current object.\n        require\n            other_not_void: other /= Void\n            type_identity: same_type (other)\n        external\n            \"built_in\"\n        ensure\n            is_standard_equal: standard_is_equal (other)\n        end\n\n    frozen clone (other: detachable ANY): like other\n            -- Void if `other' is void; otherwise new object\n            -- equal to `other'\n            --\n            -- For non-void `other', `clone' calls `copy';\n            -- to change copying/cloning semantics, redefine `copy'.\n        obsolete\n            \"Use `twin' instead.\"\n        do\n            if other /= Void then\n                Result := other.twin\n            end\n        ensure\n            equal: Result ~ other\n        end\n\n    frozen standard_clone (other: detachable ANY): like other\n            -- Void if `other' is void; otherwise new object\n            -- field-by-field identical to `other'.\n            -- Always uses default copying semantics.\n        obsolete\n            \"Use `standard_twin' instead.\"\n        do\n            if other /= Void then\n                Result := other.standard_twin\n            end\n        ensure\n            equal: standard_equal (Result, other)\n        end\n\n    frozen standard_twin: like Current\n            -- New object field-by-field identical to `other'.\n            -- Always uses default copying semantics.\n        external\n            \"built_in\"\n        ensure\n            standard_twin_not_void: Result /= Void\n            equal: standard_equal (Result, Current)\n        end\n\n    frozen deep_twin: like Current\n            -- New object structure recursively duplicated from Current.\n        external\n            \"built_in\"\n        ensure\n            deep_twin_not_void: Result /= Void\n            deep_equal: deep_equal (Current, Result)\n        end\n\n    frozen deep_clone (other: detachable ANY): like other\n            -- Void if `other' is void: otherwise, new object structure\n            -- recursively duplicated from the one attached to `other'\n        obsolete\n            \"Use `deep_twin' instead.\"\n        do\n            if other /= Void then\n                Result := other.deep_twin\n            end\n        ensure\n            deep_equal: deep_equal (other, Result)\n        end\n\n    frozen deep_copy (other: like Current)\n            -- Effect equivalent to that of:\n            --      `copy' (`other' . `deep_twin')\n        require\n            other_not_void: other /= Void\n        do\n            copy (other.deep_twin)\n        ensure\n            deep_equal: deep_equal (Current, other)\n        end\n\nfeature {NONE} -- Retrieval\n\n    frozen internal_correct_mismatch\n            -- Called from runtime to perform a proper dynamic dispatch on `correct_mismatch'\n            -- from MISMATCH_CORRECTOR.\n        local\n            l_msg: STRING\n            l_exc: EXCEPTIONS\n        do\n            if attached {MISMATCH_CORRECTOR} Current as l_corrector then\n                l_corrector.correct_mismatch\n            else\n                create l_msg.make_from_string (\"Mismatch: \")\n                create l_exc\n                l_msg.append (generating_type.name)\n                l_exc.raise_retrieval_exception (l_msg)\n            end\n        end\n\nfeature -- Output\n\n    io: STD_FILES\n            -- Handle to standard file setup\n        once\n            create Result\n            Result.set_output_default\n        ensure\n            io_not_void: Result /= Void\n        end\n\n    out: STRING\n            -- New string containing terse printable representation\n            -- of current object\n        do\n            Result := tagged_out\n        ensure\n            out_not_void: Result /= Void\n        end\n\n    frozen tagged_out: STRING\n            -- New string containing terse printable representation\n            -- of current object\n        external\n            \"built_in\"\n        ensure\n            tagged_out_not_void: Result /= Void\n        end\n\n    print (o: detachable ANY)\n            -- Write terse external representation of `o'\n            -- on standard output.\n        do\n            if o /= Void then\n                io.put_string (o.out)\n            end\n        end\n\nfeature -- Platform\n\n    Operating_environment: OPERATING_ENVIRONMENT\n            -- Objects available from the operating system\n        once\n            create Result\n        ensure\n            operating_environment_not_void: Result /= Void\n        end\n\nfeature {NONE} -- Initialization\n\n    default_create\n            -- Process instances of classes with no creation clause.\n            -- (Default: do nothing.)\n        do\n        end\n\nfeature -- Basic operations\n\n    default_rescue\n            -- Process exception for routines with no Rescue clause.\n            -- (Default: do nothing.)\n        do\n        end\n\n    frozen do_nothing\n            -- Execute a null action.\n        do\n        end\n\n    frozen default: detachable like Current\n            -- Default value of object's type\n        do\n        end\n\n    frozen default_pointer: POINTER\n            -- Default value of type `POINTER'\n            -- (Avoid the need to write `p'.`default' for\n            -- some `p' of type `POINTER'.)\n        do\n        ensure\n            -- Result = Result.default\n        end\n\n    frozen as_attached: attached like Current\n            -- Attached version of Current\n            -- (Can be used during transitional period to convert\n            -- non-void-safe classes to void-safe ones.)\n        do\n            Result := Current\n        end\n\ninvariant\n    reflexive_equality: standard_is_equal (Current)\n    reflexive_conformance: conforms_to (Current)\n\nnote\n    copyright: \"Copyright (c) 1984-2012, Eiffel Software and others\"\n    license:   \"Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)\"\n    source: \"[\n            Eiffel Software\n            5949 Hollister Ave., Goleta, CA 93117 USA\n            Telephone 805-685-1006, Fax 805-685-6869\n            Website http://www.eiffel.com\n            Customer support http://support.eiffel.com\n        ]\"\n\nend\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-eiffel\",\n        indentUnit: 4,\n        lineNumbers: true,\n        theme: \"neat\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-eiffel</code>.</p>\n\n <p> Created by <a href=\"https://github.com/ynh\">YNH</a>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/erlang/erlang.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*jshint unused:true, eqnull:true, curly:true, bitwise:true */\n/*jshint undef:true, latedef:true, trailing:true */\n/*global CodeMirror:true */\n\n// erlang mode.\n// tokenizer -> token types -> CodeMirror styles\n// tokenizer maintains a parse stack\n// indenter uses the parse stack\n\n// TODO indenter:\n//   bit syntax\n//   old guard/bif/conversion clashes (e.g. \"float/1\")\n//   type/spec/opaque\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.defineMIME(\"text/x-erlang\", \"erlang\");\n\nCodeMirror.defineMode(\"erlang\", function(cmCfg) {\n  \"use strict\";\n\n/////////////////////////////////////////////////////////////////////////////\n// constants\n\n  var typeWords = [\n    \"-type\", \"-spec\", \"-export_type\", \"-opaque\"];\n\n  var keywordWords = [\n    \"after\",\"begin\",\"catch\",\"case\",\"cond\",\"end\",\"fun\",\"if\",\n    \"let\",\"of\",\"query\",\"receive\",\"try\",\"when\"];\n\n  var separatorRE    = /[\\->,;]/;\n  var separatorWords = [\n    \"->\",\";\",\",\"];\n\n  var operatorAtomWords = [\n    \"and\",\"andalso\",\"band\",\"bnot\",\"bor\",\"bsl\",\"bsr\",\"bxor\",\n    \"div\",\"not\",\"or\",\"orelse\",\"rem\",\"xor\"];\n\n  var operatorSymbolRE    = /[\\+\\-\\*\\/<>=\\|:!]/;\n  var operatorSymbolWords = [\n    \"=\",\"+\",\"-\",\"*\",\"/\",\">\",\">=\",\"<\",\"=<\",\"=:=\",\"==\",\"=/=\",\"/=\",\"||\",\"<-\",\"!\"];\n\n  var openParenRE    = /[<\\(\\[\\{]/;\n  var openParenWords = [\n    \"<<\",\"(\",\"[\",\"{\"];\n\n  var closeParenRE    = /[>\\)\\]\\}]/;\n  var closeParenWords = [\n    \"}\",\"]\",\")\",\">>\"];\n\n  var guardWords = [\n    \"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\"is_float\",\n    \"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n    \"is_port\",\"is_record\",\"is_reference\",\"is_tuple\",\n    \"atom\",\"binary\",\"bitstring\",\"boolean\",\"function\",\"integer\",\"list\",\n    \"number\",\"pid\",\"port\",\"record\",\"reference\",\"tuple\"];\n\n  var bifWords = [\n    \"abs\",\"adler32\",\"adler32_combine\",\"alive\",\"apply\",\"atom_to_binary\",\n    \"atom_to_list\",\"binary_to_atom\",\"binary_to_existing_atom\",\n    \"binary_to_list\",\"binary_to_term\",\"bit_size\",\"bitstring_to_list\",\n    \"byte_size\",\"check_process_code\",\"contact_binary\",\"crc32\",\n    \"crc32_combine\",\"date\",\"decode_packet\",\"delete_module\",\n    \"disconnect_node\",\"element\",\"erase\",\"exit\",\"float\",\"float_to_list\",\n    \"garbage_collect\",\"get\",\"get_keys\",\"group_leader\",\"halt\",\"hd\",\n    \"integer_to_list\",\"internal_bif\",\"iolist_size\",\"iolist_to_binary\",\n    \"is_alive\",\"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\n    \"is_float\",\"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n    \"is_port\",\"is_process_alive\",\"is_record\",\"is_reference\",\"is_tuple\",\n    \"length\",\"link\",\"list_to_atom\",\"list_to_binary\",\"list_to_bitstring\",\n    \"list_to_existing_atom\",\"list_to_float\",\"list_to_integer\",\n    \"list_to_pid\",\"list_to_tuple\",\"load_module\",\"make_ref\",\"module_loaded\",\n    \"monitor_node\",\"node\",\"node_link\",\"node_unlink\",\"nodes\",\"notalive\",\n    \"now\",\"open_port\",\"pid_to_list\",\"port_close\",\"port_command\",\n    \"port_connect\",\"port_control\",\"pre_loaded\",\"process_flag\",\n    \"process_info\",\"processes\",\"purge_module\",\"put\",\"register\",\n    \"registered\",\"round\",\"self\",\"setelement\",\"size\",\"spawn\",\"spawn_link\",\n    \"spawn_monitor\",\"spawn_opt\",\"split_binary\",\"statistics\",\n    \"term_to_binary\",\"time\",\"throw\",\"tl\",\"trunc\",\"tuple_size\",\n    \"tuple_to_list\",\"unlink\",\"unregister\",\"whereis\"];\n\n// upper case: [A-Z] [Ø-Þ] [À-Ö]\n// lower case: [a-z] [ß-ö] [ø-ÿ]\n  var anumRE       = /[\\w@Ø-ÞÀ-Öß-öø-ÿ]/;\n  var escapesRE    =\n    /[0-7]{1,3}|[bdefnrstv\\\\\"']|\\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;\n\n/////////////////////////////////////////////////////////////////////////////\n// tokenizer\n\n  function tokenizer(stream,state) {\n    // in multi-line string\n    if (state.in_string) {\n      state.in_string = (!doubleQuote(stream));\n      return rval(state,stream,\"string\");\n    }\n\n    // in multi-line atom\n    if (state.in_atom) {\n      state.in_atom = (!singleQuote(stream));\n      return rval(state,stream,\"atom\");\n    }\n\n    // whitespace\n    if (stream.eatSpace()) {\n      return rval(state,stream,\"whitespace\");\n    }\n\n    // attributes and type specs\n    if (!peekToken(state) &&\n        stream.match(/-\\s*[a-zß-öø-ÿ][\\wØ-ÞÀ-Öß-öø-ÿ]*/)) {\n      if (is_member(stream.current(),typeWords)) {\n        return rval(state,stream,\"type\");\n      }else{\n        return rval(state,stream,\"attribute\");\n      }\n    }\n\n    var ch = stream.next();\n\n    // comment\n    if (ch == '%') {\n      stream.skipToEnd();\n      return rval(state,stream,\"comment\");\n    }\n\n    // colon\n    if (ch == \":\") {\n      return rval(state,stream,\"colon\");\n    }\n\n    // macro\n    if (ch == '?') {\n      stream.eatSpace();\n      stream.eatWhile(anumRE);\n      return rval(state,stream,\"macro\");\n    }\n\n    // record\n    if (ch == \"#\") {\n      stream.eatSpace();\n      stream.eatWhile(anumRE);\n      return rval(state,stream,\"record\");\n    }\n\n    // dollar escape\n    if (ch == \"$\") {\n      if (stream.next() == \"\\\\\" && !stream.match(escapesRE)) {\n        return rval(state,stream,\"error\");\n      }\n      return rval(state,stream,\"number\");\n    }\n\n    // dot\n    if (ch == \".\") {\n      return rval(state,stream,\"dot\");\n    }\n\n    // quoted atom\n    if (ch == '\\'') {\n      if (!(state.in_atom = (!singleQuote(stream)))) {\n        if (stream.match(/\\s*\\/\\s*[0-9]/,false)) {\n          stream.match(/\\s*\\/\\s*[0-9]/,true);\n          return rval(state,stream,\"fun\");      // 'f'/0 style fun\n        }\n        if (stream.match(/\\s*\\(/,false) || stream.match(/\\s*:/,false)) {\n          return rval(state,stream,\"function\");\n        }\n      }\n      return rval(state,stream,\"atom\");\n    }\n\n    // string\n    if (ch == '\"') {\n      state.in_string = (!doubleQuote(stream));\n      return rval(state,stream,\"string\");\n    }\n\n    // variable\n    if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) {\n      stream.eatWhile(anumRE);\n      return rval(state,stream,\"variable\");\n    }\n\n    // atom/keyword/BIF/function\n    if (/[a-z_ß-öø-ÿ]/.test(ch)) {\n      stream.eatWhile(anumRE);\n\n      if (stream.match(/\\s*\\/\\s*[0-9]/,false)) {\n        stream.match(/\\s*\\/\\s*[0-9]/,true);\n        return rval(state,stream,\"fun\");      // f/0 style fun\n      }\n\n      var w = stream.current();\n\n      if (is_member(w,keywordWords)) {\n        return rval(state,stream,\"keyword\");\n      }else if (is_member(w,operatorAtomWords)) {\n        return rval(state,stream,\"operator\");\n      }else if (stream.match(/\\s*\\(/,false)) {\n        // 'put' and 'erlang:put' are bifs, 'foo:put' is not\n        if (is_member(w,bifWords) &&\n            ((peekToken(state).token != \":\") ||\n             (peekToken(state,2).token == \"erlang\"))) {\n          return rval(state,stream,\"builtin\");\n        }else if (is_member(w,guardWords)) {\n          return rval(state,stream,\"guard\");\n        }else{\n          return rval(state,stream,\"function\");\n        }\n      }else if (is_member(w,operatorAtomWords)) {\n        return rval(state,stream,\"operator\");\n      }else if (lookahead(stream) == \":\") {\n        if (w == \"erlang\") {\n          return rval(state,stream,\"builtin\");\n        } else {\n          return rval(state,stream,\"function\");\n        }\n      }else if (is_member(w,[\"true\",\"false\"])) {\n        return rval(state,stream,\"boolean\");\n      }else if (is_member(w,[\"true\",\"false\"])) {\n        return rval(state,stream,\"boolean\");\n      }else{\n        return rval(state,stream,\"atom\");\n      }\n    }\n\n    // number\n    var digitRE      = /[0-9]/;\n    var radixRE      = /[0-9a-zA-Z]/;         // 36#zZ style int\n    if (digitRE.test(ch)) {\n      stream.eatWhile(digitRE);\n      if (stream.eat('#')) {                // 36#aZ  style integer\n        if (!stream.eatWhile(radixRE)) {\n          stream.backUp(1);                 //\"36#\" - syntax error\n        }\n      } else if (stream.eat('.')) {       // float\n        if (!stream.eatWhile(digitRE)) {\n          stream.backUp(1);        // \"3.\" - probably end of function\n        } else {\n          if (stream.eat(/[eE]/)) {        // float with exponent\n            if (stream.eat(/[-+]/)) {\n              if (!stream.eatWhile(digitRE)) {\n                stream.backUp(2);            // \"2e-\" - syntax error\n              }\n            } else {\n              if (!stream.eatWhile(digitRE)) {\n                stream.backUp(1);            // \"2e\" - syntax error\n              }\n            }\n          }\n        }\n      }\n      return rval(state,stream,\"number\");   // normal integer\n    }\n\n    // open parens\n    if (nongreedy(stream,openParenRE,openParenWords)) {\n      return rval(state,stream,\"open_paren\");\n    }\n\n    // close parens\n    if (nongreedy(stream,closeParenRE,closeParenWords)) {\n      return rval(state,stream,\"close_paren\");\n    }\n\n    // separators\n    if (greedy(stream,separatorRE,separatorWords)) {\n      return rval(state,stream,\"separator\");\n    }\n\n    // operators\n    if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) {\n      return rval(state,stream,\"operator\");\n    }\n\n    return rval(state,stream,null);\n  }\n\n/////////////////////////////////////////////////////////////////////////////\n// utilities\n  function nongreedy(stream,re,words) {\n    if (stream.current().length == 1 && re.test(stream.current())) {\n      stream.backUp(1);\n      while (re.test(stream.peek())) {\n        stream.next();\n        if (is_member(stream.current(),words)) {\n          return true;\n        }\n      }\n      stream.backUp(stream.current().length-1);\n    }\n    return false;\n  }\n\n  function greedy(stream,re,words) {\n    if (stream.current().length == 1 && re.test(stream.current())) {\n      while (re.test(stream.peek())) {\n        stream.next();\n      }\n      while (0 < stream.current().length) {\n        if (is_member(stream.current(),words)) {\n          return true;\n        }else{\n          stream.backUp(1);\n        }\n      }\n      stream.next();\n    }\n    return false;\n  }\n\n  function doubleQuote(stream) {\n    return quote(stream, '\"', '\\\\');\n  }\n\n  function singleQuote(stream) {\n    return quote(stream,'\\'','\\\\');\n  }\n\n  function quote(stream,quoteChar,escapeChar) {\n    while (!stream.eol()) {\n      var ch = stream.next();\n      if (ch == quoteChar) {\n        return true;\n      }else if (ch == escapeChar) {\n        stream.next();\n      }\n    }\n    return false;\n  }\n\n  function lookahead(stream) {\n    var m = stream.match(/([\\n\\s]+|%[^\\n]*\\n)*(.)/,false);\n    return m ? m.pop() : \"\";\n  }\n\n  function is_member(element,list) {\n    return (-1 < list.indexOf(element));\n  }\n\n  function rval(state,stream,type) {\n\n    // parse stack\n    pushToken(state,realToken(type,stream));\n\n    // map erlang token type to CodeMirror style class\n    //     erlang             -> CodeMirror tag\n    switch (type) {\n      case \"atom\":        return \"atom\";\n      case \"attribute\":   return \"attribute\";\n      case \"boolean\":     return \"atom\";\n      case \"builtin\":     return \"builtin\";\n      case \"close_paren\": return null;\n      case \"colon\":       return null;\n      case \"comment\":     return \"comment\";\n      case \"dot\":         return null;\n      case \"error\":       return \"error\";\n      case \"fun\":         return \"meta\";\n      case \"function\":    return \"tag\";\n      case \"guard\":       return \"property\";\n      case \"keyword\":     return \"keyword\";\n      case \"macro\":       return \"variable-2\";\n      case \"number\":      return \"number\";\n      case \"open_paren\":  return null;\n      case \"operator\":    return \"operator\";\n      case \"record\":      return \"bracket\";\n      case \"separator\":   return null;\n      case \"string\":      return \"string\";\n      case \"type\":        return \"def\";\n      case \"variable\":    return \"variable\";\n      default:            return null;\n    }\n  }\n\n  function aToken(tok,col,ind,typ) {\n    return {token:  tok,\n            column: col,\n            indent: ind,\n            type:   typ};\n  }\n\n  function realToken(type,stream) {\n    return aToken(stream.current(),\n                 stream.column(),\n                 stream.indentation(),\n                 type);\n  }\n\n  function fakeToken(type) {\n    return aToken(type,0,0,type);\n  }\n\n  function peekToken(state,depth) {\n    var len = state.tokenStack.length;\n    var dep = (depth ? depth : 1);\n\n    if (len < dep) {\n      return false;\n    }else{\n      return state.tokenStack[len-dep];\n    }\n  }\n\n  function pushToken(state,token) {\n\n    if (!(token.type == \"comment\" || token.type == \"whitespace\")) {\n      state.tokenStack = maybe_drop_pre(state.tokenStack,token);\n      state.tokenStack = maybe_drop_post(state.tokenStack);\n    }\n  }\n\n  function maybe_drop_pre(s,token) {\n    var last = s.length-1;\n\n    if (0 < last && s[last].type === \"record\" && token.type === \"dot\") {\n      s.pop();\n    }else if (0 < last && s[last].type === \"group\") {\n      s.pop();\n      s.push(token);\n    }else{\n      s.push(token);\n    }\n    return s;\n  }\n\n  function maybe_drop_post(s) {\n    var last = s.length-1;\n\n    if (s[last].type === \"dot\") {\n      return [];\n    }\n    if (s[last].type === \"fun\" && s[last-1].token === \"fun\") {\n      return s.slice(0,last-1);\n    }\n    switch (s[s.length-1].token) {\n      case \"}\":    return d(s,{g:[\"{\"]});\n      case \"]\":    return d(s,{i:[\"[\"]});\n      case \")\":    return d(s,{i:[\"(\"]});\n      case \">>\":   return d(s,{i:[\"<<\"]});\n      case \"end\":  return d(s,{i:[\"begin\",\"case\",\"fun\",\"if\",\"receive\",\"try\"]});\n      case \",\":    return d(s,{e:[\"begin\",\"try\",\"when\",\"->\",\n                                  \",\",\"(\",\"[\",\"{\",\"<<\"]});\n      case \"->\":   return d(s,{r:[\"when\"],\n                               m:[\"try\",\"if\",\"case\",\"receive\"]});\n      case \";\":    return d(s,{E:[\"case\",\"fun\",\"if\",\"receive\",\"try\",\"when\"]});\n      case \"catch\":return d(s,{e:[\"try\"]});\n      case \"of\":   return d(s,{e:[\"case\"]});\n      case \"after\":return d(s,{e:[\"receive\",\"try\"]});\n      default:     return s;\n    }\n  }\n\n  function d(stack,tt) {\n    // stack is a stack of Token objects.\n    // tt is an object; {type:tokens}\n    // type is a char, tokens is a list of token strings.\n    // The function returns (possibly truncated) stack.\n    // It will descend the stack, looking for a Token such that Token.token\n    //  is a member of tokens. If it does not find that, it will normally (but\n    //  see \"E\" below) return stack. If it does find a match, it will remove\n    //  all the Tokens between the top and the matched Token.\n    // If type is \"m\", that is all it does.\n    // If type is \"i\", it will also remove the matched Token and the top Token.\n    // If type is \"g\", like \"i\", but add a fake \"group\" token at the top.\n    // If type is \"r\", it will remove the matched Token, but not the top Token.\n    // If type is \"e\", it will keep the matched Token but not the top Token.\n    // If type is \"E\", it behaves as for type \"e\", except if there is no match,\n    //  in which case it will return an empty stack.\n\n    for (var type in tt) {\n      var len = stack.length-1;\n      var tokens = tt[type];\n      for (var i = len-1; -1 < i ; i--) {\n        if (is_member(stack[i].token,tokens)) {\n          var ss = stack.slice(0,i);\n          switch (type) {\n              case \"m\": return ss.concat(stack[i]).concat(stack[len]);\n              case \"r\": return ss.concat(stack[len]);\n              case \"i\": return ss;\n              case \"g\": return ss.concat(fakeToken(\"group\"));\n              case \"E\": return ss.concat(stack[i]);\n              case \"e\": return ss.concat(stack[i]);\n          }\n        }\n      }\n    }\n    return (type == \"E\" ? [] : stack);\n  }\n\n/////////////////////////////////////////////////////////////////////////////\n// indenter\n\n  function indenter(state,textAfter) {\n    var t;\n    var unit = cmCfg.indentUnit;\n    var wordAfter = wordafter(textAfter);\n    var currT = peekToken(state,1);\n    var prevT = peekToken(state,2);\n\n    if (state.in_string || state.in_atom) {\n      return CodeMirror.Pass;\n    }else if (!prevT) {\n      return 0;\n    }else if (currT.token == \"when\") {\n      return currT.column+unit;\n    }else if (wordAfter === \"when\" && prevT.type === \"function\") {\n      return prevT.indent+unit;\n    }else if (wordAfter === \"(\" && currT.token === \"fun\") {\n      return  currT.column+3;\n    }else if (wordAfter === \"catch\" && (t = getToken(state,[\"try\"]))) {\n      return t.column;\n    }else if (is_member(wordAfter,[\"end\",\"after\",\"of\"])) {\n      t = getToken(state,[\"begin\",\"case\",\"fun\",\"if\",\"receive\",\"try\"]);\n      return t ? t.column : CodeMirror.Pass;\n    }else if (is_member(wordAfter,closeParenWords)) {\n      t = getToken(state,openParenWords);\n      return t ? t.column : CodeMirror.Pass;\n    }else if (is_member(currT.token,[\",\",\"|\",\"||\"]) ||\n              is_member(wordAfter,[\",\",\"|\",\"||\"])) {\n      t = postcommaToken(state);\n      return t ? t.column+t.token.length : unit;\n    }else if (currT.token == \"->\") {\n      if (is_member(prevT.token, [\"receive\",\"case\",\"if\",\"try\"])) {\n        return prevT.column+unit+unit;\n      }else{\n        return prevT.column+unit;\n      }\n    }else if (is_member(currT.token,openParenWords)) {\n      return currT.column+currT.token.length;\n    }else{\n      t = defaultToken(state);\n      return truthy(t) ? t.column+unit : 0;\n    }\n  }\n\n  function wordafter(str) {\n    var m = str.match(/,|[a-z]+|\\}|\\]|\\)|>>|\\|+|\\(/);\n\n    return truthy(m) && (m.index === 0) ? m[0] : \"\";\n  }\n\n  function postcommaToken(state) {\n    var objs = state.tokenStack.slice(0,-1);\n    var i = getTokenIndex(objs,\"type\",[\"open_paren\"]);\n\n    return truthy(objs[i]) ? objs[i] : false;\n  }\n\n  function defaultToken(state) {\n    var objs = state.tokenStack;\n    var stop = getTokenIndex(objs,\"type\",[\"open_paren\",\"separator\",\"keyword\"]);\n    var oper = getTokenIndex(objs,\"type\",[\"operator\"]);\n\n    if (truthy(stop) && truthy(oper) && stop < oper) {\n      return objs[stop+1];\n    } else if (truthy(stop)) {\n      return objs[stop];\n    } else {\n      return false;\n    }\n  }\n\n  function getToken(state,tokens) {\n    var objs = state.tokenStack;\n    var i = getTokenIndex(objs,\"token\",tokens);\n\n    return truthy(objs[i]) ? objs[i] : false;\n  }\n\n  function getTokenIndex(objs,propname,propvals) {\n\n    for (var i = objs.length-1; -1 < i ; i--) {\n      if (is_member(objs[i][propname],propvals)) {\n        return i;\n      }\n    }\n    return false;\n  }\n\n  function truthy(x) {\n    return (x !== false) && (x != null);\n  }\n\n/////////////////////////////////////////////////////////////////////////////\n// this object defines the mode\n\n  return {\n    startState:\n      function() {\n        return {tokenStack: [],\n                in_string:  false,\n                in_atom:    false};\n      },\n\n    token:\n      function(stream, state) {\n        return tokenizer(stream, state);\n      },\n\n    indent:\n      function(state, textAfter) {\n        return indenter(state,textAfter);\n      },\n\n    lineComment: \"%\"\n  };\n});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/erlang/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Erlang mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/erlang-dark.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"erlang.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Erlang</a>\n  </ul>\n</div>\n\n<article>\n<h2>Erlang mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n%% -*- mode: erlang; erlang-indent-level: 2 -*-\n%%% Created :  7 May 2012 by mats cronqvist <masse@klarna.com>\n\n%% @doc\n%% Demonstrates how to print a record.\n%% @end\n\n-module('ex').\n-author('mats cronqvist').\n-export([demo/0,\n         rec_info/1]).\n\n-record(demo,{a=\"One\",b=\"Two\",c=\"Three\",d=\"Four\"}).\n\nrec_info(demo) -> record_info(fields,demo).\n\ndemo() -> expand_recs(?MODULE,#demo{a=\"A\",b=\"BB\"}).\n\nexpand_recs(M,List) when is_list(List) ->\n  [expand_recs(M,L)||L<-List];\nexpand_recs(M,Tup) when is_tuple(Tup) ->\n  case tuple_size(Tup) of\n    L when L < 1 -> Tup;\n    L ->\n      try\n        Fields = M:rec_info(element(1,Tup)),\n        L = length(Fields)+1,\n        lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))\n      catch\n        _:_ -> list_to_tuple(expand_recs(M,tuple_to_list(Tup)))\n      end\n  end;\nexpand_recs(_,Term) ->\n  Term.\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        extraKeys: {\"Tab\":  \"indentAuto\"},\n        theme: \"erlang-dark\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-erlang</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/fortran/fortran.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(\"fortran\", function() {\n  function words(array) {\n    var keys = {};\n    for (var i = 0; i < array.length; ++i) {\n      keys[array[i]] = true;\n    }\n    return keys;\n  }\n\n  var keywords = words([\n                  \"abstract\", \"accept\", \"allocatable\", \"allocate\",\n                  \"array\", \"assign\", \"asynchronous\", \"backspace\",\n                  \"bind\", \"block\", \"byte\", \"call\", \"case\",\n                  \"class\", \"close\", \"common\", \"contains\",\n                  \"continue\", \"cycle\", \"data\", \"deallocate\",\n                  \"decode\", \"deferred\", \"dimension\", \"do\",\n                  \"elemental\", \"else\", \"encode\", \"end\",\n                  \"endif\", \"entry\", \"enumerator\", \"equivalence\",\n                  \"exit\", \"external\", \"extrinsic\", \"final\",\n                  \"forall\", \"format\", \"function\", \"generic\",\n                  \"go\", \"goto\", \"if\", \"implicit\", \"import\", \"include\",\n                  \"inquire\", \"intent\", \"interface\", \"intrinsic\",\n                  \"module\", \"namelist\", \"non_intrinsic\",\n                  \"non_overridable\", \"none\", \"nopass\",\n                  \"nullify\", \"open\", \"optional\", \"options\",\n                  \"parameter\", \"pass\", \"pause\", \"pointer\",\n                  \"print\", \"private\", \"program\", \"protected\",\n                  \"public\", \"pure\", \"read\", \"recursive\", \"result\",\n                  \"return\", \"rewind\", \"save\", \"select\", \"sequence\",\n                  \"stop\", \"subroutine\", \"target\", \"then\", \"to\", \"type\",\n                  \"use\", \"value\", \"volatile\", \"where\", \"while\",\n                  \"write\"]);\n  var builtins = words([\"abort\", \"abs\", \"access\", \"achar\", \"acos\",\n                          \"adjustl\", \"adjustr\", \"aimag\", \"aint\", \"alarm\",\n                          \"all\", \"allocated\", \"alog\", \"amax\", \"amin\",\n                          \"amod\", \"and\", \"anint\", \"any\", \"asin\",\n                          \"associated\", \"atan\", \"besj\", \"besjn\", \"besy\",\n                          \"besyn\", \"bit_size\", \"btest\", \"cabs\", \"ccos\",\n                          \"ceiling\", \"cexp\", \"char\", \"chdir\", \"chmod\",\n                          \"clog\", \"cmplx\", \"command_argument_count\",\n                          \"complex\", \"conjg\", \"cos\", \"cosh\", \"count\",\n                          \"cpu_time\", \"cshift\", \"csin\", \"csqrt\", \"ctime\",\n                          \"c_funloc\", \"c_loc\", \"c_associated\", \"c_null_ptr\",\n                          \"c_null_funptr\", \"c_f_pointer\", \"c_null_char\",\n                          \"c_alert\", \"c_backspace\", \"c_form_feed\",\n                          \"c_new_line\", \"c_carriage_return\",\n                          \"c_horizontal_tab\", \"c_vertical_tab\", \"dabs\",\n                          \"dacos\", \"dasin\", \"datan\", \"date_and_time\",\n                          \"dbesj\", \"dbesj\", \"dbesjn\", \"dbesy\", \"dbesy\",\n                          \"dbesyn\", \"dble\", \"dcos\", \"dcosh\", \"ddim\", \"derf\",\n                          \"derfc\", \"dexp\", \"digits\", \"dim\", \"dint\", \"dlog\",\n                          \"dlog\", \"dmax\", \"dmin\", \"dmod\", \"dnint\",\n                          \"dot_product\", \"dprod\", \"dsign\", \"dsinh\",\n                          \"dsin\", \"dsqrt\", \"dtanh\", \"dtan\", \"dtime\",\n                          \"eoshift\", \"epsilon\", \"erf\", \"erfc\", \"etime\",\n                          \"exit\", \"exp\", \"exponent\", \"extends_type_of\",\n                          \"fdate\", \"fget\", \"fgetc\", \"float\", \"floor\",\n                          \"flush\", \"fnum\", \"fputc\", \"fput\", \"fraction\",\n                          \"fseek\", \"fstat\", \"ftell\", \"gerror\", \"getarg\",\n                          \"get_command\", \"get_command_argument\",\n                          \"get_environment_variable\", \"getcwd\",\n                          \"getenv\", \"getgid\", \"getlog\", \"getpid\",\n                          \"getuid\", \"gmtime\", \"hostnm\", \"huge\", \"iabs\",\n                          \"iachar\", \"iand\", \"iargc\", \"ibclr\", \"ibits\",\n                          \"ibset\", \"ichar\", \"idate\", \"idim\", \"idint\",\n                          \"idnint\", \"ieor\", \"ierrno\", \"ifix\", \"imag\",\n                          \"imagpart\", \"index\", \"int\", \"ior\", \"irand\",\n                          \"isatty\", \"ishft\", \"ishftc\", \"isign\",\n                          \"iso_c_binding\", \"is_iostat_end\", \"is_iostat_eor\",\n                          \"itime\", \"kill\", \"kind\", \"lbound\", \"len\", \"len_trim\",\n                          \"lge\", \"lgt\", \"link\", \"lle\", \"llt\", \"lnblnk\", \"loc\",\n                          \"log\", \"logical\", \"long\", \"lshift\", \"lstat\", \"ltime\",\n                          \"matmul\", \"max\", \"maxexponent\", \"maxloc\", \"maxval\",\n                          \"mclock\", \"merge\", \"move_alloc\", \"min\", \"minexponent\",\n                          \"minloc\", \"minval\", \"mod\", \"modulo\", \"mvbits\",\n                          \"nearest\", \"new_line\", \"nint\", \"not\", \"or\", \"pack\",\n                          \"perror\", \"precision\", \"present\", \"product\", \"radix\",\n                          \"rand\", \"random_number\", \"random_seed\", \"range\",\n                          \"real\", \"realpart\", \"rename\", \"repeat\", \"reshape\",\n                          \"rrspacing\", \"rshift\", \"same_type_as\", \"scale\",\n                          \"scan\", \"second\", \"selected_int_kind\",\n                          \"selected_real_kind\", \"set_exponent\", \"shape\",\n                          \"short\", \"sign\", \"signal\", \"sinh\", \"sin\", \"sleep\",\n                          \"sngl\", \"spacing\", \"spread\", \"sqrt\", \"srand\", \"stat\",\n                          \"sum\", \"symlnk\", \"system\", \"system_clock\", \"tan\",\n                          \"tanh\", \"time\", \"tiny\", \"transfer\", \"transpose\",\n                          \"trim\", \"ttynam\", \"ubound\", \"umask\", \"unlink\",\n                          \"unpack\", \"verify\", \"xor\", \"zabs\", \"zcos\", \"zexp\",\n                          \"zlog\", \"zsin\", \"zsqrt\"]);\n\n    var dataTypes =  words([\"c_bool\", \"c_char\", \"c_double\", \"c_double_complex\",\n                     \"c_float\", \"c_float_complex\", \"c_funptr\", \"c_int\",\n                     \"c_int16_t\", \"c_int32_t\", \"c_int64_t\", \"c_int8_t\",\n                     \"c_int_fast16_t\", \"c_int_fast32_t\", \"c_int_fast64_t\",\n                     \"c_int_fast8_t\", \"c_int_least16_t\", \"c_int_least32_t\",\n                     \"c_int_least64_t\", \"c_int_least8_t\", \"c_intmax_t\",\n                     \"c_intptr_t\", \"c_long\", \"c_long_double\",\n                     \"c_long_double_complex\", \"c_long_long\", \"c_ptr\",\n                     \"c_short\", \"c_signed_char\", \"c_size_t\", \"character\",\n                     \"complex\", \"double\", \"integer\", \"logical\", \"real\"]);\n  var isOperatorChar = /[+\\-*&=<>\\/\\:]/;\n  var litOperator = new RegExp(\"(\\.and\\.|\\.or\\.|\\.eq\\.|\\.lt\\.|\\.le\\.|\\.gt\\.|\\.ge\\.|\\.ne\\.|\\.not\\.|\\.eqv\\.|\\.neqv\\.)\", \"i\");\n\n  function tokenBase(stream, state) {\n\n    if (stream.match(litOperator)){\n        return 'operator';\n    }\n\n    var ch = stream.next();\n    if (ch == \"!\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]\\(\\),]/.test(ch)) {\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var word = stream.current().toLowerCase();\n\n    if (keywords.hasOwnProperty(word)){\n            return 'keyword';\n    }\n    if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) {\n            return 'builtin';\n    }\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) {\n            end = true;\n            break;\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !escaped) state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  // Interface\n\n  return {\n    startState: function() {\n      return {tokenize: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      return style;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-fortran\", \"fortran\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/fortran/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Fortran mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"fortran.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Fortran</a>\n  </ul>\n</div>\n\n<article>\n<h2>Fortran mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n! Example Fortran code\n  program average\n\n  ! Read in some numbers and take the average\n  ! As written, if there are no data points, an average of zero is returned\n  ! While this may not be desired behavior, it keeps this example simple\n\n  implicit none\n\n  real, dimension(:), allocatable :: points\n  integer                         :: number_of_points\n  real                            :: average_points=0., positive_average=0., negative_average=0.\n\n  write (*,*) \"Input number of points to average:\"\n  read  (*,*) number_of_points\n\n  allocate (points(number_of_points))\n\n  write (*,*) \"Enter the points to average:\"\n  read  (*,*) points\n\n  ! Take the average by summing points and dividing by number_of_points\n  if (number_of_points > 0) average_points = sum(points) / number_of_points\n\n  ! Now form average over positive and negative points only\n  if (count(points > 0.) > 0) then\n     positive_average = sum(points, points > 0.) / count(points > 0.)\n  end if\n\n  if (count(points < 0.) > 0) then\n     negative_average = sum(points, points < 0.) / count(points < 0.)\n  end if\n\n  deallocate (points)\n\n  ! Print result to terminal\n  write (*,'(a,g12.4)') 'Average = ', average_points\n  write (*,'(a,g12.4)') 'Average of positive points = ', positive_average\n  write (*,'(a,g12.4)') 'Average of negative points = ', negative_average\n\n  end program average\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"text/x-fortran\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-Fortran</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gas/gas.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(\"gas\", function(_config, parserConfig) {\n  'use strict';\n\n  // If an architecture is specified, its initialization function may\n  // populate this array with custom parsing functions which will be\n  // tried in the event that the standard functions do not find a match.\n  var custom = [];\n\n  // The symbol used to start a line comment changes based on the target\n  // architecture.\n  // If no architecture is pased in \"parserConfig\" then only multiline\n  // comments will have syntax support.\n  var lineCommentStartSymbol = \"\";\n\n  // These directives are architecture independent.\n  // Machine specific directives should go in their respective\n  // architecture initialization function.\n  // Reference:\n  // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops\n  var directives = {\n    \".abort\" : \"builtin\",\n    \".align\" : \"builtin\",\n    \".altmacro\" : \"builtin\",\n    \".ascii\" : \"builtin\",\n    \".asciz\" : \"builtin\",\n    \".balign\" : \"builtin\",\n    \".balignw\" : \"builtin\",\n    \".balignl\" : \"builtin\",\n    \".bundle_align_mode\" : \"builtin\",\n    \".bundle_lock\" : \"builtin\",\n    \".bundle_unlock\" : \"builtin\",\n    \".byte\" : \"builtin\",\n    \".cfi_startproc\" : \"builtin\",\n    \".comm\" : \"builtin\",\n    \".data\" : \"builtin\",\n    \".def\" : \"builtin\",\n    \".desc\" : \"builtin\",\n    \".dim\" : \"builtin\",\n    \".double\" : \"builtin\",\n    \".eject\" : \"builtin\",\n    \".else\" : \"builtin\",\n    \".elseif\" : \"builtin\",\n    \".end\" : \"builtin\",\n    \".endef\" : \"builtin\",\n    \".endfunc\" : \"builtin\",\n    \".endif\" : \"builtin\",\n    \".equ\" : \"builtin\",\n    \".equiv\" : \"builtin\",\n    \".eqv\" : \"builtin\",\n    \".err\" : \"builtin\",\n    \".error\" : \"builtin\",\n    \".exitm\" : \"builtin\",\n    \".extern\" : \"builtin\",\n    \".fail\" : \"builtin\",\n    \".file\" : \"builtin\",\n    \".fill\" : \"builtin\",\n    \".float\" : \"builtin\",\n    \".func\" : \"builtin\",\n    \".global\" : \"builtin\",\n    \".gnu_attribute\" : \"builtin\",\n    \".hidden\" : \"builtin\",\n    \".hword\" : \"builtin\",\n    \".ident\" : \"builtin\",\n    \".if\" : \"builtin\",\n    \".incbin\" : \"builtin\",\n    \".include\" : \"builtin\",\n    \".int\" : \"builtin\",\n    \".internal\" : \"builtin\",\n    \".irp\" : \"builtin\",\n    \".irpc\" : \"builtin\",\n    \".lcomm\" : \"builtin\",\n    \".lflags\" : \"builtin\",\n    \".line\" : \"builtin\",\n    \".linkonce\" : \"builtin\",\n    \".list\" : \"builtin\",\n    \".ln\" : \"builtin\",\n    \".loc\" : \"builtin\",\n    \".loc_mark_labels\" : \"builtin\",\n    \".local\" : \"builtin\",\n    \".long\" : \"builtin\",\n    \".macro\" : \"builtin\",\n    \".mri\" : \"builtin\",\n    \".noaltmacro\" : \"builtin\",\n    \".nolist\" : \"builtin\",\n    \".octa\" : \"builtin\",\n    \".offset\" : \"builtin\",\n    \".org\" : \"builtin\",\n    \".p2align\" : \"builtin\",\n    \".popsection\" : \"builtin\",\n    \".previous\" : \"builtin\",\n    \".print\" : \"builtin\",\n    \".protected\" : \"builtin\",\n    \".psize\" : \"builtin\",\n    \".purgem\" : \"builtin\",\n    \".pushsection\" : \"builtin\",\n    \".quad\" : \"builtin\",\n    \".reloc\" : \"builtin\",\n    \".rept\" : \"builtin\",\n    \".sbttl\" : \"builtin\",\n    \".scl\" : \"builtin\",\n    \".section\" : \"builtin\",\n    \".set\" : \"builtin\",\n    \".short\" : \"builtin\",\n    \".single\" : \"builtin\",\n    \".size\" : \"builtin\",\n    \".skip\" : \"builtin\",\n    \".sleb128\" : \"builtin\",\n    \".space\" : \"builtin\",\n    \".stab\" : \"builtin\",\n    \".string\" : \"builtin\",\n    \".struct\" : \"builtin\",\n    \".subsection\" : \"builtin\",\n    \".symver\" : \"builtin\",\n    \".tag\" : \"builtin\",\n    \".text\" : \"builtin\",\n    \".title\" : \"builtin\",\n    \".type\" : \"builtin\",\n    \".uleb128\" : \"builtin\",\n    \".val\" : \"builtin\",\n    \".version\" : \"builtin\",\n    \".vtable_entry\" : \"builtin\",\n    \".vtable_inherit\" : \"builtin\",\n    \".warning\" : \"builtin\",\n    \".weak\" : \"builtin\",\n    \".weakref\" : \"builtin\",\n    \".word\" : \"builtin\"\n  };\n\n  var registers = {};\n\n  function x86(_parserConfig) {\n    lineCommentStartSymbol = \"#\";\n\n    registers.ax  = \"variable\";\n    registers.eax = \"variable-2\";\n    registers.rax = \"variable-3\";\n\n    registers.bx  = \"variable\";\n    registers.ebx = \"variable-2\";\n    registers.rbx = \"variable-3\";\n\n    registers.cx  = \"variable\";\n    registers.ecx = \"variable-2\";\n    registers.rcx = \"variable-3\";\n\n    registers.dx  = \"variable\";\n    registers.edx = \"variable-2\";\n    registers.rdx = \"variable-3\";\n\n    registers.si  = \"variable\";\n    registers.esi = \"variable-2\";\n    registers.rsi = \"variable-3\";\n\n    registers.di  = \"variable\";\n    registers.edi = \"variable-2\";\n    registers.rdi = \"variable-3\";\n\n    registers.sp  = \"variable\";\n    registers.esp = \"variable-2\";\n    registers.rsp = \"variable-3\";\n\n    registers.bp  = \"variable\";\n    registers.ebp = \"variable-2\";\n    registers.rbp = \"variable-3\";\n\n    registers.ip  = \"variable\";\n    registers.eip = \"variable-2\";\n    registers.rip = \"variable-3\";\n\n    registers.cs  = \"keyword\";\n    registers.ds  = \"keyword\";\n    registers.ss  = \"keyword\";\n    registers.es  = \"keyword\";\n    registers.fs  = \"keyword\";\n    registers.gs  = \"keyword\";\n  }\n\n  function armv6(_parserConfig) {\n    // Reference:\n    // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf\n    // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf\n    lineCommentStartSymbol = \"@\";\n    directives.syntax = \"builtin\";\n\n    registers.r0  = \"variable\";\n    registers.r1  = \"variable\";\n    registers.r2  = \"variable\";\n    registers.r3  = \"variable\";\n    registers.r4  = \"variable\";\n    registers.r5  = \"variable\";\n    registers.r6  = \"variable\";\n    registers.r7  = \"variable\";\n    registers.r8  = \"variable\";\n    registers.r9  = \"variable\";\n    registers.r10 = \"variable\";\n    registers.r11 = \"variable\";\n    registers.r12 = \"variable\";\n\n    registers.sp  = \"variable-2\";\n    registers.lr  = \"variable-2\";\n    registers.pc  = \"variable-2\";\n    registers.r13 = registers.sp;\n    registers.r14 = registers.lr;\n    registers.r15 = registers.pc;\n\n    custom.push(function(ch, stream) {\n      if (ch === '#') {\n        stream.eatWhile(/\\w/);\n        return \"number\";\n      }\n    });\n  }\n\n  var arch = (parserConfig.architecture || \"x86\").toLowerCase();\n  if (arch === \"x86\") {\n    x86(parserConfig);\n  } else if (arch === \"arm\" || arch === \"armv6\") {\n    armv6(parserConfig);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next === end && !escaped) {\n        return false;\n      }\n      escaped = !escaped && next === \"\\\\\";\n    }\n    return escaped;\n  }\n\n  function clikeComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (ch === \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch === \"*\");\n    }\n    return \"comment\";\n  }\n\n  return {\n    startState: function() {\n      return {\n        tokenize: null\n      };\n    },\n\n    token: function(stream, state) {\n      if (state.tokenize) {\n        return state.tokenize(stream, state);\n      }\n\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      var style, cur, ch = stream.next();\n\n      if (ch === \"/\") {\n        if (stream.eat(\"*\")) {\n          state.tokenize = clikeComment;\n          return clikeComment(stream, state);\n        }\n      }\n\n      if (ch === lineCommentStartSymbol) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n\n      if (ch === '\"') {\n        nextUntilUnescaped(stream, '\"');\n        return \"string\";\n      }\n\n      if (ch === '.') {\n        stream.eatWhile(/\\w/);\n        cur = stream.current().toLowerCase();\n        style = directives[cur];\n        return style || null;\n      }\n\n      if (ch === '=') {\n        stream.eatWhile(/\\w/);\n        return \"tag\";\n      }\n\n      if (ch === '{') {\n        return \"braket\";\n      }\n\n      if (ch === '}') {\n        return \"braket\";\n      }\n\n      if (/\\d/.test(ch)) {\n        if (ch === \"0\" && stream.eat(\"x\")) {\n          stream.eatWhile(/[0-9a-fA-F]/);\n          return \"number\";\n        }\n        stream.eatWhile(/\\d/);\n        return \"number\";\n      }\n\n      if (/\\w/.test(ch)) {\n        stream.eatWhile(/\\w/);\n        if (stream.eat(\":\")) {\n          return 'tag';\n        }\n        cur = stream.current().toLowerCase();\n        style = registers[cur];\n        return style || null;\n      }\n\n      for (var i = 0; i < custom.length; i++) {\n        style = custom[i](ch, stream, state);\n        if (style) {\n          return style;\n        }\n      }\n    },\n\n    lineComment: lineCommentStartSymbol,\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\"\n  };\n});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gas/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Gas mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"gas.js\"></script>\n<style>.CodeMirror {border: 2px inset #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Gas</a>\n  </ul>\n</div>\n\n<article>\n<h2>Gas mode</h2>\n<form>\n<textarea id=\"code\" name=\"code\">\n.syntax unified\n.global main\n\n/*\n *  A\n *  multi-line\n *  comment.\n */\n\n@ A single line comment.\n\nmain:\n        push    {sp, lr}\n        ldr     r0, =message\n        bl      puts\n        mov     r0, #0\n        pop     {sp, pc}\n\nmessage:\n        .asciz \"Hello world!<br />\"\n</textarea>\n        </form>\n\n        <script>\n            var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n                lineNumbers: true,\n                mode: {name: \"gas\", architecture: \"ARMv6\"},\n            });\n        </script>\n\n        <p>Handles AT&amp;T assembler syntax (more specifically this handles\n        the GNU Assembler (gas) syntax.)\n        It takes a single optional configuration parameter:\n        <code>architecture</code>, which can be one of <code>\"ARM\"</code>,\n        <code>\"ARMv6\"</code> or <code>\"x86\"</code>.\n        Including the parameter adds syntax for the registers and special\n        directives for the supplied architecture.\n\n        <p><strong>MIME types defined:</strong> <code>text/x-gas</code></p>\n    </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gfm/gfm.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\"), require(\"../markdown/markdown\"), require(\"../../addon/mode/overlay\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../markdown/markdown\", \"../../addon/mode/overlay\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"gfm\", function(config, modeConfig) {\n  var codeDepth = 0;\n  function blankLine(state) {\n    state.code = false;\n    return null;\n  }\n  var gfmOverlay = {\n    startState: function() {\n      return {\n        code: false,\n        codeBlock: false,\n        ateSpace: false\n      };\n    },\n    copyState: function(s) {\n      return {\n        code: s.code,\n        codeBlock: s.codeBlock,\n        ateSpace: s.ateSpace\n      };\n    },\n    token: function(stream, state) {\n      state.combineTokens = null;\n\n      // Hack to prevent formatting override inside code blocks (block and inline)\n      if (state.codeBlock) {\n        if (stream.match(/^```/)) {\n          state.codeBlock = false;\n          return null;\n        }\n        stream.skipToEnd();\n        return null;\n      }\n      if (stream.sol()) {\n        state.code = false;\n      }\n      if (stream.sol() && stream.match(/^```/)) {\n        stream.skipToEnd();\n        state.codeBlock = true;\n        return null;\n      }\n      // If this block is changed, it may need to be updated in Markdown mode\n      if (stream.peek() === '`') {\n        stream.next();\n        var before = stream.pos;\n        stream.eatWhile('`');\n        var difference = 1 + stream.pos - before;\n        if (!state.code) {\n          codeDepth = difference;\n          state.code = true;\n        } else {\n          if (difference === codeDepth) { // Must be exact\n            state.code = false;\n          }\n        }\n        return null;\n      } else if (state.code) {\n        stream.next();\n        return null;\n      }\n      // Check if space. If so, links can be formatted later on\n      if (stream.eatSpace()) {\n        state.ateSpace = true;\n        return null;\n      }\n      if (stream.sol() || state.ateSpace) {\n        state.ateSpace = false;\n        if(stream.match(/^(?:[a-zA-Z0-9\\-_]+\\/)?(?:[a-zA-Z0-9\\-_]+@)?(?:[a-f0-9]{7,40}\\b)/)) {\n          // User/Project@SHA\n          // User@SHA\n          // SHA\n          state.combineTokens = true;\n          return \"link\";\n        } else if (stream.match(/^(?:[a-zA-Z0-9\\-_]+\\/)?(?:[a-zA-Z0-9\\-_]+)?#[0-9]+\\b/)) {\n          // User/Project#Num\n          // User#Num\n          // #Num\n          state.combineTokens = true;\n          return \"link\";\n        }\n      }\n      if (stream.match(/^((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]|\\([^\\s()<>]*\\))+(?:\\([^\\s()<>]*\\)|[^\\s`*!()\\[\\]{};:'\".,<>?«»“”‘’]))/i) &&\n         stream.string.slice(stream.start - 2, stream.start) != \"](\") {\n        // URLs\n        // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls\n        // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine\n        state.combineTokens = true;\n        return \"link\";\n      }\n      stream.next();\n      return null;\n    },\n    blankLine: blankLine\n  };\n\n  var markdownConfig = {\n    underscoresBreakWords: false,\n    taskLists: true,\n    fencedCodeBlocks: true,\n    strikethrough: true\n  };\n  for (var attr in modeConfig) {\n    markdownConfig[attr] = modeConfig[attr];\n  }\n  markdownConfig.name = \"markdown\";\n  CodeMirror.defineMIME(\"gfmBase\", markdownConfig);\n  return CodeMirror.overlayMode(CodeMirror.getMode(config, \"gfmBase\"), gfmOverlay);\n}, \"markdown\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gfm/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: GFM mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/mode/overlay.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../markdown/markdown.js\"></script>\n<script src=\"gfm.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"../clike/clike.js\"></script>\n<script src=\"../meta.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">GFM</a>\n  </ul>\n</div>\n\n<article>\n<h2>GFM mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nGitHub Flavored Markdown\n========================\n\nEverything from markdown plus GFM features:\n\n## URL autolinking\n\nUnderscores_are_allowed_between_words.\n\n## Strikethrough text\n\nGFM adds syntax to strikethrough text, which is missing from standard Markdown.\n\n~~Mistaken text.~~\n~~**works with other fomatting**~~\n\n~~spans across\nlines~~\n\n## Fenced code blocks (and syntax highlighting)\n\n```javascript\nfor (var i = 0; i &lt; items.length; i++) {\n    console.log(items[i], i); // log them\n}\n```\n\n## Task Lists\n\n- [ ] Incomplete task list item\n- [x] **Completed** task list item\n\n## A bit of GitHub spice\n\n* SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2\n* User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2\n* User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2\n* \\#Num: #1\n* User/#Num: mojombo#1\n* User/Project#Num: mojombo/god#1\n\nSee http://github.github.com/github-flavored-markdown/.\n\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'gfm',\n        lineNumbers: true,\n        theme: \"default\"\n      });\n    </script>\n\n    <p>Optionally depends on other modes for properly highlighted code blocks.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#gfm_*\">normal</a>,  <a href=\"../../test/index.html#verbose,gfm_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gfm/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4}, \"gfm\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n  var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: \"gfm\", highlightFormatting: true});\n  function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }\n\n  FT(\"codeBackticks\",\n     \"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]\");\n\n  FT(\"doubleBackticks\",\n     \"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]\");\n\n  FT(\"codeBlock\",\n     \"[comment&formatting&formatting-code-block ```css]\",\n     \"[tag foo]\",\n     \"[comment&formatting&formatting-code-block ```]\");\n\n  FT(\"taskList\",\n     \"[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2  foo]\",\n     \"[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2  foo]\");\n\n  FT(\"formatting_strikethrough\",\n     \"[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]\");\n\n  FT(\"formatting_strikethrough\",\n     \"foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]\");\n\n  MT(\"emInWordAsterisk\",\n     \"foo[em *bar*]hello\");\n\n  MT(\"emInWordUnderscore\",\n     \"foo_bar_hello\");\n\n  MT(\"emStrongUnderscore\",\n     \"[strong __][em&strong _foo__][em _] bar\");\n\n  MT(\"fencedCodeBlocks\",\n     \"[comment ```]\",\n     \"[comment foo]\",\n     \"\",\n     \"[comment ```]\",\n     \"bar\");\n\n  MT(\"fencedCodeBlockModeSwitching\",\n     \"[comment ```javascript]\",\n     \"[variable foo]\",\n     \"\",\n     \"[comment ```]\",\n     \"bar\");\n\n  MT(\"taskListAsterisk\",\n     \"[variable-2 * []] foo]\", // Invalid; must have space or x between []\n     \"[variable-2 * [ ]]bar]\", // Invalid; must have space after ]\n     \"[variable-2 * [x]]hello]\", // Invalid; must have space after ]\n     \"[variable-2 * ][meta [ ]]][variable-2  [world]]]\", // Valid; tests reference style links\n     \"    [variable-3 * ][property [x]]][variable-3  foo]\"); // Valid; can be nested\n\n  MT(\"taskListPlus\",\n     \"[variable-2 + []] foo]\", // Invalid; must have space or x between []\n     \"[variable-2 + [ ]]bar]\", // Invalid; must have space after ]\n     \"[variable-2 + [x]]hello]\", // Invalid; must have space after ]\n     \"[variable-2 + ][meta [ ]]][variable-2  [world]]]\", // Valid; tests reference style links\n     \"    [variable-3 + ][property [x]]][variable-3  foo]\"); // Valid; can be nested\n\n  MT(\"taskListDash\",\n     \"[variable-2 - []] foo]\", // Invalid; must have space or x between []\n     \"[variable-2 - [ ]]bar]\", // Invalid; must have space after ]\n     \"[variable-2 - [x]]hello]\", // Invalid; must have space after ]\n     \"[variable-2 - ][meta [ ]]][variable-2  [world]]]\", // Valid; tests reference style links\n     \"    [variable-3 - ][property [x]]][variable-3  foo]\"); // Valid; can be nested\n\n  MT(\"taskListNumber\",\n     \"[variable-2 1. []] foo]\", // Invalid; must have space or x between []\n     \"[variable-2 2. [ ]]bar]\", // Invalid; must have space after ]\n     \"[variable-2 3. [x]]hello]\", // Invalid; must have space after ]\n     \"[variable-2 4. ][meta [ ]]][variable-2  [world]]]\", // Valid; tests reference style links\n     \"    [variable-3 1. ][property [x]]][variable-3  foo]\"); // Valid; can be nested\n\n  MT(\"SHA\",\n     \"foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar\");\n\n  MT(\"SHAEmphasis\",\n     \"[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]\");\n\n  MT(\"shortSHA\",\n     \"foo [link be6a8cc] bar\");\n\n  MT(\"tooShortSHA\",\n     \"foo be6a8c bar\");\n\n  MT(\"longSHA\",\n     \"foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar\");\n\n  MT(\"badSHA\",\n     \"foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar\");\n\n  MT(\"userSHA\",\n     \"foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello\");\n\n  MT(\"userSHAEmphasis\",\n     \"[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]\");\n\n  MT(\"userProjectSHA\",\n     \"foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world\");\n\n  MT(\"userProjectSHAEmphasis\",\n     \"[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]\");\n\n  MT(\"num\",\n     \"foo [link #1] bar\");\n\n  MT(\"numEmphasis\",\n     \"[em *foo ][em&link #1][em *]\");\n\n  MT(\"badNum\",\n     \"foo #1bar hello\");\n\n  MT(\"userNum\",\n     \"foo [link bar#1] hello\");\n\n  MT(\"userNumEmphasis\",\n     \"[em *foo ][em&link bar#1][em *]\");\n\n  MT(\"userProjectNum\",\n     \"foo [link bar/hello#1] world\");\n\n  MT(\"userProjectNumEmphasis\",\n     \"[em *foo ][em&link bar/hello#1][em *]\");\n\n  MT(\"vanillaLink\",\n     \"foo [link http://www.example.com/] bar\");\n\n  MT(\"vanillaLinkPunctuation\",\n     \"foo [link http://www.example.com/]. bar\");\n\n  MT(\"vanillaLinkExtension\",\n     \"foo [link http://www.example.com/index.html] bar\");\n\n  MT(\"vanillaLinkEmphasis\",\n     \"foo [em *][em&link http://www.example.com/index.html][em *] bar\");\n\n  MT(\"notALink\",\n     \"[comment ```css]\",\n     \"[tag foo] {[property color]:[keyword black];}\",\n     \"[comment ```][link http://www.example.com/]\");\n\n  MT(\"notALink\",\n     \"[comment ``foo `bar` http://www.example.com/``] hello\");\n\n  MT(\"notALink\",\n     \"[comment `foo]\",\n     \"[link http://www.example.com/]\",\n     \"[comment `foo]\",\n     \"\",\n     \"[link http://www.example.com/]\");\n\n  MT(\"headerCodeBlockGithub\",\n     \"[header&header-1 # heading]\",\n     \"\",\n     \"[comment ```]\",\n     \"[comment code]\",\n     \"[comment ```]\",\n     \"\",\n     \"Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]\",\n     \"Issue: [link #1]\",\n     \"Link: [link http://www.example.com/]\");\n\n  MT(\"strikethrough\",\n     \"[strikethrough ~~foo~~]\");\n\n  MT(\"strikethroughWithStartingSpace\",\n     \"~~ foo~~\");\n\n  MT(\"strikethroughUnclosedStrayTildes\",\n    \"[strikethrough ~~foo~~~]\");\n\n  MT(\"strikethroughUnclosedStrayTildes\",\n     \"[strikethrough ~~foo ~~]\");\n\n  MT(\"strikethroughUnclosedStrayTildes\",\n    \"[strikethrough ~~foo ~~ bar]\");\n\n  MT(\"strikethroughUnclosedStrayTildes\",\n    \"[strikethrough ~~foo ~~ bar~~]hello\");\n\n  MT(\"strikethroughOneLetter\",\n     \"[strikethrough ~~a~~]\");\n\n  MT(\"strikethroughWrapped\",\n     \"[strikethrough ~~foo]\",\n     \"[strikethrough foo~~]\");\n\n  MT(\"strikethroughParagraph\",\n     \"[strikethrough ~~foo]\",\n     \"\",\n     \"foo[strikethrough ~~bar]\");\n\n  MT(\"strikethroughEm\",\n     \"[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]\");\n\n  MT(\"strikethroughEm\",\n     \"[em *][em&strikethrough ~~foo~~][em *]\");\n\n  MT(\"strikethroughStrong\",\n     \"[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]\");\n\n  MT(\"strikethroughStrong\",\n     \"[strong **][strong&strikethrough ~~foo~~][strong **]\");\n\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gherkin/gherkin.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\nGherkin mode - http://www.cukes.info/\nReport bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n*/\n\n// Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js\n//var Quotes = {\n//  SINGLE: 1,\n//  DOUBLE: 2\n//};\n\n//var regex = {\n//  keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/\n//};\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(\"gherkin\", function () {\n  return {\n    startState: function () {\n      return {\n        lineNumber: 0,\n        tableHeaderLine: false,\n        allowFeature: true,\n        allowBackground: false,\n        allowScenario: false,\n        allowSteps: false,\n        allowPlaceholders: false,\n        allowMultilineArgument: false,\n        inMultilineString: false,\n        inMultilineTable: false,\n        inKeywordLine: false\n      };\n    },\n    token: function (stream, state) {\n      if (stream.sol()) {\n        state.lineNumber++;\n        state.inKeywordLine = false;\n        if (state.inMultilineTable) {\n            state.tableHeaderLine = false;\n            if (!stream.match(/\\s*\\|/, false)) {\n              state.allowMultilineArgument = false;\n              state.inMultilineTable = false;\n            }\n        }\n      }\n\n      stream.eatSpace();\n\n      if (state.allowMultilineArgument) {\n\n        // STRING\n        if (state.inMultilineString) {\n          if (stream.match('\"\"\"')) {\n            state.inMultilineString = false;\n            state.allowMultilineArgument = false;\n          } else {\n            stream.match(/.*/);\n          }\n          return \"string\";\n        }\n\n        // TABLE\n        if (state.inMultilineTable) {\n          if (stream.match(/\\|\\s*/)) {\n            return \"bracket\";\n          } else {\n            stream.match(/[^\\|]*/);\n            return state.tableHeaderLine ? \"header\" : \"string\";\n          }\n        }\n\n        // DETECT START\n        if (stream.match('\"\"\"')) {\n          // String\n          state.inMultilineString = true;\n          return \"string\";\n        } else if (stream.match(\"|\")) {\n          // Table\n          state.inMultilineTable = true;\n          state.tableHeaderLine = true;\n          return \"bracket\";\n        }\n\n      }\n\n      // LINE COMMENT\n      if (stream.match(/#.*/)) {\n        return \"comment\";\n\n      // TAG\n      } else if (!state.inKeywordLine && stream.match(/@\\S+/)) {\n        return \"tag\";\n\n      // FEATURE\n      } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) {\n        state.allowScenario = true;\n        state.allowBackground = true;\n        state.allowPlaceholders = false;\n        state.allowSteps = false;\n        state.allowMultilineArgument = false;\n        state.inKeywordLine = true;\n        return \"keyword\";\n\n      // BACKGROUND\n      } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\\-ho\\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) {\n        state.allowPlaceholders = false;\n        state.allowSteps = true;\n        state.allowBackground = false;\n        state.allowMultilineArgument = false;\n        state.inKeywordLine = true;\n        return \"keyword\";\n\n      // SCENARIO OUTLINE\n      } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) {\n        state.allowPlaceholders = true;\n        state.allowSteps = true;\n        state.allowMultilineArgument = false;\n        state.inKeywordLine = true;\n        return \"keyword\";\n\n      // EXAMPLES\n      } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) {\n        state.allowPlaceholders = false;\n        state.allowSteps = true;\n        state.allowBackground = false;\n        state.allowMultilineArgument = true;\n        return \"keyword\";\n\n      // SCENARIO\n      } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) {\n        state.allowPlaceholders = false;\n        state.allowSteps = true;\n        state.allowBackground = false;\n        state.allowMultilineArgument = false;\n        state.inKeywordLine = true;\n        return \"keyword\";\n\n      // STEPS\n      } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\\* )/)) {\n        state.inStep = true;\n        state.allowPlaceholders = true;\n        state.allowMultilineArgument = true;\n        state.inKeywordLine = true;\n        return \"keyword\";\n\n      // INLINE STRING\n      } else if (stream.match(/\"[^\"]*\"?/)) {\n        return \"string\";\n\n      // PLACEHOLDER\n      } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) {\n        return \"variable\";\n\n      // Fall through\n      } else {\n        stream.next();\n        stream.eatWhile(/[^@\"<#]/);\n        return null;\n      }\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-feature\", \"gherkin\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/gherkin/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Gherkin mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"gherkin.js\"></script>\n<style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Gherkin</a>\n  </ul>\n</div>\n\n<article>\n<h2>Gherkin mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nFeature: Using Google\n  Background:\n    Something something\n    Something else\n  Scenario: Has a homepage\n    When I navigate to the google home page\n    Then the home page should contain the menu and the search form\n  Scenario: Searching for a term\n    When I navigate to the google home page\n    When I search for Tofu\n    Then the search results page is displayed\n    Then the search results page contains 10 individual search results\n    Then the search results contain a link to the wikipedia tofu page\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-feature</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/go/go.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(\"go\", function(config) {\n  var indentUnit = config.indentUnit;\n\n  var keywords = {\n    \"break\":true, \"case\":true, \"chan\":true, \"const\":true, \"continue\":true,\n    \"default\":true, \"defer\":true, \"else\":true, \"fallthrough\":true, \"for\":true,\n    \"func\":true, \"go\":true, \"goto\":true, \"if\":true, \"import\":true,\n    \"interface\":true, \"map\":true, \"package\":true, \"range\":true, \"return\":true,\n    \"select\":true, \"struct\":true, \"switch\":true, \"type\":true, \"var\":true,\n    \"bool\":true, \"byte\":true, \"complex64\":true, \"complex128\":true,\n    \"float32\":true, \"float64\":true, \"int8\":true, \"int16\":true, \"int32\":true,\n    \"int64\":true, \"string\":true, \"uint8\":true, \"uint16\":true, \"uint32\":true,\n    \"uint64\":true, \"int\":true, \"uint\":true, \"uintptr\":true\n  };\n\n  var atoms = {\n    \"true\":true, \"false\":true, \"iota\":true, \"nil\":true, \"append\":true,\n    \"cap\":true, \"close\":true, \"complex\":true, \"copy\":true, \"imag\":true,\n    \"len\":true, \"make\":true, \"new\":true, \"panic\":true, \"print\":true,\n    \"println\":true, \"real\":true, \"recover\":true\n  };\n\n  var isOperatorChar = /[+\\-*&^%:=<>!|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\" || ch == \"`\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\d\\.]/.test(ch)) {\n      if (ch == \".\") {\n        stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n      } else if (ch == \"0\") {\n        stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n      } else {\n        stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n      }\n      return \"number\";\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\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      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (cur == \"case\" || cur == \"default\") curPunc = \"case\";\n      return \"keyword\";\n    }\n    if (atoms.propertyIsEnumerable(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 || quote == \"`\"))\n        state.tokenize = tokenBase;\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 = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function 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  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function 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\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      };\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        if (ctx.type == \"case\") ctx.type = \"}\";\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      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 == \"case\") ctx.type = \"case\";\n      else if (curPunc == \"}\" && ctx.type == \"}\") ctx = popContext(state);\n      else if (curPunc == ctx.type) popContext(state);\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"case\" && /^(?:case|default)\\b/.test(textAfter)) {\n        state.context.type = \"}\";\n        return ctx.indented;\n      }\n      var closing = firstChar == ctx.type;\n      if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}):\",\n    fold: \"brace\",\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-go\", \"go\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/go/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Go mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/elegant.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"go.js\"></script>\n<style>.CodeMirror {border:1px solid #999; background:#ffc}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Go</a>\n  </ul>\n</div>\n\n<article>\n<h2>Go mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n// Prime Sieve in Go.\n// Taken from the Go specification.\n// Copyright © The Go Authors.\n\npackage main\n\nimport \"fmt\"\n\n// Send the sequence 2, 3, 4, ... to channel 'ch'.\nfunc generate(ch chan&lt;- int) {\n\tfor i := 2; ; i++ {\n\t\tch &lt;- i  // Send 'i' to channel 'ch'\n\t}\n}\n\n// Copy the values from channel 'src' to channel 'dst',\n// removing those divisible by 'prime'.\nfunc filter(src &lt;-chan int, dst chan&lt;- int, prime int) {\n\tfor i := range src {    // Loop over values received from 'src'.\n\t\tif i%prime != 0 {\n\t\t\tdst &lt;- i  // Send 'i' to channel 'dst'.\n\t\t}\n\t}\n}\n\n// The prime sieve: Daisy-chain filter processes together.\nfunc sieve() {\n\tch := make(chan int)  // Create a new channel.\n\tgo generate(ch)       // Start generate() as a subprocess.\n\tfor {\n\t\tprime := &lt;-ch\n\t\tfmt.Print(prime, \"\\n\")\n\t\tch1 := make(chan int)\n\t\tgo filter(ch, ch1, prime)\n\t\tch = ch1\n\t}\n}\n\nfunc main() {\n\tsieve()\n}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"elegant\",\n        matchBrackets: true,\n        indentUnit: 8,\n        tabSize: 8,\n        indentWithTabs: true,\n        mode: \"text/x-go\"\n      });\n    </script>\n\n    <p><strong>MIME type:</strong> <code>text/x-go</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/groovy/groovy.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(\"groovy\", function(config) {\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  var keywords = words(\n    \"abstract as assert boolean break byte case catch char class const continue def default \" +\n    \"do double else enum extends final finally float for goto if implements import in \" +\n    \"instanceof int interface long native new package private protected public return \" +\n    \"short static strictfp super switch synchronized threadsafe throw throws transient \" +\n    \"try void volatile while\");\n  var blockKeywords = words(\"catch class do else finally for if switch try while enum interface def\");\n  var atoms = words(\"null true false this\");\n\n  var curPunc;\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      return startString(ch, stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      if (stream.eat(/eE/)) { stream.eat(/\\+\\-/); stream.eatWhile(/\\d/); }\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize.push(tokenComment);\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      if (expectExpression(state.lastToken)) {\n        return startString(ch, stream, state);\n      }\n    }\n    if (ch == \"-\" && stream.eat(\">\")) {\n      curPunc = \"->\";\n      return null;\n    }\n    if (/[+\\-*&%=<>!?|\\/~]/.test(ch)) {\n      stream.eatWhile(/[+\\-*&%=<>|~]/);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    if (ch == \"@\") { stream.eatWhile(/[\\w\\$_\\.]/); return \"meta\"; }\n    if (state.lastToken == \".\") return \"property\";\n    if (stream.eat(\":\")) { curPunc = \"proplabel\"; return \"property\"; }\n    var cur = stream.current();\n    if (atoms.propertyIsEnumerable(cur)) { return \"atom\"; }\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    return \"variable\";\n  }\n  tokenBase.isBase = true;\n\n  function startString(quote, stream, state) {\n    var tripleQuoted = false;\n    if (quote != \"/\" && stream.eat(quote)) {\n      if (stream.eat(quote)) tripleQuoted = true;\n      else return \"string\";\n    }\n    function t(stream, state) {\n      var escaped = false, next, end = !tripleQuoted;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {\n          if (!tripleQuoted) { break; }\n          if (stream.match(quote + quote)) { end = true; break; }\n        }\n        if (quote == '\"' && next == \"$\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace());\n          return \"string\";\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end) state.tokenize.pop();\n      return \"string\";\n    }\n    state.tokenize.push(t);\n    return t(stream, state);\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n    function t(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    }\n    t.isBase = true;\n    return t;\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize.pop();\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function expectExpression(last) {\n    return !last || last == \"operator\" || last == \"->\" || /[\\.\\[\\{\\(,;:]/.test(last) ||\n      last == \"newstatement\" || last == \"keyword\" || last == \"proplabel\";\n  }\n\n  function 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  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function 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\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: [tokenBase],\n        context: new Context((basecolumn || 0) - config.indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true,\n        lastToken: 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        // Automatic semicolon insertion\n        if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) {\n          popContext(state); ctx = state.context;\n        }\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = state.tokenize[state.tokenize.length-1](stream, state);\n      if (style == \"comment\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      // Handle indentation for {x -> \\n ... }\n      else if (curPunc == \"->\" && ctx.type == \"statement\" && ctx.prev.type == \"}\") {\n        popContext(state);\n        state.context.align = false;\n      }\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 (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      state.lastToken = curPunc || style;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (!state.tokenize[state.tokenize.length-1].isBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;\n      if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : config.indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : config.indentUnit);\n    },\n\n    electricChars: \"{}\",\n    fold: \"brace\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-groovy\", \"groovy\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/groovy/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Groovy mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"groovy.js\"></script>\n<style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Groovy</a>\n  </ul>\n</div>\n\n<article>\n<h2>Groovy mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n//Pattern for groovy script\ndef p = ~/.*\\.groovy/\nnew File( 'd:\\\\scripts' ).eachFileMatch(p) {f ->\n  // imports list\n  def imports = []\n  f.eachLine {\n    // condition to detect an import instruction\n    ln -> if ( ln =~ '^import .*' ) {\n      imports << \"${ln - 'import '}\"\n    }\n  }\n  // print thmen\n  if ( ! imports.empty ) {\n    println f\n    imports.each{ println \"   $it\" }\n  }\n}\n\n/* Coin changer demo code from http://groovy.codehaus.org */\n\nenum UsCoin {\n  quarter(25), dime(10), nickel(5), penny(1)\n  UsCoin(v) { value = v }\n  final value\n}\n\nenum OzzieCoin {\n  fifty(50), twenty(20), ten(10), five(5)\n  OzzieCoin(v) { value = v }\n  final value\n}\n\ndef plural(word, count) {\n  if (count == 1) return word\n  word[-1] == 'y' ? word[0..-2] + \"ies\" : word + \"s\"\n}\n\ndef change(currency, amount) {\n  currency.values().inject([]){ list, coin ->\n     int count = amount / coin.value\n     amount = amount % coin.value\n     list += \"$count ${plural(coin.toString(), count)}\"\n  }\n}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-groovy\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-groovy</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haml/haml.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\"), require(\"../htmlmixed/htmlmixed\"), require(\"../ruby/ruby\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\", \"../ruby/ruby\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\n  // full haml mode. This handled embeded ruby and html fragments too\n  CodeMirror.defineMode(\"haml\", function(config) {\n    var htmlMode = CodeMirror.getMode(config, {name: \"htmlmixed\"});\n    var rubyMode = CodeMirror.getMode(config, \"ruby\");\n\n    function rubyInQuote(endQuote) {\n      return function(stream, state) {\n        var ch = stream.peek();\n        if (ch == endQuote && state.rubyState.tokenize.length == 1) {\n          // step out of ruby context as it seems to complete processing all the braces\n          stream.next();\n          state.tokenize = html;\n          return \"closeAttributeTag\";\n        } else {\n          return ruby(stream, state);\n        }\n      };\n    }\n\n    function ruby(stream, state) {\n      if (stream.match(\"-#\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      return rubyMode.token(stream, state.rubyState);\n    }\n\n    function html(stream, state) {\n      var ch = stream.peek();\n\n      // handle haml declarations. All declarations that cant be handled here\n      // will be passed to html mode\n      if (state.previousToken.style == \"comment\" ) {\n        if (state.indented > state.previousToken.indented) {\n          stream.skipToEnd();\n          return \"commentLine\";\n        }\n      }\n\n      if (state.startOfLine) {\n        if (ch == \"!\" && stream.match(\"!!\")) {\n          stream.skipToEnd();\n          return \"tag\";\n        } else if (stream.match(/^%[\\w:#\\.]+=/)) {\n          state.tokenize = ruby;\n          return \"hamlTag\";\n        } else if (stream.match(/^%[\\w:]+/)) {\n          return \"hamlTag\";\n        } else if (ch == \"/\" ) {\n          stream.skipToEnd();\n          return \"comment\";\n        }\n      }\n\n      if (state.startOfLine || state.previousToken.style == \"hamlTag\") {\n        if ( ch == \"#\" || ch == \".\") {\n          stream.match(/[\\w-#\\.]*/);\n          return \"hamlAttribute\";\n        }\n      }\n\n      // donot handle --> as valid ruby, make it HTML close comment instead\n      if (state.startOfLine && !stream.match(\"-->\", false) && (ch == \"=\" || ch == \"-\" )) {\n        state.tokenize = ruby;\n        return state.tokenize(stream, state);\n      }\n\n      if (state.previousToken.style == \"hamlTag\" ||\n          state.previousToken.style == \"closeAttributeTag\" ||\n          state.previousToken.style == \"hamlAttribute\") {\n        if (ch == \"(\") {\n          state.tokenize = rubyInQuote(\")\");\n          return state.tokenize(stream, state);\n        } else if (ch == \"{\") {\n          state.tokenize = rubyInQuote(\"}\");\n          return state.tokenize(stream, state);\n        }\n      }\n\n      return htmlMode.token(stream, state.htmlState);\n    }\n\n    return {\n      // default to html mode\n      startState: function() {\n        var htmlState = htmlMode.startState();\n        var rubyState = rubyMode.startState();\n        return {\n          htmlState: htmlState,\n          rubyState: rubyState,\n          indented: 0,\n          previousToken: { style: null, indented: 0},\n          tokenize: html\n        };\n      },\n\n      copyState: function(state) {\n        return {\n          htmlState : CodeMirror.copyState(htmlMode, state.htmlState),\n          rubyState: CodeMirror.copyState(rubyMode, state.rubyState),\n          indented: state.indented,\n          previousToken: state.previousToken,\n          tokenize: state.tokenize\n        };\n      },\n\n      token: function(stream, state) {\n        if (stream.sol()) {\n          state.indented = stream.indentation();\n          state.startOfLine = true;\n        }\n        if (stream.eatSpace()) return null;\n        var style = state.tokenize(stream, state);\n        state.startOfLine = false;\n        // dont record comment line as we only want to measure comment line with\n        // the opening comment block\n        if (style && style != \"commentLine\") {\n          state.previousToken = { style: style, indented: state.indented };\n        }\n        // if current state is ruby and the previous token is not `,` reset the\n        // tokenize to html\n        if (stream.eol() && state.tokenize == ruby) {\n          stream.backUp(1);\n          var ch = stream.peek();\n          stream.next();\n          if (ch && ch != \",\") {\n            state.tokenize = html;\n          }\n        }\n        // reprocess some of the specific style tag when finish setting previousToken\n        if (style == \"hamlTag\") {\n          style = \"tag\";\n        } else if (style == \"commentLine\") {\n          style = \"comment\";\n        } else if (style == \"hamlAttribute\") {\n          style = \"attribute\";\n        } else if (style == \"closeAttributeTag\") {\n          style = null;\n        }\n        return style;\n      }\n    };\n  }, \"htmlmixed\", \"ruby\");\n\n  CodeMirror.defineMIME(\"text/x-haml\", \"haml\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haml/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: HAML mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../ruby/ruby.js\"></script>\n<script src=\"haml.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">HAML</a>\n  </ul>\n</div>\n\n<article>\n<h2>HAML mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n!!!\n#content\n.left.column(title=\"title\"){:href => \"/hello\", :test => \"#{hello}_#{world}\"}\n    <!-- This is a comment -->\n    %h2 Welcome to our site!\n    %p= puts \"HAML MODE\"\n  .right.column\n    = render :partial => \"sidebar\"\n\n.container\n  .row\n    .span8\n      %h1.title= @page_title\n%p.title= @page_title\n%p\n  /\n    The same as HTML comment\n    Hello multiline comment\n\n  -# haml comment\n      This wont be displayed\n      nor will this\n  Date/Time:\n  - now = DateTime.now\n  %strong= now\n  - if now > DateTime.parse(\"December 31, 2006\")\n    = \"Happy new \" + \"year!\"\n\n%title\n  = @title\n  \\= @title\n  <h1>Title</h1>\n  <h1 title=\"HELLO\">\n    Title\n  </h1>\n    </textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"text/x-haml\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-haml</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#haml_*\">normal</a>,  <a href=\"../../test/index.html#verbose,haml_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haml/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, \"haml\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  // Requires at least one media query\n  MT(\"elementName\",\n     \"[tag %h1] Hey There\");\n\n  MT(\"oneElementPerLine\",\n     \"[tag %h1] Hey There %h2\");\n\n  MT(\"idSelector\",\n     \"[tag %h1][attribute #test] Hey There\");\n\n  MT(\"classSelector\",\n     \"[tag %h1][attribute .hello] Hey There\");\n\n  MT(\"docType\",\n     \"[tag !!! XML]\");\n\n  MT(\"comment\",\n     \"[comment / Hello WORLD]\");\n\n  MT(\"notComment\",\n     \"[tag %h1] This is not a / comment \");\n\n  MT(\"attributes\",\n     \"[tag %a]([variable title][operator =][string \\\"test\\\"]){[atom :title] [operator =>] [string \\\"test\\\"]}\");\n\n  MT(\"htmlCode\",\n     \"[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]\");\n\n  MT(\"rubyBlock\",\n     \"[operator =][variable-2 @item]\");\n\n  MT(\"selectorRubyBlock\",\n     \"[tag %a.selector=] [variable-2 @item]\");\n\n  MT(\"nestedRubyBlock\",\n      \"[tag %a]\",\n      \"   [operator =][variable puts] [string \\\"test\\\"]\");\n\n  MT(\"multilinePlaintext\",\n      \"[tag %p]\",\n      \"  Hello,\",\n      \"  World\");\n\n  MT(\"multilineRuby\",\n      \"[tag %p]\",\n      \"  [comment -# this is a comment]\",\n      \"     [comment and this is a comment too]\",\n      \"  Date/Time\",\n      \"  [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]\",\n      \"  [tag %strong=] [variable now]\",\n      \"  [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \\\"December 31, 2006\\\"])\",\n      \"     [operator =][string \\\"Happy\\\"]\",\n      \"     [operator =][string \\\"Belated\\\"]\",\n      \"     [operator =][string \\\"Birthday\\\"]\");\n\n  MT(\"multilineComment\",\n      \"[comment /]\",\n      \"  [comment Multiline]\",\n      \"  [comment Comment]\");\n\n  MT(\"hamlComment\",\n     \"[comment -# this is a comment]\");\n\n  MT(\"multilineHamlComment\",\n     \"[comment -# this is a comment]\",\n     \"   [comment and this is a comment too]\");\n\n  MT(\"multilineHTMLComment\",\n    \"[comment <!--]\",\n    \"  [comment what a comment]\",\n    \"  [comment -->]\");\n\n  MT(\"hamlAfterRubyTag\",\n    \"[attribute .block]\",\n    \"  [tag %strong=] [variable now]\",\n    \"  [attribute .test]\",\n    \"     [operator =][variable now]\",\n    \"  [attribute .right]\");\n\n  MT(\"stretchedRuby\",\n     \"[operator =] [variable puts] [string \\\"Hello\\\"],\",\n     \"   [string \\\"World\\\"]\");\n\n  MT(\"interpolationInHashAttribute\",\n     //\"[tag %div]{[atom :id] [operator =>] [string \\\"#{][variable test][string }_#{][variable ting][string }\\\"]} test\");\n     \"[tag %div]{[atom :id] [operator =>] [string \\\"#{][variable test][string }_#{][variable ting][string }\\\"]} test\");\n\n  MT(\"interpolationInHTMLAttribute\",\n     \"[tag %div]([variable title][operator =][string \\\"#{][variable test][string }_#{][variable ting]()[string }\\\"]) Test\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haskell/haskell.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(\"haskell\", function(_config, modeConfig) {\n\n  function switchState(source, setState, f) {\n    setState(f);\n    return f(source, setState);\n  }\n\n  // These should all be Unicode extended, as per the Haskell 2010 report\n  var smallRE = /[a-z_]/;\n  var largeRE = /[A-Z]/;\n  var digitRE = /\\d/;\n  var hexitRE = /[0-9A-Fa-f]/;\n  var octitRE = /[0-7]/;\n  var idRE = /[a-z_A-Z0-9'\\xa1-\\uffff]/;\n  var symbolRE = /[-!#$%&*+.\\/<=>?@\\\\^|~:]/;\n  var specialRE = /[(),;[\\]`{}]/;\n  var whiteCharRE = /[ \\t\\v\\f]/; // newlines are handled in tokenizer\n\n  function normal(source, setState) {\n    if (source.eatWhile(whiteCharRE)) {\n      return null;\n    }\n\n    var ch = source.next();\n    if (specialRE.test(ch)) {\n      if (ch == '{' && source.eat('-')) {\n        var t = \"comment\";\n        if (source.eat('#')) {\n          t = \"meta\";\n        }\n        return switchState(source, setState, ncomment(t, 1));\n      }\n      return null;\n    }\n\n    if (ch == '\\'') {\n      if (source.eat('\\\\')) {\n        source.next();  // should handle other escapes here\n      }\n      else {\n        source.next();\n      }\n      if (source.eat('\\'')) {\n        return \"string\";\n      }\n      return \"error\";\n    }\n\n    if (ch == '\"') {\n      return switchState(source, setState, stringLiteral);\n    }\n\n    if (largeRE.test(ch)) {\n      source.eatWhile(idRE);\n      if (source.eat('.')) {\n        return \"qualifier\";\n      }\n      return \"variable-2\";\n    }\n\n    if (smallRE.test(ch)) {\n      source.eatWhile(idRE);\n      return \"variable\";\n    }\n\n    if (digitRE.test(ch)) {\n      if (ch == '0') {\n        if (source.eat(/[xX]/)) {\n          source.eatWhile(hexitRE); // should require at least 1\n          return \"integer\";\n        }\n        if (source.eat(/[oO]/)) {\n          source.eatWhile(octitRE); // should require at least 1\n          return \"number\";\n        }\n      }\n      source.eatWhile(digitRE);\n      var t = \"number\";\n      if (source.match(/^\\.\\d+/)) {\n        t = \"number\";\n      }\n      if (source.eat(/[eE]/)) {\n        t = \"number\";\n        source.eat(/[-+]/);\n        source.eatWhile(digitRE); // should require at least 1\n      }\n      return t;\n    }\n\n    if (ch == \".\" && source.eat(\".\"))\n      return \"keyword\";\n\n    if (symbolRE.test(ch)) {\n      if (ch == '-' && source.eat(/-/)) {\n        source.eatWhile(/-/);\n        if (!source.eat(symbolRE)) {\n          source.skipToEnd();\n          return \"comment\";\n        }\n      }\n      var t = \"variable\";\n      if (ch == ':') {\n        t = \"variable-2\";\n      }\n      source.eatWhile(symbolRE);\n      return t;\n    }\n\n    return \"error\";\n  }\n\n  function ncomment(type, nest) {\n    if (nest == 0) {\n      return normal;\n    }\n    return function(source, setState) {\n      var currNest = nest;\n      while (!source.eol()) {\n        var ch = source.next();\n        if (ch == '{' && source.eat('-')) {\n          ++currNest;\n        }\n        else if (ch == '-' && source.eat('}')) {\n          --currNest;\n          if (currNest == 0) {\n            setState(normal);\n            return type;\n          }\n        }\n      }\n      setState(ncomment(type, currNest));\n      return type;\n    };\n  }\n\n  function stringLiteral(source, setState) {\n    while (!source.eol()) {\n      var ch = source.next();\n      if (ch == '\"') {\n        setState(normal);\n        return \"string\";\n      }\n      if (ch == '\\\\') {\n        if (source.eol() || source.eat(whiteCharRE)) {\n          setState(stringGap);\n          return \"string\";\n        }\n        if (source.eat('&')) {\n        }\n        else {\n          source.next(); // should handle other escapes here\n        }\n      }\n    }\n    setState(normal);\n    return \"error\";\n  }\n\n  function stringGap(source, setState) {\n    if (source.eat('\\\\')) {\n      return switchState(source, setState, stringLiteral);\n    }\n    source.next();\n    setState(normal);\n    return \"error\";\n  }\n\n\n  var wellKnownWords = (function() {\n    var wkw = {};\n    function setType(t) {\n      return function () {\n        for (var i = 0; i < arguments.length; i++)\n          wkw[arguments[i]] = t;\n      };\n    }\n\n    setType(\"keyword\")(\n      \"case\", \"class\", \"data\", \"default\", \"deriving\", \"do\", \"else\", \"foreign\",\n      \"if\", \"import\", \"in\", \"infix\", \"infixl\", \"infixr\", \"instance\", \"let\",\n      \"module\", \"newtype\", \"of\", \"then\", \"type\", \"where\", \"_\");\n\n    setType(\"keyword\")(\n      \"\\.\\.\", \":\", \"::\", \"=\", \"\\\\\", \"\\\"\", \"<-\", \"->\", \"@\", \"~\", \"=>\");\n\n    setType(\"builtin\")(\n      \"!!\", \"$!\", \"$\", \"&&\", \"+\", \"++\", \"-\", \".\", \"/\", \"/=\", \"<\", \"<=\", \"=<<\",\n      \"==\", \">\", \">=\", \">>\", \">>=\", \"^\", \"^^\", \"||\", \"*\", \"**\");\n\n    setType(\"builtin\")(\n      \"Bool\", \"Bounded\", \"Char\", \"Double\", \"EQ\", \"Either\", \"Enum\", \"Eq\",\n      \"False\", \"FilePath\", \"Float\", \"Floating\", \"Fractional\", \"Functor\", \"GT\",\n      \"IO\", \"IOError\", \"Int\", \"Integer\", \"Integral\", \"Just\", \"LT\", \"Left\",\n      \"Maybe\", \"Monad\", \"Nothing\", \"Num\", \"Ord\", \"Ordering\", \"Rational\", \"Read\",\n      \"ReadS\", \"Real\", \"RealFloat\", \"RealFrac\", \"Right\", \"Show\", \"ShowS\",\n      \"String\", \"True\");\n\n    setType(\"builtin\")(\n      \"abs\", \"acos\", \"acosh\", \"all\", \"and\", \"any\", \"appendFile\", \"asTypeOf\",\n      \"asin\", \"asinh\", \"atan\", \"atan2\", \"atanh\", \"break\", \"catch\", \"ceiling\",\n      \"compare\", \"concat\", \"concatMap\", \"const\", \"cos\", \"cosh\", \"curry\",\n      \"cycle\", \"decodeFloat\", \"div\", \"divMod\", \"drop\", \"dropWhile\", \"either\",\n      \"elem\", \"encodeFloat\", \"enumFrom\", \"enumFromThen\", \"enumFromThenTo\",\n      \"enumFromTo\", \"error\", \"even\", \"exp\", \"exponent\", \"fail\", \"filter\",\n      \"flip\", \"floatDigits\", \"floatRadix\", \"floatRange\", \"floor\", \"fmap\",\n      \"foldl\", \"foldl1\", \"foldr\", \"foldr1\", \"fromEnum\", \"fromInteger\",\n      \"fromIntegral\", \"fromRational\", \"fst\", \"gcd\", \"getChar\", \"getContents\",\n      \"getLine\", \"head\", \"id\", \"init\", \"interact\", \"ioError\", \"isDenormalized\",\n      \"isIEEE\", \"isInfinite\", \"isNaN\", \"isNegativeZero\", \"iterate\", \"last\",\n      \"lcm\", \"length\", \"lex\", \"lines\", \"log\", \"logBase\", \"lookup\", \"map\",\n      \"mapM\", \"mapM_\", \"max\", \"maxBound\", \"maximum\", \"maybe\", \"min\", \"minBound\",\n      \"minimum\", \"mod\", \"negate\", \"not\", \"notElem\", \"null\", \"odd\", \"or\",\n      \"otherwise\", \"pi\", \"pred\", \"print\", \"product\", \"properFraction\",\n      \"putChar\", \"putStr\", \"putStrLn\", \"quot\", \"quotRem\", \"read\", \"readFile\",\n      \"readIO\", \"readList\", \"readLn\", \"readParen\", \"reads\", \"readsPrec\",\n      \"realToFrac\", \"recip\", \"rem\", \"repeat\", \"replicate\", \"return\", \"reverse\",\n      \"round\", \"scaleFloat\", \"scanl\", \"scanl1\", \"scanr\", \"scanr1\", \"seq\",\n      \"sequence\", \"sequence_\", \"show\", \"showChar\", \"showList\", \"showParen\",\n      \"showString\", \"shows\", \"showsPrec\", \"significand\", \"signum\", \"sin\",\n      \"sinh\", \"snd\", \"span\", \"splitAt\", \"sqrt\", \"subtract\", \"succ\", \"sum\",\n      \"tail\", \"take\", \"takeWhile\", \"tan\", \"tanh\", \"toEnum\", \"toInteger\",\n      \"toRational\", \"truncate\", \"uncurry\", \"undefined\", \"unlines\", \"until\",\n      \"unwords\", \"unzip\", \"unzip3\", \"userError\", \"words\", \"writeFile\", \"zip\",\n      \"zip3\", \"zipWith\", \"zipWith3\");\n\n    var override = modeConfig.overrideKeywords;\n    if (override) for (var word in override) if (override.hasOwnProperty(word))\n      wkw[word] = override[word];\n\n    return wkw;\n  })();\n\n\n\n  return {\n    startState: function ()  { return { f: normal }; },\n    copyState:  function (s) { return { f: s.f }; },\n\n    token: function(stream, state) {\n      var t = state.f(stream, function(s) { state.f = s; });\n      var w = stream.current();\n      return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;\n    },\n\n    blockCommentStart: \"{-\",\n    blockCommentEnd: \"-}\",\n    lineComment: \"--\"\n  };\n\n});\n\nCodeMirror.defineMIME(\"text/x-haskell\", \"haskell\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haskell/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Haskell mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/elegant.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"haskell.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Haskell</a>\n  </ul>\n</div>\n\n<article>\n<h2>Haskell mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nmodule UniquePerms (\n    uniquePerms\n    )\nwhere\n\n-- | Find all unique permutations of a list where there might be duplicates.\nuniquePerms :: (Eq a) => [a] -> [[a]]\nuniquePerms = permBag . makeBag\n\n-- | An unordered collection where duplicate values are allowed,\n-- but represented with a single value and a count.\ntype Bag a = [(a, Int)]\n\nmakeBag :: (Eq a) => [a] -> Bag a\nmakeBag [] = []\nmakeBag (a:as) = mix a $ makeBag as\n  where\n    mix a []                        = [(a,1)]\n    mix a (bn@(b,n):bs) | a == b    = (b,n+1):bs\n                        | otherwise = bn : mix a bs\n\npermBag :: Bag a -> [[a]]\npermBag [] = [[]]\npermBag bs = concatMap (\\(f,cs) -> map (f:) $ permBag cs) . oneOfEach $ bs\n  where\n    oneOfEach [] = []\n    oneOfEach (an@(a,n):bs) =\n        let bs' = if n == 1 then bs else (a,n-1):bs\n        in (a,bs') : mapSnd (an:) (oneOfEach bs)\n\n    apSnd f (a,b) = (a, f b)\n    mapSnd = map . apSnd\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"elegant\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-haskell</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haxe/haxe.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(\"haxe\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"}, attribute = {type:\"attribute\", style: \"attribute\"};\n  var type = kw(\"typedef\");\n    return {\n      \"if\": A, \"while\": A, \"else\": B, \"do\": B, \"try\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"throw\": C,\n      \"var\": kw(\"var\"), \"inline\":attribute, \"static\": attribute, \"using\":kw(\"import\"),\n    \"public\": attribute, \"private\": attribute, \"cast\": kw(\"cast\"), \"import\": kw(\"import\"), \"macro\": kw(\"macro\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"), \"untyped\": kw(\"untyped\"), \"callback\": kw(\"cb\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"never\": kw(\"property_access\"), \"trace\":kw(\"trace\"),\n    \"class\": type, \"abstract\":type, \"enum\":type, \"interface\":type, \"typedef\":type, \"extends\":type, \"implements\":type, \"dynamic\":type,\n      \"true\": atom, \"false\": atom, \"null\": atom\n    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n\n  function haxeTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, haxeTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }\n    else if (/\\d/.test(ch) || ch == \"-\" && stream.eat(/\\d/)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (state.reAllowed && (ch == \"~\" && stream.eat(/\\//))) {\n      nextUntilUnescaped(stream, \"/\");\n      stream.eatWhile(/[gimsu]/);\n      return ret(\"regexp\", \"string-2\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, haxeTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"conditional\", \"meta\");\n    }\n    else if (ch == \"@\") {\n      stream.eat(/:/);\n      stream.eatWhile(/[\\w_]/);\n      return ret (\"metadata\", \"meta\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n    var word;\n    if(/[A-Z]/.test(ch))\n    {\n      stream.eatWhile(/[\\w_<>]/);\n      word = stream.current();\n      return ret(\"type\", \"variable-3\", word);\n    }\n    else\n    {\n        stream.eatWhile(/[\\w_]/);\n        var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n        return (known && state.kwAllowed) ? ret(known.type, known.style, word) :\n                       ret(\"variable\", \"variable\", word);\n    }\n    }\n  }\n\n  function haxeTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = haxeTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function haxeTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = haxeTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true};\n\n  function HaxeLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n  }\n\n  function parseHaxe(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n\n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n    if (type == \"variable\" && imported(state, content)) return \"variable-3\";\n        return style;\n      }\n    }\n  }\n\n  function imported(state, typename)\n  {\n  if (/[a-z]/.test(typename.charAt(0)))\n    return false;\n  var len = state.importedtypes.length;\n  for (var i = 0; i<len; i++)\n    if(state.importedtypes[i]==typename) return true;\n  }\n\n\n  function registerimport(importname) {\n  var state = cx.state;\n  for (var t = state.importedtypes; t; t = t.next)\n    if(t.name == importname) return;\n  state.importedtypes = { name: importname, next: state.importedtypes };\n  }\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: null};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    function f(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(f);\n    };\n    return f;\n  }\n\n  function statement(type) {\n    if (type == \"@\") return cont(metadef);\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), pushcontext, block, poplex, popcontext);\n    if (type == \";\") return cont();\n    if (type == \"attribute\") return cont(maybeattribute);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                         block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                        statement, poplex, popcontext);\n    if (type == \"import\") return cont(importdef, expect(\";\"));\n    if (type == \"typedef\") return cont(typedef);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n\n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\" || type == \":\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n\n  function maybeattribute(type) {\n    if (type == \"attribute\") return cont(maybeattribute);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"var\") return cont(vardef1);\n  }\n\n  function metadef(type) {\n    if(type == \":\") return cont(metadef);\n    if(type == \"variable\") return cont(metadef);\n    if(type == \"(\") return cont(pushlex(\")\"), commasep(metaargs, \")\"), poplex, statement);\n  }\n  function metaargs(type) {\n    if(type == \"variable\") return cont();\n  }\n\n  function importdef (type, value) {\n  if(type == \"variable\" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }\n  else if(type == \"variable\" || type == \"property\" || type == \".\" || value == \"*\") return cont(importdef);\n  }\n\n  function typedef (type, value)\n  {\n  if(type == \"variable\" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }\n  else if (type == \"type\" && /[A-Z]/.test(value.charAt(0))) { return cont(); }\n  }\n\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(typeuse, vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type, value) {\n  if (type == \"variable\") {\n    register(value);\n  }\n  return cont(pushlex(\")\"), pushcontext, forin, expression, poplex, statement, popcontext);\n  }\n  function forin(_type, value) {\n    if (value == \"in\") return cont();\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (value == \"new\") return cont(functiondef);\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, typeuse, statement, popcontext);\n  }\n  function typeuse(type) {\n    if(type == \":\") return cont(typestring);\n  }\n  function typestring(type) {\n    if(type == \"type\") return cont();\n    if(type == \"variable\") return cont();\n    if(type == \"{\") return cont(pushlex(\"}\"), commasep(typeprop, \"}\"), poplex);\n  }\n  function typeprop(type) {\n    if(type == \"variable\") return cont(typeuse);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont(typeuse);}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n    var defaulttypes = [\"Int\", \"Float\", \"String\", \"Void\", \"Std\", \"Bool\", \"Dynamic\", \"Array\"];\n      return {\n        tokenize: haxeTokenBase,\n        reAllowed: true,\n        kwAllowed: true,\n        cc: [],\n        lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n    importedtypes: defaulttypes,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = !!(type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/));\n      state.kwAllowed = type != '.';\n      return parseHaxe(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != haxeTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\",\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-haxe\", \"haxe\");\n\nCodeMirror.defineMode(\"hxml\", function () {\n\n  return {\n    startState: function () {\n      return {\n        define: false,\n        inString: false\n      };\n    },\n    token: function (stream, state) {\n      var ch = stream.peek();\n      var sol = stream.sol();\n\n      ///* comments */\n      if (ch == \"#\") {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      if (sol && ch == \"-\") {\n        var style = \"variable-2\";\n\n        stream.eat(/-/);\n\n        if (stream.peek() == \"-\") {\n          stream.eat(/-/);\n          style = \"keyword a\";\n        }\n\n        if (stream.peek() == \"D\") {\n          stream.eat(/[D]/);\n          style = \"keyword c\";\n          state.define = true;\n        }\n\n        stream.eatWhile(/[A-Z]/i);\n        return style;\n      }\n\n      var ch = stream.peek();\n\n      if (state.inString == false && ch == \"'\") {\n        state.inString = true;\n        ch = stream.next();\n      }\n\n      if (state.inString == true) {\n        if (stream.skipTo(\"'\")) {\n\n        } else {\n          stream.skipToEnd();\n        }\n\n        if (stream.peek() == \"'\") {\n          stream.next();\n          state.inString = false;\n        }\n\n        return \"string\";\n      }\n\n      stream.next();\n      return null;\n    },\n    lineComment: \"#\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-hxml\", \"hxml\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/haxe/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Haxe mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"haxe.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Haxe</a>\n  </ul>\n</div>\n\n<article>\n<h2>Haxe mode</h2>\n\n\n<div><p><textarea id=\"code-haxe\" name=\"code\">\nimport one.two.Three;\n\n@attr(\"test\")\nclass Foo&lt;T&gt; extends Three\n{\n\tpublic function new()\n\t{\n\t\tnoFoo = 12;\n\t}\n\n\tpublic static inline function doFoo(obj:{k:Int, l:Float}):Int\n\t{\n\t\tfor(i in 0...10)\n\t\t{\n\t\t\tobj.k++;\n\t\t\ttrace(i);\n\t\t\tvar var1 = new Array();\n\t\t\tif(var1.length > 1)\n\t\t\t\tthrow \"Error\";\n\t\t}\n\t\t// The following line should not be colored, the variable is scoped out\n\t\tvar1;\n\t\t/* Multi line\n\t\t * Comment test\n\t\t */\n\t\treturn obj.k;\n\t}\n\tprivate function bar():Void\n\t{\n\t\t#if flash\n\t\tvar t1:String = \"1.21\";\n\t\t#end\n\t\ttry {\n\t\t\tdoFoo({k:3, l:1.2});\n\t\t}\n\t\tcatch (e : String) {\n\t\t\ttrace(e);\n\t\t}\n\t\tvar t2:Float = cast(3.2);\n\t\tvar t3:haxe.Timer = new haxe.Timer();\n\t\tvar t4 = {k:Std.int(t2), l:Std.parseFloat(t1)};\n\t\tvar t5 = ~/123+.*$/i;\n\t\tdoFoo(t4);\n\t\tuntyped t1 = 4;\n\t\tbob = new Foo&lt;Int&gt;\n\t}\n\tpublic var okFoo(default, never):Float;\n\tvar noFoo(getFoo, null):Int;\n\tfunction getFoo():Int {\n\t\treturn noFoo;\n\t}\n\n\tpublic var three:Int;\n}\nenum Color\n{\n\tred;\n\tgreen;\n\tblue;\n\tgrey( v : Int );\n\trgb (r:Int,g:Int,b:Int);\n}\n</textarea></p>\n\n<p>Hxml mode:</p>\n\n<p><textarea id=\"code-hxml\">\n-cp test\n-js path/to/file.js\n#-remap nme:flash\n--next\n-D source-map-content\n-cmd 'test'\n-lib lime\n</textarea></p>\n</div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code-haxe\"), {\n      \tmode: \"haxe\",\n        lineNumbers: true,\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n\n      editor = CodeMirror.fromTextArea(document.getElementById(\"code-hxml\"), {\n      \tmode: \"hxml\",\n        lineNumbers: true,\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-haxe, text/x-hxml</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/htmlembedded/htmlembedded.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\"), require(\"../htmlmixed/htmlmixed\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"htmlembedded\", function(config, parserConfig) {\n\n  //config settings\n  var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,\n      scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;\n\n  //inner modes\n  var scriptingMode, htmlMixedMode;\n\n  //tokenizer when in html mode\n  function htmlDispatch(stream, state) {\n      if (stream.match(scriptStartRegex, false)) {\n          state.token=scriptingDispatch;\n          return scriptingMode.token(stream, state.scriptState);\n          }\n      else\n          return htmlMixedMode.token(stream, state.htmlState);\n    }\n\n  //tokenizer when in scripting mode\n  function scriptingDispatch(stream, state) {\n      if (stream.match(scriptEndRegex, false))  {\n          state.token=htmlDispatch;\n          return htmlMixedMode.token(stream, state.htmlState);\n         }\n      else\n          return scriptingMode.token(stream, state.scriptState);\n         }\n\n\n  return {\n    startState: function() {\n      scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);\n      htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, \"htmlmixed\");\n      return {\n          token :  parserConfig.startOpen ? scriptingDispatch : htmlDispatch,\n          htmlState : CodeMirror.startState(htmlMixedMode),\n          scriptState : CodeMirror.startState(scriptingMode)\n      };\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == htmlDispatch)\n        return htmlMixedMode.indent(state.htmlState, textAfter);\n      else if (scriptingMode.indent)\n        return scriptingMode.indent(state.scriptState, textAfter);\n    },\n\n    copyState: function(state) {\n      return {\n       token : state.token,\n       htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),\n       scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)\n      };\n    },\n\n    innerMode: function(state) {\n      if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};\n      else return {state: state.htmlState, mode: htmlMixedMode};\n    }\n  };\n}, \"htmlmixed\");\n\nCodeMirror.defineMIME(\"application/x-ejs\", { name: \"htmlembedded\", scriptingModeSpec:\"javascript\"});\nCodeMirror.defineMIME(\"application/x-aspx\", { name: \"htmlembedded\", scriptingModeSpec:\"text/x-csharp\"});\nCodeMirror.defineMIME(\"application/x-jsp\", { name: \"htmlembedded\", scriptingModeSpec:\"text/x-java\"});\nCodeMirror.defineMIME(\"application/x-erb\", { name: \"htmlembedded\", scriptingModeSpec:\"ruby\"});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/htmlembedded/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Html Embedded Scripts mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"htmlembedded.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Html Embedded Scripts</a>\n  </ul>\n</div>\n\n<article>\n<h2>Html Embedded Scripts mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n<%\nfunction hello(who) {\n\treturn \"Hello \" + who;\n}\n%>\nThis is an example of EJS (embedded javascript)\n<p>The program says <%= hello(\"world\") %>.</p>\n<script>\n\talert(\"And here is some normal JS code\"); // also colored\n</script>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"application/x-ejs\",\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n    </script>\n\n    <p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on\n    JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>\n\n    <p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET),\n    <code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/htmlmixed/htmlmixed.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\"), require(\"../xml/xml\"), require(\"../javascript/javascript\"), require(\"../css/css\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../xml/xml\", \"../javascript/javascript\", \"../css/css\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\",\n                                             htmlMode: true,\n                                             multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,\n                                             multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;\n  scriptTypes.push({matches: /^(?:text|application)\\/(?:x-)?(?:java|ecma)script$|^$/i,\n                    mode: CodeMirror.getMode(config, \"javascript\")});\n  if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {\n    var conf = scriptTypesConf[i];\n    scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});\n  }\n  scriptTypes.push({matches: /./,\n                    mode: CodeMirror.getMode(config, \"text/plain\")});\n\n  function html(stream, state) {\n    var tagName = state.htmlState.tagName;\n    if (tagName) tagName = tagName.toLowerCase();\n    var style = htmlMode.token(stream, state.htmlState);\n    if (tagName == \"script\" && /\\btag\\b/.test(style) && stream.current() == \">\") {\n      // Script block: mode to change to depends on type attribute\n      var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\\btype\\s*=\\s*(\"[^\"]+\"|'[^']+'|\\S+)[^<]*$/i);\n      scriptType = scriptType ? scriptType[1] : \"\";\n      if (scriptType && /[\\\"\\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);\n      for (var i = 0; i < scriptTypes.length; ++i) {\n        var tp = scriptTypes[i];\n        if (typeof tp.matches == \"string\" ? scriptType == tp.matches : tp.matches.test(scriptType)) {\n          if (tp.mode) {\n            state.token = script;\n            state.localMode = tp.mode;\n            state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, \"\"));\n          }\n          break;\n        }\n      }\n    } else if (tagName == \"style\" && /\\btag\\b/.test(style) && stream.current() == \">\") {\n      state.token = css;\n      state.localMode = cssMode;\n      state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat), m;\n    if (close > -1) stream.backUp(cur.length - close);\n    else if (m = cur.match(/<\\/?$/)) {\n      stream.backUp(cur.length);\n      if (!stream.match(pat, false)) stream.match(cur);\n    }\n    return style;\n  }\n  function script(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = state.localMode = null;\n      return null;\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       state.localMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = state.localMode = null;\n      return null;\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localMode: null, localState: null, htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.localMode, state.localState);\n      return {token: state.token, localMode: state.localMode, localState: local,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (!state.localMode || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.localMode.indent)\n        return state.localMode.indent(state.localState, textAfter);\n      else\n        return CodeMirror.Pass;\n    },\n\n    innerMode: function(state) {\n      return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};\n    }\n  };\n}, \"xml\", \"javascript\", \"css\");\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/htmlmixed/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: HTML mixed mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/selection/selection-pointer.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"../vbscript/vbscript.js\"></script>\n<script src=\"htmlmixed.js\"></script>\n<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">HTML mixed</a>\n  </ul>\n</div>\n\n<article>\n<h2>HTML mixed mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n<html style=\"color: green\">\n  <!-- this is a comment -->\n  <head>\n    <title>Mixed HTML Example</title>\n    <style type=\"text/css\">\n      h1 {font-family: comic sans; color: #f0f;}\n      div {background: yellow !important;}\n      body {\n        max-width: 50em;\n        margin: 1em 2em 1em 5em;\n      }\n    </style>\n  </head>\n  <body class=\"gray-bg\">\n    <h1>Mixed HTML Example</h1>\n    <script>\n      function jsFunc(arg1, arg2) {\n        if (arg1 && arg2) document.body.innerHTML = \"achoo\";\n      }\n    </script>\n  </body>\n</html>\n</textarea></form>\n    <script>\n      // Define an extended mixed-mode that understands vbscript and\n      // leaves mustache/handlebars embedded templates in html mode\n      var mixedMode = {\n        name: \"htmlmixed\",\n        scriptTypes: [{matches: /\\/x-handlebars-template|\\/x-mustache/i,\n                       mode: null},\n                      {matches: /(text|application)\\/(x-)?vb(a|script)/i,\n                       mode: \"vbscript\"}]\n      };\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: mixedMode,\n        selectionPointer: true\n      });\n    </script>\n\n    <p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>\n\n    <p>It takes an optional mode configuration\n    option, <code>scriptTypes</code>, which can be used to add custom\n    behavior for specific <code>&lt;script type=\"...\"></code> tags. If\n    given, it should hold an array of <code>{matches, mode}</code>\n    objects, where <code>matches</code> is a string or regexp that\n    matches the script type, and <code>mode</code> is\n    either <code>null</code>, for script types that should stay in\n    HTML mode, or a <a href=\"../../doc/manual.html#option_mode\">mode\n    spec</a> corresponding to the mode that should be used for the\n    script.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/html</code>\n    (redefined, only takes effect if you load this parser after the\n    XML parser).</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/http/http.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(\"http\", function() {\n  function failFirstLine(stream, state) {\n    stream.skipToEnd();\n    state.cur = header;\n    return \"error\";\n  }\n\n  function start(stream, state) {\n    if (stream.match(/^HTTP\\/\\d\\.\\d/)) {\n      state.cur = responseStatusCode;\n      return \"keyword\";\n    } else if (stream.match(/^[A-Z]+/) && /[ \\t]/.test(stream.peek())) {\n      state.cur = requestPath;\n      return \"keyword\";\n    } else {\n      return failFirstLine(stream, state);\n    }\n  }\n\n  function responseStatusCode(stream, state) {\n    var code = stream.match(/^\\d+/);\n    if (!code) return failFirstLine(stream, state);\n\n    state.cur = responseStatusText;\n    var status = Number(code[0]);\n    if (status >= 100 && status < 200) {\n      return \"positive informational\";\n    } else if (status >= 200 && status < 300) {\n      return \"positive success\";\n    } else if (status >= 300 && status < 400) {\n      return \"positive redirect\";\n    } else if (status >= 400 && status < 500) {\n      return \"negative client-error\";\n    } else if (status >= 500 && status < 600) {\n      return \"negative server-error\";\n    } else {\n      return \"error\";\n    }\n  }\n\n  function responseStatusText(stream, state) {\n    stream.skipToEnd();\n    state.cur = header;\n    return null;\n  }\n\n  function requestPath(stream, state) {\n    stream.eatWhile(/\\S/);\n    state.cur = requestProtocol;\n    return \"string-2\";\n  }\n\n  function requestProtocol(stream, state) {\n    if (stream.match(/^HTTP\\/\\d\\.\\d$/)) {\n      state.cur = header;\n      return \"keyword\";\n    } else {\n      return failFirstLine(stream, state);\n    }\n  }\n\n  function header(stream) {\n    if (stream.sol() && !stream.eat(/[ \\t]/)) {\n      if (stream.match(/^.*?:/)) {\n        return \"atom\";\n      } else {\n        stream.skipToEnd();\n        return \"error\";\n      }\n    } else {\n      stream.skipToEnd();\n      return \"string\";\n    }\n  }\n\n  function body(stream) {\n    stream.skipToEnd();\n    return null;\n  }\n\n  return {\n    token: function(stream, state) {\n      var cur = state.cur;\n      if (cur != header && cur != body && stream.eatSpace()) return null;\n      return cur(stream, state);\n    },\n\n    blankLine: function(state) {\n      state.cur = body;\n    },\n\n    startState: function() {\n      return {cur: start};\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"message/http\", \"http\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/http/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: HTTP mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"http.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">HTTP</a>\n  </ul>\n</div>\n\n<article>\n<h2>HTTP mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\nPOST /somewhere HTTP/1.1\nHost: example.com\nIf-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\nContent-Type: application/x-www-form-urlencoded;\n\tcharset=utf-8\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Ubuntu/12.04 Chromium/20.0.1132.47 Chrome/20.0.1132.47 Safari/536.11\n\nThis is the request body!\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>message/http</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/idl/idl.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', 'i');\n  };\n\n  var builtinArray = [\n    'a_correlate', 'abs', 'acos', 'adapt_hist_equal', 'alog',\n    'alog2', 'alog10', 'amoeba', 'annotate', 'app_user_dir',\n    'app_user_dir_query', 'arg_present', 'array_equal', 'array_indices',\n    'arrow', 'ascii_template', 'asin', 'assoc', 'atan',\n    'axis', 'axis', 'bandpass_filter', 'bandreject_filter', 'barplot',\n    'bar_plot', 'beseli', 'beselj', 'beselk', 'besely',\n    'beta', 'biginteger', 'bilinear', 'bin_date', 'binary_template',\n    'bindgen', 'binomial', 'bit_ffs', 'bit_population', 'blas_axpy',\n    'blk_con', 'boolarr', 'boolean', 'boxplot', 'box_cursor',\n    'breakpoint', 'broyden', 'bubbleplot', 'butterworth', 'bytarr',\n    'byte', 'byteorder', 'bytscl', 'c_correlate', 'calendar',\n    'caldat', 'call_external', 'call_function', 'call_method',\n    'call_procedure', 'canny', 'catch', 'cd', 'cdf', 'ceil',\n    'chebyshev', 'check_math', 'chisqr_cvf', 'chisqr_pdf', 'choldc',\n    'cholsol', 'cindgen', 'cir_3pnt', 'clipboard', 'close',\n    'clust_wts', 'cluster', 'cluster_tree', 'cmyk_convert', 'code_coverage',\n    'color_convert', 'color_exchange', 'color_quan', 'color_range_map',\n    'colorbar', 'colorize_sample', 'colormap_applicable',\n    'colormap_gradient', 'colormap_rotation', 'colortable',\n    'comfit', 'command_line_args', 'common', 'compile_opt', 'complex',\n    'complexarr', 'complexround', 'compute_mesh_normals', 'cond', 'congrid',\n    'conj', 'constrained_min', 'contour', 'contour', 'convert_coord',\n    'convol', 'convol_fft', 'coord2to3', 'copy_lun', 'correlate',\n    'cos', 'cosh', 'cpu', 'cramer', 'createboxplotdata',\n    'create_cursor', 'create_struct', 'create_view', 'crossp', 'crvlength',\n    'ct_luminance', 'cti_test', 'cursor', 'curvefit', 'cv_coord',\n    'cvttobm', 'cw_animate', 'cw_animate_getp', 'cw_animate_load',\n    'cw_animate_run', 'cw_arcball', 'cw_bgroup', 'cw_clr_index',\n    'cw_colorsel', 'cw_defroi', 'cw_field', 'cw_filesel', 'cw_form',\n    'cw_fslider', 'cw_light_editor', 'cw_light_editor_get',\n    'cw_light_editor_set', 'cw_orient', 'cw_palette_editor',\n    'cw_palette_editor_get', 'cw_palette_editor_set', 'cw_pdmenu',\n    'cw_rgbslider', 'cw_tmpl', 'cw_zoom', 'db_exists',\n    'dblarr', 'dcindgen', 'dcomplex', 'dcomplexarr', 'define_key',\n    'define_msgblk', 'define_msgblk_from_file', 'defroi', 'defsysv',\n    'delvar', 'dendro_plot', 'dendrogram', 'deriv', 'derivsig',\n    'determ', 'device', 'dfpmin', 'diag_matrix', 'dialog_dbconnect',\n    'dialog_message', 'dialog_pickfile', 'dialog_printersetup',\n    'dialog_printjob', 'dialog_read_image',\n    'dialog_write_image', 'dictionary', 'digital_filter', 'dilate', 'dindgen',\n    'dissolve', 'dist', 'distance_measure', 'dlm_load', 'dlm_register',\n    'doc_library', 'double', 'draw_roi', 'edge_dog', 'efont',\n    'eigenql', 'eigenvec', 'ellipse', 'elmhes', 'emboss',\n    'empty', 'enable_sysrtn', 'eof', 'eos', 'erase',\n    'erf', 'erfc', 'erfcx', 'erode', 'errorplot',\n    'errplot', 'estimator_filter', 'execute', 'exit', 'exp',\n    'expand', 'expand_path', 'expint', 'extrac', 'extract_slice',\n    'f_cvf', 'f_pdf', 'factorial', 'fft', 'file_basename',\n    'file_chmod', 'file_copy', 'file_delete', 'file_dirname',\n    'file_expand_path', 'file_gunzip', 'file_gzip', 'file_info',\n    'file_lines', 'file_link', 'file_mkdir', 'file_move',\n    'file_poll_input', 'file_readlink', 'file_same',\n    'file_search', 'file_tar', 'file_test', 'file_untar', 'file_unzip',\n    'file_which', 'file_zip', 'filepath', 'findgen', 'finite',\n    'fix', 'flick', 'float', 'floor', 'flow3',\n    'fltarr', 'flush', 'format_axis_values', 'forward_function', 'free_lun',\n    'fstat', 'fulstr', 'funct', 'function', 'fv_test',\n    'fx_root', 'fz_roots', 'gamma', 'gamma_ct', 'gauss_cvf',\n    'gauss_pdf', 'gauss_smooth', 'gauss2dfit', 'gaussfit',\n    'gaussian_function', 'gaussint', 'get_drive_list', 'get_dxf_objects',\n    'get_kbrd', 'get_login_info',\n    'get_lun', 'get_screen_size', 'getenv', 'getwindows', 'greg2jul',\n    'grib', 'grid_input', 'grid_tps', 'grid3', 'griddata',\n    'gs_iter', 'h_eq_ct', 'h_eq_int', 'hanning', 'hash',\n    'hdf', 'hdf5', 'heap_free', 'heap_gc', 'heap_nosave',\n    'heap_refcount', 'heap_save', 'help', 'hilbert', 'hist_2d',\n    'hist_equal', 'histogram', 'hls', 'hough', 'hqr',\n    'hsv', 'i18n_multibytetoutf8',\n    'i18n_multibytetowidechar', 'i18n_utf8tomultibyte',\n    'i18n_widechartomultibyte',\n    'ibeta', 'icontour', 'iconvertcoord', 'idelete', 'identity',\n    'idl_base64', 'idl_container', 'idl_validname',\n    'idlexbr_assistant', 'idlitsys_createtool',\n    'idlunit', 'iellipse', 'igamma', 'igetcurrent', 'igetdata',\n    'igetid', 'igetproperty', 'iimage', 'image', 'image_cont',\n    'image_statistics', 'image_threshold', 'imaginary', 'imap', 'indgen',\n    'int_2d', 'int_3d', 'int_tabulated', 'intarr', 'interpol',\n    'interpolate', 'interval_volume', 'invert', 'ioctl', 'iopen',\n    'ir_filter', 'iplot', 'ipolygon', 'ipolyline', 'iputdata',\n    'iregister', 'ireset', 'iresolve', 'irotate', 'isa',\n    'isave', 'iscale', 'isetcurrent', 'isetproperty', 'ishft',\n    'isocontour', 'isosurface', 'isurface', 'itext', 'itranslate',\n    'ivector', 'ivolume', 'izoom', 'journal', 'json_parse',\n    'json_serialize', 'jul2greg', 'julday', 'keyword_set', 'krig2d',\n    'kurtosis', 'kw_test', 'l64indgen', 'la_choldc', 'la_cholmprove',\n    'la_cholsol', 'la_determ', 'la_eigenproblem', 'la_eigenql', 'la_eigenvec',\n    'la_elmhes', 'la_gm_linear_model', 'la_hqr', 'la_invert',\n    'la_least_square_equality', 'la_least_squares', 'la_linear_equation',\n    'la_ludc', 'la_lumprove', 'la_lusol',\n    'la_svd', 'la_tridc', 'la_trimprove', 'la_triql', 'la_trired',\n    'la_trisol', 'label_date', 'label_region', 'ladfit', 'laguerre',\n    'lambda', 'lambdap', 'lambertw', 'laplacian', 'least_squares_filter',\n    'leefilt', 'legend', 'legendre', 'linbcg', 'lindgen',\n    'linfit', 'linkimage', 'list', 'll_arc_distance', 'lmfit',\n    'lmgr', 'lngamma', 'lnp_test', 'loadct', 'locale_get',\n    'logical_and', 'logical_or', 'logical_true', 'lon64arr', 'lonarr',\n    'long', 'long64', 'lsode', 'lu_complex', 'ludc',\n    'lumprove', 'lusol', 'm_correlate', 'machar', 'make_array',\n    'make_dll', 'make_rt', 'map', 'mapcontinents', 'mapgrid',\n    'map_2points', 'map_continents', 'map_grid', 'map_image', 'map_patch',\n    'map_proj_forward', 'map_proj_image', 'map_proj_info',\n    'map_proj_init', 'map_proj_inverse',\n    'map_set', 'matrix_multiply', 'matrix_power', 'max', 'md_test',\n    'mean', 'meanabsdev', 'mean_filter', 'median', 'memory',\n    'mesh_clip', 'mesh_decimate', 'mesh_issolid',\n    'mesh_merge', 'mesh_numtriangles',\n    'mesh_obj', 'mesh_smooth', 'mesh_surfacearea',\n    'mesh_validate', 'mesh_volume',\n    'message', 'min', 'min_curve_surf', 'mk_html_help', 'modifyct',\n    'moment', 'morph_close', 'morph_distance',\n    'morph_gradient', 'morph_hitormiss',\n    'morph_open', 'morph_thin', 'morph_tophat', 'multi', 'n_elements',\n    'n_params', 'n_tags', 'ncdf', 'newton', 'noise_hurl',\n    'noise_pick', 'noise_scatter', 'noise_slur', 'norm', 'obj_class',\n    'obj_destroy', 'obj_hasmethod', 'obj_isa', 'obj_new', 'obj_valid',\n    'objarr', 'on_error', 'on_ioerror', 'online_help', 'openr',\n    'openu', 'openw', 'oplot', 'oploterr', 'orderedhash',\n    'p_correlate', 'parse_url', 'particle_trace', 'path_cache', 'path_sep',\n    'pcomp', 'plot', 'plot3d', 'plot', 'plot_3dbox',\n    'plot_field', 'ploterr', 'plots', 'polar_contour', 'polar_surface',\n    'polyfill', 'polyshade', 'pnt_line', 'point_lun', 'polarplot',\n    'poly', 'poly_2d', 'poly_area', 'poly_fit', 'polyfillv',\n    'polygon', 'polyline', 'polywarp', 'popd', 'powell',\n    'pref_commit', 'pref_get', 'pref_set', 'prewitt', 'primes',\n    'print', 'printf', 'printd', 'pro', 'product',\n    'profile', 'profiler', 'profiles', 'project_vol', 'ps_show_fonts',\n    'psafm', 'pseudo', 'ptr_free', 'ptr_new', 'ptr_valid',\n    'ptrarr', 'pushd', 'qgrid3', 'qhull', 'qromb',\n    'qromo', 'qsimp', 'query_*', 'query_ascii', 'query_bmp',\n    'query_csv', 'query_dicom', 'query_gif', 'query_image', 'query_jpeg',\n    'query_jpeg2000', 'query_mrsid', 'query_pict', 'query_png', 'query_ppm',\n    'query_srf', 'query_tiff', 'query_video', 'query_wav', 'r_correlate',\n    'r_test', 'radon', 'randomn', 'randomu', 'ranks',\n    'rdpix', 'read', 'readf', 'read_ascii', 'read_binary',\n    'read_bmp', 'read_csv', 'read_dicom', 'read_gif', 'read_image',\n    'read_interfile', 'read_jpeg', 'read_jpeg2000', 'read_mrsid', 'read_pict',\n    'read_png', 'read_ppm', 'read_spr', 'read_srf', 'read_sylk',\n    'read_tiff', 'read_video', 'read_wav', 'read_wave', 'read_x11_bitmap',\n    'read_xwd', 'reads', 'readu', 'real_part', 'rebin',\n    'recall_commands', 'recon3', 'reduce_colors', 'reform', 'region_grow',\n    'register_cursor', 'regress', 'replicate',\n    'replicate_inplace', 'resolve_all',\n    'resolve_routine', 'restore', 'retall', 'return', 'reverse',\n    'rk4', 'roberts', 'rot', 'rotate', 'round',\n    'routine_filepath', 'routine_info', 'rs_test', 's_test', 'save',\n    'savgol', 'scale3', 'scale3d', 'scatterplot', 'scatterplot3d',\n    'scope_level', 'scope_traceback', 'scope_varfetch',\n    'scope_varname', 'search2d',\n    'search3d', 'sem_create', 'sem_delete', 'sem_lock', 'sem_release',\n    'set_plot', 'set_shading', 'setenv', 'sfit', 'shade_surf',\n    'shade_surf_irr', 'shade_volume', 'shift', 'shift_diff', 'shmdebug',\n    'shmmap', 'shmunmap', 'shmvar', 'show3', 'showfont',\n    'signum', 'simplex', 'sin', 'sindgen', 'sinh',\n    'size', 'skewness', 'skip_lun', 'slicer3', 'slide_image',\n    'smooth', 'sobel', 'socket', 'sort', 'spawn',\n    'sph_4pnt', 'sph_scat', 'spher_harm', 'spl_init', 'spl_interp',\n    'spline', 'spline_p', 'sprsab', 'sprsax', 'sprsin',\n    'sprstp', 'sqrt', 'standardize', 'stddev', 'stop',\n    'strarr', 'strcmp', 'strcompress', 'streamline', 'streamline',\n    'stregex', 'stretch', 'string', 'strjoin', 'strlen',\n    'strlowcase', 'strmatch', 'strmessage', 'strmid', 'strpos',\n    'strput', 'strsplit', 'strtrim', 'struct_assign', 'struct_hide',\n    'strupcase', 'surface', 'surface', 'surfr', 'svdc',\n    'svdfit', 'svsol', 'swap_endian', 'swap_endian_inplace', 'symbol',\n    'systime', 't_cvf', 't_pdf', 't3d', 'tag_names',\n    'tan', 'tanh', 'tek_color', 'temporary', 'terminal_size',\n    'tetra_clip', 'tetra_surface', 'tetra_volume', 'text', 'thin',\n    'thread', 'threed', 'tic', 'time_test2', 'timegen',\n    'timer', 'timestamp', 'timestamptovalues', 'tm_test', 'toc',\n    'total', 'trace', 'transpose', 'tri_surf', 'triangulate',\n    'trigrid', 'triql', 'trired', 'trisol', 'truncate_lun',\n    'ts_coef', 'ts_diff', 'ts_fcast', 'ts_smooth', 'tv',\n    'tvcrs', 'tvlct', 'tvrd', 'tvscl', 'typename',\n    'uindgen', 'uint', 'uintarr', 'ul64indgen', 'ulindgen',\n    'ulon64arr', 'ulonarr', 'ulong', 'ulong64', 'uniq',\n    'unsharp_mask', 'usersym', 'value_locate', 'variance', 'vector',\n    'vector_field', 'vel', 'velovect', 'vert_t3d', 'voigt',\n    'volume', 'voronoi', 'voxel_proj', 'wait', 'warp_tri',\n    'watershed', 'wdelete', 'wf_draw', 'where', 'widget_base',\n    'widget_button', 'widget_combobox', 'widget_control',\n    'widget_displaycontextmenu', 'widget_draw',\n    'widget_droplist', 'widget_event', 'widget_info',\n    'widget_label', 'widget_list',\n    'widget_propertysheet', 'widget_slider', 'widget_tab',\n    'widget_table', 'widget_text',\n    'widget_tree', 'widget_tree_move', 'widget_window',\n    'wiener_filter', 'window',\n    'window', 'write_bmp', 'write_csv', 'write_gif', 'write_image',\n    'write_jpeg', 'write_jpeg2000', 'write_nrif', 'write_pict', 'write_png',\n    'write_ppm', 'write_spr', 'write_srf', 'write_sylk', 'write_tiff',\n    'write_video', 'write_wav', 'write_wave', 'writeu', 'wset',\n    'wshow', 'wtn', 'wv_applet', 'wv_cwt', 'wv_cw_wavelet',\n    'wv_denoise', 'wv_dwt', 'wv_fn_coiflet',\n    'wv_fn_daubechies', 'wv_fn_gaussian',\n    'wv_fn_haar', 'wv_fn_morlet', 'wv_fn_paul',\n    'wv_fn_symlet', 'wv_import_data',\n    'wv_import_wavelet', 'wv_plot3d_wps', 'wv_plot_multires',\n    'wv_pwt', 'wv_tool_denoise',\n    'xbm_edit', 'xdisplayfile', 'xdxf', 'xfont', 'xinteranimate',\n    'xloadct', 'xmanager', 'xmng_tmpl', 'xmtool', 'xobjview',\n    'xobjview_rotate', 'xobjview_write_image',\n    'xpalette', 'xpcolor', 'xplot3d',\n    'xregistered', 'xroi', 'xsq_test', 'xsurface', 'xvaredit',\n    'xvolume', 'xvolume_rotate', 'xvolume_write_image',\n    'xyouts', 'zlib_compress', 'zlib_uncompress', 'zoom', 'zoom_24'\n  ];\n  var builtins = wordRegexp(builtinArray);\n\n  var keywordArray = [\n    'begin', 'end', 'endcase', 'endfor',\n    'endwhile', 'endif', 'endrep', 'endforeach',\n    'break', 'case', 'continue', 'for',\n    'foreach', 'goto', 'if', 'then', 'else',\n    'repeat', 'until', 'switch', 'while',\n    'do', 'pro', 'function'\n  ];\n  var keywords = wordRegexp(keywordArray);\n\n  CodeMirror.registerHelper(\"hintWords\", \"idl\", builtinArray.concat(keywordArray));\n\n  var identifiers = new RegExp('^[_a-z\\xa1-\\uffff][_a-z0-9\\xa1-\\uffff]*', 'i');\n\n  var singleOperators = /[+\\-*&=<>\\/@#~$]/;\n  var boolOperators = new RegExp('(and|or|eq|lt|le|gt|ge|ne|not)', 'i');\n\n  function tokenBase(stream) {\n    // whitespaces\n    if (stream.eatSpace()) return null;\n\n    // Handle one line Comments\n    if (stream.match(';')) {\n      stream.skipToEnd();\n      return 'comment';\n    }\n\n    // Handle Number Literals\n    if (stream.match(/^[0-9\\.+-]/, false)) {\n      if (stream.match(/^[+-]?0x[0-9a-fA-F]+/))\n        return 'number';\n      if (stream.match(/^[+-]?\\d*\\.\\d+([EeDd][+-]?\\d+)?/))\n        return 'number';\n      if (stream.match(/^[+-]?\\d+([EeDd][+-]?\\d+)?/))\n        return 'number';\n    }\n\n    // Handle Strings\n    if (stream.match(/^\"([^\"]|(\"\"))*\"/)) { return 'string'; }\n    if (stream.match(/^'([^']|(''))*'/)) { return 'string'; }\n\n    // Handle words\n    if (stream.match(keywords)) { return 'keyword'; }\n    if (stream.match(builtins)) { return 'builtin'; }\n    if (stream.match(identifiers)) { return 'variable'; }\n\n    if (stream.match(singleOperators) || stream.match(boolOperators)) {\n      return 'operator'; }\n\n    // Handle non-detected items\n    stream.next();\n    return 'error';\n  };\n\n  CodeMirror.defineMode('idl', function() {\n    return {\n      token: function(stream) {\n        return tokenBase(stream);\n      }\n    };\n  });\n\n  CodeMirror.defineMIME('text/x-idl', 'idl');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/idl/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: IDL mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"idl.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">IDL</a>\n  </ul>\n</div>\n\n<article>\n<h2>IDL mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n;; Example IDL code\nFUNCTION mean_and_stddev,array\n  ;; This program reads in an array of numbers\n  ;; and returns a structure containing the\n  ;; average and standard deviation\n\n  ave = 0.0\n  count = 0.0\n\n  for i=0,N_ELEMENTS(array)-1 do begin\n      ave = ave + array[i]\n      count = count + 1\n  endfor\n\n  ave = ave/count\n\n  std = stddev(array)\n\n  return, {average:ave,std:std}\n\nEND\n\n    </textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"idl\",\n               version: 1,\n               singleLineStringErrors: false},\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-idl</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Language Modes</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../doc/docs.css\">\n\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../index.html\">Home</a>\n    <li><a href=\"../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a class=active href=\"#\">Language modes</a>\n  </ul>\n</div>\n\n<article>\n\n  <h2>Language modes</h2>\n\n  <p>This is a list of every mode in the distribution. Each mode lives\nin a subdirectory of the <code>mode/</code> directory, and typically\ndefines a single JavaScript file that implements the mode. Loading\nsuch file will make the language available to CodeMirror, through\nthe <a href=\"../doc/manual.html#option_mode\"><code>mode</code></a>\noption.</p>\n\n  <div style=\"-webkit-columns: 100px 2; -moz-columns: 100px 2; columns: 100px 2;\">\n    <ul style=\"margin-top: 0\">\n      <li><a href=\"apl/index.html\">APL</a></li>\n      <li><a href=\"asterisk/index.html\">Asterisk dialplan</a></li>\n      <li><a href=\"clike/index.html\">C, C++, C#</a></li>\n      <li><a href=\"clojure/index.html\">Clojure</a></li>\n      <li><a href=\"cobol/index.html\">COBOL</a></li>\n      <li><a href=\"coffeescript/index.html\">CoffeeScript</a></li>\n      <li><a href=\"commonlisp/index.html\">Common Lisp</a></li>\n      <li><a href=\"css/index.html\">CSS</a></li>\n      <li><a href=\"cypher/index.html\">Cypher</a></li>\n      <li><a href=\"python/index.html\">Cython</a></li>\n      <li><a href=\"d/index.html\">D</a></li>\n      <li><a href=\"dart/index.html\">Dart</a></li>\n      <li><a href=\"django/index.html\">Django</a> (templating language)</li>\n      <li><a href=\"dockerfile/index.html\">Dockerfile</a></li>\n      <li><a href=\"diff/index.html\">diff</a></li>\n      <li><a href=\"dtd/index.html\">DTD</a></li>\n      <li><a href=\"dylan/index.html\">Dylan</a></li>\n      <li><a href=\"ebnf/index.html\">EBNF</a></li>\n      <li><a href=\"ecl/index.html\">ECL</a></li>\n      <li><a href=\"eiffel/index.html\">Eiffel</a></li>\n      <li><a href=\"erlang/index.html\">Erlang</a></li>\n      <li><a href=\"fortran/index.html\">Fortran</a></li>\n      <li><a href=\"mllike/index.html\">F#</a></li>\n      <li><a href=\"gas/index.html\">Gas</a> (AT&amp;T-style assembly)</li>\n      <li><a href=\"gherkin/index.html\">Gherkin</a></li>\n      <li><a href=\"go/index.html\">Go</a></li>\n      <li><a href=\"groovy/index.html\">Groovy</a></li>\n      <li><a href=\"haml/index.html\">HAML</a></li>\n      <li><a href=\"haskell/index.html\">Haskell</a></li>\n      <li><a href=\"haxe/index.html\">Haxe</a></li>\n      <li><a href=\"htmlembedded/index.html\">HTML embedded scripts</a></li>\n      <li><a href=\"htmlmixed/index.html\">HTML mixed-mode</a></li>\n      <li><a href=\"http/index.html\">HTTP</a></li>\n      <li><a href=\"idl/index.html\">IDL</a></li>\n      <li><a href=\"clike/index.html\">Java</a></li>\n      <li><a href=\"jade/index.html\">Jade</a></li>\n      <li><a href=\"javascript/index.html\">JavaScript</a></li>\n      <li><a href=\"jinja2/index.html\">Jinja2</a></li>\n      <li><a href=\"julia/index.html\">Julia</a></li>\n      <li><a href=\"kotlin/index.html\">Kotlin</a></li>\n      <li><a href=\"css/less.html\">LESS</a></li>\n      <li><a href=\"livescript/index.html\">LiveScript</a></li>\n      <li><a href=\"lua/index.html\">Lua</a></li>\n      <li><a href=\"markdown/index.html\">Markdown</a> (<a href=\"gfm/index.html\">GitHub-flavour</a>)</li>\n      <li><a href=\"mirc/index.html\">mIRC</a></li>\n      <li><a href=\"modelica/index.html\">Modelica</a></li>\n      <li><a href=\"nginx/index.html\">Nginx</a></li>\n      <li><a href=\"ntriples/index.html\">NTriples</a></li>\n      <li><a href=\"clike/index.html\">Objective C</a></li>\n      <li><a href=\"mllike/index.html\">OCaml</a></li>\n      <li><a href=\"octave/index.html\">Octave</a> (MATLAB)</li>\n      <li><a href=\"pascal/index.html\">Pascal</a></li>\n      <li><a href=\"pegjs/index.html\">PEG.js</a></li>\n      <li><a href=\"perl/index.html\">Perl</a></li>\n      <li><a href=\"php/index.html\">PHP</a></li>\n      <li><a href=\"pig/index.html\">Pig Latin</a></li>\n      <li><a href=\"properties/index.html\">Properties files</a></li>\n      <li><a href=\"puppet/index.html\">Puppet</a></li>\n      <li><a href=\"python/index.html\">Python</a></li>\n      <li><a href=\"q/index.html\">Q</a></li>\n      <li><a href=\"r/index.html\">R</a></li>\n      <li><a href=\"rpm/index.html\">RPM</a></li>\n      <li><a href=\"rst/index.html\">reStructuredText</a></li>\n      <li><a href=\"ruby/index.html\">Ruby</a></li>\n      <li><a href=\"rust/index.html\">Rust</a></li>\n      <li><a href=\"sass/index.html\">Sass</a></li>\n      <li><a href=\"spreadsheet/index.html\">Spreadsheet</a></li>\n      <li><a href=\"clike/scala.html\">Scala</a></li>\n      <li><a href=\"scheme/index.html\">Scheme</a></li>\n      <li><a href=\"css/scss.html\">SCSS</a></li>\n      <li><a href=\"shell/index.html\">Shell</a></li>\n      <li><a href=\"sieve/index.html\">Sieve</a></li>\n      <li><a href=\"slim/index.html\">Slim</a></li>\n      <li><a href=\"smalltalk/index.html\">Smalltalk</a></li>\n      <li><a href=\"smarty/index.html\">Smarty</a></li>\n      <li><a href=\"smartymixed/index.html\">Smarty/HTML mixed</a></li>\n      <li><a href=\"solr/index.html\">Solr</a></li>\n      <li><a href=\"soy/index.html\">Soy</a></li>\n      <li><a href=\"sql/index.html\">SQL</a> (several dialects)</li>\n      <li><a href=\"sparql/index.html\">SPARQL</a></li>\n      <li><a href=\"stex/index.html\">sTeX, LaTeX</a></li>\n      <li><a href=\"tcl/index.html\">Tcl</a></li>\n      <li><a href=\"textile/index.html\">Textile</a></li>\n      <li><a href=\"tiddlywiki/index.html\">Tiddlywiki</a></li>\n      <li><a href=\"tiki/index.html\">Tiki wiki</a></li>\n      <li><a href=\"toml/index.html\">TOML</a></li>\n      <li><a href=\"tornado/index.html\">Tornado</a> (templating language)</li>\n      <li><a href=\"turtle/index.html\">Turtle</a></li>\n      <li><a href=\"vb/index.html\">VB.NET</a></li>\n      <li><a href=\"vbscript/index.html\">VBScript</a></li>\n      <li><a href=\"velocity/index.html\">Velocity</a></li>\n      <li><a href=\"verilog/index.html\">Verilog/SystemVerilog</a></li>\n      <li><a href=\"xml/index.html\">XML/HTML</a></li>\n      <li><a href=\"xquery/index.html\">XQuery</a></li>\n      <li><a href=\"yaml/index.html\">YAML</a></li>\n      <li><a href=\"z80/index.html\">Z80</a></li>\n    </ul>\n  </div>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/jade/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Jade Templating Mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"jade.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Jade Templating Mode</a>\n  </ul>\n</div>\n\n<article>\n<h2>Jade Templating Mode</h2>\n<form><textarea id=\"code\" name=\"code\">\ndoctype html\n  html\n    head\n      title= \"Jade Templating CodeMirror Mode Example\"\n      link(rel='stylesheet', href='/css/bootstrap.min.css')\n      link(rel='stylesheet', href='/css/index.css')\n      script(type='text/javascript', src='/js/jquery-1.9.1.min.js')\n      script(type='text/javascript', src='/js/bootstrap.min.js')\n    body\n      div.header\n        h1 Welcome to this Example\n      div.spots\n        if locals.spots\n          each spot in spots\n            div.spot.well\n         div\n           if spot.logo\n             img.img-rounded.logo(src=spot.logo)\n           else\n             img.img-rounded.logo(src=\"img/placeholder.png\")\n         h3\n           a(href=spot.hash) ##{spot.hash}\n           if spot.title\n             span.title #{spot.title}\n           if spot.desc\n             div #{spot.desc}\n        else\n          h3 There are no spots currently available.\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"jade\", alignCDATA: true},\n        lineNumbers: true\n      });\n    </script>\n    <h3>The Jade Templating Mode</h3>\n      <p> Created by Forbes Lindesay. Managed as part of a Brackets extension at <a href=\"https://github.com/ForbesLindesay/jade-brackets\">https://github.com/ForbesLindesay/jade-brackets</a>.</p>\n    <p><strong>MIME type defined:</strong> <code>text/x-jade</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/jade/jade.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\"), require(\"../javascript/javascript\"), require(\"../css/css\"), require(\"../htmlmixed/htmlmixed\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../javascript/javascript\", \"../css/css\", \"../htmlmixed/htmlmixed\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode('jade', function (config) {\n  // token types\n  var KEYWORD = 'keyword';\n  var DOCTYPE = 'meta';\n  var ID = 'builtin';\n  var CLASS = 'qualifier';\n\n  var ATTRS_NEST = {\n    '{': '}',\n    '(': ')',\n    '[': ']'\n  };\n\n  var jsMode = CodeMirror.getMode(config, 'javascript');\n\n  function State() {\n    this.javaScriptLine = false;\n    this.javaScriptLineExcludesColon = false;\n\n    this.javaScriptArguments = false;\n    this.javaScriptArgumentsDepth = 0;\n\n    this.isInterpolating = false;\n    this.interpolationNesting = 0;\n\n    this.jsState = jsMode.startState();\n\n    this.restOfLine = '';\n\n    this.isIncludeFiltered = false;\n    this.isEach = false;\n\n    this.lastTag = '';\n    this.scriptType = '';\n\n    // Attributes Mode\n    this.isAttrs = false;\n    this.attrsNest = [];\n    this.inAttributeName = true;\n    this.attributeIsType = false;\n    this.attrValue = '';\n\n    // Indented Mode\n    this.indentOf = Infinity;\n    this.indentToken = '';\n\n    this.innerMode = null;\n    this.innerState = null;\n\n    this.innerModeForLine = false;\n  }\n  /**\n   * Safely copy a state\n   *\n   * @return {State}\n   */\n  State.prototype.copy = function () {\n    var res = new State();\n    res.javaScriptLine = this.javaScriptLine;\n    res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;\n    res.javaScriptArguments = this.javaScriptArguments;\n    res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;\n    res.isInterpolating = this.isInterpolating;\n    res.interpolationNesting = this.intpolationNesting;\n\n    res.jsState = CodeMirror.copyState(jsMode, this.jsState);\n\n    res.innerMode = this.innerMode;\n    if (this.innerMode && this.innerState) {\n      res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);\n    }\n\n    res.restOfLine = this.restOfLine;\n\n    res.isIncludeFiltered = this.isIncludeFiltered;\n    res.isEach = this.isEach;\n    res.lastTag = this.lastTag;\n    res.scriptType = this.scriptType;\n    res.isAttrs = this.isAttrs;\n    res.attrsNest = this.attrsNest.slice();\n    res.inAttributeName = this.inAttributeName;\n    res.attributeIsType = this.attributeIsType;\n    res.attrValue = this.attrValue;\n    res.indentOf = this.indentOf;\n    res.indentToken = this.indentToken;\n\n    res.innerModeForLine = this.innerModeForLine;\n\n    return res;\n  };\n\n  function javaScript(stream, state) {\n    if (stream.sol()) {\n      // if javaScriptLine was set at end of line, ignore it\n      state.javaScriptLine = false;\n      state.javaScriptLineExcludesColon = false;\n    }\n    if (state.javaScriptLine) {\n      if (state.javaScriptLineExcludesColon && stream.peek() === ':') {\n        state.javaScriptLine = false;\n        state.javaScriptLineExcludesColon = false;\n        return;\n      }\n      var tok = jsMode.token(stream, state.jsState);\n      if (stream.eol()) state.javaScriptLine = false;\n      return tok || true;\n    }\n  }\n  function javaScriptArguments(stream, state) {\n    if (state.javaScriptArguments) {\n      if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') {\n        state.javaScriptArguments = false;\n        return;\n      }\n      if (stream.peek() === '(') {\n        state.javaScriptArgumentsDepth++;\n      } else if (stream.peek() === ')') {\n        state.javaScriptArgumentsDepth--;\n      }\n      if (state.javaScriptArgumentsDepth === 0) {\n        state.javaScriptArguments = false;\n        return;\n      }\n\n      var tok = jsMode.token(stream, state.jsState);\n      return tok || true;\n    }\n  }\n\n  function yieldStatement(stream) {\n    if (stream.match(/^yield\\b/)) {\n        return 'keyword';\n    }\n  }\n\n  function doctype(stream) {\n    if (stream.match(/^(?:doctype) *([^\\n]+)?/)) {\n        return DOCTYPE;\n    }\n  }\n\n  function interpolation(stream, state) {\n    if (stream.match('#{')) {\n      state.isInterpolating = true;\n      state.interpolationNesting = 0;\n      return 'punctuation';\n    }\n  }\n\n  function interpolationContinued(stream, state) {\n    if (state.isInterpolating) {\n      if (stream.peek() === '}') {\n        state.interpolationNesting--;\n        if (state.interpolationNesting < 0) {\n          stream.next();\n          state.isInterpolating = false;\n          return 'puncutation';\n        }\n      } else if (stream.peek() === '{') {\n        state.interpolationNesting++;\n      }\n      return jsMode.token(stream, state.jsState) || true;\n    }\n  }\n\n  function caseStatement(stream, state) {\n    if (stream.match(/^case\\b/)) {\n      state.javaScriptLine = true;\n      return KEYWORD;\n    }\n  }\n\n  function when(stream, state) {\n    if (stream.match(/^when\\b/)) {\n      state.javaScriptLine = true;\n      state.javaScriptLineExcludesColon = true;\n      return KEYWORD;\n    }\n  }\n\n  function defaultStatement(stream) {\n    if (stream.match(/^default\\b/)) {\n      return KEYWORD;\n    }\n  }\n\n  function extendsStatement(stream, state) {\n    if (stream.match(/^extends?\\b/)) {\n      state.restOfLine = 'string';\n      return KEYWORD;\n    }\n  }\n\n  function append(stream, state) {\n    if (stream.match(/^append\\b/)) {\n      state.restOfLine = 'variable';\n      return KEYWORD;\n    }\n  }\n  function prepend(stream, state) {\n    if (stream.match(/^prepend\\b/)) {\n      state.restOfLine = 'variable';\n      return KEYWORD;\n    }\n  }\n  function block(stream, state) {\n    if (stream.match(/^block\\b *(?:(prepend|append)\\b)?/)) {\n      state.restOfLine = 'variable';\n      return KEYWORD;\n    }\n  }\n\n  function include(stream, state) {\n    if (stream.match(/^include\\b/)) {\n      state.restOfLine = 'string';\n      return KEYWORD;\n    }\n  }\n\n  function includeFiltered(stream, state) {\n    if (stream.match(/^include:([a-zA-Z0-9\\-]+)/, false) && stream.match('include')) {\n      state.isIncludeFiltered = true;\n      return KEYWORD;\n    }\n  }\n\n  function includeFilteredContinued(stream, state) {\n    if (state.isIncludeFiltered) {\n      var tok = filter(stream, state);\n      state.isIncludeFiltered = false;\n      state.restOfLine = 'string';\n      return tok;\n    }\n  }\n\n  function mixin(stream, state) {\n    if (stream.match(/^mixin\\b/)) {\n      state.javaScriptLine = true;\n      return KEYWORD;\n    }\n  }\n\n  function call(stream, state) {\n    if (stream.match(/^\\+([-\\w]+)/)) {\n      if (!stream.match(/^\\( *[-\\w]+ *=/, false)) {\n        state.javaScriptArguments = true;\n        state.javaScriptArgumentsDepth = 0;\n      }\n      return 'variable';\n    }\n    if (stream.match(/^\\+#{/, false)) {\n      stream.next();\n      state.mixinCallAfter = true;\n      return interpolation(stream, state);\n    }\n  }\n  function callArguments(stream, state) {\n    if (state.mixinCallAfter) {\n      state.mixinCallAfter = false;\n      if (!stream.match(/^\\( *[-\\w]+ *=/, false)) {\n        state.javaScriptArguments = true;\n        state.javaScriptArgumentsDepth = 0;\n      }\n      return true;\n    }\n  }\n\n  function conditional(stream, state) {\n    if (stream.match(/^(if|unless|else if|else)\\b/)) {\n      state.javaScriptLine = true;\n      return KEYWORD;\n    }\n  }\n\n  function each(stream, state) {\n    if (stream.match(/^(- *)?(each|for)\\b/)) {\n      state.isEach = true;\n      return KEYWORD;\n    }\n  }\n  function eachContinued(stream, state) {\n    if (state.isEach) {\n      if (stream.match(/^ in\\b/)) {\n        state.javaScriptLine = true;\n        state.isEach = false;\n        return KEYWORD;\n      } else if (stream.sol() || stream.eol()) {\n        state.isEach = false;\n      } else if (stream.next()) {\n        while (!stream.match(/^ in\\b/, false) && stream.next());\n        return 'variable';\n      }\n    }\n  }\n\n  function whileStatement(stream, state) {\n    if (stream.match(/^while\\b/)) {\n      state.javaScriptLine = true;\n      return KEYWORD;\n    }\n  }\n\n  function tag(stream, state) {\n    var captures;\n    if (captures = stream.match(/^(\\w(?:[-:\\w]*\\w)?)\\/?/)) {\n      state.lastTag = captures[1].toLowerCase();\n      if (state.lastTag === 'script') {\n        state.scriptType = 'application/javascript';\n      }\n      return 'tag';\n    }\n  }\n\n  function filter(stream, state) {\n    if (stream.match(/^:([\\w\\-]+)/)) {\n      var innerMode;\n      if (config && config.innerModes) {\n        innerMode = config.innerModes(stream.current().substring(1));\n      }\n      if (!innerMode) {\n        innerMode = stream.current().substring(1);\n      }\n      if (typeof innerMode === 'string') {\n        innerMode = CodeMirror.getMode(config, innerMode);\n      }\n      setInnerMode(stream, state, innerMode);\n      return 'atom';\n    }\n  }\n\n  function code(stream, state) {\n    if (stream.match(/^(!?=|-)/)) {\n      state.javaScriptLine = true;\n      return 'punctuation';\n    }\n  }\n\n  function id(stream) {\n    if (stream.match(/^#([\\w-]+)/)) {\n      return ID;\n    }\n  }\n\n  function className(stream) {\n    if (stream.match(/^\\.([\\w-]+)/)) {\n      return CLASS;\n    }\n  }\n\n  function attrs(stream, state) {\n    if (stream.peek() == '(') {\n      stream.next();\n      state.isAttrs = true;\n      state.attrsNest = [];\n      state.inAttributeName = true;\n      state.attrValue = '';\n      state.attributeIsType = false;\n      return 'punctuation';\n    }\n  }\n\n  function attrsContinued(stream, state) {\n    if (state.isAttrs) {\n      if (ATTRS_NEST[stream.peek()]) {\n        state.attrsNest.push(ATTRS_NEST[stream.peek()]);\n      }\n      if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {\n        state.attrsNest.pop();\n      } else  if (stream.eat(')')) {\n        state.isAttrs = false;\n        return 'punctuation';\n      }\n      if (state.inAttributeName && stream.match(/^[^=,\\)!]+/)) {\n        if (stream.peek() === '=' || stream.peek() === '!') {\n          state.inAttributeName = false;\n          state.jsState = jsMode.startState();\n          if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {\n            state.attributeIsType = true;\n          } else {\n            state.attributeIsType = false;\n          }\n        }\n        return 'attribute';\n      }\n\n      var tok = jsMode.token(stream, state.jsState);\n      if (state.attributeIsType && tok === 'string') {\n        state.scriptType = stream.current().toString();\n      }\n      if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) {\n        try {\n          Function('', 'var x ' + state.attrValue.replace(/,\\s*$/, '').replace(/^!/, ''));\n          state.inAttributeName = true;\n          state.attrValue = '';\n          stream.backUp(stream.current().length);\n          return attrsContinued(stream, state);\n        } catch (ex) {\n          //not the end of an attribute\n        }\n      }\n      state.attrValue += stream.current();\n      return tok || true;\n    }\n  }\n\n  function attributesBlock(stream, state) {\n    if (stream.match(/^&attributes\\b/)) {\n      state.javaScriptArguments = true;\n      state.javaScriptArgumentsDepth = 0;\n      return 'keyword';\n    }\n  }\n\n  function indent(stream) {\n    if (stream.sol() && stream.eatSpace()) {\n      return 'indent';\n    }\n  }\n\n  function comment(stream, state) {\n    if (stream.match(/^ *\\/\\/(-)?([^\\n]*)/)) {\n      state.indentOf = stream.indentation();\n      state.indentToken = 'comment';\n      return 'comment';\n    }\n  }\n\n  function colon(stream) {\n    if (stream.match(/^: */)) {\n      return 'colon';\n    }\n  }\n\n  function text(stream, state) {\n    if (stream.match(/^(?:\\| ?| )([^\\n]+)/)) {\n      return 'string';\n    }\n    if (stream.match(/^(<[^\\n]*)/, false)) {\n      // html string\n      setInnerMode(stream, state, 'htmlmixed');\n      state.innerModeForLine = true;\n      return innerMode(stream, state, true);\n    }\n  }\n\n  function dot(stream, state) {\n    if (stream.eat('.')) {\n      var innerMode = null;\n      if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) {\n        innerMode = state.scriptType.toLowerCase().replace(/\"|'/g, '');\n      } else if (state.lastTag === 'style') {\n        innerMode = 'css';\n      }\n      setInnerMode(stream, state, innerMode);\n      return 'dot';\n    }\n  }\n\n  function fail(stream) {\n    stream.next();\n    return null;\n  }\n\n\n  function setInnerMode(stream, state, mode) {\n    mode = CodeMirror.mimeModes[mode] || mode;\n    mode = config.innerModes ? config.innerModes(mode) || mode : mode;\n    mode = CodeMirror.mimeModes[mode] || mode;\n    mode = CodeMirror.getMode(config, mode);\n    state.indentOf = stream.indentation();\n\n    if (mode && mode.name !== 'null') {\n      state.innerMode = mode;\n    } else {\n      state.indentToken = 'string';\n    }\n  }\n  function innerMode(stream, state, force) {\n    if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {\n      if (state.innerMode) {\n        if (!state.innerState) {\n          state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {};\n        }\n        return stream.hideFirstChars(state.indentOf + 2, function () {\n          return state.innerMode.token(stream, state.innerState) || true;\n        });\n      } else {\n        stream.skipToEnd();\n        return state.indentToken;\n      }\n    } else if (stream.sol()) {\n      state.indentOf = Infinity;\n      state.indentToken = null;\n      state.innerMode = null;\n      state.innerState = null;\n    }\n  }\n  function restOfLine(stream, state) {\n    if (stream.sol()) {\n      // if restOfLine was set at end of line, ignore it\n      state.restOfLine = '';\n    }\n    if (state.restOfLine) {\n      stream.skipToEnd();\n      var tok = state.restOfLine;\n      state.restOfLine = '';\n      return tok;\n    }\n  }\n\n\n  function startState() {\n    return new State();\n  }\n  function copyState(state) {\n    return state.copy();\n  }\n  /**\n   * Get the next token in the stream\n   *\n   * @param {Stream} stream\n   * @param {State} state\n   */\n  function nextToken(stream, state) {\n    var tok = innerMode(stream, state)\n      || restOfLine(stream, state)\n      || interpolationContinued(stream, state)\n      || includeFilteredContinued(stream, state)\n      || eachContinued(stream, state)\n      || attrsContinued(stream, state)\n      || javaScript(stream, state)\n      || javaScriptArguments(stream, state)\n      || callArguments(stream, state)\n\n      || yieldStatement(stream, state)\n      || doctype(stream, state)\n      || interpolation(stream, state)\n      || caseStatement(stream, state)\n      || when(stream, state)\n      || defaultStatement(stream, state)\n      || extendsStatement(stream, state)\n      || append(stream, state)\n      || prepend(stream, state)\n      || block(stream, state)\n      || include(stream, state)\n      || includeFiltered(stream, state)\n      || mixin(stream, state)\n      || call(stream, state)\n      || conditional(stream, state)\n      || each(stream, state)\n      || whileStatement(stream, state)\n      || tag(stream, state)\n      || filter(stream, state)\n      || code(stream, state)\n      || id(stream, state)\n      || className(stream, state)\n      || attrs(stream, state)\n      || attributesBlock(stream, state)\n      || indent(stream, state)\n      || text(stream, state)\n      || comment(stream, state)\n      || colon(stream, state)\n      || dot(stream, state)\n      || fail(stream, state);\n\n    return tok === true ? null : tok;\n  }\n  return {\n    startState: startState,\n    copyState: copyState,\n    token: nextToken\n  };\n});\n\nCodeMirror.defineMIME('text/x-jade', 'jade');\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/javascript/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: JavaScript mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../../addon/comment/continuecomment.js\"></script>\n<script src=\"../../addon/comment/comment.js\"></script>\n<script src=\"javascript.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">JavaScript</a>\n  </ul>\n</div>\n\n<article>\n<h2>JavaScript mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n// Demo code (the actual new parser character stream implementation)\n\nfunction StringStream(string) {\n  this.pos = 0;\n  this.string = string;\n}\n\nStringStream.prototype = {\n  done: function() {return this.pos >= this.string.length;},\n  peek: function() {return this.string.charAt(this.pos);},\n  next: function() {\n    if (this.pos &lt; 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 &amp;&amp; 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    if (this.pos > start) return this.string.slice(start, this.pos);\n  },\n  backUp: function(n) {this.pos -= n;},\n  column: function() {return this.pos;},\n  eatSpace: function() {\n    var start = this.pos;\n    while (/\\s/.test(this.string.charAt(this.pos))) this.pos++;\n    return this.pos - start;\n  },\n  match: function(pattern, consume, caseInsensitive) {\n    if (typeof pattern == \"string\") {\n      function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}\n      if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {\n        if (consume !== false) this.pos += str.length;\n        return true;\n      }\n    }\n    else {\n      var match = this.string.slice(this.pos).match(pattern);\n      if (match &amp;&amp; consume !== false) this.pos += match[0].length;\n      return match;\n    }\n  }\n};\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        continueComments: \"Enter\",\n        extraKeys: {\"Ctrl-Q\": \"toggleComment\"}\n      });\n    </script>\n\n    <p>\n      JavaScript mode supports several configuration options:\n      <ul>\n        <li><code>json</code> which will set the mode to expect JSON\n        data rather than a JavaScript program.</li>\n        <li><code>jsonld</code> which will set the mode to expect\n        <a href=\"http://json-ld.org\">JSON-LD</a> linked data rather\n        than a JavaScript program (<a href=\"json-ld.html\">demo</a>).</li>\n        <li><code>typescript</code> which will activate additional\n        syntax highlighting and some other things for TypeScript code\n        (<a href=\"typescript.html\">demo</a>).</li>\n        <li><code>statementIndent</code> which (given a number) will\n        determine the amount of indentation to use for statements\n        continued on a new line.</li>\n        <li><code>wordCharacters</code>, a regexp that indicates which\n        characters should be considered part of an identifier.\n        Defaults to <code>/[\\w$]/</code>, which does not handle\n        non-ASCII identifiers. Can be set to something more elaborate\n        to improve Unicode support.</li>\n      </ul>\n    </p>\n\n    <p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>, <code>application/ld+json</code>, <code>text/typescript</code>, <code>application/typescript</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/javascript/javascript.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// TODO actually recognize syntax of TypeScript constructs\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(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var statementIndent = parserConfig.statementIndent;\n  var jsonldMode = parserConfig.jsonld;\n  var jsonMode = parserConfig.json || jsonldMode;\n  var isTS = parserConfig.typescript;\n  var wordRE = parserConfig.wordCharacters || /[\\w$\\xa1-\\uffff]/;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n\n    var jsKeywords = {\n      \"if\": kw(\"if\"), \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"delete\": C, \"throw\": C, \"debugger\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom,\n      \"this\": kw(\"this\"), \"module\": kw(\"module\"), \"class\": kw(\"class\"), \"super\": kw(\"atom\"),\n      \"yield\": C, \"export\": kw(\"export\"), \"import\": kw(\"import\"), \"extends\": C\n    };\n\n    // Extend the 'normal' keywords with the TypeScript language extensions\n    if (isTS) {\n      var type = {type: \"variable\", style: \"variable-3\"};\n      var tsKeywords = {\n        // object-like things\n        \"interface\": kw(\"interface\"),\n        \"extends\": kw(\"extends\"),\n        \"constructor\": kw(\"constructor\"),\n\n        // scope modifiers\n        \"public\": kw(\"public\"),\n        \"private\": kw(\"private\"),\n        \"protected\": kw(\"protected\"),\n        \"static\": kw(\"static\"),\n\n        // types\n        \"string\": type, \"number\": type, \"bool\": type, \"any\": type\n      };\n\n      for (var attr in tsKeywords) {\n        jsKeywords[attr] = tsKeywords[attr];\n      }\n    }\n\n    return jsKeywords;\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|~^]/;\n  var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;\n\n  function readRegexp(stream) {\n    var escaped = false, next, inSet = false;\n    while ((next = stream.next()) != null) {\n      if (!escaped) {\n        if (next == \"/\" && !inSet) return;\n        if (next == \"[\") inSet = true;\n        else if (inSet && next == \"]\") inSet = false;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    } else if (ch == \".\" && stream.match(/^\\d+(?:[eE][+\\-]?\\d+)?/)) {\n      return ret(\"number\", \"number\");\n    } else if (ch == \".\" && stream.match(\"..\")) {\n      return ret(\"spread\", \"meta\");\n    } else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      return ret(ch);\n    } else if (ch == \"=\" && stream.eat(\">\")) {\n      return ret(\"=>\", \"operator\");\n    } else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    } else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      } else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      } else if (state.lastType == \"operator\" || state.lastType == \"keyword c\" ||\n               state.lastType == \"sof\" || /^[\\[{}\\(,;:]$/.test(state.lastType)) {\n        readRegexp(stream);\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      } else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\", stream.current());\n      }\n    } else if (ch == \"`\") {\n      state.tokenize = tokenQuasi;\n      return tokenQuasi(stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return ret(\"error\", \"error\");\n    } else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", \"operator\", stream.current());\n    } else if (wordRE.test(ch)) {\n      stream.eatWhile(wordRE);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.lastType != \".\") ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next;\n      if (jsonldMode && stream.peek() == \"@\" && stream.match(isJsonldKeyword)){\n        state.tokenize = tokenBase;\n        return ret(\"jsonld-keyword\", \"meta\");\n      }\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) break;\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"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 = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenQuasi(stream, state) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (!escaped && (next == \"`\" || next == \"$\" && stream.eat(\"{\"))) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return ret(\"quasi\", \"string-2\", stream.current());\n  }\n\n  var brackets = \"([{}])\";\n  // This is a crude lookahead trick to try and notice that we're\n  // parsing the argument patterns for a fat-arrow function before we\n  // actually hit the arrow token. It only works if the arrow is on\n  // the same line as the arguments and there's no strange noise\n  // (comments) in between. Fallback is to only notice when we hit the\n  // arrow, and not declare the arguments as locals for the arrow\n  // body.\n  function findFatArrow(stream, state) {\n    if (state.fatArrowAt) state.fatArrowAt = null;\n    var arrow = stream.string.indexOf(\"=>\", stream.start);\n    if (arrow < 0) return;\n\n    var depth = 0, sawSomething = false;\n    for (var pos = arrow - 1; pos >= 0; --pos) {\n      var ch = stream.string.charAt(pos);\n      var bracket = brackets.indexOf(ch);\n      if (bracket >= 0 && bracket < 3) {\n        if (!depth) { ++pos; break; }\n        if (--depth == 0) break;\n      } else if (bracket >= 3 && bracket < 6) {\n        ++depth;\n      } else if (wordRE.test(ch)) {\n        sawSomething = true;\n      } else if (/[\"'\\/]/.test(ch)) {\n        return;\n      } else if (sawSomething && !depth) {\n        ++pos;\n        break;\n      }\n    }\n    if (sawSomething && !depth) state.fatArrowAt = pos;\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true, \"this\": true, \"jsonld-keyword\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n    for (var cx = state.context; cx; cx = cx.prev) {\n      for (var v = cx.vars; v; v = v.next)\n        if (v.name == varname) return true;\n    }\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;\n\n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    function inList(list) {\n      for (var v = list; v; v = v.next)\n        if (v.name == varname) return true;\n      return false;\n    }\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      if (inList(state.localVars)) return;\n      state.localVars = {name: varname, next: state.localVars};\n    } else {\n      if (inList(state.globalVars)) return;\n      if (parserConfig.globalVars)\n        state.globalVars = {name: varname, next: state.globalVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n    cx.state.localVars = defaultVars;\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state, indent = state.indented;\n      if (state.lexical.type == \"stat\") indent = state.lexical.indented;\n      else for (var outer = state.lexical; outer && outer.type == \")\" && outer.align; outer = outer.prev)\n        indent = outer.indented;\n      state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    function exp(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(exp);\n    };\n    return exp;\n  }\n\n  function statement(type, value) {\n    if (type == \"var\") return cont(pushlex(\"vardef\", value.length), vardef, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"if\") {\n      if (cx.state.lexical.info == \"else\" && cx.state.cc[cx.state.cc.length - 1] == poplex)\n        cx.state.cc.pop()();\n      return cont(pushlex(\"form\"), expression, statement, poplex, maybeelse);\n    }\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), forspec, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                      block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                     statement, poplex, popcontext);\n    if (type == \"module\") return cont(pushlex(\"form\"), pushcontext, afterModule, popcontext, poplex);\n    if (type == \"class\") return cont(pushlex(\"form\"), className, poplex);\n    if (type == \"export\") return cont(pushlex(\"form\"), afterExport, poplex);\n    if (type == \"import\") return cont(pushlex(\"form\"), afterImport, poplex);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    return expressionInner(type, false);\n  }\n  function expressionNoComma(type) {\n    return expressionInner(type, true);\n  }\n  function expressionInner(type, noComma) {\n    if (cx.state.fatArrowAt == cx.stream.start) {\n      var body = noComma ? arrowBodyNoComma : arrowBody;\n      if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(pattern, \")\"), poplex, expect(\"=>\"), body, popcontext);\n      else if (type == \"variable\") return pass(pushcontext, pattern, expect(\"=>\"), body, popcontext);\n    }\n\n    var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);\n    if (type == \"function\") return cont(functiondef, maybeop);\n    if (type == \"keyword c\") return cont(noComma ? maybeexpressionNoComma : maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, comprehension, expect(\")\"), poplex, maybeop);\n    if (type == \"operator\" || type == \"spread\") return cont(noComma ? expressionNoComma : expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), arrayLiteral, poplex, maybeop);\n    if (type == \"{\") return contCommasep(objprop, \"}\", null, maybeop);\n    if (type == \"quasi\") { return pass(quasi, maybeop); }\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n  function maybeexpressionNoComma(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expressionNoComma);\n  }\n\n  function maybeoperatorComma(type, value) {\n    if (type == \",\") return cont(expression);\n    return maybeoperatorNoComma(type, value, false);\n  }\n  function maybeoperatorNoComma(type, value, noComma) {\n    var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;\n    var expr = noComma == false ? expression : expressionNoComma;\n    if (type == \"=>\") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n    if (type == \"operator\") {\n      if (/\\+\\+|--/.test(value)) return cont(me);\n      if (value == \"?\") return cont(expression, expect(\":\"), expr);\n      return cont(expr);\n    }\n    if (type == \"quasi\") { return pass(quasi, me); }\n    if (type == \";\") return;\n    if (type == \"(\") return contCommasep(expressionNoComma, \")\", \"call\", me);\n    if (type == \".\") return cont(property, me);\n    if (type == \"[\") return cont(pushlex(\"]\"), maybeexpression, expect(\"]\"), poplex, me);\n  }\n  function quasi(type, value) {\n    if (type != \"quasi\") return pass();\n    if (value.slice(value.length - 2) != \"${\") return cont(quasi);\n    return cont(expression, continueQuasi);\n  }\n  function continueQuasi(type) {\n    if (type == \"}\") {\n      cx.marked = \"string-2\";\n      cx.state.tokenize = tokenQuasi;\n      return cont(quasi);\n    }\n  }\n  function arrowBody(type) {\n    findFatArrow(cx.stream, cx.state);\n    return pass(type == \"{\" ? statement : expression);\n  }\n  function arrowBodyNoComma(type) {\n    findFatArrow(cx.stream, cx.state);\n    return pass(type == \"{\" ? statement : expressionNoComma);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperatorComma, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type, value) {\n    if (type == \"variable\" || cx.style == \"keyword\") {\n      cx.marked = \"property\";\n      if (value == \"get\" || value == \"set\") return cont(getterSetter);\n      return cont(afterprop);\n    } else if (type == \"number\" || type == \"string\") {\n      cx.marked = jsonldMode ? \"property\" : (cx.style + \" property\");\n      return cont(afterprop);\n    } else if (type == \"jsonld-keyword\") {\n      return cont(afterprop);\n    } else if (type == \"[\") {\n      return cont(expression, expect(\"]\"), afterprop);\n    }\n  }\n  function getterSetter(type) {\n    if (type != \"variable\") return pass(afterprop);\n    cx.marked = \"property\";\n    return cont(functiondef);\n  }\n  function afterprop(type) {\n    if (type == \":\") return cont(expressionNoComma);\n    if (type == \"(\") return pass(functiondef);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") {\n        var lex = cx.state.lexical;\n        if (lex.info == \"call\") lex.pos = (lex.pos || 0) + 1;\n        return cont(what, proceed);\n      }\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function(type) {\n      if (type == end) return cont();\n      return pass(what, proceed);\n    };\n  }\n  function contCommasep(what, end, info) {\n    for (var i = 3; i < arguments.length; i++)\n      cx.cc.push(arguments[i]);\n    return cont(pushlex(end, info), commasep(what, end), poplex);\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function maybetype(type) {\n    if (isTS && type == \":\") return cont(typedef);\n  }\n  function typedef(type) {\n    if (type == \"variable\"){cx.marked = \"variable-3\"; return cont();}\n  }\n  function vardef() {\n    return pass(pattern, maybetype, maybeAssign, vardefCont);\n  }\n  function pattern(type, value) {\n    if (type == \"variable\") { register(value); return cont(); }\n    if (type == \"[\") return contCommasep(pattern, \"]\");\n    if (type == \"{\") return contCommasep(proppattern, \"}\");\n  }\n  function proppattern(type, value) {\n    if (type == \"variable\" && !cx.stream.match(/^\\s*:/, false)) {\n      register(value);\n      return cont(maybeAssign);\n    }\n    if (type == \"variable\") cx.marked = \"property\";\n    return cont(expect(\":\"), pattern, maybeAssign);\n  }\n  function maybeAssign(_type, value) {\n    if (value == \"=\") return cont(expressionNoComma);\n  }\n  function vardefCont(type) {\n    if (type == \",\") return cont(vardef);\n  }\n  function maybeelse(type, value) {\n    if (type == \"keyword b\" && value == \"else\") return cont(pushlex(\"form\", \"else\"), statement, poplex);\n  }\n  function forspec(type) {\n    if (type == \"(\") return cont(pushlex(\")\"), forspec1, expect(\")\"), poplex);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef, expect(\";\"), forspec2);\n    if (type == \";\") return cont(forspec2);\n    if (type == \"variable\") return cont(formaybeinof);\n    return pass(expression, expect(\";\"), forspec2);\n  }\n  function formaybeinof(_type, value) {\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return cont(maybeoperatorComma, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return pass(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (value == \"*\") {cx.marked = \"keyword\"; return cont(functiondef);}\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type) {\n    if (type == \"spread\") return cont(funarg);\n    return pass(pattern, maybetype);\n  }\n  function className(type, value) {\n    if (type == \"variable\") {register(value); return cont(classNameAfter);}\n  }\n  function classNameAfter(type, value) {\n    if (value == \"extends\") return cont(expression, classNameAfter);\n    if (type == \"{\") return cont(pushlex(\"}\"), classBody, poplex);\n  }\n  function classBody(type, value) {\n    if (type == \"variable\" || cx.style == \"keyword\") {\n      cx.marked = \"property\";\n      if (value == \"get\" || value == \"set\") return cont(classGetterSetter, functiondef, classBody);\n      return cont(functiondef, classBody);\n    }\n    if (value == \"*\") {\n      cx.marked = \"keyword\";\n      return cont(classBody);\n    }\n    if (type == \";\") return cont(classBody);\n    if (type == \"}\") return cont();\n  }\n  function classGetterSetter(type) {\n    if (type != \"variable\") return pass();\n    cx.marked = \"property\";\n    return cont();\n  }\n  function afterModule(type, value) {\n    if (type == \"string\") return cont(statement);\n    if (type == \"variable\") { register(value); return cont(maybeFrom); }\n  }\n  function afterExport(_type, value) {\n    if (value == \"*\") { cx.marked = \"keyword\"; return cont(maybeFrom, expect(\";\")); }\n    if (value == \"default\") { cx.marked = \"keyword\"; return cont(expression, expect(\";\")); }\n    return pass(statement);\n  }\n  function afterImport(type) {\n    if (type == \"string\") return cont();\n    return pass(importSpec, maybeFrom);\n  }\n  function importSpec(type, value) {\n    if (type == \"{\") return contCommasep(importSpec, \"}\");\n    if (type == \"variable\") register(value);\n    return cont();\n  }\n  function maybeFrom(_type, value) {\n    if (value == \"from\") { cx.marked = \"keyword\"; return cont(expression); }\n  }\n  function arrayLiteral(type) {\n    if (type == \"]\") return cont();\n    return pass(expressionNoComma, maybeArrayComprehension);\n  }\n  function maybeArrayComprehension(type) {\n    if (type == \"for\") return pass(comprehension, expect(\"]\"));\n    if (type == \",\") return cont(commasep(maybeexpressionNoComma, \"]\"));\n    return pass(commasep(expressionNoComma, \"]\"));\n  }\n  function comprehension(type) {\n    if (type == \"for\") return cont(forspec, comprehension);\n    if (type == \"if\") return cont(expression, comprehension);\n  }\n\n  function isContinuedStatement(state, textAfter) {\n    return state.lastType == \"operator\" || state.lastType == \",\" ||\n      isOperatorChar.test(textAfter.charAt(0)) ||\n      /[,.]/.test(textAfter.charAt(0));\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      var state = {\n        tokenize: tokenBase,\n        lastType: \"sof\",\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n      if (parserConfig.globalVars && typeof parserConfig.globalVars == \"object\")\n        state.globalVars = parserConfig.globalVars;\n      return state;\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n        findFatArrow(stream, state);\n      }\n      if (state.tokenize != tokenComment && stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.lastType = type == \"operator\" && (content == \"++\" || content == \"--\") ? \"incdec\" : type;\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize == tokenComment) return CodeMirror.Pass;\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      // Kludge to prevent 'maybelse' from blocking lexical scope pops\n      if (!/^\\s*else\\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {\n        var c = state.cc[i];\n        if (c == poplex) lexical = lexical.prev;\n        else if (c != maybeelse) break;\n      }\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      if (statementIndent && lexical.type == \")\" && lexical.prev.type == \"stat\")\n        lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n\n      if (type == \"vardef\") return lexical.indented + (state.lastType == \"operator\" || state.lastType == \",\" ? lexical.info + 1 : 0);\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"form\") return lexical.indented + indentUnit;\n      else if (type == \"stat\")\n        return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);\n      else if (lexical.info == \"switch\" && !closing && parserConfig.doubleIndentSwitch != false)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricInput: /^\\s*(?:case .*?:|default:|\\{|\\})$/,\n    blockCommentStart: jsonMode ? null : \"/*\",\n    blockCommentEnd: jsonMode ? null : \"*/\",\n    lineComment: jsonMode ? null : \"//\",\n    fold: \"brace\",\n\n    helperType: jsonMode ? \"json\" : \"javascript\",\n    jsonldMode: jsonldMode,\n    jsonMode: jsonMode\n  };\n});\n\nCodeMirror.registerHelper(\"wordChars\", \"javascript\", /[\\w$]/);\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"text/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/x-javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/x-json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/ld+json\", {name: \"javascript\", jsonld: true});\nCodeMirror.defineMIME(\"text/typescript\", { name: \"javascript\", typescript: true });\nCodeMirror.defineMIME(\"application/typescript\", { name: \"javascript\", typescript: true });\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/javascript/json-ld.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: JSON-LD mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../../addon/comment/continuecomment.js\"></script>\n<script src=\"../../addon/comment/comment.js\"></script>\n<script src=\"javascript.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=\"nav\">\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"/></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">JSON-LD</a>\n  </ul>\n</div>\n\n<article>\n<h2>JSON-LD mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n{\n  \"@context\": {\n    \"name\": \"http://schema.org/name\",\n    \"description\": \"http://schema.org/description\",\n    \"image\": {\n      \"@id\": \"http://schema.org/image\",\n      \"@type\": \"@id\"\n    },\n    \"geo\": \"http://schema.org/geo\",\n    \"latitude\": {\n      \"@id\": \"http://schema.org/latitude\",\n      \"@type\": \"xsd:float\"\n    },\n    \"longitude\": {\n      \"@id\": \"http://schema.org/longitude\",\n      \"@type\": \"xsd:float\"\n    },\n    \"xsd\": \"http://www.w3.org/2001/XMLSchema#\"\n  },\n  \"name\": \"The Empire State Building\",\n  \"description\": \"The Empire State Building is a 102-story landmark in New York City.\",\n  \"image\": \"http://www.civil.usherbrooke.ca/cours/gci215a/empire-state-building.jpg\",\n  \"geo\": {\n    \"latitude\": \"40.75\",\n    \"longitude\": \"73.98\"\n  }\n}\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        matchBrackets: true,\n        autoCloseBrackets: true,\n        mode: \"application/ld+json\",\n        lineWrapping: true\n      });\n    </script>\n\n    <p>This is a specialization of the <a href=\"index.html\">JavaScript mode</a>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/javascript/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"javascript\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"locals\",\n     \"[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }\");\n\n  MT(\"comma-and-binop\",\n     \"[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }\");\n\n  MT(\"destructuring\",\n     \"([keyword function]([def a], [[[def b], [def c] ]]) {\",\n     \"  [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);\",\n     \"  [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];\",\n     \"})();\");\n\n  MT(\"class_body\",\n     \"[keyword class] [variable Foo] {\",\n     \"  [property constructor]() {}\",\n     \"  [property sayName]() {\",\n     \"    [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];\",\n     \"  }\",\n     \"}\");\n\n  MT(\"class\",\n     \"[keyword class] [variable Point] [keyword extends] [variable SuperThing] {\",\n     \"  [property get] [property prop]() { [keyword return] [number 24]; }\",\n     \"  [property constructor]([def x], [def y]) {\",\n     \"    [keyword super]([string 'something']);\",\n     \"    [keyword this].[property x] [operator =] [variable-2 x];\",\n     \"  }\",\n     \"}\");\n\n  MT(\"module\",\n     \"[keyword module] [string 'foo'] {\",\n     \"  [keyword export] [keyword let] [def x] [operator =] [number 42];\",\n     \"  [keyword export] [keyword *] [keyword from] [string 'somewhere'];\",\n     \"}\");\n\n  MT(\"import\",\n     \"[keyword function] [variable foo]() {\",\n     \"  [keyword import] [def $] [keyword from] [string 'jquery'];\",\n     \"  [keyword module] [def crypto] [keyword from] [string 'crypto'];\",\n     \"  [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];\",\n     \"}\");\n\n  MT(\"const\",\n     \"[keyword function] [variable f]() {\",\n     \"  [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];\",\n     \"}\");\n\n  MT(\"for/of\",\n     \"[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}\");\n\n  MT(\"generator\",\n     \"[keyword function*] [variable repeat]([def n]) {\",\n     \"  [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])\",\n     \"    [keyword yield] [variable-2 i];\",\n     \"}\");\n\n  MT(\"quotedStringAddition\",\n     \"[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];\");\n\n  MT(\"quotedFatArrow\",\n     \"[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];\");\n\n  MT(\"fatArrow\",\n     \"[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);\",\n     \"[variable a];\", // No longer in scope\n     \"[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];\",\n     \"[variable c];\");\n\n  MT(\"spread\",\n     \"[keyword function] [variable f]([def a], [meta ...][def b]) {\",\n     \"  [variable something]([variable-2 a], [meta ...][variable-2 b]);\",\n     \"}\");\n\n  MT(\"comprehension\",\n     \"[keyword function] [variable f]() {\",\n     \"  [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];\",\n     \"  ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));\",\n     \"}\");\n\n  MT(\"quasi\",\n     \"[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]\");\n\n  MT(\"quasi_no_function\",\n     \"[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]\");\n\n  MT(\"indent_statement\",\n     \"[keyword var] [variable x] [operator =] [number 10]\",\n     \"[variable x] [operator +=] [variable y] [operator +]\",\n     \"  [atom Infinity]\",\n     \"[keyword debugger];\");\n\n  MT(\"indent_if\",\n     \"[keyword if] ([number 1])\",\n     \"  [keyword break];\",\n     \"[keyword else] [keyword if] ([number 2])\",\n     \"  [keyword continue];\",\n     \"[keyword else]\",\n     \"  [number 10];\",\n     \"[keyword if] ([number 1]) {\",\n     \"  [keyword break];\",\n     \"} [keyword else] [keyword if] ([number 2]) {\",\n     \"  [keyword continue];\",\n     \"} [keyword else] {\",\n     \"  [number 10];\",\n     \"}\");\n\n  MT(\"indent_for\",\n     \"[keyword for] ([keyword var] [variable i] [operator =] [number 0];\",\n     \"     [variable i] [operator <] [number 100];\",\n     \"     [variable i][operator ++])\",\n     \"  [variable doSomething]([variable i]);\",\n     \"[keyword debugger];\");\n\n  MT(\"indent_c_style\",\n     \"[keyword function] [variable foo]()\",\n     \"{\",\n     \"  [keyword debugger];\",\n     \"}\");\n\n  MT(\"indent_else\",\n     \"[keyword for] (;;)\",\n     \"  [keyword if] ([variable foo])\",\n     \"    [keyword if] ([variable bar])\",\n     \"      [number 1];\",\n     \"    [keyword else]\",\n     \"      [number 2];\",\n     \"  [keyword else]\",\n     \"    [number 3];\");\n\n  MT(\"indent_funarg\",\n     \"[variable foo]([number 10000],\",\n     \"    [keyword function]([def a]) {\",\n     \"  [keyword debugger];\",\n     \"};\");\n\n  MT(\"indent_below_if\",\n     \"[keyword for] (;;)\",\n     \"  [keyword if] ([variable foo])\",\n     \"    [number 1];\",\n     \"[number 2];\");\n\n  MT(\"multilinestring\",\n     \"[keyword var] [variable x] [operator =] [string 'foo\\\\]\",\n     \"[string bar'];\");\n\n  MT(\"scary_regexp\",\n     \"[string-2 /foo[[/]]bar/];\");\n\n  MT(\"indent_strange_array\",\n     \"[keyword var] [variable x] [operator =] [[\",\n     \"  [number 1],,\",\n     \"  [number 2],\",\n     \"]];\",\n     \"[number 10];\");\n\n  var jsonld_mode = CodeMirror.getMode(\n    {indentUnit: 2},\n    {name: \"javascript\", jsonld: true}\n  );\n  function LD(name) {\n    test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1));\n  }\n\n  LD(\"json_ld_keywords\",\n    '{',\n    '  [meta \"@context\"]: {',\n    '    [meta \"@base\"]: [string \"http://example.com\"],',\n    '    [meta \"@vocab\"]: [string \"http://xmlns.com/foaf/0.1/\"],',\n    '    [property \"likesFlavor\"]: {',\n    '      [meta \"@container\"]: [meta \"@list\"]',\n    '      [meta \"@reverse\"]: [string \"@beFavoriteOf\"]',\n    '    },',\n    '    [property \"nick\"]: { [meta \"@container\"]: [meta \"@set\"] },',\n    '    [property \"nick\"]: { [meta \"@container\"]: [meta \"@index\"] }',\n    '  },',\n    '  [meta \"@graph\"]: [[ {',\n    '    [meta \"@id\"]: [string \"http://dbpedia.org/resource/John_Lennon\"],',\n    '    [property \"name\"]: [string \"John Lennon\"],',\n    '    [property \"modified\"]: {',\n    '      [meta \"@value\"]: [string \"2010-05-29T14:17:39+02:00\"],',\n    '      [meta \"@type\"]: [string \"http://www.w3.org/2001/XMLSchema#dateTime\"]',\n    '    }',\n    '  } ]]',\n    '}');\n\n  LD(\"json_ld_fake\",\n    '{',\n    '  [property \"@fake\"]: [string \"@fake\"],',\n    '  [property \"@contextual\"]: [string \"@identifier\"],',\n    '  [property \"user@domain.com\"]: [string \"@graphical\"],',\n    '  [property \"@ID\"]: [string \"@@ID\"]',\n    '}');\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/javascript/typescript.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: TypeScript mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"javascript.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">TypeScript</a>\n  </ul>\n</div>\n\n<article>\n<h2>TypeScript mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\nclass Greeter {\n\tgreeting: string;\n\tconstructor (message: string) {\n\t\tthis.greeting = message;\n\t}\n\tgreet() {\n\t\treturn \"Hello, \" + this.greeting;\n\t}\n}\n\nvar greeter = new Greeter(\"world\");\n\nvar button = document.createElement('button')\nbutton.innerText = \"Say Hello\"\nbutton.onclick = function() {\n\talert(greeter.greet())\n}\n\ndocument.body.appendChild(button)\n\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/typescript\"\n      });\n    </script>\n\n    <p>This is a specialization of the <a href=\"index.html\">JavaScript mode</a>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/jinja2/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Jinja2 mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"jinja2.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Jinja2</a>\n  </ul>\n</div>\n\n<article>\n<h2>Jinja2 mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n{# this is a comment #}\n{%- for item in li -%}\n  &lt;li&gt;{{ item.label }}&lt;/li&gt;\n{% endfor -%}\n{{ item.sand == true and item.keyword == false ? 1 : 0 }}\n{{ app.get(55, 1.2, true) }}\n{% if app.get(&#39;_route&#39;) == (&#39;_home&#39;) %}home{% endif %}\n{% if app.session.flashbag.has(&#39;message&#39;) %}\n  {% for message in app.session.flashbag.get(&#39;message&#39;) %}\n    {{ message.content }}\n  {% endfor %}\n{% endif %}\n{{ path(&#39;_home&#39;, {&#39;section&#39;: app.request.get(&#39;section&#39;)}) }}\n{{ path(&#39;_home&#39;, {\n    &#39;section&#39;: app.request.get(&#39;section&#39;),\n    &#39;boolean&#39;: true,\n    &#39;number&#39;: 55.33\n  })\n}}\n{% include (&#39;test.incl.html.twig&#39;) %}\n</textarea></form>\n    <script>\n      var editor =\n      CodeMirror.fromTextArea(document.getElementById(\"code\"), {mode:\n        {name: \"jinja2\", htmlMode: true}});\n    </script>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/jinja2/jinja2.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  CodeMirror.defineMode(\"jinja2\", function() {\n    var keywords = [\"and\", \"as\", \"block\", \"endblock\", \"by\", \"cycle\", \"debug\", \"else\", \"elif\",\n      \"extends\", \"filter\", \"endfilter\", \"firstof\", \"for\",\n      \"endfor\", \"if\", \"endif\", \"ifchanged\", \"endifchanged\",\n      \"ifequal\", \"endifequal\", \"ifnotequal\",\n      \"endifnotequal\", \"in\", \"include\", \"load\", \"not\", \"now\", \"or\",\n      \"parsed\", \"regroup\", \"reversed\", \"spaceless\",\n      \"endspaceless\", \"ssi\", \"templatetag\", \"openblock\",\n      \"closeblock\", \"openvariable\", \"closevariable\",\n      \"openbrace\", \"closebrace\", \"opencomment\",\n      \"closecomment\", \"widthratio\", \"url\", \"with\", \"endwith\",\n      \"get_current_language\", \"trans\", \"endtrans\", \"noop\", \"blocktrans\",\n      \"endblocktrans\", \"get_available_languages\",\n      \"get_current_language_bidi\", \"plural\"],\n    operator = /^[+\\-*&%=<>!?|~^]/,\n    sign = /^[:\\[\\(\\{]/,\n    atom = [\"true\", \"false\"],\n    number = /^(\\d[+\\-\\*\\/])?\\d+(\\.\\d+)?/;\n\n    keywords = new RegExp(\"((\" + keywords.join(\")|(\") + \"))\\\\b\");\n    atom = new RegExp(\"((\" + atom.join(\")|(\") + \"))\\\\b\");\n\n    function tokenBase (stream, state) {\n      var ch = stream.peek();\n\n      //Comment\n      if (state.incomment) {\n        if(!stream.skipTo(\"#}\")) {\n          stream.skipToEnd();\n        } else {\n          stream.eatWhile(/\\#|}/);\n          state.incomment = false;\n        }\n        return \"comment\";\n      //Tag\n      } else if (state.intag) {\n        //After operator\n        if(state.operator) {\n          state.operator = false;\n          if(stream.match(atom)) {\n            return \"atom\";\n          }\n          if(stream.match(number)) {\n            return \"number\";\n          }\n        }\n        //After sign\n        if(state.sign) {\n          state.sign = false;\n          if(stream.match(atom)) {\n            return \"atom\";\n          }\n          if(stream.match(number)) {\n            return \"number\";\n          }\n        }\n\n        if(state.instring) {\n          if(ch == state.instring) {\n            state.instring = false;\n          }\n          stream.next();\n          return \"string\";\n        } else if(ch == \"'\" || ch == '\"') {\n          state.instring = ch;\n          stream.next();\n          return \"string\";\n        } else if(stream.match(state.intag + \"}\") || stream.eat(\"-\") && stream.match(state.intag + \"}\")) {\n          state.intag = false;\n          return \"tag\";\n        } else if(stream.match(operator)) {\n          state.operator = true;\n          return \"operator\";\n        } else if(stream.match(sign)) {\n          state.sign = true;\n        } else {\n          if(stream.eat(\" \") || stream.sol()) {\n            if(stream.match(keywords)) {\n              return \"keyword\";\n            }\n            if(stream.match(atom)) {\n              return \"atom\";\n            }\n            if(stream.match(number)) {\n              return \"number\";\n            }\n            if(stream.sol()) {\n              stream.next();\n            }\n          } else {\n            stream.next();\n          }\n\n        }\n        return \"variable\";\n      } else if (stream.eat(\"{\")) {\n        if (ch = stream.eat(\"#\")) {\n          state.incomment = true;\n          if(!stream.skipTo(\"#}\")) {\n            stream.skipToEnd();\n          } else {\n            stream.eatWhile(/\\#|}/);\n            state.incomment = false;\n          }\n          return \"comment\";\n        //Open tag\n        } else if (ch = stream.eat(/\\{|%/)) {\n          //Cache close tag\n          state.intag = ch;\n          if(ch == \"{\") {\n            state.intag = \"}\";\n          }\n          stream.eat(\"-\");\n          return \"tag\";\n        }\n      }\n      stream.next();\n    };\n\n    return {\n      startState: function () {\n        return {tokenize: tokenBase};\n      },\n      token: function (stream, state) {\n        return state.tokenize(stream, state);\n      }\n    };\n  });\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/julia/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Julia mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"julia.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Julia</a>\n  </ul>\n</div>\n\n<article>\n<h2>Julia mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n#numbers\n1234\n1234im\n.234\n.234im\n2.23im\n2.3f3\n23e2\n0x234\n\n#strings\n'a'\n\"asdf\"\nr\"regex\"\nb\"bytestring\"\n\n\"\"\"\nmultiline string\n\"\"\"\n\n#identifiers\na\nas123\nfunction_name!\n\n#unicode identifiers\n# a = x\\ddot\na⃗ = ẍ\n# a = v\\dot\na⃗ = v̇\n#F\\vec = m \\cdotp a\\vec\nF⃗ = m·a⃗\n\n#literal identifier multiples\n3x\n4[1, 2, 3]\n\n#dicts and indexing\nx=[1, 2, 3]\nx[end-1]\nx={\"julia\"=>\"language of technical computing\"}\n\n\n#exception handling\ntry\n  f()\ncatch\n  @printf \"Error\"\nfinally\n  g()\nend\n\n#types\nimmutable Color{T<:Number}\n  r::T\n  g::T\n  b::T\nend\n\n#functions\nfunction change!(x::Vector{Float64})\n  for i = 1:length(x)\n    x[i] *= 2\n  end\nend\n\n#function invocation\nf('b', (2, 3)...)\n\n#operators\n|=\n&=\n^=\n\\-\n%=\n*=\n+=\n-=\n<=\n>=\n!=\n==\n%\n*\n+\n-\n<\n>\n!\n=\n|\n&\n^\n\\\n?\n~\n:\n$\n<:\n.<\n.>\n<<\n<<=\n>>\n>>>>\n>>=\n>>>=\n<<=\n<<<=\n.<=\n.>=\n.==\n->\n//\nin\n...\n//\n:=\n.//=\n.*=\n./=\n.^=\n.%=\n.+=\n.-=\n\\=\n\\\\=\n||\n===\n&&\n|=\n.|=\n<:\n>:\n|>\n<|\n::\nx ? y : z\n\n#macros\n@spawnat 2 1+1\n@eval(:x)\n\n#keywords and operators\nif else elseif while for\n begin let end do\ntry catch finally return break continue\nglobal local const\nexport import importall using\nfunction macro module baremodule\ntype immutable quote\ntrue false enumerate\n\n\n    </textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"julia\",\n               },\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-julia</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/julia/julia.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(\"julia\", function(_conf, parserConf) {\n  var ERRORCLASS = 'error';\n\n  function wordRegexp(words) {\n    return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n  }\n\n  var operators = parserConf.operators || /^\\.?[|&^\\\\%*+\\-<>!=\\/]=?|\\?|~|:|\\$|\\.[<>]|<<=?|>>>?=?|\\.[<>=]=|->?|\\/\\/|\\bin\\b/;\n  var delimiters = parserConf.delimiters || /^[;,()[\\]{}]/;\n  var identifiers = parserConf.identifiers|| /^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*!*/;\n  var blockOpeners = [\"begin\", \"function\", \"type\", \"immutable\", \"let\", \"macro\", \"for\", \"while\", \"quote\", \"if\", \"else\", \"elseif\", \"try\", \"finally\", \"catch\", \"do\"];\n  var blockClosers = [\"end\", \"else\", \"elseif\", \"catch\", \"finally\"];\n  var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall'];\n  var builtinList = ['true', 'false', 'enumerate', 'open', 'close', 'nothing', 'NaN', 'Inf', 'print', 'println', 'Int', 'Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Int64', 'Uint64', 'Int128', 'Uint128', 'Bool', 'Char', 'Float16', 'Float32', 'Float64', 'Array', 'Vector', 'Matrix', 'String', 'UTF8String', 'ASCIIString', 'error', 'warn', 'info', '@printf'];\n\n  //var stringPrefixes = new RegExp(\"^[br]?('|\\\")\")\n  var stringPrefixes = /^(`|'|\"{3}|([br]?\"))/;\n  var keywords = wordRegexp(keywordList);\n  var builtins = wordRegexp(builtinList);\n  var openers = wordRegexp(blockOpeners);\n  var closers = wordRegexp(blockClosers);\n  var macro = /^@[_A-Za-z][_A-Za-z0-9]*/;\n  var symbol = /^:[_A-Za-z][_A-Za-z0-9]*/;\n  var indentInfo = null;\n\n  function in_array(state) {\n    var ch = cur_scope(state);\n    if(ch==\"[\" || ch==\"{\") {\n      return true;\n    }\n    else {\n      return false;\n    }\n  }\n\n  function cur_scope(state) {\n    if(state.scopes.length==0) {\n      return null;\n    }\n    return state.scopes[state.scopes.length - 1];\n  }\n\n  // tokenizers\n  function tokenBase(stream, state) {\n    // Handle scope changes\n    var leaving_expr = state.leaving_expr;\n    if(stream.sol()) {\n      leaving_expr = false;\n    }\n    state.leaving_expr = false;\n    if(leaving_expr) {\n      if(stream.match(/^'+/)) {\n        return 'operator';\n      }\n\n    }\n\n    if(stream.match(/^\\.{2,3}/)) {\n      return 'operator';\n    }\n\n    if (stream.eatSpace()) {\n      return null;\n    }\n\n    var ch = stream.peek();\n    // Handle Comments\n    if (ch === '#') {\n        stream.skipToEnd();\n        return 'comment';\n    }\n    if(ch==='[') {\n      state.scopes.push(\"[\");\n    }\n\n    if(ch==='{') {\n      state.scopes.push(\"{\");\n    }\n\n    var scope=cur_scope(state);\n\n    if(scope==='[' && ch===']') {\n      state.scopes.pop();\n      state.leaving_expr=true;\n    }\n\n    if(scope==='{' && ch==='}') {\n      state.scopes.pop();\n      state.leaving_expr=true;\n    }\n\n    if(ch===')') {\n      state.leaving_expr = true;\n    }\n\n    var match;\n    if(!in_array(state) && (match=stream.match(openers, false))) {\n      state.scopes.push(match);\n    }\n\n    if(!in_array(state) && stream.match(closers, false)) {\n      state.scopes.pop();\n    }\n\n    if(in_array(state)) {\n      if(stream.match(/^end/)) {\n        return 'number';\n      }\n\n    }\n\n    if(stream.match(/^=>/)) {\n      return 'operator';\n    }\n\n\n    // Handle Number Literals\n    if (stream.match(/^[0-9\\.]/, false)) {\n      var imMatcher = RegExp(/^im\\b/);\n      var floatLiteral = false;\n      // Floats\n      if (stream.match(/^\\d*\\.(?!\\.)\\d+([ef][\\+\\-]?\\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.match(imMatcher);\n          state.leaving_expr = true;\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          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.match(imMatcher);\n          state.leaving_expr = true;\n          return 'number';\n      }\n    }\n\n    if(stream.match(/^(::)|(<:)/)) {\n      return 'operator';\n    }\n\n    // Handle symbols\n    if(!leaving_expr && stream.match(symbol)) {\n      return 'string';\n    }\n\n    // Handle operators and Delimiters\n    if (stream.match(operators)) {\n      return 'operator';\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    if (stream.match(macro)) {\n      return 'meta';\n    }\n\n\n    if (stream.match(delimiters)) {\n      return null;\n    }\n\n    if (stream.match(keywords)) {\n      return 'keyword';\n    }\n\n    if (stream.match(builtins)) {\n      return 'builtin';\n    }\n\n\n    if (stream.match(identifiers)) {\n      state.leaving_expr=true;\n      return 'variable';\n    }\n    // Handle non-detected items\n    stream.next();\n    return ERRORCLASS;\n  }\n\n  function tokenStringFactory(delimiter) {\n    while ('rub'.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            }\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      }\n      return OUTCLASS;\n    }\n    tokenString.isString = true;\n    return tokenString;\n  }\n\n  function tokenLexer(stream, state) {\n    indentInfo = null;\n    var style = state.tokenize(stream, state);\n    var current = stream.current();\n\n    // Handle '.' connected identifiers\n    if (current === '.') {\n      style = stream.match(identifiers, false) ? null : ERRORCLASS;\n      if (style === null && state.lastStyle === 'meta') {\n          // Apply 'meta' style to '.' connected identifiers when\n          // appropriate.\n        style = 'meta';\n      }\n      return style;\n    }\n\n    return style;\n  }\n\n  var external = {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        scopes: [],\n        leaving_expr: false\n      };\n    },\n\n    token: function(stream, state) {\n      var style = tokenLexer(stream, state);\n      state.lastStyle = style;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var delta = 0;\n      if(textAfter==\"end\" || textAfter==\"]\" || textAfter==\"}\" || textAfter==\"else\" || textAfter==\"elseif\" || textAfter==\"catch\" || textAfter==\"finally\") {\n        delta = -1;\n      }\n      return (state.scopes.length + delta) * 4;\n    },\n\n    lineComment: \"#\",\n    fold: \"indent\",\n    electricChars: \"edlsifyh]}\"\n  };\n  return external;\n});\n\n\nCodeMirror.defineMIME(\"text/x-julia\", \"julia\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/kotlin/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Kotlin mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"kotlin.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Kotlin</a>\n  </ul>\n</div>\n\n<article>\n<h2>Kotlin mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\npackage org.wasabi.http\n\nimport java.util.concurrent.Executors\nimport java.net.InetSocketAddress\nimport org.wasabi.app.AppConfiguration\nimport io.netty.bootstrap.ServerBootstrap\nimport io.netty.channel.nio.NioEventLoopGroup\nimport io.netty.channel.socket.nio.NioServerSocketChannel\nimport org.wasabi.app.AppServer\n\npublic class HttpServer(private val appServer: AppServer) {\n\n    val bootstrap: ServerBootstrap\n    val primaryGroup: NioEventLoopGroup\n    val workerGroup:  NioEventLoopGroup\n\n    {\n        // Define worker groups\n        primaryGroup = NioEventLoopGroup()\n        workerGroup = NioEventLoopGroup()\n\n        // Initialize bootstrap of server\n        bootstrap = ServerBootstrap()\n\n        bootstrap.group(primaryGroup, workerGroup)\n        bootstrap.channel(javaClass<NioServerSocketChannel>())\n        bootstrap.childHandler(NettyPipelineInitializer(appServer))\n    }\n\n    public fun start(wait: Boolean = true) {\n        val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()\n\n        if (wait) {\n            channel?.closeFuture()?.sync()\n        }\n    }\n\n    public fun stop() {\n        // Shutdown all event loops\n        primaryGroup.shutdownGracefully()\n        workerGroup.shutdownGracefully()\n\n        // Wait till all threads are terminated\n        primaryGroup.terminationFuture().sync()\n        workerGroup.terminationFuture().sync()\n    }\n}\n</textarea></div>\n\n    <script>\n        var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n            mode: {name: \"kotlin\"},\n            lineNumbers: true,\n            indentUnit: 4\n        });\n    </script>\n    <h3>Mode for Kotlin (http://kotlin.jetbrains.org/)</h3>\n    <p>Developed by Hadi Hariri (https://github.com/hhariri).</p>\n    <p><strong>MIME type defined:</strong> <code>text/x-kotlin</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/kotlin/kotlin.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(\"kotlin\", function (config, parserConfig) {\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\n  var multiLineStrings = parserConfig.multiLineStrings;\n\n  var keywords = words(\n          \"package continue return object while break class data trait throw super\" +\n          \" when type this else This try val var fun for is in if do as true false null get set\");\n  var softKeywords = words(\"import\" +\n      \" where by get set abstract enum open annotation override private public internal\" +\n      \" protected catch out vararg inline finally final ref\");\n  var blockKeywords = words(\"catch class do else finally for if where try while enum\");\n  var atoms = words(\"null true false this\");\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      return startString(ch, stream, state);\n    }\n    // Wildcard import w/o trailing semicolon (import smth.*)\n    if (ch == \".\" && stream.eat(\"*\")) {\n      return \"word\";\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      if (stream.eat(/eE/)) {\n        stream.eat(/\\+\\-/);\n        stream.eatWhile(/\\d/);\n      }\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize.push(tokenComment);\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      if (expectExpression(state.lastToken)) {\n        return startString(ch, stream, state);\n      }\n    }\n    // Commented\n    if (ch == \"-\" && stream.eat(\">\")) {\n      curPunc = \"->\";\n      return null;\n    }\n    if (/[\\-+*&%=<>!?|\\/~]/.test(ch)) {\n      stream.eatWhile(/[\\-+*&%=<>|~]/);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n\n    var cur = stream.current();\n    if (atoms.propertyIsEnumerable(cur)) {\n      return \"atom\";\n    }\n    if (softKeywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"softKeyword\";\n    }\n\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    return \"word\";\n  }\n\n  tokenBase.isBase = true;\n\n  function startString(quote, stream, state) {\n    var tripleQuoted = false;\n    if (quote != \"/\" && stream.eat(quote)) {\n      if (stream.eat(quote)) tripleQuoted = true;\n      else return \"string\";\n    }\n    function t(stream, state) {\n      var escaped = false, next, end = !tripleQuoted;\n\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {\n          if (!tripleQuoted) {\n            break;\n          }\n          if (stream.match(quote + quote)) {\n            end = true;\n            break;\n          }\n        }\n\n        if (quote == '\"' && next == \"$\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace());\n          return \"string\";\n        }\n\n        if (next == \"$\" && !escaped && !stream.eat(\" \")) {\n          state.tokenize.push(tokenBaseUntilSpace());\n          return \"string\";\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (multiLineStrings)\n        state.tokenize.push(t);\n      if (end) state.tokenize.pop();\n      return \"string\";\n    }\n\n    state.tokenize.push(t);\n    return t(stream, state);\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n\n    function t(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length - 1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    }\n\n    t.isBase = true;\n    return t;\n  }\n\n  function tokenBaseUntilSpace() {\n    function t(stream, state) {\n      if (stream.eat(/[\\w]/)) {\n        var isWord = stream.eatWhile(/[\\w]/);\n        if (isWord) {\n          state.tokenize.pop();\n          return \"word\";\n        }\n      }\n      state.tokenize.pop();\n      return \"string\";\n    }\n\n    t.isBase = true;\n    return t;\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize.pop();\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function expectExpression(last) {\n    return !last || last == \"operator\" || last == \"->\" || /[\\.\\[\\{\\(,;:]/.test(last) ||\n        last == \"newstatement\" || last == \"keyword\" || last == \"proplabel\";\n  }\n\n  function 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  }\n\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n\n  function 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\n  // Interface\n\n  return {\n    startState: function (basecolumn) {\n      return {\n        tokenize: [tokenBase],\n        context: new Context((basecolumn || 0) - config.indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true,\n        lastToken: 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        // Automatic semicolon insertion\n        if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) {\n          popContext(state);\n          ctx = state.context;\n        }\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = state.tokenize[state.tokenize.length - 1](stream, state);\n      if (style == \"comment\") return style;\n      if (ctx.align == null) ctx.align = true;\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      // Handle indentation for {x -> \\n ... }\n      else if (curPunc == \"->\" && ctx.type == \"statement\" && ctx.prev.type == \"}\") {\n        popContext(state);\n        state.context.align = false;\n      }\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 (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      state.lastToken = curPunc || style;\n      return style;\n    },\n\n    indent: function (state, textAfter) {\n      if (!state.tokenize[state.tokenize.length - 1].isBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;\n      if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") {\n        return ctx.indented + (firstChar == \"{\" ? 0 : config.indentUnit);\n      }\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : config.indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-kotlin\", \"kotlin\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/livescript/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: LiveScript mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/solarized.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"livescript.js\"></script>\n<style>.CodeMirror {font-size: 80%;border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">LiveScript</a>\n  </ul>\n</div>\n\n<article>\n<h2>LiveScript mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# LiveScript mode for CodeMirror\n# The following script, prelude.ls, is used to\n# demonstrate LiveScript mode for CodeMirror.\n#   https://github.com/gkz/prelude-ls\n\nexport objToFunc = objToFunc = (obj) ->\n  (key) -> obj[key]\n\nexport each = (f, xs) -->\n  if typeof! xs is \\Object\n    for , x of xs then f x\n  else\n    for x in xs then f x\n  xs\n\nexport map = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  type = typeof! xs\n  if type is \\Object\n    {[key, f x] for key, x of xs}\n  else\n    result = [f x for x in xs]\n    if type is \\String then result * '' else result\n\nexport filter = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  type = typeof! xs\n  if type is \\Object\n    {[key, x] for key, x of xs when f x}\n  else\n    result = [x for x in xs when f x]\n    if type is \\String then result * '' else result\n\nexport reject = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  type = typeof! xs\n  if type is \\Object\n    {[key, x] for key, x of xs when not f x}\n  else\n    result = [x for x in xs when not f x]\n    if type is \\String then result * '' else result\n\nexport partition = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  type = typeof! xs\n  if type is \\Object\n    passed = {}\n    failed = {}\n    for key, x of xs\n      (if f x then passed else failed)[key] = x\n  else\n    passed = []\n    failed = []\n    for x in xs\n      (if f x then passed else failed)push x\n    if type is \\String\n      passed *= ''\n      failed *= ''\n  [passed, failed]\n\nexport find = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  if typeof! xs is \\Object\n    for , x of xs when f x then return x\n  else\n    for x in xs when f x then return x\n  void\n\nexport head = export first = (xs) ->\n  return void if not xs.length\n  xs.0\n\nexport tail = (xs) ->\n  return void if not xs.length\n  xs.slice 1\n\nexport last = (xs) ->\n  return void if not xs.length\n  xs[*-1]\n\nexport initial = (xs) ->\n  return void if not xs.length\n  xs.slice 0 xs.length - 1\n\nexport empty = (xs) ->\n  if typeof! xs is \\Object\n    for x of xs then return false\n    return yes\n  not xs.length\n\nexport values = (obj) ->\n  [x for , x of obj]\n\nexport keys = (obj) ->\n  [x for x of obj]\n\nexport len = (xs) ->\n  xs = values xs if typeof! xs is \\Object\n  xs.length\n\nexport cons = (x, xs) -->\n  if typeof! xs is \\String then x + xs else [x] ++ xs\n\nexport append = (xs, ys) -->\n  if typeof! ys is \\String then xs + ys else xs ++ ys\n\nexport join = (sep, xs) -->\n  xs = values xs if typeof! xs is \\Object\n  xs.join sep\n\nexport reverse = (xs) ->\n  if typeof! xs is \\String\n  then (xs / '')reverse! * ''\n  else xs.slice!reverse!\n\nexport fold = export foldl = (f, memo, xs) -->\n  if typeof! xs is \\Object\n    for , x of xs then memo = f memo, x\n  else\n    for x in xs then memo = f memo, x\n  memo\n\nexport fold1 = export foldl1 = (f, xs) --> fold f, xs.0, xs.slice 1\n\nexport foldr = (f, memo, xs) --> fold f, memo, xs.slice!reverse!\n\nexport foldr1 = (f, xs) -->\n  xs.=slice!reverse!\n  fold f, xs.0, xs.slice 1\n\nexport unfoldr = export unfold = (f, b) -->\n  if (f b)?\n    [that.0] ++ unfoldr f, that.1\n  else\n    []\n\nexport andList = (xs) ->\n  for x in xs when not x\n    return false\n  true\n\nexport orList = (xs) ->\n  for x in xs when x\n    return true\n  false\n\nexport any = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  for x in xs when f x\n    return yes\n  no\n\nexport all = (f, xs) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  for x in xs when not f x\n    return no\n  yes\n\nexport unique = (xs) ->\n  result = []\n  if typeof! xs is \\Object\n    for , x of xs when x not in result then result.push x\n  else\n    for x   in xs when x not in result then result.push x\n  if typeof! xs is \\String then result * '' else result\n\nexport sort = (xs) ->\n  xs.concat!sort (x, y) ->\n    | x > y =>  1\n    | x < y => -1\n    | _     =>  0\n\nexport sortBy = (f, xs) -->\n  return [] unless xs.length\n  xs.concat!sort f\n\nexport compare = (f, x, y) -->\n  | (f x) > (f y) =>  1\n  | (f x) < (f y) => -1\n  | otherwise     =>  0\n\nexport sum = (xs) ->\n  result = 0\n  if typeof! xs is \\Object\n    for , x of xs then result += x\n  else\n    for x   in xs then result += x\n  result\n\nexport product = (xs) ->\n  result = 1\n  if typeof! xs is \\Object\n    for , x of xs then result *= x\n  else\n    for x   in xs then result *= x\n  result\n\nexport mean = export average = (xs) -> (sum xs) / len xs\n\nexport concat = (xss) -> fold append, [], xss\n\nexport concatMap = (f, xs) --> fold ((memo, x) -> append memo, f x), [], xs\n\nexport listToObj = (xs) ->\n  {[x.0, x.1] for x in xs}\n\nexport maximum = (xs) -> fold1 (>?), xs\n\nexport minimum = (xs) -> fold1 (<?), xs\n\nexport scan = export scanl = (f, memo, xs) -->\n  last = memo\n  if typeof! xs is \\Object\n  then [memo] ++ [last = f last, x for , x of xs]\n  else [memo] ++ [last = f last, x for x in xs]\n\nexport scan1 = export scanl1 = (f, xs) --> scan f, xs.0, xs.slice 1\n\nexport scanr = (f, memo, xs) -->\n  xs.=slice!reverse!\n  scan f, memo, xs .reverse!\n\nexport scanr1 = (f, xs) -->\n  xs.=slice!reverse!\n  scan f, xs.0, xs.slice 1 .reverse!\n\nexport replicate = (n, x) -->\n  result = []\n  i = 0\n  while i < n, ++i then result.push x\n  result\n\nexport take = (n, xs) -->\n  | n <= 0\n    if typeof! xs is \\String then '' else []\n  | not xs.length => xs\n  | otherwise     => xs.slice 0, n\n\nexport drop = (n, xs) -->\n  | n <= 0        => xs\n  | not xs.length => xs\n  | otherwise     => xs.slice n\n\nexport splitAt = (n, xs) --> [(take n, xs), (drop n, xs)]\n\nexport takeWhile = (p, xs) -->\n  return xs if not xs.length\n  p = objToFunc p if typeof! p isnt \\Function\n  result = []\n  for x in xs\n    break if not p x\n    result.push x\n  if typeof! xs is \\String then result * '' else result\n\nexport dropWhile = (p, xs) -->\n  return xs if not xs.length\n  p = objToFunc p if typeof! p isnt \\Function\n  i = 0\n  for x in xs\n    break if not p x\n    ++i\n  drop i, xs\n\nexport span = (p, xs) --> [(takeWhile p, xs), (dropWhile p, xs)]\n\nexport breakIt = (p, xs) --> span (not) << p, xs\n\nexport zip = (xs, ys) -->\n  result = []\n  for zs, i in [xs, ys]\n    for z, j in zs\n      result.push [] if i is 0\n      result[j]?push z\n  result\n\nexport zipWith = (f,xs, ys) -->\n  f = objToFunc f if typeof! f isnt \\Function\n  if not xs.length or not ys.length\n    []\n  else\n    [f.apply this, zs for zs in zip.call this, xs, ys]\n\nexport zipAll = (...xss) ->\n  result = []\n  for xs, i in xss\n    for x, j in xs\n      result.push [] if i is 0\n      result[j]?push x\n  result\n\nexport zipAllWith = (f, ...xss) ->\n  f = objToFunc f if typeof! f isnt \\Function\n  if not xss.0.length or not xss.1.length\n    []\n  else\n    [f.apply this, xs for xs in zipAll.apply this, xss]\n\nexport compose = (...funcs) ->\n  ->\n    args = arguments\n    for f in funcs\n      args = [f.apply this, args]\n    args.0\n\nexport curry = (f) ->\n  curry$ f # using util method curry$ from livescript\n\nexport id = (x) -> x\n\nexport flip = (f, x, y) --> f y, x\n\nexport fix = (f) ->\n  ( (g, x) -> -> f(g g) ...arguments ) do\n    (g, x) -> -> f(g g) ...arguments\n\nexport lines = (str) ->\n  return [] if not str.length\n  str / \\\\n\n\nexport unlines = (strs) -> strs * \\\\n\n\nexport words = (str) ->\n  return [] if not str.length\n  str / /[ ]+/\n\nexport unwords = (strs) -> strs * ' '\n\nexport max = (>?)\n\nexport min = (<?)\n\nexport negate = (x) -> -x\n\nexport abs = Math.abs\n\nexport signum = (x) ->\n  | x < 0     => -1\n  | x > 0     =>  1\n  | otherwise =>  0\n\nexport quot = (x, y) --> ~~(x / y)\n\nexport rem = (%)\n\nexport div = (x, y) --> Math.floor x / y\n\nexport mod = (%%)\n\nexport recip = (1 /)\n\nexport pi = Math.PI\n\nexport tau = pi * 2\n\nexport exp = Math.exp\n\nexport sqrt = Math.sqrt\n\n# changed from log as log is a\n# common function for logging things\nexport ln = Math.log\n\nexport pow = (^)\n\nexport sin = Math.sin\n\nexport tan = Math.tan\n\nexport cos = Math.cos\n\nexport asin = Math.asin\n\nexport acos = Math.acos\n\nexport atan = Math.atan\n\nexport atan2 = (x, y) --> Math.atan2 x, y\n\n# sinh\n# tanh\n# cosh\n# asinh\n# atanh\n# acosh\n\nexport truncate = (x) -> ~~x\n\nexport round = Math.round\n\nexport ceiling = Math.ceil\n\nexport floor = Math.floor\n\nexport isItNaN = (x) -> x isnt x\n\nexport even = (x) -> x % 2 == 0\n\nexport odd = (x) -> x % 2 != 0\n\nexport gcd = (x, y) -->\n  x = Math.abs x\n  y = Math.abs y\n  until y is 0\n    z = x % y\n    x = y\n    y = z\n  x\n\nexport lcm = (x, y) -->\n  Math.abs Math.floor (x / (gcd x, y) * y)\n\n# meta\nexport installPrelude = !(target) ->\n  unless target.prelude?isInstalled\n    target <<< out$ # using out$ generated by livescript\n    target <<< target.prelude.isInstalled = true\n\nexport prelude = out$\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"solarized light\",\n        lineNumbers: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-livescript</code>.</p>\n\n    <p>The LiveScript mode was written by Kenneth Bentley.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/livescript/livescript.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Link to the project's GitHub page:\n * https://github.com/duralog/CodeMirror\n */\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  CodeMirror.defineMode('livescript', function(){\n    var tokenBase = function(stream, state) {\n      var next_rule = state.next || \"start\";\n      if (next_rule) {\n        state.next = state.next;\n        var nr = Rules[next_rule];\n        if (nr.splice) {\n          for (var i$ = 0; i$ < nr.length; ++i$) {\n            var r = nr[i$], m;\n            if (r.regex && (m = stream.match(r.regex))) {\n              state.next = r.next || state.next;\n              return r.token;\n            }\n          }\n          stream.next();\n          return 'error';\n        }\n        if (stream.match(r = Rules[next_rule])) {\n          if (r.regex && stream.match(r.regex)) {\n            state.next = r.next;\n            return r.token;\n          } else {\n            stream.next();\n            return 'error';\n          }\n        }\n      }\n      stream.next();\n      return 'error';\n    };\n    var external = {\n      startState: function(){\n        return {\n          next: 'start',\n          lastToken: null\n        };\n      },\n      token: function(stream, state){\n        while (stream.pos == stream.start)\n          var style = tokenBase(stream, state);\n        state.lastToken = {\n          style: style,\n          indent: stream.indentation(),\n          content: stream.current()\n        };\n        return style.replace(/\\./g, ' ');\n      },\n      indent: function(state){\n        var indentation = state.lastToken.indent;\n        if (state.lastToken.content.match(indenter)) {\n          indentation += 2;\n        }\n        return indentation;\n      }\n    };\n    return external;\n  });\n\n  var identifier = '(?![\\\\d\\\\s])[$\\\\w\\\\xAA-\\\\uFFDC](?:(?!\\\\s)[$\\\\w\\\\xAA-\\\\uFFDC]|-[A-Za-z])*';\n  var indenter = RegExp('(?:[({[=:]|[-~]>|\\\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\\\s*all)?|const|var|let|new|catch(?:\\\\s*' + identifier + ')?))\\\\s*$');\n  var keywordend = '(?![$\\\\w]|-[A-Za-z]|\\\\s*:(?![:=]))';\n  var stringfill = {\n    token: 'string',\n    regex: '.+'\n  };\n  var Rules = {\n    start: [\n      {\n        token: 'comment.doc',\n        regex: '/\\\\*',\n        next: 'comment'\n      }, {\n        token: 'comment',\n        regex: '#.*'\n      }, {\n        token: 'keyword',\n        regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend\n      }, {\n        token: 'constant.language',\n        regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend\n      }, {\n        token: 'invalid.illegal',\n        regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend\n      }, {\n        token: 'language.support.class',\n        regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend\n      }, {\n        token: 'language.support.function',\n        regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend\n      }, {\n        token: 'variable.language',\n        regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend\n      }, {\n        token: 'identifier',\n        regex: identifier + '\\\\s*:(?![:=])'\n      }, {\n        token: 'variable',\n        regex: identifier\n      }, {\n        token: 'keyword.operator',\n        regex: '(?:\\\\.{3}|\\\\s+\\\\?)'\n      }, {\n        token: 'keyword.variable',\n        regex: '(?:@+|::|\\\\.\\\\.)',\n        next: 'key'\n      }, {\n        token: 'keyword.operator',\n        regex: '\\\\.\\\\s*',\n        next: 'key'\n      }, {\n        token: 'string',\n        regex: '\\\\\\\\\\\\S[^\\\\s,;)}\\\\]]*'\n      }, {\n        token: 'string.doc',\n        regex: '\\'\\'\\'',\n        next: 'qdoc'\n      }, {\n        token: 'string.doc',\n        regex: '\"\"\"',\n        next: 'qqdoc'\n      }, {\n        token: 'string',\n        regex: '\\'',\n        next: 'qstring'\n      }, {\n        token: 'string',\n        regex: '\"',\n        next: 'qqstring'\n      }, {\n        token: 'string',\n        regex: '`',\n        next: 'js'\n      }, {\n        token: 'string',\n        regex: '<\\\\[',\n        next: 'words'\n      }, {\n        token: 'string.regex',\n        regex: '//',\n        next: 'heregex'\n      }, {\n        token: 'string.regex',\n        regex: '\\\\/(?:[^[\\\\/\\\\n\\\\\\\\]*(?:(?:\\\\\\\\.|\\\\[[^\\\\]\\\\n\\\\\\\\]*(?:\\\\\\\\.[^\\\\]\\\\n\\\\\\\\]*)*\\\\])[^[\\\\/\\\\n\\\\\\\\]*)*)\\\\/[gimy$]{0,4}',\n        next: 'key'\n      }, {\n        token: 'constant.numeric',\n        regex: '(?:0x[\\\\da-fA-F][\\\\da-fA-F_]*|(?:[2-9]|[12]\\\\d|3[0-6])r[\\\\da-zA-Z][\\\\da-zA-Z_]*|(?:\\\\d[\\\\d_]*(?:\\\\.\\\\d[\\\\d_]*)?|\\\\.\\\\d[\\\\d_]*)(?:e[+-]?\\\\d[\\\\d_]*)?[\\\\w$]*)'\n      }, {\n        token: 'lparen',\n        regex: '[({[]'\n      }, {\n        token: 'rparen',\n        regex: '[)}\\\\]]',\n        next: 'key'\n      }, {\n        token: 'keyword.operator',\n        regex: '\\\\S+'\n      }, {\n        token: 'text',\n        regex: '\\\\s+'\n      }\n    ],\n    heregex: [\n      {\n        token: 'string.regex',\n        regex: '.*?//[gimy$?]{0,4}',\n        next: 'start'\n      }, {\n        token: 'string.regex',\n        regex: '\\\\s*#{'\n      }, {\n        token: 'comment.regex',\n        regex: '\\\\s+(?:#.*)?'\n      }, {\n        token: 'string.regex',\n        regex: '\\\\S+'\n      }\n    ],\n    key: [\n      {\n        token: 'keyword.operator',\n        regex: '[.?@!]+'\n      }, {\n        token: 'identifier',\n        regex: identifier,\n        next: 'start'\n      }, {\n        token: 'text',\n        regex: '',\n        next: 'start'\n      }\n    ],\n    comment: [\n      {\n        token: 'comment.doc',\n        regex: '.*?\\\\*/',\n        next: 'start'\n      }, {\n        token: 'comment.doc',\n        regex: '.+'\n      }\n    ],\n    qdoc: [\n      {\n        token: 'string',\n        regex: \".*?'''\",\n        next: 'key'\n      }, stringfill\n    ],\n    qqdoc: [\n      {\n        token: 'string',\n        regex: '.*?\"\"\"',\n        next: 'key'\n      }, stringfill\n    ],\n    qstring: [\n      {\n        token: 'string',\n        regex: '[^\\\\\\\\\\']*(?:\\\\\\\\.[^\\\\\\\\\\']*)*\\'',\n        next: 'key'\n      }, stringfill\n    ],\n    qqstring: [\n      {\n        token: 'string',\n        regex: '[^\\\\\\\\\"]*(?:\\\\\\\\.[^\\\\\\\\\"]*)*\"',\n        next: 'key'\n      }, stringfill\n    ],\n    js: [\n      {\n        token: 'string',\n        regex: '[^\\\\\\\\`]*(?:\\\\\\\\.[^\\\\\\\\`]*)*`',\n        next: 'key'\n      }, stringfill\n    ],\n    words: [\n      {\n        token: 'string',\n        regex: '.*?\\\\]>',\n        next: 'key'\n      }, stringfill\n    ]\n  };\n  for (var idx in Rules) {\n    var r = Rules[idx];\n    if (r.splice) {\n      for (var i = 0, len = r.length; i < len; ++i) {\n        var rr = r[i];\n        if (typeof rr.regex === 'string') {\n          Rules[idx][i].regex = new RegExp('^' + rr.regex);\n        }\n      }\n    } else if (typeof rr.regex === 'string') {\n      Rules[idx].regex = new RegExp('^' + r.regex);\n    }\n  }\n\n  CodeMirror.defineMIME('text/x-livescript', 'livescript');\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/lua/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Lua mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/neat.css\">\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"lua.js\"></script>\n<style>.CodeMirror {border: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Lua</a>\n  </ul>\n</div>\n\n<article>\n<h2>Lua mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n--[[\nexample useless code to show lua syntax highlighting\nthis is multiline comment\n]]\n\nfunction blahblahblah(x)\n\n  local table = {\n    \"asd\" = 123,\n    \"x\" = 0.34,\n  }\n  if x ~= 3 then\n    print( x )\n  elseif x == \"string\"\n    my_custom_function( 0x34 )\n  else\n    unknown_function( \"some string\" )\n  end\n\n  --single line comment\n\nend\n\nfunction blablabla3()\n\n  for k,v in ipairs( table ) do\n    --abcde..\n    y=[=[\n  x=[[\n      x is a multi line string\n   ]]\n  but its definition is iside a highest level string!\n  ]=]\n    print(\" \\\"\\\" \")\n\n    s = math.sin( x )\n  end\n\nend\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        matchBrackets: true,\n        theme: \"neat\"\n      });\n    </script>\n\n    <p>Loosely based on Franciszek\n    Wawrzak's <a href=\"http://codemirror.net/1/contrib/lua\">CodeMirror\n    1 mode</a>. One configuration parameter is\n    supported, <code>specials</code>, to which you can provide an\n    array of strings to have those identifiers highlighted with\n    the <code>lua-special</code> style.</p>\n    <p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/lua/lua.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's\n// CodeMirror 1 mode.\n// highlights keywords, strings, comments (no leveling supported! (\"[==[\")), tokens, basic indenting\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(\"lua\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n\n  function prefixRE(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")\", \"i\");\n  }\n  function wordRE(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var specials = wordRE(parserConfig.specials || []);\n\n  // long list of standard functions from lua manual\n  var builtins = wordRE([\n    \"_G\",\"_VERSION\",\"assert\",\"collectgarbage\",\"dofile\",\"error\",\"getfenv\",\"getmetatable\",\"ipairs\",\"load\",\n    \"loadfile\",\"loadstring\",\"module\",\"next\",\"pairs\",\"pcall\",\"print\",\"rawequal\",\"rawget\",\"rawset\",\"require\",\n    \"select\",\"setfenv\",\"setmetatable\",\"tonumber\",\"tostring\",\"type\",\"unpack\",\"xpcall\",\n\n    \"coroutine.create\",\"coroutine.resume\",\"coroutine.running\",\"coroutine.status\",\"coroutine.wrap\",\"coroutine.yield\",\n\n    \"debug.debug\",\"debug.getfenv\",\"debug.gethook\",\"debug.getinfo\",\"debug.getlocal\",\"debug.getmetatable\",\n    \"debug.getregistry\",\"debug.getupvalue\",\"debug.setfenv\",\"debug.sethook\",\"debug.setlocal\",\"debug.setmetatable\",\n    \"debug.setupvalue\",\"debug.traceback\",\n\n    \"close\",\"flush\",\"lines\",\"read\",\"seek\",\"setvbuf\",\"write\",\n\n    \"io.close\",\"io.flush\",\"io.input\",\"io.lines\",\"io.open\",\"io.output\",\"io.popen\",\"io.read\",\"io.stderr\",\"io.stdin\",\n    \"io.stdout\",\"io.tmpfile\",\"io.type\",\"io.write\",\n\n    \"math.abs\",\"math.acos\",\"math.asin\",\"math.atan\",\"math.atan2\",\"math.ceil\",\"math.cos\",\"math.cosh\",\"math.deg\",\n    \"math.exp\",\"math.floor\",\"math.fmod\",\"math.frexp\",\"math.huge\",\"math.ldexp\",\"math.log\",\"math.log10\",\"math.max\",\n    \"math.min\",\"math.modf\",\"math.pi\",\"math.pow\",\"math.rad\",\"math.random\",\"math.randomseed\",\"math.sin\",\"math.sinh\",\n    \"math.sqrt\",\"math.tan\",\"math.tanh\",\n\n    \"os.clock\",\"os.date\",\"os.difftime\",\"os.execute\",\"os.exit\",\"os.getenv\",\"os.remove\",\"os.rename\",\"os.setlocale\",\n    \"os.time\",\"os.tmpname\",\n\n    \"package.cpath\",\"package.loaded\",\"package.loaders\",\"package.loadlib\",\"package.path\",\"package.preload\",\n    \"package.seeall\",\n\n    \"string.byte\",\"string.char\",\"string.dump\",\"string.find\",\"string.format\",\"string.gmatch\",\"string.gsub\",\n    \"string.len\",\"string.lower\",\"string.match\",\"string.rep\",\"string.reverse\",\"string.sub\",\"string.upper\",\n\n    \"table.concat\",\"table.insert\",\"table.maxn\",\"table.remove\",\"table.sort\"\n  ]);\n  var keywords = wordRE([\"and\",\"break\",\"elseif\",\"false\",\"nil\",\"not\",\"or\",\"return\",\n                         \"true\",\"function\", \"end\", \"if\", \"then\", \"else\", \"do\",\n                         \"while\", \"repeat\", \"until\", \"for\", \"in\", \"local\" ]);\n\n  var indentTokens = wordRE([\"function\", \"if\",\"repeat\",\"do\", \"\\\\(\", \"{\"]);\n  var dedentTokens = wordRE([\"end\", \"until\", \"\\\\)\", \"}\"]);\n  var dedentPartial = prefixRE([\"end\", \"until\", \"\\\\)\", \"}\", \"else\", \"elseif\"]);\n\n  function readBracket(stream) {\n    var level = 0;\n    while (stream.eat(\"=\")) ++level;\n    stream.eat(\"[\");\n    return level;\n  }\n\n  function normal(stream, state) {\n    var ch = stream.next();\n    if (ch == \"-\" && stream.eat(\"-\")) {\n      if (stream.eat(\"[\") && stream.eat(\"[\"))\n        return (state.cur = bracketed(readBracket(stream), \"comment\"))(stream, state);\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    if (ch == \"\\\"\" || ch == \"'\")\n      return (state.cur = string(ch))(stream, state);\n    if (ch == \"[\" && /[\\[=]/.test(stream.peek()))\n      return (state.cur = bracketed(readBracket(stream), \"string\"))(stream, state);\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return \"number\";\n    }\n    if (/[\\w_]/.test(ch)) {\n      stream.eatWhile(/[\\w\\\\\\-_.]/);\n      return \"variable\";\n    }\n    return null;\n  }\n\n  function bracketed(level, style) {\n    return function(stream, state) {\n      var curlev = null, ch;\n      while ((ch = stream.next()) != null) {\n        if (curlev == null) {if (ch == \"]\") curlev = 0;}\n        else if (ch == \"=\") ++curlev;\n        else if (ch == \"]\" && curlev == level) { state.cur = normal; break; }\n        else curlev = null;\n      }\n      return style;\n    };\n  }\n\n  function string(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.cur = normal;\n      return \"string\";\n    };\n  }\n\n  return {\n    startState: function(basecol) {\n      return {basecol: basecol || 0, indentDepth: 0, cur: normal};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.cur(stream, state);\n      var word = stream.current();\n      if (style == \"variable\") {\n        if (keywords.test(word)) style = \"keyword\";\n        else if (builtins.test(word)) style = \"builtin\";\n        else if (specials.test(word)) style = \"variable-2\";\n      }\n      if ((style != \"comment\") && (style != \"string\")){\n        if (indentTokens.test(word)) ++state.indentDepth;\n        else if (dedentTokens.test(word)) --state.indentDepth;\n      }\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var closing = dedentPartial.test(textAfter);\n      return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));\n    },\n\n    lineComment: \"--\",\n    blockCommentStart: \"--[[\",\n    blockCommentEnd: \"]]\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-lua\", \"lua\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/markdown/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Markdown mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/continuelist.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"markdown.js\"></script>\n<style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .cm-s-default .cm-trailing-space-a:before,\n      .cm-s-default .cm-trailing-space-b:before {position: absolute; content: \"\\00B7\"; color: #777;}\n      .cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: \"\\21B5\"; color: #777;}\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Markdown</a>\n  </ul>\n</div>\n\n<article>\n<h2>Markdown mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nMarkdown: Basics\n================\n\n&lt;ul id=\"ProjectSubmenu\"&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/\" title=\"Markdown Project Page\"&gt;Main&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a class=\"selected\" title=\"Markdown Basics\"&gt;Basics&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\"&gt;Syntax&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/license\" title=\"Pricing and License Information\"&gt;License&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\"&gt;Dingus&lt;/a&gt;&lt;/li&gt;\n&lt;/ul&gt;\n\n\nGetting the Gist of Markdown's Formatting Syntax\n------------------------------------------------\n\nThis page offers a brief overview of what it's like to use Markdown.\nThe [syntax page] [s] provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.\n\nIt's also helpful to simply try Markdown out; the [Dingus] [d] is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL] [src].\n\n  [s]: /projects/markdown/syntax  \"Markdown Syntax\"\n  [d]: /projects/markdown/dingus  \"Markdown Dingus\"\n  [src]: /projects/markdown/basics.text\n\n\n## Paragraphs, Headers, Blockquotes ##\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like\na blank line -- a line containing nothing but spaces or tabs is\nconsidered blank.) Normal paragraphs should not be indented with\nspaces or tabs.\n\nMarkdown offers two styles of headers: *Setext* and *atx*.\nSetext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by\n\"underlining\" with equal signs (`=`) and hyphens (`-`), respectively.\nTo create an atx-style header, you put 1-6 hash marks (`#`) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.\n\nBlockquotes are indicated using email-style '`&gt;`' angle brackets.\n\nMarkdown:\n\n    A First Level Header\n    ====================\n\n    A Second Level Header\n    ---------------------\n\n    Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.\n\n    The quick brown fox jumped over the lazy\n    dog's back.\n\n    ### Header 3\n\n    &gt; This is a blockquote.\n    &gt;\n    &gt; This is the second paragraph in the blockquote.\n    &gt;\n    &gt; ## This is an H2 in a blockquote\n\n\nOutput:\n\n    &lt;h1&gt;A First Level Header&lt;/h1&gt;\n\n    &lt;h2&gt;A Second Level Header&lt;/h2&gt;\n\n    &lt;p&gt;Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.&lt;/p&gt;\n\n    &lt;p&gt;The quick brown fox jumped over the lazy\n    dog's back.&lt;/p&gt;\n\n    &lt;h3&gt;Header 3&lt;/h3&gt;\n\n    &lt;blockquote&gt;\n        &lt;p&gt;This is a blockquote.&lt;/p&gt;\n\n        &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;\n\n        &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;\n    &lt;/blockquote&gt;\n\n\n\n### Phrase Emphasis ###\n\nMarkdown uses asterisks and underscores to indicate spans of emphasis.\n\nMarkdown:\n\n    Some of these words *are emphasized*.\n    Some of these words _are emphasized also_.\n\n    Use two asterisks for **strong emphasis**.\n    Or, if you prefer, __use two underscores instead__.\n\nOutput:\n\n    &lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.\n    Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;\n\n    &lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.\n    Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;\n\n\n\n## Lists ##\n\nUnordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,\n`+`, and `-`) as list markers. These three markers are\ninterchangable; this:\n\n    *   Candy.\n    *   Gum.\n    *   Booze.\n\nthis:\n\n    +   Candy.\n    +   Gum.\n    +   Booze.\n\nand this:\n\n    -   Candy.\n    -   Gum.\n    -   Booze.\n\nall produce the same output:\n\n    &lt;ul&gt;\n    &lt;li&gt;Candy.&lt;/li&gt;\n    &lt;li&gt;Gum.&lt;/li&gt;\n    &lt;li&gt;Booze.&lt;/li&gt;\n    &lt;/ul&gt;\n\nOrdered (numbered) lists use regular numbers, followed by periods, as\nlist markers:\n\n    1.  Red\n    2.  Green\n    3.  Blue\n\nOutput:\n\n    &lt;ol&gt;\n    &lt;li&gt;Red&lt;/li&gt;\n    &lt;li&gt;Green&lt;/li&gt;\n    &lt;li&gt;Blue&lt;/li&gt;\n    &lt;/ol&gt;\n\nIf you put blank lines between items, you'll get `&lt;p&gt;` tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:\n\n    *   A list item.\n\n        With multiple paragraphs.\n\n    *   Another item in the list.\n\nOutput:\n\n    &lt;ul&gt;\n    &lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;\n    &lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;\n    &lt;/ul&gt;\n\n\n\n### Links ###\n\nMarkdown supports two styles for creating links: *inline* and\n*reference*. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.\n\nInline-style links use parentheses immediately after the link text.\nFor example:\n\n    This is an [example link](http://example.com/).\n\nOutput:\n\n    &lt;p&gt;This is an &lt;a href=\"http://example.com/\"&gt;\n    example link&lt;/a&gt;.&lt;/p&gt;\n\nOptionally, you may include a title attribute in the parentheses:\n\n    This is an [example link](http://example.com/ \"With a Title\").\n\nOutput:\n\n    &lt;p&gt;This is an &lt;a href=\"http://example.com/\" title=\"With a Title\"&gt;\n    example link&lt;/a&gt;.&lt;/p&gt;\n\nReference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:\n\n    I get 10 times more traffic from [Google][1] than from\n    [Yahoo][2] or [MSN][3].\n\n    [1]: http://google.com/        \"Google\"\n    [2]: http://search.yahoo.com/  \"Yahoo Search\"\n    [3]: http://search.msn.com/    \"MSN Search\"\n\nOutput:\n\n    &lt;p&gt;I get 10 times more traffic from &lt;a href=\"http://google.com/\"\n    title=\"Google\"&gt;Google&lt;/a&gt; than from &lt;a href=\"http://search.yahoo.com/\"\n    title=\"Yahoo Search\"&gt;Yahoo&lt;/a&gt; or &lt;a href=\"http://search.msn.com/\"\n    title=\"MSN Search\"&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n\nThe title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are *not* case sensitive:\n\n    I start my morning with a cup of coffee and\n    [The New York Times][NY Times].\n\n    [ny times]: http://www.nytimes.com/\n\nOutput:\n\n    &lt;p&gt;I start my morning with a cup of coffee and\n    &lt;a href=\"http://www.nytimes.com/\"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;\n\n\n### Images ###\n\nImage syntax is very much like link syntax.\n\nInline (titles are optional):\n\n    ![alt text](/path/to/img.jpg \"Title\")\n\nReference-style:\n\n    ![alt text][id]\n\n    [id]: /path/to/img.jpg \"Title\"\n\nBoth of the above examples produce the same output:\n\n    &lt;img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" /&gt;\n\n\n\n### Code ###\n\nIn a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or\n`&gt;`) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:\n\n    I strongly recommend against using any `&lt;blink&gt;` tags.\n\n    I wish SmartyPants used named entities like `&amp;mdash;`\n    instead of decimal-encoded entites like `&amp;#8212;`.\n\nOutput:\n\n    &lt;p&gt;I strongly recommend against using any\n    &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n\n    &lt;p&gt;I wish SmartyPants used named entities like\n    &lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded\n    entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;\n\n\nTo specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,\nand `&gt;` characters will be escaped automatically.\n\nMarkdown:\n\n    If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:\n\n        &lt;blockquote&gt;\n            &lt;p&gt;For example.&lt;/p&gt;\n        &lt;/blockquote&gt;\n\nOutput:\n\n    &lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:&lt;/p&gt;\n\n    &lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;\n        &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;\n    &amp;lt;/blockquote&amp;gt;\n    &lt;/code&gt;&lt;/pre&gt;\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'markdown',\n        lineNumbers: true,\n        theme: \"default\",\n        extraKeys: {\"Enter\": \"newlineAndIndentContinueMarkdownList\"}\n      });\n    </script>\n\n    <p>Optionally depends on the XML mode for properly highlighted inline XML blocks.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#markdown_*\">normal</a>,  <a href=\"../../test/index.html#verbose,markdown_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/markdown/markdown.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\"), require(\"../xml/xml\"), require(\"../meta\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../xml/xml\", \"../meta\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"markdown\", function(cmCfg, modeCfg) {\n\n  var htmlFound = CodeMirror.modes.hasOwnProperty(\"xml\");\n  var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: \"xml\", htmlMode: true} : \"text/plain\");\n\n  function getMode(name) {\n    if (CodeMirror.findModeByName) {\n      var found = CodeMirror.findModeByName(name);\n      if (found) name = found.mime || found.mimes[0];\n    }\n    var mode = CodeMirror.getMode(cmCfg, name);\n    return mode.name == \"null\" ? null : mode;\n  }\n\n  // Should characters that affect highlighting be highlighted separate?\n  // Does not include characters that will be output (such as `1.` and `-` for lists)\n  if (modeCfg.highlightFormatting === undefined)\n    modeCfg.highlightFormatting = false;\n\n  // Maximum number of nested blockquotes. Set to 0 for infinite nesting.\n  // Excess `>` will emit `error` token.\n  if (modeCfg.maxBlockquoteDepth === undefined)\n    modeCfg.maxBlockquoteDepth = 0;\n\n  // Should underscores in words open/close em/strong?\n  if (modeCfg.underscoresBreakWords === undefined)\n    modeCfg.underscoresBreakWords = true;\n\n  // Turn on fenced code blocks? (\"```\" to start/end)\n  if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;\n\n  // Turn on task lists? (\"- [ ] \" and \"- [x] \")\n  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;\n\n  // Turn on strikethrough syntax\n  if (modeCfg.strikethrough === undefined)\n    modeCfg.strikethrough = false;\n\n  var codeDepth = 0;\n\n  var header   = 'header'\n  ,   code     = 'comment'\n  ,   quote    = 'quote'\n  ,   list1    = 'variable-2'\n  ,   list2    = 'variable-3'\n  ,   list3    = 'keyword'\n  ,   hr       = 'hr'\n  ,   image    = 'tag'\n  ,   formatting = 'formatting'\n  ,   linkinline = 'link'\n  ,   linkemail = 'link'\n  ,   linktext = 'link'\n  ,   linkhref = 'string'\n  ,   em       = 'em'\n  ,   strong   = 'strong'\n  ,   strikethrough = 'strikethrough';\n\n  var hrRE = /^([*\\-=_])(?:\\s*\\1){2,}\\s*$/\n  ,   ulRE = /^[*\\-+]\\s+/\n  ,   olRE = /^[0-9]+\\.\\s+/\n  ,   taskListRE = /^\\[(x| )\\](?=\\s)/ // Must follow ulRE or olRE\n  ,   atxHeaderRE = /^#+/\n  ,   setextHeaderRE = /^(?:\\={1,}|-{1,})$/\n  ,   textRE = /^[^#!\\[\\]*_\\\\<>` \"'(~]+/;\n\n  function switchInline(stream, state, f) {\n    state.f = state.inline = f;\n    return f(stream, state);\n  }\n\n  function switchBlock(stream, state, f) {\n    state.f = state.block = f;\n    return f(stream, state);\n  }\n\n\n  // Blocks\n\n  function blankLine(state) {\n    // Reset linkTitle state\n    state.linkTitle = false;\n    // Reset EM state\n    state.em = false;\n    // Reset STRONG state\n    state.strong = false;\n    // Reset strikethrough state\n    state.strikethrough = false;\n    // Reset state.quote\n    state.quote = 0;\n    if (!htmlFound && state.f == htmlBlock) {\n      state.f = inlineNormal;\n      state.block = blockNormal;\n    }\n    // Reset state.trailingSpace\n    state.trailingSpace = 0;\n    state.trailingSpaceNewLine = false;\n    // Mark this line as blank\n    state.thisLineHasContent = false;\n    return null;\n  }\n\n  function blockNormal(stream, state) {\n\n    var sol = stream.sol();\n\n    var prevLineIsList = (state.list !== false);\n    if (state.list !== false && state.indentationDiff >= 0) { // Continued list\n      if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block\n        state.indentation -= state.indentationDiff;\n      }\n      state.list = null;\n    } else if (state.list !== false && state.indentation > 0) {\n      state.list = null;\n      state.listDepth = Math.floor(state.indentation / 4);\n    } else if (state.list !== false) { // No longer a list\n      state.list = false;\n      state.listDepth = 0;\n    }\n\n    var match = null;\n    if (state.indentationDiff >= 4) {\n      state.indentation -= 4;\n      stream.skipToEnd();\n      return code;\n    } else if (stream.eatSpace()) {\n      return null;\n    } else if (match = stream.match(atxHeaderRE)) {\n      state.header = match[0].length <= 6 ? match[0].length : 6;\n      if (modeCfg.highlightFormatting) state.formatting = \"header\";\n      state.f = state.inline;\n      return getType(state);\n    } else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {\n      state.header = match[0].charAt(0) == '=' ? 1 : 2;\n      if (modeCfg.highlightFormatting) state.formatting = \"header\";\n      state.f = state.inline;\n      return getType(state);\n    } else if (stream.eat('>')) {\n      state.indentation++;\n      state.quote = sol ? 1 : state.quote + 1;\n      if (modeCfg.highlightFormatting) state.formatting = \"quote\";\n      stream.eatSpace();\n      return getType(state);\n    } else if (stream.peek() === '[') {\n      return switchInline(stream, state, footnoteLink);\n    } else if (stream.match(hrRE, true)) {\n      return hr;\n    } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {\n      var listType = null;\n      if (stream.match(ulRE, true)) {\n        listType = 'ul';\n      } else {\n        stream.match(olRE, true);\n        listType = 'ol';\n      }\n      state.indentation += 4;\n      state.list = true;\n      state.listDepth++;\n      if (modeCfg.taskLists && stream.match(taskListRE, false)) {\n        state.taskList = true;\n      }\n      state.f = state.inline;\n      if (modeCfg.highlightFormatting) state.formatting = [\"list\", \"list-\" + listType];\n      return getType(state);\n    } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \\t]*([\\w+#]*)/, true)) {\n      // try switching mode\n      state.localMode = getMode(RegExp.$1);\n      if (state.localMode) state.localState = state.localMode.startState();\n      state.f = state.block = local;\n      if (modeCfg.highlightFormatting) state.formatting = \"code-block\";\n      state.code = true;\n      return getType(state);\n    }\n\n    return switchInline(stream, state, state.inline);\n  }\n\n  function htmlBlock(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||\n        (state.md_inside && stream.current().indexOf(\">\") > -1)) {\n      state.f = inlineNormal;\n      state.block = blockNormal;\n      state.htmlState = null;\n    }\n    return style;\n  }\n\n  function local(stream, state) {\n    if (stream.sol() && stream.match(\"```\", false)) {\n      state.localMode = state.localState = null;\n      state.f = state.block = leavingLocal;\n      return null;\n    } else if (state.localMode) {\n      return state.localMode.token(stream, state.localState);\n    } else {\n      stream.skipToEnd();\n      return code;\n    }\n  }\n\n  function leavingLocal(stream, state) {\n    stream.match(\"```\");\n    state.block = blockNormal;\n    state.f = inlineNormal;\n    if (modeCfg.highlightFormatting) state.formatting = \"code-block\";\n    state.code = true;\n    var returnType = getType(state);\n    state.code = false;\n    return returnType;\n  }\n\n  // Inline\n  function getType(state) {\n    var styles = [];\n\n    if (state.formatting) {\n      styles.push(formatting);\n\n      if (typeof state.formatting === \"string\") state.formatting = [state.formatting];\n\n      for (var i = 0; i < state.formatting.length; i++) {\n        styles.push(formatting + \"-\" + state.formatting[i]);\n\n        if (state.formatting[i] === \"header\") {\n          styles.push(formatting + \"-\" + state.formatting[i] + \"-\" + state.header);\n        }\n\n        // Add `formatting-quote` and `formatting-quote-#` for blockquotes\n        // Add `error` instead if the maximum blockquote nesting depth is passed\n        if (state.formatting[i] === \"quote\") {\n          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {\n            styles.push(formatting + \"-\" + state.formatting[i] + \"-\" + state.quote);\n          } else {\n            styles.push(\"error\");\n          }\n        }\n      }\n    }\n\n    if (state.taskOpen) {\n      styles.push(\"meta\");\n      return styles.length ? styles.join(' ') : null;\n    }\n    if (state.taskClosed) {\n      styles.push(\"property\");\n      return styles.length ? styles.join(' ') : null;\n    }\n\n    if (state.linkHref) {\n      styles.push(linkhref);\n      return styles.length ? styles.join(' ') : null;\n    }\n\n    if (state.strong) { styles.push(strong); }\n    if (state.em) { styles.push(em); }\n    if (state.strikethrough) { styles.push(strikethrough); }\n\n    if (state.linkText) { styles.push(linktext); }\n\n    if (state.code) { styles.push(code); }\n\n    if (state.header) { styles.push(header); styles.push(header + \"-\" + state.header); }\n\n    if (state.quote) {\n      styles.push(quote);\n\n      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth\n      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {\n        styles.push(quote + \"-\" + state.quote);\n      } else {\n        styles.push(quote + \"-\" + modeCfg.maxBlockquoteDepth);\n      }\n    }\n\n    if (state.list !== false) {\n      var listMod = (state.listDepth - 1) % 3;\n      if (!listMod) {\n        styles.push(list1);\n      } else if (listMod === 1) {\n        styles.push(list2);\n      } else {\n        styles.push(list3);\n      }\n    }\n\n    if (state.trailingSpaceNewLine) {\n      styles.push(\"trailing-space-new-line\");\n    } else if (state.trailingSpace) {\n      styles.push(\"trailing-space-\" + (state.trailingSpace % 2 ? \"a\" : \"b\"));\n    }\n\n    return styles.length ? styles.join(' ') : null;\n  }\n\n  function handleText(stream, state) {\n    if (stream.match(textRE, true)) {\n      return getType(state);\n    }\n    return undefined;\n  }\n\n  function inlineNormal(stream, state) {\n    var style = state.text(stream, state);\n    if (typeof style !== 'undefined')\n      return style;\n\n    if (state.list) { // List marker (*, +, -, 1., etc)\n      state.list = null;\n      return getType(state);\n    }\n\n    if (state.taskList) {\n      var taskOpen = stream.match(taskListRE, true)[1] !== \"x\";\n      if (taskOpen) state.taskOpen = true;\n      else state.taskClosed = true;\n      if (modeCfg.highlightFormatting) state.formatting = \"task\";\n      state.taskList = false;\n      return getType(state);\n    }\n\n    state.taskOpen = false;\n    state.taskClosed = false;\n\n    if (state.header && stream.match(/^#+$/, true)) {\n      if (modeCfg.highlightFormatting) state.formatting = \"header\";\n      return getType(state);\n    }\n\n    // Get sol() value now, before character is consumed\n    var sol = stream.sol();\n\n    var ch = stream.next();\n\n    if (ch === '\\\\') {\n      stream.next();\n      if (modeCfg.highlightFormatting) {\n        var type = getType(state);\n        return type ? type + \" formatting-escape\" : \"formatting-escape\";\n      }\n    }\n\n    // Matches link titles present on next line\n    if (state.linkTitle) {\n      state.linkTitle = false;\n      var matchCh = ch;\n      if (ch === '(') {\n        matchCh = ')';\n      }\n      matchCh = (matchCh+'').replace(/([.?*+^$[\\]\\\\(){}|-])/g, \"\\\\$1\");\n      var regex = '^\\\\s*(?:[^' + matchCh + '\\\\\\\\]+|\\\\\\\\\\\\\\\\|\\\\\\\\.)' + matchCh;\n      if (stream.match(new RegExp(regex), true)) {\n        return linkhref;\n      }\n    }\n\n    // If this block is changed, it may need to be updated in GFM mode\n    if (ch === '`') {\n      var previousFormatting = state.formatting;\n      if (modeCfg.highlightFormatting) state.formatting = \"code\";\n      var t = getType(state);\n      var before = stream.pos;\n      stream.eatWhile('`');\n      var difference = 1 + stream.pos - before;\n      if (!state.code) {\n        codeDepth = difference;\n        state.code = true;\n        return getType(state);\n      } else {\n        if (difference === codeDepth) { // Must be exact\n          state.code = false;\n          return t;\n        }\n        state.formatting = previousFormatting;\n        return getType(state);\n      }\n    } else if (state.code) {\n      return getType(state);\n    }\n\n    if (ch === '!' && stream.match(/\\[[^\\]]*\\] ?(?:\\(|\\[)/, false)) {\n      stream.match(/\\[[^\\]]*\\]/);\n      state.inline = state.f = linkHref;\n      return image;\n    }\n\n    if (ch === '[' && stream.match(/.*\\](\\(.*\\)| ?\\[.*\\])/, false)) {\n      state.linkText = true;\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      return getType(state);\n    }\n\n    if (ch === ']' && state.linkText && stream.match(/\\(.*\\)| ?\\[.*\\]/, false)) {\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      var type = getType(state);\n      state.linkText = false;\n      state.inline = state.f = linkHref;\n      return type;\n    }\n\n    if (ch === '<' && stream.match(/^(https?|ftps?):\\/\\/(?:[^\\\\>]|\\\\.)+>/, false)) {\n      state.f = state.inline = linkInline;\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      var type = getType(state);\n      if (type){\n        type += \" \";\n      } else {\n        type = \"\";\n      }\n      return type + linkinline;\n    }\n\n    if (ch === '<' && stream.match(/^[^> \\\\]+@(?:[^\\\\>]|\\\\.)+>/, false)) {\n      state.f = state.inline = linkInline;\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      var type = getType(state);\n      if (type){\n        type += \" \";\n      } else {\n        type = \"\";\n      }\n      return type + linkemail;\n    }\n\n    if (ch === '<' && stream.match(/^\\w/, false)) {\n      if (stream.string.indexOf(\">\") != -1) {\n        var atts = stream.string.substring(1,stream.string.indexOf(\">\"));\n        if (/markdown\\s*=\\s*('|\"){0,1}1('|\"){0,1}/.test(atts)) {\n          state.md_inside = true;\n        }\n      }\n      stream.backUp(1);\n      state.htmlState = CodeMirror.startState(htmlMode);\n      return switchBlock(stream, state, htmlBlock);\n    }\n\n    if (ch === '<' && stream.match(/^\\/\\w*?>/)) {\n      state.md_inside = false;\n      return \"tag\";\n    }\n\n    var ignoreUnderscore = false;\n    if (!modeCfg.underscoresBreakWords) {\n      if (ch === '_' && stream.peek() !== '_' && stream.match(/(\\w)/, false)) {\n        var prevPos = stream.pos - 2;\n        if (prevPos >= 0) {\n          var prevCh = stream.string.charAt(prevPos);\n          if (prevCh !== '_' && prevCh.match(/(\\w)/, false)) {\n            ignoreUnderscore = true;\n          }\n        }\n      }\n    }\n    if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {\n      if (sol && stream.peek() === ' ') {\n        // Do nothing, surrounded by newline and space\n      } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG\n        if (modeCfg.highlightFormatting) state.formatting = \"strong\";\n        var t = getType(state);\n        state.strong = false;\n        return t;\n      } else if (!state.strong && stream.eat(ch)) { // Add STRONG\n        state.strong = ch;\n        if (modeCfg.highlightFormatting) state.formatting = \"strong\";\n        return getType(state);\n      } else if (state.em === ch) { // Remove EM\n        if (modeCfg.highlightFormatting) state.formatting = \"em\";\n        var t = getType(state);\n        state.em = false;\n        return t;\n      } else if (!state.em) { // Add EM\n        state.em = ch;\n        if (modeCfg.highlightFormatting) state.formatting = \"em\";\n        return getType(state);\n      }\n    } else if (ch === ' ') {\n      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces\n        if (stream.peek() === ' ') { // Surrounded by spaces, ignore\n          return getType(state);\n        } else { // Not surrounded by spaces, back up pointer\n          stream.backUp(1);\n        }\n      }\n    }\n\n    if (modeCfg.strikethrough) {\n      if (ch === '~' && stream.eatWhile(ch)) {\n        if (state.strikethrough) {// Remove strikethrough\n          if (modeCfg.highlightFormatting) state.formatting = \"strikethrough\";\n          var t = getType(state);\n          state.strikethrough = false;\n          return t;\n        } else if (stream.match(/^[^\\s]/, false)) {// Add strikethrough\n          state.strikethrough = true;\n          if (modeCfg.highlightFormatting) state.formatting = \"strikethrough\";\n          return getType(state);\n        }\n      } else if (ch === ' ') {\n        if (stream.match(/^~~/, true)) { // Probably surrounded by space\n          if (stream.peek() === ' ') { // Surrounded by spaces, ignore\n            return getType(state);\n          } else { // Not surrounded by spaces, back up pointer\n            stream.backUp(2);\n          }\n        }\n      }\n    }\n\n    if (ch === ' ') {\n      if (stream.match(/ +$/, false)) {\n        state.trailingSpace++;\n      } else if (state.trailingSpace) {\n        state.trailingSpaceNewLine = true;\n      }\n    }\n\n    return getType(state);\n  }\n\n  function linkInline(stream, state) {\n    var ch = stream.next();\n\n    if (ch === \">\") {\n      state.f = state.inline = inlineNormal;\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      var type = getType(state);\n      if (type){\n        type += \" \";\n      } else {\n        type = \"\";\n      }\n      return type + linkinline;\n    }\n\n    stream.match(/^[^>]+/, true);\n\n    return linkinline;\n  }\n\n  function linkHref(stream, state) {\n    // Check if space, and return NULL if so (to avoid marking the space)\n    if(stream.eatSpace()){\n      return null;\n    }\n    var ch = stream.next();\n    if (ch === '(' || ch === '[') {\n      state.f = state.inline = getLinkHrefInside(ch === \"(\" ? \")\" : \"]\");\n      if (modeCfg.highlightFormatting) state.formatting = \"link-string\";\n      state.linkHref = true;\n      return getType(state);\n    }\n    return 'error';\n  }\n\n  function getLinkHrefInside(endChar) {\n    return function(stream, state) {\n      var ch = stream.next();\n\n      if (ch === endChar) {\n        state.f = state.inline = inlineNormal;\n        if (modeCfg.highlightFormatting) state.formatting = \"link-string\";\n        var returnState = getType(state);\n        state.linkHref = false;\n        return returnState;\n      }\n\n      if (stream.match(inlineRE(endChar), true)) {\n        stream.backUp(1);\n      }\n\n      state.linkHref = true;\n      return getType(state);\n    };\n  }\n\n  function footnoteLink(stream, state) {\n    if (stream.match(/^[^\\]]*\\]:/, false)) {\n      state.f = footnoteLinkInside;\n      stream.next(); // Consume [\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      state.linkText = true;\n      return getType(state);\n    }\n    return switchInline(stream, state, inlineNormal);\n  }\n\n  function footnoteLinkInside(stream, state) {\n    if (stream.match(/^\\]:/, true)) {\n      state.f = state.inline = footnoteUrl;\n      if (modeCfg.highlightFormatting) state.formatting = \"link\";\n      var returnType = getType(state);\n      state.linkText = false;\n      return returnType;\n    }\n\n    stream.match(/^[^\\]]+/, true);\n\n    return linktext;\n  }\n\n  function footnoteUrl(stream, state) {\n    // Check if space, and return NULL if so (to avoid marking the space)\n    if(stream.eatSpace()){\n      return null;\n    }\n    // Match URL\n    stream.match(/^[^\\s]+/, true);\n    // Check for link title\n    if (stream.peek() === undefined) { // End of line, set flag to check next line\n      state.linkTitle = true;\n    } else { // More content on line, check if link title\n      stream.match(/^(?:\\s+(?:\"(?:[^\"\\\\]|\\\\\\\\|\\\\.)+\"|'(?:[^'\\\\]|\\\\\\\\|\\\\.)+'|\\((?:[^)\\\\]|\\\\\\\\|\\\\.)+\\)))?/, true);\n    }\n    state.f = state.inline = inlineNormal;\n    return linkhref;\n  }\n\n  var savedInlineRE = [];\n  function inlineRE(endChar) {\n    if (!savedInlineRE[endChar]) {\n      // Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)\n      endChar = (endChar+'').replace(/([.?*+^$[\\]\\\\(){}|-])/g, \"\\\\$1\");\n      // Match any non-endChar, escaped character, as well as the closing\n      // endChar.\n      savedInlineRE[endChar] = new RegExp('^(?:[^\\\\\\\\]|\\\\\\\\.)*?(' + endChar + ')');\n    }\n    return savedInlineRE[endChar];\n  }\n\n  var mode = {\n    startState: function() {\n      return {\n        f: blockNormal,\n\n        prevLineHasContent: false,\n        thisLineHasContent: false,\n\n        block: blockNormal,\n        htmlState: null,\n        indentation: 0,\n\n        inline: inlineNormal,\n        text: handleText,\n\n        formatting: false,\n        linkText: false,\n        linkHref: false,\n        linkTitle: false,\n        em: false,\n        strong: false,\n        header: 0,\n        taskList: false,\n        list: false,\n        listDepth: 0,\n        quote: 0,\n        trailingSpace: 0,\n        trailingSpaceNewLine: false,\n        strikethrough: false\n      };\n    },\n\n    copyState: function(s) {\n      return {\n        f: s.f,\n\n        prevLineHasContent: s.prevLineHasContent,\n        thisLineHasContent: s.thisLineHasContent,\n\n        block: s.block,\n        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),\n        indentation: s.indentation,\n\n        localMode: s.localMode,\n        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,\n\n        inline: s.inline,\n        text: s.text,\n        formatting: false,\n        linkTitle: s.linkTitle,\n        em: s.em,\n        strong: s.strong,\n        strikethrough: s.strikethrough,\n        header: s.header,\n        taskList: s.taskList,\n        list: s.list,\n        listDepth: s.listDepth,\n        quote: s.quote,\n        trailingSpace: s.trailingSpace,\n        trailingSpaceNewLine: s.trailingSpaceNewLine,\n        md_inside: s.md_inside\n      };\n    },\n\n    token: function(stream, state) {\n\n      // Reset state.formatting\n      state.formatting = false;\n\n      if (stream.sol()) {\n        var forceBlankLine = !!state.header;\n\n        // Reset state.header\n        state.header = 0;\n\n        if (stream.match(/^\\s*$/, true) || forceBlankLine) {\n          state.prevLineHasContent = false;\n          blankLine(state);\n          return forceBlankLine ? this.token(stream, state) : null;\n        } else {\n          state.prevLineHasContent = state.thisLineHasContent;\n          state.thisLineHasContent = true;\n        }\n\n        // Reset state.taskList\n        state.taskList = false;\n\n        // Reset state.code\n        state.code = false;\n\n        // Reset state.trailingSpace\n        state.trailingSpace = 0;\n        state.trailingSpaceNewLine = false;\n\n        state.f = state.block;\n        var indentation = stream.match(/^\\s*/, true)[0].replace(/\\t/g, '    ').length;\n        var difference = Math.floor((indentation - state.indentation) / 4) * 4;\n        if (difference > 4) difference = 4;\n        var adjustedIndentation = state.indentation + difference;\n        state.indentationDiff = adjustedIndentation - state.indentation;\n        state.indentation = adjustedIndentation;\n        if (indentation > 0) return null;\n      }\n      return state.f(stream, state);\n    },\n\n    innerMode: function(state) {\n      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};\n      if (state.localState) return {state: state.localState, mode: state.localMode};\n      return {state: state, mode: mode};\n    },\n\n    blankLine: blankLine,\n\n    getType: getType,\n\n    fold: \"markdown\"\n  };\n  return mode;\n}, \"xml\");\n\nCodeMirror.defineMIME(\"text/x-markdown\", \"markdown\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/markdown/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4}, \"markdown\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n  var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: \"markdown\", highlightFormatting: true});\n  function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }\n\n  FT(\"formatting_emAsterisk\",\n     \"[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]\");\n\n  FT(\"formatting_emUnderscore\",\n     \"[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]\");\n\n  FT(\"formatting_strongAsterisk\",\n     \"[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]\");\n\n  FT(\"formatting_strongUnderscore\",\n     \"[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]\");\n\n  FT(\"formatting_codeBackticks\",\n     \"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]\");\n\n  FT(\"formatting_doubleBackticks\",\n     \"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]\");\n\n  FT(\"formatting_atxHeader\",\n     \"[header&header-1&formatting&formatting-header&formatting-header-1 #][header&header-1  foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]\");\n\n  FT(\"formatting_setextHeader\",\n     \"foo\",\n     \"[header&header-1&formatting&formatting-header&formatting-header-1 =]\");\n\n  FT(\"formatting_blockquote\",\n     \"[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]\");\n\n  FT(\"formatting_list\",\n     \"[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]\");\n  FT(\"formatting_list\",\n     \"[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]\");\n\n  FT(\"formatting_link\",\n     \"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]\");\n\n  FT(\"formatting_linkReference\",\n     \"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]\",\n     \"[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]\");\n\n  FT(\"formatting_linkWeb\",\n     \"[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]\");\n\n  FT(\"formatting_linkEmail\",\n     \"[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]\");\n\n  FT(\"formatting_escape\",\n     \"[formatting-escape \\\\*]\");\n\n  MT(\"plainText\",\n     \"foo\");\n\n  // Don't style single trailing space\n  MT(\"trailingSpace1\",\n     \"foo \");\n\n  // Two or more trailing spaces should be styled with line break character\n  MT(\"trailingSpace2\",\n     \"foo[trailing-space-a  ][trailing-space-new-line  ]\");\n\n  MT(\"trailingSpace3\",\n     \"foo[trailing-space-a  ][trailing-space-b  ][trailing-space-new-line  ]\");\n\n  MT(\"trailingSpace4\",\n     \"foo[trailing-space-a  ][trailing-space-b  ][trailing-space-a  ][trailing-space-new-line  ]\");\n\n  // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)\n  MT(\"codeBlocksUsing4Spaces\",\n     \"    [comment foo]\");\n\n  // Code blocks using 4 spaces with internal indentation\n  MT(\"codeBlocksUsing4SpacesIndentation\",\n     \"    [comment bar]\",\n     \"        [comment hello]\",\n     \"            [comment world]\",\n     \"    [comment foo]\",\n     \"bar\");\n\n  // Code blocks using 4 spaces with internal indentation\n  MT(\"codeBlocksUsing4SpacesIndentation\",\n     \" foo\",\n     \"    [comment bar]\",\n     \"        [comment hello]\",\n     \"    [comment world]\");\n\n  // Code blocks should end even after extra indented lines\n  MT(\"codeBlocksWithTrailingIndentedLine\",\n     \"    [comment foo]\",\n     \"        [comment bar]\",\n     \"    [comment baz]\",\n     \"    \",\n     \"hello\");\n\n  // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)\n  MT(\"codeBlocksUsing1Tab\",\n     \"\\t[comment foo]\");\n\n  // Inline code using backticks\n  MT(\"inlineCodeUsingBackticks\",\n     \"foo [comment `bar`]\");\n\n  // Block code using single backtick (shouldn't work)\n  MT(\"blockCodeSingleBacktick\",\n     \"[comment `]\",\n     \"foo\",\n     \"[comment `]\");\n\n  // Unclosed backticks\n  // Instead of simply marking as CODE, it would be nice to have an\n  // incomplete flag for CODE, that is styled slightly different.\n  MT(\"unclosedBackticks\",\n     \"foo [comment `bar]\");\n\n  // Per documentation: \"To include a literal backtick character within a\n  // code span, you can use multiple backticks as the opening and closing\n  // delimiters\"\n  MT(\"doubleBackticks\",\n     \"[comment ``foo ` bar``]\");\n\n  // Tests based on Dingus\n  // http://daringfireball.net/projects/markdown/dingus\n  //\n  // Multiple backticks within an inline code block\n  MT(\"consecutiveBackticks\",\n     \"[comment `foo```bar`]\");\n\n  // Multiple backticks within an inline code block with a second code block\n  MT(\"consecutiveBackticks\",\n     \"[comment `foo```bar`] hello [comment `world`]\");\n\n  // Unclosed with several different groups of backticks\n  MT(\"unclosedBackticks\",\n     \"[comment ``foo ``` bar` hello]\");\n\n  // Closed with several different groups of backticks\n  MT(\"closedBackticks\",\n     \"[comment ``foo ``` bar` hello``] world\");\n\n  // atx headers\n  // http://daringfireball.net/projects/markdown/syntax#header\n\n  MT(\"atxH1\",\n     \"[header&header-1 # foo]\");\n\n  MT(\"atxH2\",\n     \"[header&header-2 ## foo]\");\n\n  MT(\"atxH3\",\n     \"[header&header-3 ### foo]\");\n\n  MT(\"atxH4\",\n     \"[header&header-4 #### foo]\");\n\n  MT(\"atxH5\",\n     \"[header&header-5 ##### foo]\");\n\n  MT(\"atxH6\",\n     \"[header&header-6 ###### foo]\");\n\n  // H6 - 7x '#' should still be H6, per Dingus\n  // http://daringfireball.net/projects/markdown/dingus\n  MT(\"atxH6NotH7\",\n     \"[header&header-6 ####### foo]\");\n\n  // Inline styles should be parsed inside headers\n  MT(\"atxH1inline\",\n     \"[header&header-1 # foo ][header&header-1&em *bar*]\");\n\n  // Setext headers - H1, H2\n  // Per documentation, \"Any number of underlining =’s or -’s will work.\"\n  // http://daringfireball.net/projects/markdown/syntax#header\n  // Ideally, the text would be marked as `header` as well, but this is\n  // not really feasible at the moment. So, instead, we're testing against\n  // what works today, to avoid any regressions.\n  //\n  // Check if single underlining = works\n  MT(\"setextH1\",\n     \"foo\",\n     \"[header&header-1 =]\");\n\n  // Check if 3+ ='s work\n  MT(\"setextH1\",\n     \"foo\",\n     \"[header&header-1 ===]\");\n\n  // Check if single underlining - works\n  MT(\"setextH2\",\n     \"foo\",\n     \"[header&header-2 -]\");\n\n  // Check if 3+ -'s work\n  MT(\"setextH2\",\n     \"foo\",\n     \"[header&header-2 ---]\");\n\n  // Single-line blockquote with trailing space\n  MT(\"blockquoteSpace\",\n     \"[quote&quote-1 > foo]\");\n\n  // Single-line blockquote\n  MT(\"blockquoteNoSpace\",\n     \"[quote&quote-1 >foo]\");\n\n  // No blank line before blockquote\n  MT(\"blockquoteNoBlankLine\",\n     \"foo\",\n     \"[quote&quote-1 > bar]\");\n\n  // Nested blockquote\n  MT(\"blockquoteSpace\",\n     \"[quote&quote-1 > foo]\",\n     \"[quote&quote-1 >][quote&quote-2 > foo]\",\n     \"[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]\");\n\n  // Single-line blockquote followed by normal paragraph\n  MT(\"blockquoteThenParagraph\",\n     \"[quote&quote-1 >foo]\",\n     \"\",\n     \"bar\");\n\n  // Multi-line blockquote (lazy mode)\n  MT(\"multiBlockquoteLazy\",\n     \"[quote&quote-1 >foo]\",\n     \"[quote&quote-1 bar]\");\n\n  // Multi-line blockquote followed by normal paragraph (lazy mode)\n  MT(\"multiBlockquoteLazyThenParagraph\",\n     \"[quote&quote-1 >foo]\",\n     \"[quote&quote-1 bar]\",\n     \"\",\n     \"hello\");\n\n  // Multi-line blockquote (non-lazy mode)\n  MT(\"multiBlockquote\",\n     \"[quote&quote-1 >foo]\",\n     \"[quote&quote-1 >bar]\");\n\n  // Multi-line blockquote followed by normal paragraph (non-lazy mode)\n  MT(\"multiBlockquoteThenParagraph\",\n     \"[quote&quote-1 >foo]\",\n     \"[quote&quote-1 >bar]\",\n     \"\",\n     \"hello\");\n\n  // Check list types\n\n  MT(\"listAsterisk\",\n     \"foo\",\n     \"bar\",\n     \"\",\n     \"[variable-2 * foo]\",\n     \"[variable-2 * bar]\");\n\n  MT(\"listPlus\",\n     \"foo\",\n     \"bar\",\n     \"\",\n     \"[variable-2 + foo]\",\n     \"[variable-2 + bar]\");\n\n  MT(\"listDash\",\n     \"foo\",\n     \"bar\",\n     \"\",\n     \"[variable-2 - foo]\",\n     \"[variable-2 - bar]\");\n\n  MT(\"listNumber\",\n     \"foo\",\n     \"bar\",\n     \"\",\n     \"[variable-2 1. foo]\",\n     \"[variable-2 2. bar]\");\n\n  // Lists require a preceding blank line (per Dingus)\n  MT(\"listBogus\",\n     \"foo\",\n     \"1. bar\",\n     \"2. hello\");\n\n  // List after header\n  MT(\"listAfterHeader\",\n     \"[header&header-1 # foo]\",\n     \"[variable-2 - bar]\");\n\n  // Formatting in lists (*)\n  MT(\"listAsteriskFormatting\",\n     \"[variable-2 * ][variable-2&em *foo*][variable-2  bar]\",\n     \"[variable-2 * ][variable-2&strong **foo**][variable-2  bar]\",\n     \"[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]\",\n     \"[variable-2 * ][variable-2&comment `foo`][variable-2  bar]\");\n\n  // Formatting in lists (+)\n  MT(\"listPlusFormatting\",\n     \"[variable-2 + ][variable-2&em *foo*][variable-2  bar]\",\n     \"[variable-2 + ][variable-2&strong **foo**][variable-2  bar]\",\n     \"[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]\",\n     \"[variable-2 + ][variable-2&comment `foo`][variable-2  bar]\");\n\n  // Formatting in lists (-)\n  MT(\"listDashFormatting\",\n     \"[variable-2 - ][variable-2&em *foo*][variable-2  bar]\",\n     \"[variable-2 - ][variable-2&strong **foo**][variable-2  bar]\",\n     \"[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]\",\n     \"[variable-2 - ][variable-2&comment `foo`][variable-2  bar]\");\n\n  // Formatting in lists (1.)\n  MT(\"listNumberFormatting\",\n     \"[variable-2 1. ][variable-2&em *foo*][variable-2  bar]\",\n     \"[variable-2 2. ][variable-2&strong **foo**][variable-2  bar]\",\n     \"[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]\",\n     \"[variable-2 4. ][variable-2&comment `foo`][variable-2  bar]\");\n\n  // Paragraph lists\n  MT(\"listParagraph\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\");\n\n  // Multi-paragraph lists\n  //\n  // 4 spaces\n  MT(\"listMultiParagraph\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"    [variable-2 hello]\");\n\n  // 4 spaces, extra blank lines (should still be list, per Dingus)\n  MT(\"listMultiParagraphExtra\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"\",\n     \"    [variable-2 hello]\");\n\n  // 4 spaces, plus 1 space (should still be list, per Dingus)\n  MT(\"listMultiParagraphExtraSpace\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"     [variable-2 hello]\",\n     \"\",\n     \"    [variable-2 world]\");\n\n  // 1 tab\n  MT(\"listTab\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"\\t[variable-2 hello]\");\n\n  // No indent\n  MT(\"listNoIndent\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"hello\");\n\n  // Blockquote\n  MT(\"blockquote\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"    [variable-2&quote&quote-1 > hello]\");\n\n  // Code block\n  MT(\"blockquoteCode\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"[variable-2 * bar]\",\n     \"\",\n     \"        [comment > hello]\",\n     \"\",\n     \"    [variable-2 world]\");\n\n  // Code block followed by text\n  MT(\"blockquoteCodeText\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"    [variable-2 bar]\",\n     \"\",\n     \"        [comment hello]\",\n     \"\",\n     \"    [variable-2 world]\");\n\n  // Nested list\n\n  MT(\"listAsteriskNested\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"    [variable-3 * bar]\");\n\n  MT(\"listPlusNested\",\n     \"[variable-2 + foo]\",\n     \"\",\n     \"    [variable-3 + bar]\");\n\n  MT(\"listDashNested\",\n     \"[variable-2 - foo]\",\n     \"\",\n     \"    [variable-3 - bar]\");\n\n  MT(\"listNumberNested\",\n     \"[variable-2 1. foo]\",\n     \"\",\n     \"    [variable-3 2. bar]\");\n\n  MT(\"listMixed\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"    [variable-3 + bar]\",\n     \"\",\n     \"        [keyword - hello]\",\n     \"\",\n     \"            [variable-2 1. world]\");\n\n  MT(\"listBlockquote\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"    [variable-3 + bar]\",\n     \"\",\n     \"        [quote&quote-1&variable-3 > hello]\");\n\n  MT(\"listCode\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"    [variable-3 + bar]\",\n     \"\",\n     \"            [comment hello]\");\n\n  // Code with internal indentation\n  MT(\"listCodeIndentation\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"        [comment bar]\",\n     \"            [comment hello]\",\n     \"                [comment world]\",\n     \"        [comment foo]\",\n     \"    [variable-2 bar]\");\n\n  // List nesting edge cases\n  MT(\"listNested\",\n    \"[variable-2 * foo]\",\n    \"\",\n    \"    [variable-3 * bar]\",\n    \"\",\n    \"       [variable-2 hello]\"\n  );\n  MT(\"listNested\",\n    \"[variable-2 * foo]\",\n    \"\",\n    \"    [variable-3 * bar]\",\n    \"\",\n    \"      [variable-3 * foo]\"\n  );\n\n  // Code followed by text\n  MT(\"listCodeText\",\n     \"[variable-2 * foo]\",\n     \"\",\n     \"        [comment bar]\",\n     \"\",\n     \"hello\");\n\n  // Following tests directly from official Markdown documentation\n  // http://daringfireball.net/projects/markdown/syntax#hr\n\n  MT(\"hrSpace\",\n     \"[hr * * *]\");\n\n  MT(\"hr\",\n     \"[hr ***]\");\n\n  MT(\"hrLong\",\n     \"[hr *****]\");\n\n  MT(\"hrSpaceDash\",\n     \"[hr - - -]\");\n\n  MT(\"hrDashLong\",\n     \"[hr ---------------------------------------]\");\n\n  // Inline link with title\n  MT(\"linkTitle\",\n     \"[link [[foo]]][string (http://example.com/ \\\"bar\\\")] hello\");\n\n  // Inline link without title\n  MT(\"linkNoTitle\",\n     \"[link [[foo]]][string (http://example.com/)] bar\");\n\n  // Inline link with image\n  MT(\"linkImage\",\n     \"[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar\");\n\n  // Inline link with Em\n  MT(\"linkEm\",\n     \"[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar\");\n\n  // Inline link with Strong\n  MT(\"linkStrong\",\n     \"[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar\");\n\n  // Inline link with EmStrong\n  MT(\"linkEmStrong\",\n     \"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar\");\n\n  // Image with title\n  MT(\"imageTitle\",\n     \"[tag ![[foo]]][string (http://example.com/ \\\"bar\\\")] hello\");\n\n  // Image without title\n  MT(\"imageNoTitle\",\n     \"[tag ![[foo]]][string (http://example.com/)] bar\");\n\n  // Image with asterisks\n  MT(\"imageAsterisks\",\n     \"[tag ![[*foo*]]][string (http://example.com/)] bar\");\n\n  // Not a link. Should be normal text due to square brackets being used\n  // regularly in text, especially in quoted material, and no space is allowed\n  // between square brackets and parentheses (per Dingus).\n  MT(\"notALink\",\n     \"[[foo]] (bar)\");\n\n  // Reference-style links\n  MT(\"linkReference\",\n     \"[link [[foo]]][string [[bar]]] hello\");\n\n  // Reference-style links with Em\n  MT(\"linkReferenceEm\",\n     \"[link [[][link&em *foo*][link ]]][string [[bar]]] hello\");\n\n  // Reference-style links with Strong\n  MT(\"linkReferenceStrong\",\n     \"[link [[][link&strong **foo**][link ]]][string [[bar]]] hello\");\n\n  // Reference-style links with EmStrong\n  MT(\"linkReferenceEmStrong\",\n     \"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello\");\n\n  // Reference-style links with optional space separator (per docuentation)\n  // \"You can optionally use a space to separate the sets of brackets\"\n  MT(\"linkReferenceSpace\",\n     \"[link [[foo]]] [string [[bar]]] hello\");\n\n  // Should only allow a single space (\"...use *a* space...\")\n  MT(\"linkReferenceDoubleSpace\",\n     \"[[foo]]  [[bar]] hello\");\n\n  // Reference-style links with implicit link name\n  MT(\"linkImplicit\",\n     \"[link [[foo]]][string [[]]] hello\");\n\n  // @todo It would be nice if, at some point, the document was actually\n  // checked to see if the referenced link exists\n\n  // Link label, for reference-style links (taken from documentation)\n\n  MT(\"labelNoTitle\",\n     \"[link [[foo]]:] [string http://example.com/]\");\n\n  MT(\"labelIndented\",\n     \"   [link [[foo]]:] [string http://example.com/]\");\n\n  MT(\"labelSpaceTitle\",\n     \"[link [[foo bar]]:] [string http://example.com/ \\\"hello\\\"]\");\n\n  MT(\"labelDoubleTitle\",\n     \"[link [[foo bar]]:] [string http://example.com/ \\\"hello\\\"] \\\"world\\\"\");\n\n  MT(\"labelTitleDoubleQuotes\",\n     \"[link [[foo]]:] [string http://example.com/  \\\"bar\\\"]\");\n\n  MT(\"labelTitleSingleQuotes\",\n     \"[link [[foo]]:] [string http://example.com/  'bar']\");\n\n  MT(\"labelTitleParenthese\",\n     \"[link [[foo]]:] [string http://example.com/  (bar)]\");\n\n  MT(\"labelTitleInvalid\",\n     \"[link [[foo]]:] [string http://example.com/] bar\");\n\n  MT(\"labelLinkAngleBrackets\",\n     \"[link [[foo]]:] [string <http://example.com/>  \\\"bar\\\"]\");\n\n  MT(\"labelTitleNextDoubleQuotes\",\n     \"[link [[foo]]:] [string http://example.com/]\",\n     \"[string \\\"bar\\\"] hello\");\n\n  MT(\"labelTitleNextSingleQuotes\",\n     \"[link [[foo]]:] [string http://example.com/]\",\n     \"[string 'bar'] hello\");\n\n  MT(\"labelTitleNextParenthese\",\n     \"[link [[foo]]:] [string http://example.com/]\",\n     \"[string (bar)] hello\");\n\n  MT(\"labelTitleNextMixed\",\n     \"[link [[foo]]:] [string http://example.com/]\",\n     \"(bar\\\" hello\");\n\n  MT(\"linkWeb\",\n     \"[link <http://example.com/>] foo\");\n\n  MT(\"linkWebDouble\",\n     \"[link <http://example.com/>] foo [link <http://example.com/>]\");\n\n  MT(\"linkEmail\",\n     \"[link <user@example.com>] foo\");\n\n  MT(\"linkEmailDouble\",\n     \"[link <user@example.com>] foo [link <user@example.com>]\");\n\n  MT(\"emAsterisk\",\n     \"[em *foo*] bar\");\n\n  MT(\"emUnderscore\",\n     \"[em _foo_] bar\");\n\n  MT(\"emInWordAsterisk\",\n     \"foo[em *bar*]hello\");\n\n  MT(\"emInWordUnderscore\",\n     \"foo[em _bar_]hello\");\n\n  // Per documentation: \"...surround an * or _ with spaces, it’ll be\n  // treated as a literal asterisk or underscore.\"\n\n  MT(\"emEscapedBySpaceIn\",\n     \"foo [em _bar _ hello_] world\");\n\n  MT(\"emEscapedBySpaceOut\",\n     \"foo _ bar[em _hello_]world\");\n\n  MT(\"emEscapedByNewline\",\n     \"foo\",\n     \"_ bar[em _hello_]world\");\n\n  // Unclosed emphasis characters\n  // Instead of simply marking as EM / STRONG, it would be nice to have an\n  // incomplete flag for EM and STRONG, that is styled slightly different.\n  MT(\"emIncompleteAsterisk\",\n     \"foo [em *bar]\");\n\n  MT(\"emIncompleteUnderscore\",\n     \"foo [em _bar]\");\n\n  MT(\"strongAsterisk\",\n     \"[strong **foo**] bar\");\n\n  MT(\"strongUnderscore\",\n     \"[strong __foo__] bar\");\n\n  MT(\"emStrongAsterisk\",\n     \"[em *foo][em&strong **bar*][strong hello**] world\");\n\n  MT(\"emStrongUnderscore\",\n     \"[em _foo][em&strong __bar_][strong hello__] world\");\n\n  // \"...same character must be used to open and close an emphasis span.\"\"\n  MT(\"emStrongMixed\",\n     \"[em _foo][em&strong **bar*hello__ world]\");\n\n  MT(\"emStrongMixed\",\n     \"[em *foo][em&strong __bar_hello** world]\");\n\n  // These characters should be escaped:\n  // \\   backslash\n  // `   backtick\n  // *   asterisk\n  // _   underscore\n  // {}  curly braces\n  // []  square brackets\n  // ()  parentheses\n  // #   hash mark\n  // +   plus sign\n  // -   minus sign (hyphen)\n  // .   dot\n  // !   exclamation mark\n\n  MT(\"escapeBacktick\",\n     \"foo \\\\`bar\\\\`\");\n\n  MT(\"doubleEscapeBacktick\",\n     \"foo \\\\\\\\[comment `bar\\\\\\\\`]\");\n\n  MT(\"escapeAsterisk\",\n     \"foo \\\\*bar\\\\*\");\n\n  MT(\"doubleEscapeAsterisk\",\n     \"foo \\\\\\\\[em *bar\\\\\\\\*]\");\n\n  MT(\"escapeUnderscore\",\n     \"foo \\\\_bar\\\\_\");\n\n  MT(\"doubleEscapeUnderscore\",\n     \"foo \\\\\\\\[em _bar\\\\\\\\_]\");\n\n  MT(\"escapeHash\",\n     \"\\\\# foo\");\n\n  MT(\"doubleEscapeHash\",\n     \"\\\\\\\\# foo\");\n\n  MT(\"escapeNewline\",\n     \"\\\\\",\n     \"[em *foo*]\");\n\n\n  // Tests to make sure GFM-specific things aren't getting through\n\n  MT(\"taskList\",\n     \"[variable-2 * [ ]] bar]\");\n\n  MT(\"fencedCodeBlocks\",\n     \"[comment ```]\",\n     \"foo\",\n     \"[comment ```]\");\n\n  // Tests that require XML mode\n\n  MT(\"xmlMode\",\n     \"[tag&bracket <][tag div][tag&bracket >]\",\n     \"*foo*\",\n     \"[tag&bracket <][tag http://github.com][tag&bracket />]\",\n     \"[tag&bracket </][tag div][tag&bracket >]\",\n     \"[link <http://github.com/>]\");\n\n  MT(\"xmlModeWithMarkdownInside\",\n     \"[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]\",\n     \"[em *foo*]\",\n     \"[link <http://github.com/>]\",\n     \"[tag </div>]\",\n     \"[link <http://github.com/>]\",\n     \"[tag&bracket <][tag div][tag&bracket >]\",\n     \"[tag&bracket </][tag div][tag&bracket >]\");\n\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/meta.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  CodeMirror.modeInfo = [\n    {name: \"APL\", mime: \"text/apl\", mode: \"apl\", ext: [\"dyalog\", \"apl\"]},\n    {name: \"Asterisk\", mime: \"text/x-asterisk\", mode: \"asterisk\", file: /^extensions\\.conf$/i},\n    {name: \"C\", mime: \"text/x-csrc\", mode: \"clike\", ext: [\"c\", \"h\"]},\n    {name: \"C++\", mime: \"text/x-c++src\", mode: \"clike\", ext: [\"cpp\", \"c++\", \"cc\", \"cxx\", \"hpp\", \"h++\", \"hh\", \"hxx\"], alias: [\"cpp\"]},\n    {name: \"Cobol\", mime: \"text/x-cobol\", mode: \"cobol\", ext: [\"cob\", \"cpy\"]},\n    {name: \"C#\", mime: \"text/x-csharp\", mode: \"clike\", ext: [\"cs\"], alias: [\"csharp\"]},\n    {name: \"Clojure\", mime: \"text/x-clojure\", mode: \"clojure\", ext: [\"clj\"]},\n    {name: \"CoffeeScript\", mime: \"text/x-coffeescript\", mode: \"coffeescript\", ext: [\"coffee\"], alias: [\"coffee\", \"coffee-script\"]},\n    {name: \"Common Lisp\", mime: \"text/x-common-lisp\", mode: \"commonlisp\", ext: [\"cl\", \"lisp\", \"el\"], alias: [\"lisp\"]},\n    {name: \"Cypher\", mime: \"application/x-cypher-query\", mode: \"cypher\", ext: [\"cyp\", \"cypher\"]},\n    {name: \"Cython\", mime: \"text/x-cython\", mode: \"python\", ext: [\"pyx\", \"pxd\", \"pxi\"]},\n    {name: \"CSS\", mime: \"text/css\", mode: \"css\", ext: [\"css\"]},\n    {name: \"CQL\", mime: \"text/x-cassandra\", mode: \"sql\", ext: [\"cql\"]},\n    {name: \"D\", mime: \"text/x-d\", mode: \"d\", ext: [\"d\"]},\n    {name: \"Dart\", mimes: [\"application/dart\", \"text/x-dart\"], mode: \"dart\", ext: [\"dart\"]},\n    {name: \"diff\", mime: \"text/x-diff\", mode: \"diff\", ext: [\"diff\", \"patch\"]},\n    {name: \"Django\", mime: \"text/x-django\", mode: \"django\"},\n    {name: \"Dockerfile\", mime: \"text/x-dockerfile\", mode: \"dockerfile\", file: /^Dockerfile$/},\n    {name: \"DTD\", mime: \"application/xml-dtd\", mode: \"dtd\", ext: [\"dtd\"]},\n    {name: \"Dylan\", mime: \"text/x-dylan\", mode: \"dylan\", ext: [\"dylan\", \"dyl\", \"intr\"]},\n    {name: \"EBNF\", mime: \"text/x-ebnf\", mode: \"ebnf\"},\n    {name: \"ECL\", mime: \"text/x-ecl\", mode: \"ecl\", ext: [\"ecl\"]},\n    {name: \"Eiffel\", mime: \"text/x-eiffel\", mode: \"eiffel\", ext: [\"e\"]},\n    {name: \"Embedded Javascript\", mime: \"application/x-ejs\", mode: \"htmlembedded\", ext: [\"ejs\"]},\n    {name: \"Embedded Ruby\", mime: \"application/x-erb\", mode: \"htmlembedded\", ext: [\"erb\"]},\n    {name: \"Erlang\", mime: \"text/x-erlang\", mode: \"erlang\", ext: [\"erl\"]},\n    {name: \"Fortran\", mime: \"text/x-fortran\", mode: \"fortran\", ext: [\"f\", \"for\", \"f77\", \"f90\"]},\n    {name: \"F#\", mime: \"text/x-fsharp\", mode: \"mllike\", ext: [\"fs\"], alias: [\"fsharp\"]},\n    {name: \"Gas\", mime: \"text/x-gas\", mode: \"gas\", ext: [\"s\"]},\n    {name: \"Gherkin\", mime: \"text/x-feature\", mode: \"gherkin\", ext: [\"feature\"]},\n    {name: \"GitHub Flavored Markdown\", mime: \"text/x-gfm\", mode: \"gfm\", file: /^(readme|contributing|history).md$/i},\n    {name: \"Go\", mime: \"text/x-go\", mode: \"go\", ext: [\"go\"]},\n    {name: \"Groovy\", mime: \"text/x-groovy\", mode: \"groovy\", ext: [\"groovy\"]},\n    {name: \"HAML\", mime: \"text/x-haml\", mode: \"haml\", ext: [\"haml\"]},\n    {name: \"Haskell\", mime: \"text/x-haskell\", mode: \"haskell\", ext: [\"hs\"]},\n    {name: \"Haxe\", mime: \"text/x-haxe\", mode: \"haxe\", ext: [\"hx\"]},\n    {name: \"HXML\", mime: \"text/x-hxml\", mode: \"haxe\", ext: [\"hxml\"]},\n    {name: \"ASP.NET\", mime: \"application/x-aspx\", mode: \"htmlembedded\", ext: [\"aspx\"], alias: [\"asp\", \"aspx\"]},\n    {name: \"HTML\", mime: \"text/html\", mode: \"htmlmixed\", ext: [\"html\", \"htm\"], alias: [\"xhtml\"]},\n    {name: \"HTTP\", mime: \"message/http\", mode: \"http\"},\n    {name: \"IDL\", mime: \"text/x-idl\", mode: \"idl\", ext: [\"pro\"]},\n    {name: \"Jade\", mime: \"text/x-jade\", mode: \"jade\", ext: [\"jade\"]},\n    {name: \"Java\", mime: \"text/x-java\", mode: \"clike\", ext: [\"java\"]},\n    {name: \"Java Server Pages\", mime: \"application/x-jsp\", mode: \"htmlembedded\", ext: [\"jsp\"], alias: [\"jsp\"]},\n    {name: \"JavaScript\", mimes: [\"text/javascript\", \"text/ecmascript\", \"application/javascript\", \"application/x-javascript\", \"application/ecmascript\"],\n     mode: \"javascript\", ext: [\"js\"], alias: [\"ecmascript\", \"js\", \"node\"]},\n    {name: \"JSON\", mimes: [\"application/json\", \"application/x-json\"], mode: \"javascript\", ext: [\"json\", \"map\"], alias: [\"json5\"]},\n    {name: \"JSON-LD\", mime: \"application/ld+json\", mode: \"javascript\", ext: [\"jsonld\"], alias: [\"jsonld\"]},\n    {name: \"Jinja2\", mime: \"null\", mode: \"jinja2\"},\n    {name: \"Julia\", mime: \"text/x-julia\", mode: \"julia\", ext: [\"jl\"]},\n    {name: \"Kotlin\", mime: \"text/x-kotlin\", mode: \"kotlin\", ext: [\"kt\"]},\n    {name: \"LESS\", mime: \"text/x-less\", mode: \"css\", ext: [\"less\"]},\n    {name: \"LiveScript\", mime: \"text/x-livescript\", mode: \"livescript\", ext: [\"ls\"], alias: [\"ls\"]},\n    {name: \"Lua\", mime: \"text/x-lua\", mode: \"lua\", ext: [\"lua\"]},\n    {name: \"Markdown\", mime: \"text/x-markdown\", mode: \"markdown\", ext: [\"markdown\", \"md\", \"mkd\"]},\n    {name: \"mIRC\", mime: \"text/mirc\", mode: \"mirc\"},\n    {name: \"MariaDB SQL\", mime: \"text/x-mariadb\", mode: \"sql\"},\n    {name: \"Modelica\", mime: \"text/x-modelica\", mode: \"modelica\", ext: [\"mo\"]},\n    {name: \"MS SQL\", mime: \"text/x-mssql\", mode: \"sql\"},\n    {name: \"MySQL\", mime: \"text/x-mysql\", mode: \"sql\"},\n    {name: \"Nginx\", mime: \"text/x-nginx-conf\", mode: \"nginx\", file: /nginx.*\\.conf$/i},\n    {name: \"NTriples\", mime: \"text/n-triples\", mode: \"ntriples\", ext: [\"nt\"]},\n    {name: \"Objective C\", mime: \"text/x-objectivec\", mode: \"clike\", ext: [\"m\", \"mm\"]},\n    {name: \"OCaml\", mime: \"text/x-ocaml\", mode: \"mllike\", ext: [\"ml\", \"mli\", \"mll\", \"mly\"]},\n    {name: \"Octave\", mime: \"text/x-octave\", mode: \"octave\", ext: [\"m\"]},\n    {name: \"Pascal\", mime: \"text/x-pascal\", mode: \"pascal\", ext: [\"p\", \"pas\"]},\n    {name: \"PEG.js\", mime: \"null\", mode: \"pegjs\", ext: [\"jsonld\"]},\n    {name: \"Perl\", mime: \"text/x-perl\", mode: \"perl\", ext: [\"pl\", \"pm\"]},\n    {name: \"PHP\", mime: \"application/x-httpd-php\", mode: \"php\", ext: [\"php\", \"php3\", \"php4\", \"php5\", \"phtml\"]},\n    {name: \"Pig\", mime: \"text/x-pig\", mode: \"pig\", ext: [\"pig\"]},\n    {name: \"Plain Text\", mime: \"text/plain\", mode: \"null\", ext: [\"txt\", \"text\", \"conf\", \"def\", \"list\", \"log\"]},\n    {name: \"PLSQL\", mime: \"text/x-plsql\", mode: \"sql\", ext: [\"pls\"]},\n    {name: \"Properties files\", mime: \"text/x-properties\", mode: \"properties\", ext: [\"properties\", \"ini\", \"in\"], alias: [\"ini\", \"properties\"]},\n    {name: \"Python\", mime: \"text/x-python\", mode: \"python\", ext: [\"py\", \"pyw\"]},\n    {name: \"Puppet\", mime: \"text/x-puppet\", mode: \"puppet\", ext: [\"pp\"]},\n    {name: \"Q\", mime: \"text/x-q\", mode: \"q\", ext: [\"q\"]},\n    {name: \"R\", mime: \"text/x-rsrc\", mode: \"r\", ext: [\"r\"], alias: [\"rscript\"]},\n    {name: \"reStructuredText\", mime: \"text/x-rst\", mode: \"rst\", ext: [\"rst\"], alias: [\"rst\"]},\n    {name: \"RPM Changes\", mime: \"text/x-rpm-changes\", mode: \"rpm\"},\n    {name: \"RPM Spec\", mime: \"text/x-rpm-spec\", mode: \"rpm\", ext: [\"spec\"]},\n    {name: \"Ruby\", mime: \"text/x-ruby\", mode: \"ruby\", ext: [\"rb\"], alias: [\"jruby\", \"macruby\", \"rake\", \"rb\", \"rbx\"]},\n    {name: \"Rust\", mime: \"text/x-rustsrc\", mode: \"rust\", ext: [\"rs\"]},\n    {name: \"Sass\", mime: \"text/x-sass\", mode: \"sass\", ext: [\"sass\"]},\n    {name: \"Scala\", mime: \"text/x-scala\", mode: \"clike\", ext: [\"scala\"]},\n    {name: \"Scheme\", mime: \"text/x-scheme\", mode: \"scheme\", ext: [\"scm\", \"ss\"]},\n    {name: \"SCSS\", mime: \"text/x-scss\", mode: \"css\", ext: [\"scss\"]},\n    {name: \"Shell\", mime: \"text/x-sh\", mode: \"shell\", ext: [\"sh\", \"ksh\", \"bash\"], alias: [\"bash\", \"sh\", \"zsh\"]},\n    {name: \"Sieve\", mime: \"application/sieve\", mode: \"sieve\", ext: [\"siv\", \"sieve\"]},\n    {name: \"Slim\", mimes: [\"text/x-slim\", \"application/x-slim\"], mode: \"slim\", ext: [\"slim\"]},\n    {name: \"Smalltalk\", mime: \"text/x-stsrc\", mode: \"smalltalk\", ext: [\"st\"]},\n    {name: \"Smarty\", mime: \"text/x-smarty\", mode: \"smarty\", ext: [\"tpl\"]},\n    {name: \"SmartyMixed\", mime: \"text/x-smarty\", mode: \"smartymixed\"},\n    {name: \"Solr\", mime: \"text/x-solr\", mode: \"solr\"},\n    {name: \"Soy\", mime: \"text/x-soy\", mode: \"soy\", ext: [\"soy\"], alias: [\"closure template\"]},\n    {name: \"SPARQL\", mime: \"application/sparql-query\", mode: \"sparql\", ext: [\"rq\", \"sparql\"], alias: [\"sparul\"]},\n    {name: \"Spreadsheet\", mime: \"text/x-spreadsheet\", mode: \"spreadsheet\", alias: [\"excel\", \"formula\"]},\n    {name: \"SQL\", mime: \"text/x-sql\", mode: \"sql\", ext: [\"sql\"]},\n    {name: \"MariaDB\", mime: \"text/x-mariadb\", mode: \"sql\"},\n    {name: \"sTeX\", mime: \"text/x-stex\", mode: \"stex\"},\n    {name: \"LaTeX\", mime: \"text/x-latex\", mode: \"stex\", ext: [\"text\", \"ltx\"], alias: [\"tex\"]},\n    {name: \"SystemVerilog\", mime: \"text/x-systemverilog\", mode: \"verilog\", ext: [\"v\"]},\n    {name: \"Tcl\", mime: \"text/x-tcl\", mode: \"tcl\", ext: [\"tcl\"]},\n    {name: \"Textile\", mime: \"text/x-textile\", mode: \"textile\", ext: [\"textile\"]},\n    {name: \"TiddlyWiki \", mime: \"text/x-tiddlywiki\", mode: \"tiddlywiki\"},\n    {name: \"Tiki wiki\", mime: \"text/tiki\", mode: \"tiki\"},\n    {name: \"TOML\", mime: \"text/x-toml\", mode: \"toml\", ext: [\"toml\"]},\n    {name: \"Tornado\", mime: \"text/x-tornado\", mode: \"tornado\"},\n    {name: \"Turtle\", mime: \"text/turtle\", mode: \"turtle\", ext: [\"ttl\"]},\n    {name: \"TypeScript\", mime: \"application/typescript\", mode: \"javascript\", ext: [\"ts\"], alias: [\"ts\"]},\n    {name: \"VB.NET\", mime: \"text/x-vb\", mode: \"vb\", ext: [\"vb\"]},\n    {name: \"VBScript\", mime: \"text/vbscript\", mode: \"vbscript\", ext: [\"vbs\"]},\n    {name: \"Velocity\", mime: \"text/velocity\", mode: \"velocity\", ext: [\"vtl\"]},\n    {name: \"Verilog\", mime: \"text/x-verilog\", mode: \"verilog\", ext: [\"v\"]},\n    {name: \"XML\", mimes: [\"application/xml\", \"text/xml\"], mode: \"xml\", ext: [\"xml\", \"xsl\", \"xsd\"], alias: [\"rss\", \"wsdl\", \"xsd\"]},\n    {name: \"XQuery\", mime: \"application/xquery\", mode: \"xquery\", ext: [\"xy\", \"xquery\"]},\n    {name: \"YAML\", mime: \"text/x-yaml\", mode: \"yaml\", ext: [\"yaml\"], alias: [\"yml\"]},\n    {name: \"Z80\", mime: \"text/x-z80\", mode: \"z80\", ext: [\"z80\"]}\n  ];\n  // Ensure all modes have a mime property for backwards compatibility\n  for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n    var info = CodeMirror.modeInfo[i];\n    if (info.mimes) info.mime = info.mimes[0];\n  }\n\n  CodeMirror.findModeByMIME = function(mime) {\n    mime = mime.toLowerCase();\n    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n      var info = CodeMirror.modeInfo[i];\n      if (info.mime == mime) return info;\n      if (info.mimes) for (var j = 0; j < info.mimes.length; j++)\n        if (info.mimes[j] == mime) return info;\n    }\n  };\n\n  CodeMirror.findModeByExtension = function(ext) {\n    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n      var info = CodeMirror.modeInfo[i];\n      if (info.ext) for (var j = 0; j < info.ext.length; j++)\n        if (info.ext[j] == ext) return info;\n    }\n  };\n\n  CodeMirror.findModeByFileName = function(filename) {\n    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n      var info = CodeMirror.modeInfo[i];\n      if (info.file && info.file.test(filename)) return info;\n    }\n    var dot = filename.lastIndexOf(\".\");\n    var ext = dot > -1 && filename.substring(dot + 1, filename.length);\n    if (ext) return CodeMirror.findModeByExtension(ext);\n  };\n\n  CodeMirror.findModeByName = function(name) {\n    name = name.toLowerCase();\n    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n      var info = CodeMirror.modeInfo[i];\n      if (info.name.toLowerCase() == name) return info;\n      if (info.alias) for (var j = 0; j < info.alias.length; j++)\n        if (info.alias[j].toLowerCase() == name) return info;\n    }\n  };\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/mirc/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: mIRC mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/twilight.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"mirc.js\"></script>\n<style>.CodeMirror {border: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">mIRC</a>\n  </ul>\n</div>\n\n<article>\n<h2>mIRC mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n;AKA Nick Tracker by Ford_Lawnmower irc.GeekShed.net #Script-Help\n;*****************************************************************************;\n;**Start Setup\n;Change JoinDisplay, below, for On Join AKA Display. On = 1 - Off = 0\nalias -l JoinDisplay { return 1 }\n;Change MaxNicks, below, to the number of nicknames you want to store for each hostmask. I wouldn't go over 400 with this ;/\nalias -l MaxNicks { return 20 }\n;Change AKALogo, below, To the text you want displayed before each AKA result.\nalias -l AKALogo { return \u000306\u0007 \u000305A\u000306K\u000307A \u000306\u0007 }\n;**End Setup\n;*****************************************************************************;\nOn *:Join:#: {\n  if ($nick == $me) { .timer 1 1 ialupdateCheck $chan }\n  NickNamesAdd $nick $+($network,$wildsite)\n  if ($JoinDisplay) { .timerNickNames $+ $nick 1 2 NickNames.display $nick $chan $network $wildsite }\n}\non *:Nick: { NickNamesAdd $newnick $+($network,$wildsite) $nick }\nalias -l NickNames.display {\n  if ($gettok($hget(NickNames,$+($3,$4)),0,126) > 1) {\n    echo -g $2 $AKALogo $+(\u000309,$1) $AKALogo \u000307 $mid($replace($hget(NickNames,$+($3,$4)),$chr(126),$chr(44)),2,-1)\n  }\n}\nalias -l NickNamesAdd {\n  if ($hget(NickNames,$2)) {\n    if (!$regex($hget(NickNames,$2),/~\\Q $+ $replacecs($1,\\E,\\E\\\\E\\Q) $+ \\E~/i)) {\n      if ($gettok($hget(NickNames,$2),0,126) <= $MaxNicks) {\n        hadd NickNames $2 $+($hget(NickNames,$2),$1,~)\n      }\n      else {\n        hadd NickNames $2 $+($mid($hget(NickNames,$2),$pos($hget(NickNames,$2),~,2)),$1,~)\n      }\n    }\n  }\n  else {\n    hadd -m NickNames $2 $+(~,$1,~,$iif($3,$+($3,~)))\n  }\n}\nalias -l Fix.All.MindUser {\n  var %Fix.Count = $hfind(NickNames,/[^~]+[0-9]{4}~/,0,r).data\n  while (%Fix.Count) {\n    if ($Fix.MindUser($hget(NickNames,$hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data))) {\n      echo -ag Record %Fix.Count - $v1 - Was Cleaned\n      hadd NickNames $hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data $v1\n    }\n    dec %Fix.Count\n  }\n}\nalias -l Fix.MindUser { return $regsubex($1,/[^~]+[0-9]{4}~/g,$null) }\nmenu nicklist,query {\n  -\n  .AKA\n  ..Check $$1: {\n    if ($gettok($hget(NickNames,$+($network,$address($1,2))),0,126) > 1) {\n      NickNames.display $1 $active $network $address($1,2)\n    }\n    else { echo -ag $AKALogo $+(\u000309,$1) \u000307has not been known by any other nicknames while I have been watching. }\n  }\n  ..Cleanup $$1:hadd NickNames $+($network,$address($1,2)) $fix.minduser($hget(NickNames,$+($network,$address($1,2))))\n  ..Clear $$1:hadd NickNames $+($network,$address($1,2)) $+(~,$1,~)\n  ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search\n  -\n}\nmenu status,channel {\n  -\n  .AKA\n  ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search\n  ..Clean All Records:Fix.All.Minduser\n  -\n}\ndialog AKA_Search {\n  title \"AKA Search Engine\"\n  size -1 -1 206 221\n  option dbu\n  edit \"\", 1, 8 5 149 10, autohs\n  button \"Search\", 2, 163 4 32 12\n  radio \"Search HostMask\", 4, 61 22 55 10\n  radio \"Search Nicknames\", 5, 123 22 56 10\n  list 6, 8 38 190 169, sort extsel vsbar\n  button \"Check Selected\", 7, 67 206 40 12\n  button \"Close\", 8, 160 206 38 12, cancel\n  box \"Search Type\", 3, 11 17 183 18\n  button \"Copy to Clipboard\", 9, 111 206 46 12\n}\nOn *:Dialog:Aka_Search:init:*: { did -c $dname 5 }\nOn *:Dialog:Aka_Search:Sclick:2,7,9: {\n  if ($did == 2) && ($did($dname,1)) {\n    did -r $dname 6\n    var %search $+(*,$v1,*), %type $iif($did($dname,5).state,data,item), %matches = $hfind(NickNames,%search,0,w). [ $+ [ %type ] ]\n    while (%matches) {\n      did -a $dname 6 $hfind(NickNames,%search,%matches,w). [ $+ [ %type ] ]\n      dec %matches\n    }\n    did -c $dname 6 1\n  }\n  elseif ($did == 7) && ($did($dname,6).seltext) { echo -ga $AKALogo \u000307 $mid($replace($hget(NickNames,$v1),$chr(126),$chr(44)),2,-1) }\n  elseif ($did == 9) && ($did($dname,6).seltext) { clipboard $mid($v1,$pos($v1,*,1)) }\n}\nOn *:Start:{\n  if (!$hget(NickNames)) { hmake NickNames 10 }\n  if ($isfile(NickNames.hsh)) { hload  NickNames NickNames.hsh }\n}\nOn *:Exit: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }\nOn *:Disconnect: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }\nOn *:Unload: { hfree NickNames }\nalias -l ialupdateCheck {\n  inc -z $+(%,ialupdateCheck,$network) $calc($nick($1,0) / 4)\n  ;If your ial is already being updated on join .who $1 out.\n  ;If you are using /names to update ial you will still need this line.\n  .who $1\n}\nRaw 352:*: {\n  if ($($+(%,ialupdateCheck,$network),2)) haltdef\n  NickNamesAdd $6 $+($network,$address($6,2))\n}\nRaw 315:*: {\n  if ($($+(%,ialupdateCheck,$network),2)) haltdef\n}\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"twilight\",\n        lineNumbers: true,\n        matchBrackets: true,\n        indentUnit: 4,\n        mode: \"text/mirc\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/mirc</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/mirc/mirc.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n//mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara\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.defineMIME(\"text/mirc\", \"mirc\");\nCodeMirror.defineMode(\"mirc\", function() {\n  function parseWords(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  var specials = parseWords(\"$! $$ $& $? $+ $abook $abs $active $activecid \" +\n                            \"$activewid $address $addtok $agent $agentname $agentstat $agentver \" +\n                            \"$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime \" +\n                            \"$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind \" +\n                            \"$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes \" +\n                            \"$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color \" +\n                            \"$com $comcall $comchan $comerr $compact $compress $comval $cos $count \" +\n                            \"$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight \" +\n                            \"$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress \" +\n                            \"$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll \" +\n                            \"$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error \" +\n                            \"$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir \" +\n                            \"$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve \" +\n                            \"$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt \" +\n                            \"$group $halted $hash $height $hfind $hget $highlight $hnick $hotline \" +\n                            \"$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil \" +\n                            \"$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect \" +\n                            \"$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile \" +\n                            \"$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive \" +\n                            \"$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock \" +\n                            \"$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer \" +\n                            \"$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext \" +\n                            \"$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode \" +\n                            \"$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile \" +\n                            \"$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly \" +\n                            \"$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree \" +\n                            \"$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo \" +\n                            \"$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex \" +\n                            \"$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline \" +\n                            \"$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin \" +\n                            \"$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname \" +\n                            \"$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped \" +\n                            \"$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp \" +\n                            \"$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel \" +\n                            \"$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver \" +\n                            \"$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor\");\n  var keywords = parseWords(\"abook ajinvite alias aline ame amsg anick aop auser autojoin avoice \" +\n                            \"away background ban bcopy beep bread break breplace bset btrunc bunset bwrite \" +\n                            \"channel clear clearall cline clipboard close cnick color comclose comopen \" +\n                            \"comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver \" +\n                            \"debug dec describe dialog did didtok disable disconnect dlevel dline dll \" +\n                            \"dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace \" +\n                            \"drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable \" +\n                            \"events exit fclose filter findtext finger firewall flash flist flood flush \" +\n                            \"flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove \" +\n                            \"gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd \" +\n                            \"halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear \" +\n                            \"ialmark identd if ignore iline inc invite iuser join kick linesep links list \" +\n                            \"load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice \" +\n                            \"notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice \" +\n                            \"qme qmsg query queryn quit raw reload remini remote remove rename renwin \" +\n                            \"reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini \" +\n                            \"say scid scon server set showmirc signam sline sockaccept sockclose socklist \" +\n                            \"socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite \" +\n                            \"sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize \" +\n                            \"toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho \" +\n                            \"var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum \" +\n                            \"isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower \" +\n                            \"isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs \" +\n                            \"elseif else goto menu nicklist status title icon size option text edit \" +\n                            \"button check radio box scroll list combo link tab item\");\n  var functions = parseWords(\"if elseif else and not or eq ne in ni for foreach while switch\");\n  var isOperatorChar = /[+\\-*&%=<>!?^\\/\\|]/;\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n  function tokenBase(stream, state) {\n    var beforeParams = state.beforeParams;\n    state.beforeParams = false;\n    var ch = stream.next();\n    if (/[\\[\\]{}\\(\\),\\.]/.test(ch)) {\n      if (ch == \"(\" && beforeParams) state.inParams = true;\n      else if (ch == \")\") state.inParams = false;\n      return null;\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    else if (ch == \"\\\\\") {\n      stream.eat(\"\\\\\");\n      stream.eat(/./);\n      return \"number\";\n    }\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      return chain(stream, state, tokenComment);\n    }\n    else if (ch == \";\" && stream.match(/ *\\( *\\(/)) {\n      return chain(stream, state, tokenUnparsed);\n    }\n    else if (ch == \";\" && !state.inParams) {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    else if (ch == '\"') {\n      stream.eat(/\"/);\n      return \"keyword\";\n    }\n    else if (ch == \"$\") {\n      stream.eatWhile(/[$_a-z0-9A-Z\\.:]/);\n      if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {\n        return \"keyword\";\n      }\n      else {\n        state.beforeParams = true;\n        return \"builtin\";\n      }\n    }\n    else if (ch == \"%\") {\n      stream.eatWhile(/[^,^\\s^\\(^\\)]/);\n      state.beforeParams = true;\n      return \"string\";\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_{}]/);\n      var word = stream.current().toLowerCase();\n      if (keywords && keywords.propertyIsEnumerable(word))\n        return \"keyword\";\n      if (functions && functions.propertyIsEnumerable(word)) {\n        state.beforeParams = true;\n        return \"keyword\";\n      }\n      return null;\n    }\n  }\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n  function tokenUnparsed(stream, state) {\n    var maybeEnd = 0, ch;\n    while (ch = stream.next()) {\n      if (ch == \";\" && maybeEnd == 2) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      if (ch == \")\")\n        maybeEnd++;\n      else if (ch != \" \")\n        maybeEnd = 0;\n    }\n    return \"meta\";\n  }\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        beforeParams: false,\n        inParams: false\n      };\n    },\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      return state.tokenize(stream, state);\n    }\n  };\n});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/mllike/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: ML-like mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=stylesheet href=../../lib/codemirror.css>\n<script src=../../lib/codemirror.js></script>\n<script src=../../addon/edit/matchbrackets.js></script>\n<script src=mllike.js></script>\n<style type=text/css>\n  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">ML-like</a>\n  </ul>\n</div>\n\n<article>\n<h2>OCaml mode</h2>\n\n\n<textarea id=\"ocamlCode\">\n(* Summing a list of integers *)\nlet rec sum xs =\n  match xs with\n    | []       -&gt; 0\n    | x :: xs' -&gt; x + sum xs'\n\n(* Quicksort *)\nlet rec qsort = function\n   | [] -&gt; []\n   | pivot :: rest -&gt;\n       let is_less x = x &lt; pivot in\n       let left, right = List.partition is_less rest in\n       qsort left @ [pivot] @ qsort right\n\n(* Fibonacci Sequence *)\nlet rec fib_aux n a b =\n  match n with\n  | 0 -&gt; a\n  | _ -&gt; fib_aux (n - 1) (a + b) a\nlet fib n = fib_aux n 0 1\n\n(* Birthday paradox *)\nlet year_size = 365.\n\nlet rec birthday_paradox prob people =\n    let prob' = (year_size -. float people) /. year_size *. prob  in\n    if prob' &lt; 0.5 then\n        Printf.printf \"answer = %d\\n\" (people+1)\n    else\n        birthday_paradox prob' (people+1) ;;\n\nbirthday_paradox 1.0 1\n\n(* Church numerals *)\nlet zero f x = x\nlet succ n f x = f (n f x)\nlet one = succ zero\nlet two = succ (succ zero)\nlet add n1 n2 f x = n1 f (n2 f x)\nlet to_string n = n (fun k -&gt; \"S\" ^ k) \"0\"\nlet _ = to_string (add (succ two) two)\n\n(* Elementary functions *)\nlet square x = x * x;;\nlet rec fact x =\n  if x &lt;= 1 then 1 else x * fact (x - 1);;\n\n(* Automatic memory management *)\nlet l = 1 :: 2 :: 3 :: [];;\n[1; 2; 3];;\n5 :: l;;\n\n(* Polymorphism: sorting lists *)\nlet rec sort = function\n  | [] -&gt; []\n  | x :: l -&gt; insert x (sort l)\n\nand insert elem = function\n  | [] -&gt; [elem]\n  | x :: l -&gt;\n      if elem &lt; x then elem :: x :: l else x :: insert elem l;;\n\n(* Imperative features *)\nlet add_polynom p1 p2 =\n  let n1 = Array.length p1\n  and n2 = Array.length p2 in\n  let result = Array.create (max n1 n2) 0 in\n  for i = 0 to n1 - 1 do result.(i) &lt;- p1.(i) done;\n  for i = 0 to n2 - 1 do result.(i) &lt;- result.(i) + p2.(i) done;\n  result;;\nadd_polynom [| 1; 2 |] [| 1; 2; 3 |];;\n\n(* We may redefine fact using a reference cell and a for loop *)\nlet fact n =\n  let result = ref 1 in\n  for i = 2 to n do\n    result := i * !result\n   done;\n   !result;;\nfact 5;;\n\n(* Triangle (graphics) *)\nlet () =\n  ignore( Glut.init Sys.argv );\n  Glut.initDisplayMode ~double_buffer:true ();\n  ignore (Glut.createWindow ~title:\"OpenGL Demo\");\n  let angle t = 10. *. t *. t in\n  let render () =\n    GlClear.clear [ `color ];\n    GlMat.load_identity ();\n    GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();\n    GlDraw.begins `triangles;\n    List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];\n    GlDraw.ends ();\n    Glut.swapBuffers () in\n  GlMat.mode `modelview;\n  Glut.displayFunc ~cb:render;\n  Glut.idleFunc ~cb:(Some Glut.postRedisplay);\n  Glut.mainLoop ()\n\n(* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *)\n(* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)\n</textarea>\n\n<h2>F# mode</h2>\n<textarea id=\"fsharpCode\">\nmodule CodeMirror.FSharp\n\nlet rec fib = function\n    | 0 -> 0\n    | 1 -> 1\n    | n -> fib (n - 1) + fib (n - 2)\n\ntype Point =\n    {\n        x : int\n        y : int\n    }\n\ntype Color =\n    | Red\n    | Green\n    | Blue\n\n[0 .. 10]\n|> List.map ((+) 2)\n|> List.fold (fun x y -> x + y) 0\n|> printf \"%i\"\n</textarea>\n\n\n<script>\n  var ocamlEditor = CodeMirror.fromTextArea(document.getElementById('ocamlCode'), {\n    mode: 'text/x-ocaml',\n    lineNumbers: true,\n    matchBrackets: true\n  });\n\n  var fsharpEditor = CodeMirror.fromTextArea(document.getElementById('fsharpCode'), {\n    mode: 'text/x-fsharp',\n    lineNumbers: true,\n    matchBrackets: true\n  });\n</script>\n\n<p><strong>MIME types defined:</strong> <code>text/x-ocaml</code> (OCaml) and <code>text/x-fsharp</code> (F#).</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/mllike/mllike.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('mllike', function(_config, parserConfig) {\n  var words = {\n    'let': 'keyword',\n    'rec': 'keyword',\n    'in': 'keyword',\n    'of': 'keyword',\n    'and': 'keyword',\n    'if': 'keyword',\n    'then': 'keyword',\n    'else': 'keyword',\n    'for': 'keyword',\n    'to': 'keyword',\n    'while': 'keyword',\n    'do': 'keyword',\n    'done': 'keyword',\n    'fun': 'keyword',\n    'function': 'keyword',\n    'val': 'keyword',\n    'type': 'keyword',\n    'mutable': 'keyword',\n    'match': 'keyword',\n    'with': 'keyword',\n    'try': 'keyword',\n    'open': 'builtin',\n    'ignore': 'builtin',\n    'begin': 'keyword',\n    'end': 'keyword'\n  };\n\n  var extraWords = parserConfig.extraWords || {};\n  for (var prop in extraWords) {\n    if (extraWords.hasOwnProperty(prop)) {\n      words[prop] = parserConfig.extraWords[prop];\n    }\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n    if (ch === '\"') {\n      state.tokenize = tokenString;\n      return state.tokenize(stream, state);\n    }\n    if (ch === '(') {\n      if (stream.eat('*')) {\n        state.commentLevel++;\n        state.tokenize = tokenComment;\n        return state.tokenize(stream, state);\n      }\n    }\n    if (ch === '~') {\n      stream.eatWhile(/\\w/);\n      return 'variable-2';\n    }\n    if (ch === '`') {\n      stream.eatWhile(/\\w/);\n      return 'quote';\n    }\n    if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {\n      stream.skipToEnd();\n      return 'comment';\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\d]/);\n      if (stream.eat('.')) {\n        stream.eatWhile(/[\\d]/);\n      }\n      return 'number';\n    }\n    if ( /[+\\-*&%=<>!?|]/.test(ch)) {\n      return 'operator';\n    }\n    stream.eatWhile(/\\w/);\n    var cur = stream.current();\n    return words[cur] || 'variable';\n  }\n\n  function tokenString(stream, state) {\n    var next, end = false, escaped = false;\n    while ((next = stream.next()) != null) {\n      if (next === '\"' && !escaped) {\n        end = true;\n        break;\n      }\n      escaped = !escaped && next === '\\\\';\n    }\n    if (end && !escaped) {\n      state.tokenize = tokenBase;\n    }\n    return 'string';\n  };\n\n  function tokenComment(stream, state) {\n    var prev, next;\n    while(state.commentLevel > 0 && (next = stream.next()) != null) {\n      if (prev === '(' && next === '*') state.commentLevel++;\n      if (prev === '*' && next === ')') state.commentLevel--;\n      prev = next;\n    }\n    if (state.commentLevel <= 0) {\n      state.tokenize = tokenBase;\n    }\n    return 'comment';\n  }\n\n  return {\n    startState: function() {return {tokenize: tokenBase, commentLevel: 0};},\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      return state.tokenize(stream, state);\n    },\n\n    blockCommentStart: \"(*\",\n    blockCommentEnd: \"*)\",\n    lineComment: parserConfig.slashComments ? \"//\" : null\n  };\n});\n\nCodeMirror.defineMIME('text/x-ocaml', {\n  name: 'mllike',\n  extraWords: {\n    'succ': 'keyword',\n    'trace': 'builtin',\n    'exit': 'builtin',\n    'print_string': 'builtin',\n    'print_endline': 'builtin',\n    'true': 'atom',\n    'false': 'atom',\n    'raise': 'keyword'\n  }\n});\n\nCodeMirror.defineMIME('text/x-fsharp', {\n  name: 'mllike',\n  extraWords: {\n    'abstract': 'keyword',\n    'as': 'keyword',\n    'assert': 'keyword',\n    'base': 'keyword',\n    'class': 'keyword',\n    'default': 'keyword',\n    'delegate': 'keyword',\n    'downcast': 'keyword',\n    'downto': 'keyword',\n    'elif': 'keyword',\n    'exception': 'keyword',\n    'extern': 'keyword',\n    'finally': 'keyword',\n    'global': 'keyword',\n    'inherit': 'keyword',\n    'inline': 'keyword',\n    'interface': 'keyword',\n    'internal': 'keyword',\n    'lazy': 'keyword',\n    'let!': 'keyword',\n    'member' : 'keyword',\n    'module': 'keyword',\n    'namespace': 'keyword',\n    'new': 'keyword',\n    'null': 'keyword',\n    'override': 'keyword',\n    'private': 'keyword',\n    'public': 'keyword',\n    'return': 'keyword',\n    'return!': 'keyword',\n    'select': 'keyword',\n    'static': 'keyword',\n    'struct': 'keyword',\n    'upcast': 'keyword',\n    'use': 'keyword',\n    'use!': 'keyword',\n    'val': 'keyword',\n    'when': 'keyword',\n    'yield': 'keyword',\n    'yield!': 'keyword',\n\n    'List': 'builtin',\n    'Seq': 'builtin',\n    'Map': 'builtin',\n    'Set': 'builtin',\n    'int': 'builtin',\n    'string': 'builtin',\n    'raise': 'builtin',\n    'failwith': 'builtin',\n    'not': 'builtin',\n    'true': 'builtin',\n    'false': 'builtin'\n  },\n  slashComments: true\n});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/modelica/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Modelica mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<link rel=\"stylesheet\" href=\"../../addon/hint/show-hint.css\">\n<script src=\"../../addon/hint/show-hint.js\"></script>\n<script src=\"modelica.js\"></script>\n<style>.CodeMirror {border: 2px inset #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Modelica</a>\n  </ul>\n</div>\n\n<article>\n<h2>Modelica mode</h2>\n\n<div><textarea id=\"modelica\">\nmodel BouncingBall\n  parameter Real e = 0.7;\n  parameter Real g = 9.81;\n  Real h(start=1);\n  Real v;\n  Boolean flying(start=true);\n  Boolean impact;\n  Real v_new;\nequation\n  impact = h <= 0.0;\n  der(v) = if flying then -g else 0;\n  der(h) = v;\n  when {h <= 0.0 and v <= 0.0, impact} then\n    v_new = if edge(impact) then -e*pre(v) else 0;\n    flying = v_new > 0;\n    reinit(v, v_new);\n  end when;\n  annotation (uses(Modelica(version=\"3.2\")));\nend BouncingBall;\n</textarea></div>\n\n    <script>\n      var modelicaEditor = CodeMirror.fromTextArea(document.getElementById(\"modelica\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-modelica\"\n      });\n      var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;\n      CodeMirror.keyMap.default[(mac ? \"Cmd\" : \"Ctrl\") + \"-Space\"] = \"autocomplete\";\n    </script>\n\n    <p>Simple mode that tries to handle Modelica as well as it can.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-modelica</code>\n    (Modlica code).</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/modelica/modelica.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// Modelica support for CodeMirror, copyright (c) by Lennart Ochel\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})\n\n(function(CodeMirror) {\n  \"use strict\";\n\n  CodeMirror.defineMode(\"modelica\", function(config, parserConfig) {\n\n    var indentUnit = config.indentUnit;\n    var keywords = parserConfig.keywords || {};\n    var builtin = parserConfig.builtin || {};\n    var atoms = parserConfig.atoms || {};\n\n    var isSingleOperatorChar = /[;=\\(:\\),{}.*<>+\\-\\/^\\[\\]]/;\n    var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\\.\\+|\\.\\-|\\.\\*|\\.\\/|\\.\\^)/;\n    var isDigit = /[0-9]/;\n    var isNonDigit = /[_a-zA-Z]/;\n\n    function tokenLineComment(stream, state) {\n      stream.skipToEnd();\n      state.tokenize = null;\n      return \"comment\";\n    }\n\n    function tokenBlockComment(stream, state) {\n      var maybeEnd = false, ch;\n      while (ch = stream.next()) {\n        if (maybeEnd && ch == \"/\") {\n          state.tokenize = null;\n          break;\n        }\n        maybeEnd = (ch == \"*\");\n      }\n      return \"comment\";\n    }\n\n    function tokenString(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == '\"' && !escaped) {\n          state.tokenize = null;\n          state.sol = false;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n\n      return \"string\";\n    }\n\n    function tokenIdent(stream, state) {\n      stream.eatWhile(isDigit);\n      while (stream.eat(isDigit) || stream.eat(isNonDigit)) { }\n\n\n      var cur = stream.current();\n\n      if(state.sol && (cur == \"package\" || cur == \"model\" || cur == \"when\" || cur == \"connector\")) state.level++;\n      else if(state.sol && cur == \"end\" && state.level > 0) state.level--;\n\n      state.tokenize = null;\n      state.sol = false;\n\n      if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n      else if (builtin.propertyIsEnumerable(cur)) return \"builtin\";\n      else if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n      else return \"variable\";\n    }\n\n    function tokenQIdent(stream, state) {\n      while (stream.eat(/[^']/)) { }\n\n      state.tokenize = null;\n      state.sol = false;\n\n      if(stream.eat(\"'\"))\n        return \"variable\";\n      else\n        return \"error\";\n    }\n\n    function tokenUnsignedNuber(stream, state) {\n      stream.eatWhile(isDigit);\n      if (stream.eat('.')) {\n        stream.eatWhile(isDigit);\n      }\n      if (stream.eat('e') || stream.eat('E')) {\n        if (!stream.eat('-'))\n          stream.eat('+');\n        stream.eatWhile(isDigit);\n      }\n\n      state.tokenize = null;\n      state.sol = false;\n      return \"number\";\n    }\n\n    // Interface\n    return {\n      startState: function() {\n        return {\n          tokenize: null,\n          level: 0,\n          sol: true\n        };\n      },\n\n      token: function(stream, state) {\n        if(state.tokenize != null) {\n          return state.tokenize(stream, state);\n        }\n\n        if(stream.sol()) {\n          state.sol = true;\n        }\n\n        // WHITESPACE\n        if(stream.eatSpace()) {\n          state.tokenize = null;\n          return null;\n        }\n\n        var ch = stream.next();\n\n        // LINECOMMENT\n        if(ch == '/' && stream.eat('/')) {\n          state.tokenize = tokenLineComment;\n        }\n        // BLOCKCOMMENT\n        else if(ch == '/' && stream.eat('*')) {\n          state.tokenize = tokenBlockComment;\n        }\n        // TWO SYMBOL TOKENS\n        else if(isDoubleOperatorChar.test(ch+stream.peek())) {\n          stream.next();\n          state.tokenize = null;\n          return \"operator\";\n        }\n        // SINGLE SYMBOL TOKENS\n        else if(isSingleOperatorChar.test(ch)) {\n          state.tokenize = null;\n          return \"operator\";\n        }\n        // IDENT\n        else if(isNonDigit.test(ch)) {\n          state.tokenize = tokenIdent;\n        }\n        // Q-IDENT\n        else if(ch == \"'\" && stream.peek() && stream.peek() != \"'\") {\n          state.tokenize = tokenQIdent;\n        }\n        // STRING\n        else if(ch == '\"') {\n          state.tokenize = tokenString;\n        }\n        // UNSIGNED_NUBER\n        else if(isDigit.test(ch)) {\n          state.tokenize = tokenUnsignedNuber;\n        }\n        // ERROR\n        else {\n          state.tokenize = null;\n          return \"error\";\n        }\n\n        return state.tokenize(stream, state);\n      },\n\n      indent: function(state, textAfter) {\n        if (state.tokenize != null) return CodeMirror.Pass;\n\n        var level = state.level;\n        if(/(algorithm)/.test(textAfter)) level--;\n        if(/(equation)/.test(textAfter)) level--;\n        if(/(initial algorithm)/.test(textAfter)) level--;\n        if(/(initial equation)/.test(textAfter)) level--;\n        if(/(end)/.test(textAfter)) level--;\n\n        if(level > 0)\n          return indentUnit*level;\n        else\n          return 0;\n      },\n\n      blockCommentStart: \"/*\",\n      blockCommentEnd: \"*/\",\n      lineComment: \"//\"\n    };\n  });\n\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i=0; i<words.length; ++i)\n      obj[words[i]] = true;\n    return obj;\n  }\n\n  var modelicaKeywords = \"algorithm and annotation assert block break class connect connector constant constrainedby der discrete each else elseif elsewhen encapsulated end enumeration equation expandable extends external false final flow for function if import impure in initial inner input loop model not operator or outer output package parameter partial protected public pure record redeclare replaceable return stream then true type when while within\";\n  var modelicaBuiltin = \"abs acos actualStream asin atan atan2 cardinality ceil cos cosh delay div edge exp floor getInstanceName homotopy inStream integer log log10 mod pre reinit rem semiLinear sign sin sinh spatialDistribution sqrt tan tanh\";\n  var modelicaAtoms = \"Real Boolean Integer String\";\n\n  function def(mimes, mode) {\n    if (typeof mimes == \"string\")\n      mimes = [mimes];\n\n    var words = [];\n\n    function add(obj) {\n      if (obj)\n        for (var prop in obj)\n          if (obj.hasOwnProperty(prop))\n            words.push(prop);\n    }\n\n    add(mode.keywords);\n    add(mode.builtin);\n    add(mode.atoms);\n\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-modelica\"], {\n    name: \"modelica\",\n    keywords: words(modelicaKeywords),\n    builtin: words(modelicaBuiltin),\n    atoms: words(modelicaAtoms)\n  });\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/nginx/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: NGINX mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"nginx.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n\n  <style>\n    body {\n      margin: 0em auto;\n    }\n\n    .CodeMirror, .CodeMirror-scroll {\n      height: 600px;\n    }\n  </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">NGINX</a>\n  </ul>\n</div>\n\n<article>\n<h2>NGINX mode</h2>\n<form><textarea id=\"code\" name=\"code\" style=\"height: 800px;\">\nserver {\n  listen 173.255.219.235:80;\n  server_name website.com.au;\n  rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www\n}\n\nserver {\n  listen 173.255.219.235:443;\n  server_name website.com.au;\n  rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www\n}\n\nserver {\n\n  listen      173.255.219.235:80;\n  server_name www.website.com.au;\n\n\n\n  root        /data/www;\n  index       index.html index.php;\n\n  location / {\n    index index.html index.php;     ## Allow a static html file to be shown first\n    try_files $uri $uri/ @handler;  ## If missing pass the URI to Magento's front handler\n    expires 30d;                    ## Assume all files are cachable\n  }\n\n  ## These locations would be hidden by .htaccess normally\n  location /app/                { deny all; }\n  location /includes/           { deny all; }\n  location /lib/                { deny all; }\n  location /media/downloadable/ { deny all; }\n  location /pkginfo/            { deny all; }\n  location /report/config.xml   { deny all; }\n  location /var/                { deny all; }\n\n  location /var/export/ { ## Allow admins only to view export folder\n    auth_basic           \"Restricted\"; ## Message shown in login window\n    auth_basic_user_file /rs/passwords/testfile; ## See /etc/nginx/htpassword\n    autoindex            on;\n  }\n\n  location  /. { ## Disable .htaccess and other hidden files\n    return 404;\n  }\n\n  location @handler { ## Magento uses a common front handler\n    rewrite / /index.php;\n  }\n\n  location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler\n    rewrite ^/(.*.php)/ /$1 last;\n  }\n\n  location ~ \\.php$ {\n    if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss\n\n    fastcgi_pass   127.0.0.1:9000;\n    fastcgi_index  index.php;\n    fastcgi_param PATH_INFO $fastcgi_script_name;\n    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;\n    include        /rs/confs/nginx/fastcgi_params;\n  }\n\n}\n\n\nserver {\n\n  listen              173.255.219.235:443;\n  server_name         website.com.au www.website.com.au;\n\n  root   /data/www;\n  index index.html index.php;\n\n  ssl                 on;\n  ssl_certificate     /rs/ssl/ssl.crt;\n  ssl_certificate_key /rs/ssl/ssl.key;\n\n  ssl_session_timeout  5m;\n\n  ssl_protocols  SSLv2 SSLv3 TLSv1;\n  ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;\n  ssl_prefer_server_ciphers   on;\n\n\n\n  location / {\n    index index.html index.php; ## Allow a static html file to be shown first\n    try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler\n    expires 30d; ## Assume all files are cachable\n  }\n\n  ## These locations would be hidden by .htaccess normally\n  location /app/                { deny all; }\n  location /includes/           { deny all; }\n  location /lib/                { deny all; }\n  location /media/downloadable/ { deny all; }\n  location /pkginfo/            { deny all; }\n  location /report/config.xml   { deny all; }\n  location /var/                { deny all; }\n\n  location /var/export/ { ## Allow admins only to view export folder\n    auth_basic           \"Restricted\"; ## Message shown in login window\n    auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword\n    autoindex            on;\n  }\n\n  location  /. { ## Disable .htaccess and other hidden files\n    return 404;\n  }\n\n  location @handler { ## Magento uses a common front handler\n    rewrite / /index.php;\n  }\n\n  location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler\n    rewrite ^/(.*.php)/ /$1 last;\n  }\n\n  location ~ .php$ { ## Execute PHP scripts\n    if (!-e $request_filename) { rewrite  /index.php last; } ## Catch 404s that try_files miss\n\n    fastcgi_pass 127.0.0.1:9000;\n    fastcgi_index  index.php;\n    fastcgi_param PATH_INFO $fastcgi_script_name;\n    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;\n    include        /rs/confs/nginx/fastcgi_params;\n\n    fastcgi_param HTTPS on;\n  }\n\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/nginx</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/nginx/nginx.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(\"nginx\", function(config) {\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\n  var keywords = words(\n    /* ngxDirectiveControl */ \"break return rewrite set\" +\n    /* ngxDirective */ \" accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23\"\n    );\n\n  var keywords_block = words(\n    /* ngxDirectiveBlock */ \"http mail events server types location upstream charset_map limit_except if geo map\"\n    );\n\n  var keywords_important = words(\n    /* ngxDirectiveImportant */ \"include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files\"\n    );\n\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n\n\n    stream.eatWhile(/[\\w\\$_]/);\n\n    var cur = stream.current();\n\n\n    if (keywords.propertyIsEnumerable(cur)) {\n      return \"keyword\";\n    }\n    else if (keywords_block.propertyIsEnumerable(cur)) {\n      return \"variable-2\";\n    }\n    else if (keywords_important.propertyIsEnumerable(cur)) {\n      return \"string-2\";\n    }\n    /**/\n\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.skipToEnd();\n      return ret(\"comment\", \"comment\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      type = null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context == \"rule\") style = \"atom\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/nginx\", \"text/x-nginx-conf\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ntriples/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: NTriples mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"ntriples.js\"></script>\n<style type=\"text/css\">\n      .CodeMirror {\n        border: 1px solid #eee;\n      }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">NTriples</a>\n  </ul>\n</div>\n\n<article>\n<h2>NTriples mode</h2>\n<form>\n<textarea id=\"ntriples\" name=\"ntriples\">\n<http://Sub1>     <http://pred1>     <http://obj> .\n<http://Sub2>     <http://pred2#an2> \"literal 1\" .\n<http://Sub3#an3> <http://pred3>     _:bnode3 .\n_:bnode4          <http://pred4>     \"literal 2\"@lang .\n_:bnode5          <http://pred5>     \"literal 3\"^^<http://type> .\n</textarea>\n</form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"ntriples\"), {});\n    </script>\n    <p><strong>MIME types defined:</strong> <code>text/n-triples</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ntriples/ntriples.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**********************************************************\n* This script provides syntax highlighting support for\n* the Ntriples format.\n* Ntriples format specification:\n*     http://www.w3.org/TR/rdf-testcases/#ntriples\n***********************************************************/\n\n/*\n    The following expression defines the defined ASF grammar transitions.\n\n    pre_subject ->\n        {\n        ( writing_subject_uri | writing_bnode_uri )\n            -> pre_predicate\n                -> writing_predicate_uri\n                    -> pre_object\n                        -> writing_object_uri | writing_object_bnode |\n                          (\n                            writing_object_literal\n                                -> writing_literal_lang | writing_literal_type\n                          )\n                            -> post_object\n                                -> BEGIN\n         } otherwise {\n             -> ERROR\n         }\n*/\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(\"ntriples\", function() {\n\n  var Location = {\n    PRE_SUBJECT         : 0,\n    WRITING_SUB_URI     : 1,\n    WRITING_BNODE_URI   : 2,\n    PRE_PRED            : 3,\n    WRITING_PRED_URI    : 4,\n    PRE_OBJ             : 5,\n    WRITING_OBJ_URI     : 6,\n    WRITING_OBJ_BNODE   : 7,\n    WRITING_OBJ_LITERAL : 8,\n    WRITING_LIT_LANG    : 9,\n    WRITING_LIT_TYPE    : 10,\n    POST_OBJ            : 11,\n    ERROR               : 12\n  };\n  function transitState(currState, c) {\n    var currLocation = currState.location;\n    var ret;\n\n    // Opening.\n    if     (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;\n    else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;\n    else if(currLocation == Location.PRE_PRED    && c == '<') ret = Location.WRITING_PRED_URI;\n    else if(currLocation == Location.PRE_OBJ     && c == '<') ret = Location.WRITING_OBJ_URI;\n    else if(currLocation == Location.PRE_OBJ     && c == '_') ret = Location.WRITING_OBJ_BNODE;\n    else if(currLocation == Location.PRE_OBJ     && c == '\"') ret = Location.WRITING_OBJ_LITERAL;\n\n    // Closing.\n    else if(currLocation == Location.WRITING_SUB_URI     && c == '>') ret = Location.PRE_PRED;\n    else if(currLocation == Location.WRITING_BNODE_URI   && c == ' ') ret = Location.PRE_PRED;\n    else if(currLocation == Location.WRITING_PRED_URI    && c == '>') ret = Location.PRE_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_URI     && c == '>') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_BNODE   && c == ' ') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '\"') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;\n\n    // Closing typed and language literal.\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;\n\n    // Spaces.\n    else if( c == ' ' &&\n             (\n               currLocation == Location.PRE_SUBJECT ||\n               currLocation == Location.PRE_PRED    ||\n               currLocation == Location.PRE_OBJ     ||\n               currLocation == Location.POST_OBJ\n             )\n           ) ret = currLocation;\n\n    // Reset.\n    else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;\n\n    // Error\n    else ret = Location.ERROR;\n\n    currState.location=ret;\n  }\n\n  return {\n    startState: function() {\n       return {\n           location : Location.PRE_SUBJECT,\n           uris     : [],\n           anchors  : [],\n           bnodes   : [],\n           langs    : [],\n           types    : []\n       };\n    },\n    token: function(stream, state) {\n      var ch = stream.next();\n      if(ch == '<') {\n         transitState(state, ch);\n         var parsedURI = '';\n         stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );\n         state.uris.push(parsedURI);\n         if( stream.match('#', false) ) return 'variable';\n         stream.next();\n         transitState(state, '>');\n         return 'variable';\n      }\n      if(ch == '#') {\n        var parsedAnchor = '';\n        stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;});\n        state.anchors.push(parsedAnchor);\n        return 'variable-2';\n      }\n      if(ch == '>') {\n          transitState(state, '>');\n          return 'variable';\n      }\n      if(ch == '_') {\n          transitState(state, ch);\n          var parsedBNode = '';\n          stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});\n          state.bnodes.push(parsedBNode);\n          stream.next();\n          transitState(state, ' ');\n          return 'builtin';\n      }\n      if(ch == '\"') {\n          transitState(state, ch);\n          stream.eatWhile( function(c) { return c != '\"'; } );\n          stream.next();\n          if( stream.peek() != '@' && stream.peek() != '^' ) {\n              transitState(state, '\"');\n          }\n          return 'string';\n      }\n      if( ch == '@' ) {\n          transitState(state, '@');\n          var parsedLang = '';\n          stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});\n          state.langs.push(parsedLang);\n          stream.next();\n          transitState(state, ' ');\n          return 'string-2';\n      }\n      if( ch == '^' ) {\n          stream.next();\n          transitState(state, '^');\n          var parsedType = '';\n          stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );\n          state.types.push(parsedType);\n          stream.next();\n          transitState(state, '>');\n          return 'variable';\n      }\n      if( ch == ' ' ) {\n          transitState(state, ch);\n      }\n      if( ch == '.' ) {\n          transitState(state, ch);\n      }\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/n-triples\", \"ntriples\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/octave/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Octave mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"octave.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Octave</a>\n  </ul>\n</div>\n\n<article>\n<h2>Octave mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n%numbers\n[1234 1234i 1234j]\n[.234 .234j 2.23i]\n[23e2 12E1j 123D-4 0x234]\n\n%strings\n'asda''a'\n\"asda\"\"a\"\n\n%identifiers\na + as123 - __asd__\n\n%operators\n-\n+\n=\n==\n>\n<\n>=\n<=\n&\n~\n...\nbreak zeros default margin round ones rand\nceil floor size clear zeros eye mean std cov\nerror eval function\nabs acos atan asin cos cosh exp log prod sum\nlog10 max min sign sin sinh sqrt tan reshape\nreturn\ncase switch\nelse elseif end if otherwise\ndo for while\ntry catch\nclassdef properties events methods\nglobal persistent\n\n%one line comment\n%{ multi\nline commment %}\n\n    </textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"octave\",\n               version: 2,\n               singleLineStringErrors: false},\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-octave</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/octave/octave.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(\"octave\", function() {\n  function wordRegexp(words) {\n    return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n  }\n\n  var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/&|\\\\^~<>!@'\\\\\\\\]\");\n  var singleDelimiters = new RegExp('^[\\\\(\\\\[\\\\{\\\\},:=;]');\n  var doubleOperators = new RegExp(\"^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\\\.[\\\\+\\\\-\\\\*/\\\\^\\\\\\\\]))\");\n  var doubleDelimiters = new RegExp(\"^((!=)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n  var tripleDelimiters = new RegExp(\"^((>>=)|(<<=))\");\n  var expressionEnd = new RegExp(\"^[\\\\]\\\\)]\");\n  var identifiers = new RegExp(\"^[_A-Za-z\\xa1-\\uffff][_A-Za-z0-9\\xa1-\\uffff]*\");\n\n  var builtins = wordRegexp([\n    'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos',\n    'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh',\n    'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones',\n    'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov',\n    'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot',\n    'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str',\n    'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember'\n  ]);\n\n  var keywords = wordRegexp([\n    'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction',\n    'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events',\n    'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until',\n    'continue', 'pkg'\n  ]);\n\n\n  // tokenizers\n  function tokenTranspose(stream, state) {\n    if (!stream.sol() && stream.peek() === '\\'') {\n      stream.next();\n      state.tokenize = tokenBase;\n      return 'operator';\n    }\n    state.tokenize = tokenBase;\n    return tokenBase(stream, state);\n  }\n\n\n  function tokenComment(stream, state) {\n    if (stream.match(/^.*%}/)) {\n      state.tokenize = tokenBase;\n      return 'comment';\n    };\n    stream.skipToEnd();\n    return 'comment';\n  }\n\n  function tokenBase(stream, state) {\n    // whitespaces\n    if (stream.eatSpace()) return null;\n\n    // Handle one line Comments\n    if (stream.match('%{')){\n      state.tokenize = tokenComment;\n      stream.skipToEnd();\n      return 'comment';\n    }\n\n    if (stream.match(/^[%#]/)){\n      stream.skipToEnd();\n      return 'comment';\n    }\n\n    // Handle Number Literals\n    if (stream.match(/^[0-9\\.+-]/, false)) {\n      if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) {\n        stream.tokenize = tokenBase;\n        return 'number'; };\n      if (stream.match(/^[+-]?\\d*\\.\\d+([EeDd][+-]?\\d+)?[ij]?/)) { return 'number'; };\n      if (stream.match(/^[+-]?\\d+([EeDd][+-]?\\d+)?[ij]?/)) { return 'number'; };\n    }\n    if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; };\n\n    // Handle Strings\n    if (stream.match(/^\"([^\"]|(\"\"))*\"/)) { return 'string'; } ;\n    if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ;\n\n    // Handle words\n    if (stream.match(keywords)) { return 'keyword'; } ;\n    if (stream.match(builtins)) { return 'builtin'; } ;\n    if (stream.match(identifiers)) { return 'variable'; } ;\n\n    if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; };\n    if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; };\n\n    if (stream.match(expressionEnd)) {\n      state.tokenize = tokenTranspose;\n      return null;\n    };\n\n\n    // Handle non-detected items\n    stream.next();\n    return 'error';\n  };\n\n\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase\n      };\n    },\n\n    token: function(stream, state) {\n      var style = state.tokenize(stream, state);\n      if (style === 'number' || style === 'variable'){\n        state.tokenize = tokenTranspose;\n      }\n      return style;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-octave\", \"octave\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pascal/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Pascal mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"pascal.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Pascal</a>\n  </ul>\n</div>\n\n<article>\n<h2>Pascal mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n(* Example Pascal code *)\n\nwhile a <> b do writeln('Waiting');\n\nif a > b then\n  writeln('Condition met')\nelse\n  writeln('Condition not met');\n\nfor i := 1 to 10 do\n  writeln('Iteration: ', i:1);\n\nrepeat\n  a := a + 1\nuntil a = 10;\n\ncase i of\n  0: write('zero');\n  1: write('one');\n  2: write('two')\nend;\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"text/x-pascal\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-pascal</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pascal/pascal.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(\"pascal\", function() {\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  var keywords = words(\"and array begin case const div do downto else end file for forward integer \" +\n                       \"boolean char function goto if in label mod nil not of or packed procedure \" +\n                       \"program record repeat set string then to type until var while with\");\n  var atoms = {\"null\": true};\n\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"#\" && state.startOfLine) {\n      stream.skipToEnd();\n      return \"meta\";\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (ch == \"(\" && stream.eat(\"*\")) {\n      state.tokenize = tokenComment;\n      return tokenComment(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n    if (atoms.propertyIsEnumerable(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) 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() {\n      return {tokenize: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      return style;\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-pascal\", \"pascal\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pegjs/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: PEG.js Mode</title>\n    <meta charset=\"utf-8\"/>\n    <link rel=stylesheet href=\"../../doc/docs.css\">\n\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <script src=\"pegjs.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body class=\"gray-bg\">\n    <div id=nav>\n      <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n      <ul>\n        <li><a href=\"../../index.html\">Home</a>\n        <li><a href=\"../../doc/manual.html\">Manual</a>\n        <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n      </ul>\n      <ul>\n        <li><a href=\"../index.html\">Language modes</a>\n        <li><a class=active href=\"#\">PEG.js Mode</a>\n      </ul>\n    </div>\n\n    <article>\n      <h2>PEG.js Mode</h2>\n      <form><textarea id=\"code\" name=\"code\">\n/*\n * Classic example grammar, which recognizes simple arithmetic expressions like\n * \"2*(3+4)\". The parser generated from this grammar then computes their value.\n */\n\nstart\n  = additive\n\nadditive\n  = left:multiplicative \"+\" right:additive { return left + right; }\n  / multiplicative\n\nmultiplicative\n  = left:primary \"*\" right:multiplicative { return left * right; }\n  / primary\n\nprimary\n  = integer\n  / \"(\" additive:additive \")\" { return additive; }\n\ninteger \"integer\"\n  = digits:[0-9]+ { return parseInt(digits.join(\"\"), 10); }\n\nletter = [a-z]+</textarea></form>\n      <script>\n        var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n          mode: {name: \"pegjs\"},\n          lineNumbers: true\n        });\n      </script>\n      <h3>The PEG.js Mode</h3>\n      <p> Created by Forbes Lindesay.</p>\n    </article>\n  </body>\n</html>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pegjs/pegjs.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\"), require(\"../javascript/javascript\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../javascript/javascript\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"pegjs\", function (config) {\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n\n  function identifier(stream) {\n    return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/);\n  }\n\n  return {\n    startState: function () {\n      return {\n        inString: false,\n        stringType: null,\n        inComment: false,\n        inChracterClass: false,\n        braced: 0,\n        lhs: true,\n        localState: null\n      };\n    },\n    token: function (stream, state) {\n      if (stream)\n\n      //check for state changes\n      if (!state.inString && !state.inComment && ((stream.peek() == '\"') || (stream.peek() == \"'\"))) {\n        state.stringType = stream.peek();\n        stream.next(); // Skip quote\n        state.inString = true; // Update state\n      }\n      if (!state.inString && !state.inComment && stream.match(/^\\/\\*/)) {\n        state.inComment = true;\n      }\n\n      //return state\n      if (state.inString) {\n        while (state.inString && !stream.eol()) {\n          if (stream.peek() === state.stringType) {\n            stream.next(); // Skip quote\n            state.inString = false; // Clear flag\n          } else if (stream.peek() === '\\\\') {\n            stream.next();\n            stream.next();\n          } else {\n            stream.match(/^.[^\\\\\\\"\\']*/);\n          }\n        }\n        return state.lhs ? \"property string\" : \"string\"; // Token style\n      } else if (state.inComment) {\n        while (state.inComment && !stream.eol()) {\n          if (stream.match(/\\*\\//)) {\n            state.inComment = false; // Clear flag\n          } else {\n            stream.match(/^.[^\\*]*/);\n          }\n        }\n        return \"comment\";\n      } else if (state.inChracterClass) {\n          while (state.inChracterClass && !stream.eol()) {\n            if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./))) {\n              state.inChracterClass = false;\n            }\n          }\n      } else if (stream.peek() === '[') {\n        stream.next();\n        state.inChracterClass = true;\n        return 'bracket';\n      } else if (stream.match(/^\\/\\//)) {\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (state.braced || stream.peek() === '{') {\n        if (state.localState === null) {\n          state.localState = jsMode.startState();\n        }\n        var token = jsMode.token(stream, state.localState);\n        var text = stream.current();\n        if (!token) {\n          for (var i = 0; i < text.length; i++) {\n            if (text[i] === '{') {\n              state.braced++;\n            } else if (text[i] === '}') {\n              state.braced--;\n            }\n          };\n        }\n        return token;\n      } else if (identifier(stream)) {\n        if (stream.peek() === ':') {\n          return 'variable';\n        }\n        return 'variable-2';\n      } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) {\n        stream.next();\n        return 'bracket';\n      } else if (!stream.eatSpace()) {\n        stream.next();\n      }\n      return null;\n    }\n  };\n}, \"javascript\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/perl/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Perl mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"perl.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Perl</a>\n  </ul>\n</div>\n\n<article>\n<h2>Perl mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n#!/usr/bin/perl\n\nuse Something qw(func1 func2);\n\n# strings\nmy $s1 = qq'single line';\nour $s2 = q(multi-\n              line);\n\n=item Something\n\tExample.\n=cut\n\nmy $html=<<'HTML'\n<html>\n<title>hi!</title>\n</html>\nHTML\n\nprint \"first,\".join(',', 'second', qq~third~);\n\nif($s1 =~ m[(?<!\\s)(l.ne)\\z]o) {\n\t$h->{$1}=$$.' predefined variables';\n\t$s2 =~ s/\\-line//ox;\n\t$s1 =~ s[\n\t\t  line ]\n\t\t[\n\t\t  block\n\t\t]ox;\n}\n\n1; # numbers and comments\n\n__END__\nsomething...\n\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-perl</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/perl/perl.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)\n// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)\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(\"perl\",function(){\n        // http://perldoc.perl.org\n        var PERL={                                      //   null - magic touch\n                                                        //   1 - keyword\n                                                        //   2 - def\n                                                        //   3 - atom\n                                                        //   4 - operator\n                                                        //   5 - variable-2 (predefined)\n                                                        //   [x,y] - x=1,2,3; y=must be defined if x{...}\n                                                //      PERL operators\n                '->'                            :   4,\n                '++'                            :   4,\n                '--'                            :   4,\n                '**'                            :   4,\n                                                        //   ! ~ \\ and unary + and -\n                '=~'                            :   4,\n                '!~'                            :   4,\n                '*'                             :   4,\n                '/'                             :   4,\n                '%'                             :   4,\n                'x'                             :   4,\n                '+'                             :   4,\n                '-'                             :   4,\n                '.'                             :   4,\n                '<<'                            :   4,\n                '>>'                            :   4,\n                                                        //   named unary operators\n                '<'                             :   4,\n                '>'                             :   4,\n                '<='                            :   4,\n                '>='                            :   4,\n                'lt'                            :   4,\n                'gt'                            :   4,\n                'le'                            :   4,\n                'ge'                            :   4,\n                '=='                            :   4,\n                '!='                            :   4,\n                '<=>'                           :   4,\n                'eq'                            :   4,\n                'ne'                            :   4,\n                'cmp'                           :   4,\n                '~~'                            :   4,\n                '&'                             :   4,\n                '|'                             :   4,\n                '^'                             :   4,\n                '&&'                            :   4,\n                '||'                            :   4,\n                '//'                            :   4,\n                '..'                            :   4,\n                '...'                           :   4,\n                '?'                             :   4,\n                ':'                             :   4,\n                '='                             :   4,\n                '+='                            :   4,\n                '-='                            :   4,\n                '*='                            :   4,  //   etc. ???\n                ','                             :   4,\n                '=>'                            :   4,\n                '::'                            :   4,\n                                                        //   list operators (rightward)\n                'not'                           :   4,\n                'and'                           :   4,\n                'or'                            :   4,\n                'xor'                           :   4,\n                                                //      PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)\n                'BEGIN'                         :   [5,1],\n                'END'                           :   [5,1],\n                'PRINT'                         :   [5,1],\n                'PRINTF'                        :   [5,1],\n                'GETC'                          :   [5,1],\n                'READ'                          :   [5,1],\n                'READLINE'                      :   [5,1],\n                'DESTROY'                       :   [5,1],\n                'TIE'                           :   [5,1],\n                'TIEHANDLE'                     :   [5,1],\n                'UNTIE'                         :   [5,1],\n                'STDIN'                         :    5,\n                'STDIN_TOP'                     :    5,\n                'STDOUT'                        :    5,\n                'STDOUT_TOP'                    :    5,\n                'STDERR'                        :    5,\n                'STDERR_TOP'                    :    5,\n                '$ARG'                          :    5,\n                '$_'                            :    5,\n                '@ARG'                          :    5,\n                '@_'                            :    5,\n                '$LIST_SEPARATOR'               :    5,\n                '$\"'                            :    5,\n                '$PROCESS_ID'                   :    5,\n                '$PID'                          :    5,\n                '$$'                            :    5,\n                '$REAL_GROUP_ID'                :    5,\n                '$GID'                          :    5,\n                '$('                            :    5,\n                '$EFFECTIVE_GROUP_ID'           :    5,\n                '$EGID'                         :    5,\n                '$)'                            :    5,\n                '$PROGRAM_NAME'                 :    5,\n                '$0'                            :    5,\n                '$SUBSCRIPT_SEPARATOR'          :    5,\n                '$SUBSEP'                       :    5,\n                '$;'                            :    5,\n                '$REAL_USER_ID'                 :    5,\n                '$UID'                          :    5,\n                '$<'                            :    5,\n                '$EFFECTIVE_USER_ID'            :    5,\n                '$EUID'                         :    5,\n                '$>'                            :    5,\n                '$a'                            :    5,\n                '$b'                            :    5,\n                '$COMPILING'                    :    5,\n                '$^C'                           :    5,\n                '$DEBUGGING'                    :    5,\n                '$^D'                           :    5,\n                '${^ENCODING}'                  :    5,\n                '$ENV'                          :    5,\n                '%ENV'                          :    5,\n                '$SYSTEM_FD_MAX'                :    5,\n                '$^F'                           :    5,\n                '@F'                            :    5,\n                '${^GLOBAL_PHASE}'              :    5,\n                '$^H'                           :    5,\n                '%^H'                           :    5,\n                '@INC'                          :    5,\n                '%INC'                          :    5,\n                '$INPLACE_EDIT'                 :    5,\n                '$^I'                           :    5,\n                '$^M'                           :    5,\n                '$OSNAME'                       :    5,\n                '$^O'                           :    5,\n                '${^OPEN}'                      :    5,\n                '$PERLDB'                       :    5,\n                '$^P'                           :    5,\n                '$SIG'                          :    5,\n                '%SIG'                          :    5,\n                '$BASETIME'                     :    5,\n                '$^T'                           :    5,\n                '${^TAINT}'                     :    5,\n                '${^UNICODE}'                   :    5,\n                '${^UTF8CACHE}'                 :    5,\n                '${^UTF8LOCALE}'                :    5,\n                '$PERL_VERSION'                 :    5,\n                '$^V'                           :    5,\n                '${^WIN32_SLOPPY_STAT}'         :    5,\n                '$EXECUTABLE_NAME'              :    5,\n                '$^X'                           :    5,\n                '$1'                            :    5, // - regexp $1, $2...\n                '$MATCH'                        :    5,\n                '$&'                            :    5,\n                '${^MATCH}'                     :    5,\n                '$PREMATCH'                     :    5,\n                '$`'                            :    5,\n                '${^PREMATCH}'                  :    5,\n                '$POSTMATCH'                    :    5,\n                \"$'\"                            :    5,\n                '${^POSTMATCH}'                 :    5,\n                '$LAST_PAREN_MATCH'             :    5,\n                '$+'                            :    5,\n                '$LAST_SUBMATCH_RESULT'         :    5,\n                '$^N'                           :    5,\n                '@LAST_MATCH_END'               :    5,\n                '@+'                            :    5,\n                '%LAST_PAREN_MATCH'             :    5,\n                '%+'                            :    5,\n                '@LAST_MATCH_START'             :    5,\n                '@-'                            :    5,\n                '%LAST_MATCH_START'             :    5,\n                '%-'                            :    5,\n                '$LAST_REGEXP_CODE_RESULT'      :    5,\n                '$^R'                           :    5,\n                '${^RE_DEBUG_FLAGS}'            :    5,\n                '${^RE_TRIE_MAXBUF}'            :    5,\n                '$ARGV'                         :    5,\n                '@ARGV'                         :    5,\n                'ARGV'                          :    5,\n                'ARGVOUT'                       :    5,\n                '$OUTPUT_FIELD_SEPARATOR'       :    5,\n                '$OFS'                          :    5,\n                '$,'                            :    5,\n                '$INPUT_LINE_NUMBER'            :    5,\n                '$NR'                           :    5,\n                '$.'                            :    5,\n                '$INPUT_RECORD_SEPARATOR'       :    5,\n                '$RS'                           :    5,\n                '$/'                            :    5,\n                '$OUTPUT_RECORD_SEPARATOR'      :    5,\n                '$ORS'                          :    5,\n                '$\\\\'                           :    5,\n                '$OUTPUT_AUTOFLUSH'             :    5,\n                '$|'                            :    5,\n                '$ACCUMULATOR'                  :    5,\n                '$^A'                           :    5,\n                '$FORMAT_FORMFEED'              :    5,\n                '$^L'                           :    5,\n                '$FORMAT_PAGE_NUMBER'           :    5,\n                '$%'                            :    5,\n                '$FORMAT_LINES_LEFT'            :    5,\n                '$-'                            :    5,\n                '$FORMAT_LINE_BREAK_CHARACTERS' :    5,\n                '$:'                            :    5,\n                '$FORMAT_LINES_PER_PAGE'        :    5,\n                '$='                            :    5,\n                '$FORMAT_TOP_NAME'              :    5,\n                '$^'                            :    5,\n                '$FORMAT_NAME'                  :    5,\n                '$~'                            :    5,\n                '${^CHILD_ERROR_NATIVE}'        :    5,\n                '$EXTENDED_OS_ERROR'            :    5,\n                '$^E'                           :    5,\n                '$EXCEPTIONS_BEING_CAUGHT'      :    5,\n                '$^S'                           :    5,\n                '$WARNING'                      :    5,\n                '$^W'                           :    5,\n                '${^WARNING_BITS}'              :    5,\n                '$OS_ERROR'                     :    5,\n                '$ERRNO'                        :    5,\n                '$!'                            :    5,\n                '%OS_ERROR'                     :    5,\n                '%ERRNO'                        :    5,\n                '%!'                            :    5,\n                '$CHILD_ERROR'                  :    5,\n                '$?'                            :    5,\n                '$EVAL_ERROR'                   :    5,\n                '$@'                            :    5,\n                '$OFMT'                         :    5,\n                '$#'                            :    5,\n                '$*'                            :    5,\n                '$ARRAY_BASE'                   :    5,\n                '$['                            :    5,\n                '$OLD_PERL_VERSION'             :    5,\n                '$]'                            :    5,\n                                                //      PERL blocks\n                'if'                            :[1,1],\n                elsif                           :[1,1],\n                'else'                          :[1,1],\n                'while'                         :[1,1],\n                unless                          :[1,1],\n                'for'                           :[1,1],\n                foreach                         :[1,1],\n                                                //      PERL functions\n                'abs'                           :1,     // - absolute value function\n                accept                          :1,     // - accept an incoming socket connect\n                alarm                           :1,     // - schedule a SIGALRM\n                'atan2'                         :1,     // - arctangent of Y/X in the range -PI to PI\n                bind                            :1,     // - binds an address to a socket\n                binmode                         :1,     // - prepare binary files for I/O\n                bless                           :1,     // - create an object\n                bootstrap                       :1,     //\n                'break'                         :1,     // - break out of a \"given\" block\n                caller                          :1,     // - get context of the current subroutine call\n                chdir                           :1,     // - change your current working directory\n                chmod                           :1,     // - changes the permissions on a list of files\n                chomp                           :1,     // - remove a trailing record separator from a string\n                chop                            :1,     // - remove the last character from a string\n                chown                           :1,     // - change the owership on a list of files\n                chr                             :1,     // - get character this number represents\n                chroot                          :1,     // - make directory new root for path lookups\n                close                           :1,     // - close file (or pipe or socket) handle\n                closedir                        :1,     // - close directory handle\n                connect                         :1,     // - connect to a remote socket\n                'continue'                      :[1,1], // - optional trailing block in a while or foreach\n                'cos'                           :1,     // - cosine function\n                crypt                           :1,     // - one-way passwd-style encryption\n                dbmclose                        :1,     // - breaks binding on a tied dbm file\n                dbmopen                         :1,     // - create binding on a tied dbm file\n                'default'                       :1,     //\n                defined                         :1,     // - test whether a value, variable, or function is defined\n                'delete'                        :1,     // - deletes a value from a hash\n                die                             :1,     // - raise an exception or bail out\n                'do'                            :1,     // - turn a BLOCK into a TERM\n                dump                            :1,     // - create an immediate core dump\n                each                            :1,     // - retrieve the next key/value pair from a hash\n                endgrent                        :1,     // - be done using group file\n                endhostent                      :1,     // - be done using hosts file\n                endnetent                       :1,     // - be done using networks file\n                endprotoent                     :1,     // - be done using protocols file\n                endpwent                        :1,     // - be done using passwd file\n                endservent                      :1,     // - be done using services file\n                eof                             :1,     // - test a filehandle for its end\n                'eval'                          :1,     // - catch exceptions or compile and run code\n                'exec'                          :1,     // - abandon this program to run another\n                exists                          :1,     // - test whether a hash key is present\n                exit                            :1,     // - terminate this program\n                'exp'                           :1,     // - raise I to a power\n                fcntl                           :1,     // - file control system call\n                fileno                          :1,     // - return file descriptor from filehandle\n                flock                           :1,     // - lock an entire file with an advisory lock\n                fork                            :1,     // - create a new process just like this one\n                format                          :1,     // - declare a picture format with use by the write() function\n                formline                        :1,     // - internal function used for formats\n                getc                            :1,     // - get the next character from the filehandle\n                getgrent                        :1,     // - get next group record\n                getgrgid                        :1,     // - get group record given group user ID\n                getgrnam                        :1,     // - get group record given group name\n                gethostbyaddr                   :1,     // - get host record given its address\n                gethostbyname                   :1,     // - get host record given name\n                gethostent                      :1,     // - get next hosts record\n                getlogin                        :1,     // - return who logged in at this tty\n                getnetbyaddr                    :1,     // - get network record given its address\n                getnetbyname                    :1,     // - get networks record given name\n                getnetent                       :1,     // - get next networks record\n                getpeername                     :1,     // - find the other end of a socket connection\n                getpgrp                         :1,     // - get process group\n                getppid                         :1,     // - get parent process ID\n                getpriority                     :1,     // - get current nice value\n                getprotobyname                  :1,     // - get protocol record given name\n                getprotobynumber                :1,     // - get protocol record numeric protocol\n                getprotoent                     :1,     // - get next protocols record\n                getpwent                        :1,     // - get next passwd record\n                getpwnam                        :1,     // - get passwd record given user login name\n                getpwuid                        :1,     // - get passwd record given user ID\n                getservbyname                   :1,     // - get services record given its name\n                getservbyport                   :1,     // - get services record given numeric port\n                getservent                      :1,     // - get next services record\n                getsockname                     :1,     // - retrieve the sockaddr for a given socket\n                getsockopt                      :1,     // - get socket options on a given socket\n                given                           :1,     //\n                glob                            :1,     // - expand filenames using wildcards\n                gmtime                          :1,     // - convert UNIX time into record or string using Greenwich time\n                'goto'                          :1,     // - create spaghetti code\n                grep                            :1,     // - locate elements in a list test true against a given criterion\n                hex                             :1,     // - convert a string to a hexadecimal number\n                'import'                        :1,     // - patch a module's namespace into your own\n                index                           :1,     // - find a substring within a string\n                'int'                           :1,     // - get the integer portion of a number\n                ioctl                           :1,     // - system-dependent device control system call\n                'join'                          :1,     // - join a list into a string using a separator\n                keys                            :1,     // - retrieve list of indices from a hash\n                kill                            :1,     // - send a signal to a process or process group\n                last                            :1,     // - exit a block prematurely\n                lc                              :1,     // - return lower-case version of a string\n                lcfirst                         :1,     // - return a string with just the next letter in lower case\n                length                          :1,     // - return the number of bytes in a string\n                'link'                          :1,     // - create a hard link in the filesytem\n                listen                          :1,     // - register your socket as a server\n                local                           : 2,    // - create a temporary value for a global variable (dynamic scoping)\n                localtime                       :1,     // - convert UNIX time into record or string using local time\n                lock                            :1,     // - get a thread lock on a variable, subroutine, or method\n                'log'                           :1,     // - retrieve the natural logarithm for a number\n                lstat                           :1,     // - stat a symbolic link\n                m                               :null,  // - match a string with a regular expression pattern\n                map                             :1,     // - apply a change to a list to get back a new list with the changes\n                mkdir                           :1,     // - create a directory\n                msgctl                          :1,     // - SysV IPC message control operations\n                msgget                          :1,     // - get SysV IPC message queue\n                msgrcv                          :1,     // - receive a SysV IPC message from a message queue\n                msgsnd                          :1,     // - send a SysV IPC message to a message queue\n                my                              : 2,    // - declare and assign a local variable (lexical scoping)\n                'new'                           :1,     //\n                next                            :1,     // - iterate a block prematurely\n                no                              :1,     // - unimport some module symbols or semantics at compile time\n                oct                             :1,     // - convert a string to an octal number\n                open                            :1,     // - open a file, pipe, or descriptor\n                opendir                         :1,     // - open a directory\n                ord                             :1,     // - find a character's numeric representation\n                our                             : 2,    // - declare and assign a package variable (lexical scoping)\n                pack                            :1,     // - convert a list into a binary representation\n                'package'                       :1,     // - declare a separate global namespace\n                pipe                            :1,     // - open a pair of connected filehandles\n                pop                             :1,     // - remove the last element from an array and return it\n                pos                             :1,     // - find or set the offset for the last/next m//g search\n                print                           :1,     // - output a list to a filehandle\n                printf                          :1,     // - output a formatted list to a filehandle\n                prototype                       :1,     // - get the prototype (if any) of a subroutine\n                push                            :1,     // - append one or more elements to an array\n                q                               :null,  // - singly quote a string\n                qq                              :null,  // - doubly quote a string\n                qr                              :null,  // - Compile pattern\n                quotemeta                       :null,  // - quote regular expression magic characters\n                qw                              :null,  // - quote a list of words\n                qx                              :null,  // - backquote quote a string\n                rand                            :1,     // - retrieve the next pseudorandom number\n                read                            :1,     // - fixed-length buffered input from a filehandle\n                readdir                         :1,     // - get a directory from a directory handle\n                readline                        :1,     // - fetch a record from a file\n                readlink                        :1,     // - determine where a symbolic link is pointing\n                readpipe                        :1,     // - execute a system command and collect standard output\n                recv                            :1,     // - receive a message over a Socket\n                redo                            :1,     // - start this loop iteration over again\n                ref                             :1,     // - find out the type of thing being referenced\n                rename                          :1,     // - change a filename\n                require                         :1,     // - load in external functions from a library at runtime\n                reset                           :1,     // - clear all variables of a given name\n                'return'                        :1,     // - get out of a function early\n                reverse                         :1,     // - flip a string or a list\n                rewinddir                       :1,     // - reset directory handle\n                rindex                          :1,     // - right-to-left substring search\n                rmdir                           :1,     // - remove a directory\n                s                               :null,  // - replace a pattern with a string\n                say                             :1,     // - print with newline\n                scalar                          :1,     // - force a scalar context\n                seek                            :1,     // - reposition file pointer for random-access I/O\n                seekdir                         :1,     // - reposition directory pointer\n                select                          :1,     // - reset default output or do I/O multiplexing\n                semctl                          :1,     // - SysV semaphore control operations\n                semget                          :1,     // - get set of SysV semaphores\n                semop                           :1,     // - SysV semaphore operations\n                send                            :1,     // - send a message over a socket\n                setgrent                        :1,     // - prepare group file for use\n                sethostent                      :1,     // - prepare hosts file for use\n                setnetent                       :1,     // - prepare networks file for use\n                setpgrp                         :1,     // - set the process group of a process\n                setpriority                     :1,     // - set a process's nice value\n                setprotoent                     :1,     // - prepare protocols file for use\n                setpwent                        :1,     // - prepare passwd file for use\n                setservent                      :1,     // - prepare services file for use\n                setsockopt                      :1,     // - set some socket options\n                shift                           :1,     // - remove the first element of an array, and return it\n                shmctl                          :1,     // - SysV shared memory operations\n                shmget                          :1,     // - get SysV shared memory segment identifier\n                shmread                         :1,     // - read SysV shared memory\n                shmwrite                        :1,     // - write SysV shared memory\n                shutdown                        :1,     // - close down just half of a socket connection\n                'sin'                           :1,     // - return the sine of a number\n                sleep                           :1,     // - block for some number of seconds\n                socket                          :1,     // - create a socket\n                socketpair                      :1,     // - create a pair of sockets\n                'sort'                          :1,     // - sort a list of values\n                splice                          :1,     // - add or remove elements anywhere in an array\n                'split'                         :1,     // - split up a string using a regexp delimiter\n                sprintf                         :1,     // - formatted print into a string\n                'sqrt'                          :1,     // - square root function\n                srand                           :1,     // - seed the random number generator\n                stat                            :1,     // - get a file's status information\n                state                           :1,     // - declare and assign a state variable (persistent lexical scoping)\n                study                           :1,     // - optimize input data for repeated searches\n                'sub'                           :1,     // - declare a subroutine, possibly anonymously\n                'substr'                        :1,     // - get or alter a portion of a stirng\n                symlink                         :1,     // - create a symbolic link to a file\n                syscall                         :1,     // - execute an arbitrary system call\n                sysopen                         :1,     // - open a file, pipe, or descriptor\n                sysread                         :1,     // - fixed-length unbuffered input from a filehandle\n                sysseek                         :1,     // - position I/O pointer on handle used with sysread and syswrite\n                system                          :1,     // - run a separate program\n                syswrite                        :1,     // - fixed-length unbuffered output to a filehandle\n                tell                            :1,     // - get current seekpointer on a filehandle\n                telldir                         :1,     // - get current seekpointer on a directory handle\n                tie                             :1,     // - bind a variable to an object class\n                tied                            :1,     // - get a reference to the object underlying a tied variable\n                time                            :1,     // - return number of seconds since 1970\n                times                           :1,     // - return elapsed time for self and child processes\n                tr                              :null,  // - transliterate a string\n                truncate                        :1,     // - shorten a file\n                uc                              :1,     // - return upper-case version of a string\n                ucfirst                         :1,     // - return a string with just the next letter in upper case\n                umask                           :1,     // - set file creation mode mask\n                undef                           :1,     // - remove a variable or function definition\n                unlink                          :1,     // - remove one link to a file\n                unpack                          :1,     // - convert binary structure into normal perl variables\n                unshift                         :1,     // - prepend more elements to the beginning of a list\n                untie                           :1,     // - break a tie binding to a variable\n                use                             :1,     // - load in a module at compile time\n                utime                           :1,     // - set a file's last access and modify times\n                values                          :1,     // - return a list of the values in a hash\n                vec                             :1,     // - test or set particular bits in a string\n                wait                            :1,     // - wait for any child process to die\n                waitpid                         :1,     // - wait for a particular child process to die\n                wantarray                       :1,     // - get void vs scalar vs list context of current subroutine call\n                warn                            :1,     // - print debugging info\n                when                            :1,     //\n                write                           :1,     // - print a picture record\n                y                               :null}; // - transliterate a string\n\n        var RXstyle=\"string-2\";\n        var RXmodifiers=/[goseximacplud]/;              // NOTE: \"m\", \"s\", \"y\" and \"tr\" need to correct real modifiers for each regexp type\n\n        function tokenChain(stream,state,chain,style,tail){     // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)\n                state.chain=null;                               //                                                          12   3tail\n                state.style=null;\n                state.tail=null;\n                state.tokenize=function(stream,state){\n                        var e=false,c,i=0;\n                        while(c=stream.next()){\n                                if(c===chain[i]&&!e){\n                                        if(chain[++i]!==undefined){\n                                                state.chain=chain[i];\n                                                state.style=style;\n                                                state.tail=tail;}\n                                        else if(tail)\n                                                stream.eatWhile(tail);\n                                        state.tokenize=tokenPerl;\n                                        return style;}\n                                e=!e&&c==\"\\\\\";}\n                        return style;};\n                return state.tokenize(stream,state);}\n\n        function tokenSOMETHING(stream,state,string){\n                state.tokenize=function(stream,state){\n                        if(stream.string==string)\n                                state.tokenize=tokenPerl;\n                        stream.skipToEnd();\n                        return \"string\";};\n                return state.tokenize(stream,state);}\n\n        function tokenPerl(stream,state){\n                if(stream.eatSpace())\n                        return null;\n                if(state.chain)\n                        return tokenChain(stream,state,state.chain,state.style,state.tail);\n                if(stream.match(/^\\-?[\\d\\.]/,false))\n                        if(stream.match(/^(\\-?(\\d*\\.\\d+(e[+-]?\\d+)?|\\d+\\.\\d*)|0x[\\da-fA-F]+|0b[01]+|\\d+(e[+-]?\\d+)?)/))\n                                return 'number';\n                if(stream.match(/^<<(?=\\w)/)){                  // NOTE: <<SOMETHING\\n...\\nSOMETHING\\n\n                        stream.eatWhile(/\\w/);\n                        return tokenSOMETHING(stream,state,stream.current().substr(2));}\n                if(stream.sol()&&stream.match(/^\\=item(?!\\w)/)){// NOTE: \\n=item...\\n=cut\\n\n                        return tokenSOMETHING(stream,state,'=cut');}\n                var ch=stream.next();\n                if(ch=='\"'||ch==\"'\"){                           // NOTE: ' or \" or <<'SOMETHING'\\n...\\nSOMETHING\\n or <<\"SOMETHING\"\\n...\\nSOMETHING\\n\n                        if(prefix(stream, 3)==\"<<\"+ch){\n                                var p=stream.pos;\n                                stream.eatWhile(/\\w/);\n                                var n=stream.current().substr(1);\n                                if(n&&stream.eat(ch))\n                                        return tokenSOMETHING(stream,state,n);\n                                stream.pos=p;}\n                        return tokenChain(stream,state,[ch],\"string\");}\n                if(ch==\"q\"){\n                        var c=look(stream, -2);\n                        if(!(c&&/\\w/.test(c))){\n                                c=look(stream, 0);\n                                if(c==\"x\"){\n                                        c=look(stream, 1);\n                                        if(c==\"(\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers);}\n                                        if(c==\"[\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers);}\n                                        if(c==\"{\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers);}\n                                        if(c==\"<\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers);}\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}\n                                else if(c==\"q\"){\n                                        c=look(stream, 1);\n                                        if(c==\"(\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\")\"],\"string\");}\n                                        if(c==\"[\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"]\"],\"string\");}\n                                        if(c==\"{\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"}\"],\"string\");}\n                                        if(c==\"<\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\">\"],\"string\");}\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[stream.eat(c)],\"string\");}}\n                                else if(c==\"w\"){\n                                        c=look(stream, 1);\n                                        if(c==\"(\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\")\"],\"bracket\");}\n                                        if(c==\"[\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"]\"],\"bracket\");}\n                                        if(c==\"{\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"}\"],\"bracket\");}\n                                        if(c==\"<\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\">\"],\"bracket\");}\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[stream.eat(c)],\"bracket\");}}\n                                else if(c==\"r\"){\n                                        c=look(stream, 1);\n                                        if(c==\"(\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers);}\n                                        if(c==\"[\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers);}\n                                        if(c==\"{\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers);}\n                                        if(c==\"<\"){\n                                                eatSuffix(stream, 2);\n                                                return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers);}\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}\n                                else if(/[\\^'\"!~\\/(\\[{<]/.test(c)){\n                                        if(c==\"(\"){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[\")\"],\"string\");}\n                                        if(c==\"[\"){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[\"]\"],\"string\");}\n                                        if(c==\"{\"){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[\"}\"],\"string\");}\n                                        if(c==\"<\"){\n                                                eatSuffix(stream, 1);\n                                                return tokenChain(stream,state,[\">\"],\"string\");}\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                return tokenChain(stream,state,[stream.eat(c)],\"string\");}}}}\n                if(ch==\"m\"){\n                        var c=look(stream, -2);\n                        if(!(c&&/\\w/.test(c))){\n                                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                                if(c){\n                                        if(/[\\^'\"!~\\/]/.test(c)){\n                                                return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}\n                                        if(c==\"(\"){\n                                                return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers);}\n                                        if(c==\"[\"){\n                                                return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers);}\n                                        if(c==\"{\"){\n                                                return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers);}\n                                        if(c==\"<\"){\n                                                return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers);}}}}\n                if(ch==\"s\"){\n                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n                        if(!c){\n                                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                                if(c){\n                                        if(c==\"[\")\n                                                return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                                        if(c==\"{\")\n                                                return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                                        if(c==\"<\")\n                                                return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                                        if(c==\"(\")\n                                                return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                                        return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}\n                if(ch==\"y\"){\n                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n                        if(!c){\n                                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                                if(c){\n                                        if(c==\"[\")\n                                                return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                                        if(c==\"{\")\n                                                return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                                        if(c==\"<\")\n                                                return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                                        if(c==\"(\")\n                                                return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                                        return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}\n                if(ch==\"t\"){\n                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n                        if(!c){\n                                c=stream.eat(\"r\");if(c){\n                                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                                if(c){\n                                        if(c==\"[\")\n                                                return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                                        if(c==\"{\")\n                                                return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                                        if(c==\"<\")\n                                                return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                                        if(c==\"(\")\n                                                return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                                        return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}\n                if(ch==\"`\"){\n                        return tokenChain(stream,state,[ch],\"variable-2\");}\n                if(ch==\"/\"){\n                        if(!/~\\s*$/.test(prefix(stream)))\n                                return \"operator\";\n                        else\n                                return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}\n                if(ch==\"$\"){\n                        var p=stream.pos;\n                        if(stream.eatWhile(/\\d/)||stream.eat(\"{\")&&stream.eatWhile(/\\d/)&&stream.eat(\"}\"))\n                                return \"variable-2\";\n                        else\n                                stream.pos=p;}\n                if(/[$@%]/.test(ch)){\n                        var p=stream.pos;\n                        if(stream.eat(\"^\")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*'\"$+.,\\/<>()]/)){\n                                var c=stream.current();\n                                if(PERL[c])\n                                        return \"variable-2\";}\n                        stream.pos=p;}\n                if(/[$@%&]/.test(ch)){\n                        if(stream.eatWhile(/[\\w$\\[\\]]/)||stream.eat(\"{\")&&stream.eatWhile(/[\\w$\\[\\]]/)&&stream.eat(\"}\")){\n                                var c=stream.current();\n                                if(PERL[c])\n                                        return \"variable-2\";\n                                else\n                                        return \"variable\";}}\n                if(ch==\"#\"){\n                        if(look(stream, -2)!=\"$\"){\n                                stream.skipToEnd();\n                                return \"comment\";}}\n                if(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/.test(ch)){\n                        var p=stream.pos;\n                        stream.eatWhile(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/);\n                        if(PERL[stream.current()])\n                                return \"operator\";\n                        else\n                                stream.pos=p;}\n                if(ch==\"_\"){\n                        if(stream.pos==1){\n                                if(suffix(stream, 6)==\"_END__\"){\n                                        return tokenChain(stream,state,['\\0'],\"comment\");}\n                                else if(suffix(stream, 7)==\"_DATA__\"){\n                                        return tokenChain(stream,state,['\\0'],\"variable-2\");}\n                                else if(suffix(stream, 7)==\"_C__\"){\n                                        return tokenChain(stream,state,['\\0'],\"string\");}}}\n                if(/\\w/.test(ch)){\n                        var p=stream.pos;\n                        if(look(stream, -2)==\"{\"&&(look(stream, 0)==\"}\"||stream.eatWhile(/\\w/)&&look(stream, 0)==\"}\"))\n                                return \"string\";\n                        else\n                                stream.pos=p;}\n                if(/[A-Z]/.test(ch)){\n                        var l=look(stream, -2);\n                        var p=stream.pos;\n                        stream.eatWhile(/[A-Z_]/);\n                        if(/[\\da-z]/.test(look(stream, 0))){\n                                stream.pos=p;}\n                        else{\n                                var c=PERL[stream.current()];\n                                if(!c)\n                                        return \"meta\";\n                                if(c[1])\n                                        c=c[0];\n                                if(l!=\":\"){\n                                        if(c==1)\n                                                return \"keyword\";\n                                        else if(c==2)\n                                                return \"def\";\n                                        else if(c==3)\n                                                return \"atom\";\n                                        else if(c==4)\n                                                return \"operator\";\n                                        else if(c==5)\n                                                return \"variable-2\";\n                                        else\n                                                return \"meta\";}\n                                else\n                                        return \"meta\";}}\n                if(/[a-zA-Z_]/.test(ch)){\n                        var l=look(stream, -2);\n                        stream.eatWhile(/\\w/);\n                        var c=PERL[stream.current()];\n                        if(!c)\n                                return \"meta\";\n                        if(c[1])\n                                c=c[0];\n                        if(l!=\":\"){\n                                if(c==1)\n                                        return \"keyword\";\n                                else if(c==2)\n                                        return \"def\";\n                                else if(c==3)\n                                        return \"atom\";\n                                else if(c==4)\n                                        return \"operator\";\n                                else if(c==5)\n                                        return \"variable-2\";\n                                else\n                                        return \"meta\";}\n                        else\n                                return \"meta\";}\n                return null;}\n\n        return {\n            startState: function() {\n                return {\n                    tokenize: tokenPerl,\n                    chain: null,\n                    style: null,\n                    tail: null\n                };\n            },\n            token: function(stream, state) {\n                return (state.tokenize || tokenPerl)(stream, state);\n            },\n            lineComment: '#'\n        };\n});\n\nCodeMirror.registerHelper(\"wordChars\", \"perl\", /[\\w$]/);\n\nCodeMirror.defineMIME(\"text/x-perl\", \"perl\");\n\n// it's like \"peek\", but need for look-ahead or look-behind if index < 0\nfunction look(stream, c){\n  return stream.string.charAt(stream.pos+(c||0));\n}\n\n// return a part of prefix of current stream from current position\nfunction prefix(stream, c){\n  if(c){\n    var x=stream.pos-c;\n    return stream.string.substr((x>=0?x:0),c);}\n  else{\n    return stream.string.substr(0,stream.pos-1);\n  }\n}\n\n// return a part of suffix of current stream from current position\nfunction suffix(stream, c){\n  var y=stream.string.length;\n  var x=y-stream.pos+1;\n  return stream.string.substr(stream.pos,(c&&c<y?c:x));\n}\n\n// eating and vomiting a part of stream from current position\nfunction eatSuffix(stream, c){\n  var x=stream.pos+c;\n  var y;\n  if(x<=0)\n    stream.pos=0;\n  else if(x>=(y=stream.string.length-1))\n    stream.pos=y;\n  else\n    stream.pos=x;\n}\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/php/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: PHP mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"../clike/clike.js\"></script>\n<script src=\"php.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">PHP</a>\n  </ul>\n</div>\n\n<article>\n<h2>PHP mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n<?php\n$a = array('a' => 1, 'b' => 2, 3 => 'c');\n\necho \"$a[a] ${a[3] /* } comment */} {$a[b]} \\$a[a]\";\n\nfunction hello($who) {\n\treturn \"Hello $who!\";\n}\n?>\n<p>The program says <?= hello(\"World\") ?>.</p>\n<script>\n\talert(\"And here is some JS code\"); // also colored\n</script>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"application/x-httpd-php\",\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n    </script>\n\n    <p>Simple HTML/PHP mode based on\n    the <a href=\"../clike/\">C-like</a> mode. Depends on XML,\n    JavaScript, CSS, HTMLMixed, and C-like modes.</p>\n\n    <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/php/php.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\"), require(\"../htmlmixed/htmlmixed\"), require(\"../clike/clike\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\", \"../clike/clike\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  function keywords(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\n  // Helper for stringWithEscapes\n  function matchSequence(list, end) {\n    if (list.length == 0) return stringWithEscapes(end);\n    return function (stream, state) {\n      var patterns = list[0];\n      for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {\n        state.tokenize = matchSequence(list.slice(1), end);\n        return patterns[i][1];\n      }\n      state.tokenize = stringWithEscapes(end);\n      return \"string\";\n    };\n  }\n  function stringWithEscapes(closing) {\n    return function(stream, state) { return stringWithEscapes_(stream, state, closing); };\n  }\n  function stringWithEscapes_(stream, state, closing) {\n    // \"Complex\" syntax\n    if (stream.match(\"${\", false) || stream.match(\"{$\", false)) {\n      state.tokenize = null;\n      return \"string\";\n    }\n\n    // Simple syntax\n    if (stream.match(/^\\$[a-zA-Z_][a-zA-Z0-9_]*/)) {\n      // After the variable name there may appear array or object operator.\n      if (stream.match(\"[\", false)) {\n        // Match array operator\n        state.tokenize = matchSequence([\n          [[\"[\", null]],\n          [[/\\d[\\w\\.]*/, \"number\"],\n           [/\\$[a-zA-Z_][a-zA-Z0-9_]*/, \"variable-2\"],\n           [/[\\w\\$]+/, \"variable\"]],\n          [[\"]\", null]]\n        ], closing);\n      }\n      if (stream.match(/\\-\\>\\w/, false)) {\n        // Match object operator\n        state.tokenize = matchSequence([\n          [[\"->\", null]],\n          [[/[\\w]+/, \"variable\"]]\n        ], closing);\n      }\n      return \"variable-2\";\n    }\n\n    var escaped = false;\n    // Normal string\n    while (!stream.eol() &&\n           (escaped || (!stream.match(\"{$\", false) &&\n                        !stream.match(/^(\\$[a-zA-Z_][a-zA-Z0-9_]*|\\$\\{)/, false)))) {\n      if (!escaped && stream.match(closing)) {\n        state.tokenize = null;\n        state.tokStack.pop(); state.tokStack.pop();\n        break;\n      }\n      escaped = stream.next() == \"\\\\\" && !escaped;\n    }\n    return \"string\";\n  }\n\n  var phpKeywords = \"abstract and array as break case catch class clone const continue declare default \" +\n    \"do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final \" +\n    \"for foreach function global goto if implements interface instanceof namespace \" +\n    \"new or private protected public static switch throw trait try use var while xor \" +\n    \"die echo empty exit eval include include_once isset list require require_once return \" +\n    \"print unset __halt_compiler self static parent yield insteadof finally\";\n  var phpAtoms = \"true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__\";\n  var phpBuiltin = \"func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count\";\n  CodeMirror.registerHelper(\"hintWords\", \"php\", [phpKeywords, phpAtoms, phpBuiltin].join(\" \").split(\" \"));\n  CodeMirror.registerHelper(\"wordChars\", \"php\", /[\\w$]/);\n\n  var phpConfig = {\n    name: \"clike\",\n    helperType: \"php\",\n    keywords: keywords(phpKeywords),\n    blockKeywords: keywords(\"catch do else elseif for foreach if switch try while finally\"),\n    atoms: keywords(phpAtoms),\n    builtin: keywords(phpBuiltin),\n    multiLineStrings: true,\n    hooks: {\n      \"$\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"variable-2\";\n      },\n      \"<\": function(stream, state) {\n        if (stream.match(/<</)) {\n          stream.eatWhile(/[\\w\\.]/);\n          var delim = stream.current().slice(3);\n          if (delim) {\n            (state.tokStack || (state.tokStack = [])).push(delim, 0);\n            state.tokenize = stringWithEscapes(delim);\n            return \"string\";\n          }\n        }\n        return false;\n      },\n      \"#\": function(stream) {\n        while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n        return \"comment\";\n      },\n      \"/\": function(stream) {\n        if (stream.eat(\"/\")) {\n          while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n          return \"comment\";\n        }\n        return false;\n      },\n      '\"': function(_stream, state) {\n        (state.tokStack || (state.tokStack = [])).push('\"', 0);\n        state.tokenize = stringWithEscapes('\"');\n        return \"string\";\n      },\n      \"{\": function(_stream, state) {\n        if (state.tokStack && state.tokStack.length)\n          state.tokStack[state.tokStack.length - 1]++;\n        return false;\n      },\n      \"}\": function(_stream, state) {\n        if (state.tokStack && state.tokStack.length > 0 &&\n            !--state.tokStack[state.tokStack.length - 1]) {\n          state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]);\n        }\n        return false;\n      }\n    }\n  };\n\n  CodeMirror.defineMode(\"php\", function(config, parserConfig) {\n    var htmlMode = CodeMirror.getMode(config, \"text/html\");\n    var phpMode = CodeMirror.getMode(config, phpConfig);\n\n    function dispatch(stream, state) {\n      var isPHP = state.curMode == phpMode;\n      if (stream.sol() && state.pending && state.pending != '\"' && state.pending != \"'\") state.pending = null;\n      if (!isPHP) {\n        if (stream.match(/^<\\?\\w*/)) {\n          state.curMode = phpMode;\n          state.curState = state.php;\n          return \"meta\";\n        }\n        if (state.pending == '\"' || state.pending == \"'\") {\n          while (!stream.eol() && stream.next() != state.pending) {}\n          var style = \"string\";\n        } else if (state.pending && stream.pos < state.pending.end) {\n          stream.pos = state.pending.end;\n          var style = state.pending.style;\n        } else {\n          var style = htmlMode.token(stream, state.curState);\n        }\n        if (state.pending) state.pending = null;\n        var cur = stream.current(), openPHP = cur.search(/<\\?/), m;\n        if (openPHP != -1) {\n          if (style == \"string\" && (m = cur.match(/[\\'\\\"]$/)) && !/\\?>/.test(cur)) state.pending = m[0];\n          else state.pending = {end: stream.pos, style: style};\n          stream.backUp(cur.length - openPHP);\n        }\n        return style;\n      } else if (isPHP && state.php.tokenize == null && stream.match(\"?>\")) {\n        state.curMode = htmlMode;\n        state.curState = state.html;\n        return \"meta\";\n      } else {\n        return phpMode.token(stream, state.curState);\n      }\n    }\n\n    return {\n      startState: function() {\n        var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);\n        return {html: html,\n                php: php,\n                curMode: parserConfig.startOpen ? phpMode : htmlMode,\n                curState: parserConfig.startOpen ? php : html,\n                pending: null};\n      },\n\n      copyState: function(state) {\n        var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),\n            php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;\n        if (state.curMode == htmlMode) cur = htmlNew;\n        else cur = phpNew;\n        return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,\n                pending: state.pending};\n      },\n\n      token: dispatch,\n\n      indent: function(state, textAfter) {\n        if ((state.curMode != phpMode && /^\\s*<\\//.test(textAfter)) ||\n            (state.curMode == phpMode && /^\\?>/.test(textAfter)))\n          return htmlMode.indent(state.html, textAfter);\n        return state.curMode.indent(state.curState, textAfter);\n      },\n\n      blockCommentStart: \"/*\",\n      blockCommentEnd: \"*/\",\n      lineComment: \"//\",\n\n      innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }\n    };\n  }, \"htmlmixed\", \"clike\");\n\n  CodeMirror.defineMIME(\"application/x-httpd-php\", \"php\");\n  CodeMirror.defineMIME(\"application/x-httpd-php-open\", {name: \"php\", startOpen: true});\n  CodeMirror.defineMIME(\"text/x-php\", phpConfig);\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/php/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"php\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT('simple_test',\n     '[meta <?php] ' +\n     '[keyword echo] [string \"aaa\"]; ' +\n     '[meta ?>]');\n\n  MT('variable_interpolation_non_alphanumeric',\n     '[meta <?php]',\n     '[keyword echo] [string \"aaa$~$!$@$#$$$%$^$&$*$($)$.$<$>$/$\\\\$}$\\\\\\\"$:$;$?$|$[[$]]$+$=aaa\"]',\n     '[meta ?>]');\n\n  MT('variable_interpolation_digits',\n     '[meta <?php]',\n     '[keyword echo] [string \"aaa$1$2$3$4$5$6$7$8$9$0aaa\"]',\n     '[meta ?>]');\n\n  MT('variable_interpolation_simple_syntax_1',\n     '[meta <?php]',\n     '[keyword echo] [string \"aaa][variable-2 $aaa][string .aaa\"];',\n     '[meta ?>]');\n\n  MT('variable_interpolation_simple_syntax_2',\n     '[meta <?php]',\n     '[keyword echo] [string \"][variable-2 $aaaa][[','[number 2]',         ']][string aa\"];',\n     '[keyword echo] [string \"][variable-2 $aaaa][[','[number 2345]',      ']][string aa\"];',\n     '[keyword echo] [string \"][variable-2 $aaaa][[','[number 2.3]',       ']][string aa\"];',\n     '[keyword echo] [string \"][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa\"];',\n     '[keyword echo] [string \"][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa\"];',\n\n     '[keyword echo] [string \"1aaa][variable-2 $aaaa][[','[number 2]',         ']][string aa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa][[','[number 2345]',      ']][string aa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa][[','[number 2.3]',       ']][string aa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa\"];',\n     '[meta ?>]');\n\n  MT('variable_interpolation_simple_syntax_3',\n     '[meta <?php]',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa]->[variable aaaaa][string .aaaaaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa\"];',\n     '[meta ?>]');\n\n  MT('variable_interpolation_escaping',\n     '[meta <?php] [comment /* Escaping */]',\n     '[keyword echo] [string \"aaa\\\\$aaaa->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa\\\\$aaaa[[2]]aaa.aaa\"];',\n     '[keyword echo] [string \"aaa\\\\$aaaa[[asd]]aaa.aaa\"];',\n     '[keyword echo] [string \"aaa{\\\\$aaaa->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa{\\\\$aaaa[[2]]aaa.aaa\"];',\n     '[keyword echo] [string \"aaa{\\\\aaaaa[[asd]]aaa.aaa\"];',\n     '[keyword echo] [string \"aaa\\\\${aaaa->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa\\\\${aaaa[[2]]aaa.aaa\"];',\n     '[keyword echo] [string \"aaa\\\\${aaaa[[asd]]aaa.aaa\"];',\n     '[meta ?>]');\n\n  MT('variable_interpolation_complex_syntax_1',\n     '[meta <?php]',\n     '[keyword echo] [string \"aaa][variable-2 $]{[variable aaaa]}[string ->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $]{[variable-2 $aaaa][[','  [number 42]',']]}[string ->aaa.aaa\"];',\n     '[keyword echo] [string \"aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa');\n\n  MT('variable_interpolation_complex_syntax_2',\n     '[meta <?php] [comment /* Monsters */]',\n     '[keyword echo] [string \"][variable-2 $]{[variable aaa][comment /*}?>} $aaa<?php } */]}[string ->aaa.aaa\"];',\n     '[keyword echo] [string \"][variable-2 $]{[variable aaa][comment /*}?>*/][[','  [string \"aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string \"]',']]}[string ->aaa.aaa\"];',\n     '[keyword echo] [string \"][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa\"];');\n\n\n  function build_recursive_monsters(nt, t, n){\n    var monsters = [t];\n    for (var i = 1; i <= n; ++i)\n      monsters[i] = nt.join(monsters[i - 1]);\n    return monsters;\n  }\n\n  var m1 = build_recursive_monsters(\n    ['[string \"][variable-2 $]{[variable aaa] [operator +] ', '}[string \"]'],\n    '[comment /* }?>} */] [string \"aaa][variable-2 $aaa][string .aaa\"]',\n    10\n  );\n\n  MT('variable_interpolation_complex_syntax_3_1',\n     '[meta <?php] [comment /* Recursive monsters */]',\n     '[keyword echo] ' + m1[4] + ';',\n     '[keyword echo] ' + m1[7] + ';',\n     '[keyword echo] ' + m1[8] + ';',\n     '[keyword echo] ' + m1[5] + ';',\n     '[keyword echo] ' + m1[1] + ';',\n     '[keyword echo] ' + m1[6] + ';',\n     '[keyword echo] ' + m1[9] + ';',\n     '[keyword echo] ' + m1[0] + ';',\n     '[keyword echo] ' + m1[10] + ';',\n     '[keyword echo] ' + m1[2] + ';',\n     '[keyword echo] ' + m1[3] + ';',\n     '[keyword echo] [string \"end\"];',\n     '[meta ?>]');\n\n  var m2 = build_recursive_monsters(\n    ['[string \"a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', '}[string .a\"]'],\n    '[comment /* }?>{{ */] [string \"a?>}{{aa][variable-2 $aaa][string .a}a?>a\"]',\n    5\n  );\n\n  MT('variable_interpolation_complex_syntax_3_2',\n     '[meta <?php] [comment /* Recursive monsters 2 */]',\n     '[keyword echo] ' + m2[0] + ';',\n     '[keyword echo] ' + m2[1] + ';',\n     '[keyword echo] ' + m2[5] + ';',\n     '[keyword echo] ' + m2[4] + ';',\n     '[keyword echo] ' + m2[2] + ';',\n     '[keyword echo] ' + m2[3] + ';',\n     '[keyword echo] [string \"end\"];',\n     '[meta ?>]');\n\n  function build_recursive_monsters_2(mf1, mf2, nt, t, n){\n    var monsters = [t];\n    for (var i = 1; i <= n; ++i)\n      monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3];\n    return monsters;\n  }\n\n  var m3 = build_recursive_monsters_2(\n    m1,\n    m2,\n    ['[string \"a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', ' [operator +] ', '}[string .a\"]'],\n    '[comment /* }?>{{ */] [string \"a?>}{{aa][variable-2 $aaa][string .a}a?>a\"]',\n    4\n  );\n\n  MT('variable_interpolation_complex_syntax_3_3',\n     '[meta <?php] [comment /* Recursive monsters 2 */]',\n     '[keyword echo] ' + m3[4] + ';',\n     '[keyword echo] ' + m3[0] + ';',\n     '[keyword echo] ' + m3[3] + ';',\n     '[keyword echo] ' + m3[1] + ';',\n     '[keyword echo] ' + m3[2] + ';',\n     '[keyword echo] [string \"end\"];',\n     '[meta ?>]');\n\n  MT(\"variable_interpolation_heredoc\",\n     \"[meta <?php]\",\n     \"[string <<<here]\",\n     \"[string doc ][variable-2 $]{[variable yay]}[string more]\",\n     \"[string here]; [comment // normal]\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pig/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Pig Latin mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"pig.js\"></script>\n<style>.CodeMirror {border: 2px inset #dee;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Pig Latin</a>\n  </ul>\n</div>\n\n<article>\n<h2>Pig Latin mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n-- Apache Pig (Pig Latin Language) Demo\n/*\nThis is a multiline comment.\n*/\na = LOAD \"\\path\\to\\input\" USING PigStorage('\\t') AS (x:long, y:chararray, z:bytearray);\nb = GROUP a BY (x,y,3+4);\nc = FOREACH b GENERATE flatten(group) as (x,y), SUM(group.$2) as z;\nSTORE c INTO \"\\path\\to\\output\";\n\n--\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        indentUnit: 4,\n        mode: \"text/x-pig\"\n      });\n    </script>\n\n    <p>\n        Simple mode that handles Pig Latin language.\n    </p>\n\n    <p><strong>MIME type defined:</strong> <code>text/x-pig</code>\n    (PIG code)\n</html>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/pig/pig.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\n *      Pig Latin Mode for CodeMirror 2\n *      @author 郑保乐\n *      @link   https://github.com/prasanthj/pig-codemirror-2\n *  This implementation is adapted from PL/SQL mode in CodeMirror 2.\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(\"pig\", function(_config, parserConfig) {\n  var keywords = parserConfig.keywords,\n  builtins = parserConfig.builtins,\n  types = parserConfig.types,\n  multiLineStrings = parserConfig.multiLineStrings;\n\n  var isOperatorChar = /[*+\\-%<>=&?:\\/!|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  var type;\n  function ret(tp, style) {\n    type = tp;\n    return style;\n  }\n\n  function tokenComment(stream, state) {\n    var isEnd = false;\n    var ch;\n    while(ch = stream.next()) {\n      if(ch == \"/\" && isEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      isEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\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) {\n          end = true; break;\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = tokenBase;\n      return ret(\"string\", \"error\");\n    };\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n    // is a start of string?\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, tokenString(ch));\n    // is it one of the special chars\n    else if(/[\\[\\]{}\\(\\),;\\.]/.test(ch))\n      return ret(ch);\n    // is it a number?\n    else if(/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return ret(\"number\", \"number\");\n    }\n    // multi line comment or operator\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, tokenComment);\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\");\n      }\n    }\n    // single line comment or operator\n    else if (ch==\"-\") {\n      if(stream.eat(\"-\")){\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\");\n      }\n    }\n    // is it an operator\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", \"operator\");\n    }\n    else {\n      // get the while word\n      stream.eatWhile(/[\\w\\$_]/);\n      // is it one of the listed keywords?\n      if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {\n        if (stream.eat(\")\") || stream.eat(\".\")) {\n          //keywords can be used as variables like flatten(group), group.$0 etc..\n        }\n        else {\n          return (\"keyword\", \"keyword\");\n        }\n      }\n      // is it one of the builtin functions?\n      if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))\n      {\n        return (\"keyword\", \"variable-2\");\n      }\n      // is it one of the listed types?\n      if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))\n        return (\"keyword\", \"variable-3\");\n      // default is a 'variable'\n      return ret(\"variable\", \"pig-word\");\n    }\n  }\n\n  // Interface\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      if(stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    }\n  };\n});\n\n(function() {\n  function keywords(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\n  // builtin funcs taken from trunk revision 1303237\n  var pBuiltins = \"ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL \"\n    + \"CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS \"\n    + \"DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG \"\n    + \"FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN \"\n    + \"INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER \"\n    + \"ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS \"\n    + \"LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  \"\n    + \"PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE \"\n    + \"SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG \"\n    + \"TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER \";\n\n  // taken from QueryLexer.g\n  var pKeywords = \"VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP \"\n    + \"JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL \"\n    + \"PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE \"\n    + \"SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE \"\n    + \"NEQ MATCHES TRUE FALSE DUMP\";\n\n  // data types\n  var pTypes = \"BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP \";\n\n  CodeMirror.defineMIME(\"text/x-pig\", {\n    name: \"pig\",\n    builtins: keywords(pBuiltins),\n    keywords: keywords(pKeywords),\n    types: keywords(pTypes)\n  });\n\n  CodeMirror.registerHelper(\"hintWords\", \"pig\", (pBuiltins + pTypes + pKeywords).split(\" \"));\n}());\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/properties/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Properties files mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"properties.js\"></script>\n<style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Properties files</a>\n  </ul>\n</div>\n\n<article>\n<h2>Properties files mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# This is a properties file\na.key = A value\nanother.key = http://example.com\n! Exclamation mark as comment\nbut.not=Within ! A value # indeed\n   # Spaces at the beginning of a line\n   spaces.before.key=value\nbackslash=Used for multi\\\n          line entries,\\\n          that's convenient.\n# Unicode sequences\nunicode.key=This is \\u0020 Unicode\nno.multiline=here\n# Colons\ncolons : can be used too\n# Spaces\nspaces\\ in\\ keys=Not very common...\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-properties</code>,\n    <code>text/x-ini</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/properties/properties.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(\"properties\", function() {\n  return {\n    token: function(stream, state) {\n      var sol = stream.sol() || state.afterSection;\n      var eol = stream.eol();\n\n      state.afterSection = false;\n\n      if (sol) {\n        if (state.nextMultiline) {\n          state.inMultiline = true;\n          state.nextMultiline = false;\n        } else {\n          state.position = \"def\";\n        }\n      }\n\n      if (eol && ! state.nextMultiline) {\n        state.inMultiline = false;\n        state.position = \"def\";\n      }\n\n      if (sol) {\n        while(stream.eatSpace());\n      }\n\n      var ch = stream.next();\n\n      if (sol && (ch === \"#\" || ch === \"!\" || ch === \";\")) {\n        state.position = \"comment\";\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (sol && ch === \"[\") {\n        state.afterSection = true;\n        stream.skipTo(\"]\"); stream.eat(\"]\");\n        return \"header\";\n      } else if (ch === \"=\" || ch === \":\") {\n        state.position = \"quote\";\n        return null;\n      } else if (ch === \"\\\\\" && state.position === \"quote\") {\n        if (stream.next() !== \"u\") {    // u = Unicode sequence \\u1234\n          // Multiline value\n          state.nextMultiline = true;\n        }\n      }\n\n      return state.position;\n    },\n\n    startState: function() {\n      return {\n        position : \"def\",       // Current position, \"def\", \"quote\" or \"comment\"\n        nextMultiline : false,  // Is the next line multiline value\n        inMultiline : false,    // Is the current line a multiline value\n        afterSection : false    // Did we just open a section\n      };\n    }\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-properties\", \"properties\");\nCodeMirror.defineMIME(\"text/x-ini\", \"properties\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/puppet/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Puppet mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"puppet.js\"></script>\n<style>\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .cm-s-default span.cm-arrow { color: red; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Puppet</a>\n  </ul>\n</div>\n\n<article>\n<h2>Puppet mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# == Class: automysqlbackup\n#\n# Puppet module to install AutoMySQLBackup for periodic MySQL backups.\n#\n# class { 'automysqlbackup':\n#   backup_dir => '/mnt/backups',\n# }\n#\n\nclass automysqlbackup (\n  $bin_dir = $automysqlbackup::params::bin_dir,\n  $etc_dir = $automysqlbackup::params::etc_dir,\n  $backup_dir = $automysqlbackup::params::backup_dir,\n  $install_multicore = undef,\n  $config = {},\n  $config_defaults = {},\n) inherits automysqlbackup::params {\n\n# Ensure valid paths are assigned\n  validate_absolute_path($bin_dir)\n  validate_absolute_path($etc_dir)\n  validate_absolute_path($backup_dir)\n\n# Create a subdirectory in /etc for config files\n  file { $etc_dir:\n    ensure => directory,\n    owner => 'root',\n    group => 'root',\n    mode => '0750',\n  }\n\n# Create an example backup file, useful for reference\n  file { \"${etc_dir}/automysqlbackup.conf.example\":\n    ensure => file,\n    owner => 'root',\n    group => 'root',\n    mode => '0660',\n    source => 'puppet:///modules/automysqlbackup/automysqlbackup.conf',\n  }\n\n# Add files from the developer\n  file { \"${etc_dir}/AMB_README\":\n    ensure => file,\n    source => 'puppet:///modules/automysqlbackup/AMB_README',\n  }\n  file { \"${etc_dir}/AMB_LICENSE\":\n    ensure => file,\n    source => 'puppet:///modules/automysqlbackup/AMB_LICENSE',\n  }\n\n# Install the actual binary file\n  file { \"${bin_dir}/automysqlbackup\":\n    ensure => file,\n    owner => 'root',\n    group => 'root',\n    mode => '0755',\n    source => 'puppet:///modules/automysqlbackup/automysqlbackup',\n  }\n\n# Create the base backup directory\n  file { $backup_dir:\n    ensure => directory,\n    owner => 'root',\n    group => 'root',\n    mode => '0755',\n  }\n\n# If you'd like to keep your config in hiera and pass it to this class\n  if !empty($config) {\n    create_resources('automysqlbackup::backup', $config, $config_defaults)\n  }\n\n# If using RedHat family, must have the RPMforge repo's enabled\n  if $install_multicore {\n    package { ['pigz', 'pbzip2']: ensure => installed }\n  }\n\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-puppet\",\n        matchBrackets: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-puppet</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/puppet/puppet.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(\"puppet\", function () {\n  // Stores the words from the define method\n  var words = {};\n  // Taken, mostly, from the Puppet official variable standards regex\n  var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/;\n\n  // Takes a string of words separated by spaces and adds them as\n  // keys with the value of the first argument 'style'\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  // Takes commonly known puppet types/words and classifies them to a style\n  define('keyword', 'class define site node include import inherits');\n  define('keyword', 'case if else in and elsif default or');\n  define('atom', 'false true running present absent file directory undef');\n  define('builtin', 'action augeas burst chain computer cron destination dport exec ' +\n    'file filebucket group host icmp iniface interface jump k5login limit log_level ' +\n    'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' +\n    'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' +\n    'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' +\n    'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' +\n    'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' +\n    'resources router schedule scheduled_task selboolean selmodule service source ' +\n    'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' +\n    'user vlan yumrepo zfs zone zpool');\n\n  // After finding a start of a string ('|\") this function attempts to find the end;\n  // If a variable is encountered along the way, we display it differently when it\n  // is encapsulated in a double-quoted string.\n  function tokenString(stream, state) {\n    var current, prev, found_var = false;\n    while (!stream.eol() && (current = stream.next()) != state.pending) {\n      if (current === '$' && prev != '\\\\' && state.pending == '\"') {\n        found_var = true;\n        break;\n      }\n      prev = current;\n    }\n    if (found_var) {\n      stream.backUp(1);\n    }\n    if (current == state.pending) {\n      state.continueString = false;\n    } else {\n      state.continueString = true;\n    }\n    return \"string\";\n  }\n\n  // Main function\n  function tokenize(stream, state) {\n    // Matches one whole word\n    var word = stream.match(/[\\w]+/, false);\n    // Matches attributes (i.e. ensure => present ; 'ensure' would be matched)\n    var attribute = stream.match(/(\\s+)?\\w+\\s+=>.*/, false);\n    // Matches non-builtin resource declarations\n    // (i.e. \"apache::vhost {\" or \"mycustomclasss {\" would be matched)\n    var resource = stream.match(/(\\s+)?[\\w:_]+(\\s+)?{/, false);\n    // Matches virtual and exported resources (i.e. @@user { ; and the like)\n    var special_resource = stream.match(/(\\s+)?[@]{1,2}[\\w:_]+(\\s+)?{/, false);\n\n    // Finally advance the stream\n    var ch = stream.next();\n\n    // Have we found a variable?\n    if (ch === '$') {\n      if (stream.match(variable_regex)) {\n        // If so, and its in a string, assign it a different color\n        return state.continueString ? 'variable-2' : 'variable';\n      }\n      // Otherwise return an invalid variable\n      return \"error\";\n    }\n    // Should we still be looking for the end of a string?\n    if (state.continueString) {\n      // If so, go through the loop again\n      stream.backUp(1);\n      return tokenString(stream, state);\n    }\n    // Are we in a definition (class, node, define)?\n    if (state.inDefinition) {\n      // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched)\n      if (stream.match(/(\\s+)?[\\w:_]+(\\s+)?/)) {\n        return 'def';\n      }\n      // Match the rest it the next time around\n      stream.match(/\\s+{/);\n      state.inDefinition = false;\n    }\n    // Are we in an 'include' statement?\n    if (state.inInclude) {\n      // Match and return the included class\n      stream.match(/(\\s+)?\\S+(\\s+)?/);\n      state.inInclude = false;\n      return 'def';\n    }\n    // Do we just have a function on our hands?\n    // In 'ensure_resource(\"myclass\")', 'ensure_resource' is matched\n    if (stream.match(/(\\s+)?\\w+\\(/)) {\n      stream.backUp(1);\n      return 'def';\n    }\n    // Have we matched the prior attribute regex?\n    if (attribute) {\n      stream.match(/(\\s+)?\\w+/);\n      return 'tag';\n    }\n    // Do we have Puppet specific words?\n    if (word && words.hasOwnProperty(word)) {\n      // Negates the initial next()\n      stream.backUp(1);\n      // Acutally move the stream\n      stream.match(/[\\w]+/);\n      // We want to process these words differently\n      // do to the importance they have in Puppet\n      if (stream.match(/\\s+\\S+\\s+{/, false)) {\n        state.inDefinition = true;\n      }\n      if (word == 'include') {\n        state.inInclude = true;\n      }\n      // Returns their value as state in the prior define methods\n      return words[word];\n    }\n    // Is there a match on a reference?\n    if (/(^|\\s+)[A-Z][\\w:_]+/.test(word)) {\n      // Negate the next()\n      stream.backUp(1);\n      // Match the full reference\n      stream.match(/(^|\\s+)[A-Z][\\w:_]+/);\n      return 'def';\n    }\n    // Have we matched the prior resource regex?\n    if (resource) {\n      stream.match(/(\\s+)?[\\w:_]+/);\n      return 'def';\n    }\n    // Have we matched the prior special_resource regex?\n    if (special_resource) {\n      stream.match(/(\\s+)?[@]{1,2}/);\n      return 'special';\n    }\n    // Match all the comments. All of them.\n    if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    // Have we found a string?\n    if (ch == \"'\" || ch == '\"') {\n      // Store the type (single or double)\n      state.pending = ch;\n      // Perform the looping function to find the end\n      return tokenString(stream, state);\n    }\n    // Match all the brackets\n    if (ch == '{' || ch == '}') {\n      return 'bracket';\n    }\n    // Match characters that we are going to assume\n    // are trying to be regex\n    if (ch == '/') {\n      stream.match(/.*?\\//);\n      return 'variable-3';\n    }\n    // Match all the numbers\n    if (ch.match(/[0-9]/)) {\n      stream.eatWhile(/[0-9]+/);\n      return 'number';\n    }\n    // Match the '=' and '=>' operators\n    if (ch == '=') {\n      if (stream.peek() == '>') {\n          stream.next();\n      }\n      return \"operator\";\n    }\n    // Keep advancing through all the rest\n    stream.eatWhile(/[\\w-]/);\n    // Return a blank line for everything else\n    return null;\n  }\n  // Start it all\n  return {\n    startState: function () {\n      var state = {};\n      state.inDefinition = false;\n      state.inInclude = false;\n      state.continueString = false;\n      state.pending = false;\n      return state;\n    },\n    token: function (stream, state) {\n      // Strip the spaces, but regex will account for them eitherway\n      if (stream.eatSpace()) return null;\n      // Go through the main process\n      return tokenize(stream, state);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-puppet\", \"puppet\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/python/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Python mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"python.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Python</a>\n  </ul>\n</div>\n\n<article>\n<h2>Python mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n# Literals\n1234\n0.0e101\n.123\n0b01010011100\n0o01234567\n0x0987654321abcdef\n7\n2147483647\n3L\n79228162514264337593543950336L\n0x100000000L\n79228162514264337593543950336\n0xdeadbeef\n3.14j\n10.j\n10j\n.001j\n1e100j\n3.14e-10j\n\n\n# String Literals\n'For\\''\n\"God\\\"\"\n\"\"\"so loved\nthe world\"\"\"\n'''that he gave\nhis only begotten\\' '''\n'that whosoever believeth \\\nin him'\n''\n\n# Identifiers\n__a__\na.b\na.b.c\n\n#Unicode identifiers on Python3\n# a = x\\ddot\na⃗ = ẍ\n# a = v\\dot\na⃗ = v̇\n\n#F\\vec = m \\cdot a\\vec\nF⃗ = m•a⃗\n\n# Operators\n+ - * / % & | ^ ~ < >\n== != <= >= <> << >> // **\nand or not in is\n\n#infix matrix multiplication operator (PEP 465)\nA @ B\n\n# Delimiters\n() [] {} , : ` = ; @ .  # Note that @ and . require the proper context on Python 2.\n+= -= *= /= %= &= |= ^=\n//= >>= <<= **=\n\n# Keywords\nas assert break class continue def del elif else except\nfinally for from global if import lambda pass raise\nreturn try while with yield\n\n# Python 2 Keywords (otherwise Identifiers)\nexec print\n\n# Python 3 Keywords (otherwise Identifiers)\nnonlocal\n\n# Types\nbool classmethod complex dict enumerate float frozenset int list object\nproperty reversed set slice staticmethod str super tuple type\n\n# Python 2 Types (otherwise Identifiers)\nbasestring buffer file long unicode xrange\n\n# Python 3 Types (otherwise Identifiers)\nbytearray bytes filter map memoryview open range zip\n\n# Some Example code\nimport os\nfrom package import ParentClass\n\n@nonsenseDecorator\ndef doesNothing():\n    pass\n\nclass ExampleClass(ParentClass):\n    @staticmethod\n    def example(inputStr):\n        a = list(inputStr)\n        a.reverse()\n        return ''.join(a)\n\n    def __init__(self, mixin = 'Hello'):\n        self.mixin = mixin\n\n</textarea></div>\n\n\n<h2>Cython mode</h2>\n\n<div><textarea id=\"code-cython\" name=\"code-cython\">\n\nimport numpy as np\ncimport cython\nfrom libc.math cimport sqrt\n\n@cython.boundscheck(False)\n@cython.wraparound(False)\ndef pairwise_cython(double[:, ::1] X):\n    cdef int M = X.shape[0]\n    cdef int N = X.shape[1]\n    cdef double tmp, d\n    cdef double[:, ::1] D = np.empty((M, M), dtype=np.float64)\n    for i in range(M):\n        for j in range(M):\n            d = 0.0\n            for k in range(N):\n                tmp = X[i, k] - X[j, k]\n                d += tmp * tmp\n            D[i, j] = sqrt(d)\n    return np.asarray(D)\n\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"python\",\n               version: 3,\n               singleLineStringErrors: false},\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n    });\n\n    CodeMirror.fromTextArea(document.getElementById(\"code-cython\"), {\n        mode: {name: \"text/x-cython\",\n               version: 2,\n               singleLineStringErrors: false},\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n      });\n    </script>\n    <h2>Configuration Options for Python mode:</h2>\n    <ul>\n      <li>version - 2/3 - The version of Python to recognize.  Default is 2.</li>\n      <li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>\n      <li>hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.</li>\n    </ul>\n    <h2>Advanced Configuration Options:</h2>\n    <p>Usefull for superset of python syntax like Enthought enaml, IPython magics and  questionmark help</p>\n    <ul>\n      <li>singleOperators - RegEx - Regular Expression for single operator matching,  default : <pre>^[\\\\+\\\\-\\\\*/%&amp;|\\\\^~&lt;&gt;!]</pre> including <pre>@</pre> on Python 3</li>\n      <li>singleDelimiters - RegEx - Regular Expression for single delimiter matching, default :  <pre>^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]</pre></li>\n      <li>doubleOperators - RegEx - Regular Expression for double operators matching, default : <pre>^((==)|(!=)|(&lt;=)|(&gt;=)|(&lt;&gt;)|(&lt;&lt;)|(&gt;&gt;)|(//)|(\\\\*\\\\*))</pre></li>\n      <li>doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default : <pre>^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&amp;=)|(\\\\|=)|(\\\\^=))</pre></li>\n      <li>tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default : <pre>^((//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\\\*\\\\*=))</pre></li>\n      <li>identifiers - RegEx - Regular Expression for identifier, default : <pre>^[_A-Za-z][_A-Za-z0-9]*</pre> on Python 2 and <pre>^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*</pre> on Python 3.</li>\n      <li>extra_keywords - list of string - List of extra words ton consider as keywords</li>\n      <li>extra_builtins - list of string - List of extra words ton consider as builtins</li>\n    </ul>\n\n\n    <p><strong>MIME types defined:</strong> <code>text/x-python</code> and <code>text/x-cython</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/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  var py2 = {builtins: [\"apply\", \"basestring\", \"buffer\", \"cmp\", \"coerce\", \"execfile\",\n                        \"file\", \"intern\", \"long\", \"raw_input\", \"reduce\", \"reload\",\n                        \"unichr\", \"unicode\", \"xrange\", \"False\", \"True\", \"None\"],\n             keywords: [\"exec\", \"print\"]};\n  var py3 = {builtins: [\"ascii\", \"bytes\", \"exec\", \"print\"],\n             keywords: [\"nonlocal\", \"False\", \"True\", \"None\"]};\n\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 || new RegExp(\"^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]\");\n    var doubleOperators = parserConf.doubleOperators || new RegExp(\"^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\\\*\\\\*))\");\n    var doubleDelimiters = parserConf.doubleDelimiters || new RegExp(\"^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = parserConf.tripleDelimiters || new RegExp(\"^((//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n\n    if (parserConf.version && parseInt(parserConf.version, 10) == 3){\n        // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator\n        var singleOperators = parserConf.singleOperators || new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!@]\");\n        var identifiers = parserConf.identifiers|| new RegExp(\"^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*\");\n    } else {\n        var singleOperators = parserConf.singleOperators || new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!]\");\n        var identifiers = parserConf.identifiers|| new RegExp(\"^[_A-Za-z][_A-Za-z0-9]*\");\n    }\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    if (parserConf.version && parseInt(parserConf.version, 10) == 3) {\n      myKeywords = myKeywords.concat(py3.keywords);\n      myBuiltins = myBuiltins.concat(py3.builtins);\n      var stringPrefixes = new RegExp(\"^(([rb]|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n    } else {\n      myKeywords = myKeywords.concat(py2.keywords);\n      myBuiltins = myBuiltins.concat(py2.builtins);\n      var stringPrefixes = new RegExp(\"^(([rub]|(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      // 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            pushScope(stream, state, \"py\");\n          else if (lineOffset < scopeOffset && dedent(stream, state))\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 null;\n\n      if (stream.match(doubleOperators)\n          || stream.match(singleOperators)\n          || stream.match(wordOperators))\n        return \"operator\";\n\n      if (stream.match(singleDelimiters))\n        return null;\n\n      if (stream.match(keywords))\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 (\"rub\".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 pushScope(stream, state, type) {\n      var offset = 0, align = null;\n      if (type == \"py\") {\n        while (top(state).type != \"py\")\n          state.scopes.pop();\n      }\n      offset = top(state).offset + (type == \"py\" ? conf.indentUnit : hangingIndent);\n      if (type != \"py\" && !stream.match(/^(\\s|#.*)*$/, false))\n        align = stream.column() + 1;\n      state.scopes.push({offset: offset, type: type, align: align});\n    }\n\n    function dedent(stream, state) {\n      var indented = stream.indentation();\n      while (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      var style = state.tokenize(stream, state);\n      var current = stream.current();\n\n      // Handle '.' connected identifiers\n      if (current == \".\") {\n        style = stream.match(identifiers, false) ? null : ERRORCLASS;\n        if (style == null && state.lastStyle == \"meta\") {\n          // Apply 'meta' style to '.' connected identifiers when\n          // appropriate.\n          style = \"meta\";\n        }\n        return style;\n      }\n\n      // Handle decorators\n      if (current == \"@\"){\n        if(parserConf.version && parseInt(parserConf.version, 10) == 3){\n            return stream.match(identifiers, false) ? \"meta\" : \"operator\";\n        } else {\n            return stream.match(identifiers, false) ? \"meta\" : ERRORCLASS;\n        }\n      }\n\n      if ((style == \"variable\" || style == \"builtin\")\n          && state.lastStyle == \"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        pushScope(stream, state, \"py\");\n\n      var delimiter_index = current.length == 1 ? \"[({\".indexOf(current) : -1;\n      if (delimiter_index != -1)\n        pushScope(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.scopes.pop();\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          lastStyle: null,\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        state.lastStyle = style;\n\n        var current = stream.current();\n        if (current && style)\n          state.lastToken = current;\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);\n        var closing = textAfter && textAfter.charAt(0) == scope.type;\n        if (scope.align != null)\n          return scope.align - (closing ? 1 : 0);\n        else if (closing && state.scopes.length > 1)\n          return state.scopes[state.scopes.length - 2].offset;\n        else\n          return scope.offset;\n      },\n\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": "src/main/resources/static/js/plugins/codemirror/mode/q/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Q mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"q.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Q</a>\n  </ul>\n</div>\n\n<article>\n<h2>Q mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n/ utilities to quickly load a csv file - for more exhaustive analysis of the csv contents see csvguess.q\n/ 2009.09.20 - updated to match latest csvguess.q\n\n/ .csv.colhdrs[file] - return a list of colhdrs from file\n/ info:.csv.info[file] - return a table of information about the file\n/ columns are:\n/\tc - column name; ci - column index; t - load type; mw - max width;\n/\tdchar - distinct characters in values; rule - rule that caught the type\n/\tmaybe - needs checking, _could_ be say a date, but perhaps just a float?\n/ .csv.info0[file;onlycols] - like .csv.info except that it only analyses <onlycols>\n/ example:\n/\tinfo:.csv.info0[file;(.csv.colhdrs file)like\"*price\"]\n/\tinfo:.csv.infolike[file;\"*price\"]\n/\tshow delete from info where t=\" \"\n/ .csv.data[file;info] - use the info from .csv.info to read the data\n/ .csv.data10[file;info] - like .csv.data but only returns the first 10 rows\n/ bulkload[file;info] - bulk loads file into table DATA (which must be already defined :: DATA:() )\n/ .csv.read[file]/read10[file] - for when you don't care about checking/tweaking the <info> before reading\n\n\\d .csv\nDELIM:\",\"\nZAPHDRS:0b / lowercase and remove _ from colhdrs (junk characters are always removed)\nWIDTHHDR:25000 / number of characters read to get the header\nREADLINES:222 / number of lines read and used to guess the types\nSYMMAXWIDTH:11 / character columns narrower than this are stored as symbols\nSYMMAXGR:10 / max symbol granularity% before we give up and keep as a * string\nFORCECHARWIDTH:30 / every field (of any type) with values this wide or more is forced to character \"*\"\nDISCARDEMPTY:0b / completely ignore empty columns if true else set them to \"C\"\nCHUNKSIZE:50000000 / used in fs2 (modified .Q.fs)\n\nk)nameltrim:{$[~@x;.z.s'x;~(*x)in aA:.Q.a,.Q.A;(+/&\\~x in aA)_x;x]}\nk)fs2:{[f;s]((-7!s)>){[f;s;x]i:1+last@&0xa=r:1:(s;x;CHUNKSIZE);f@`\\:i#r;x+i}[f;s]/0j}\ncleanhdrs:{{$[ZAPHDRS;lower x except\"_\";x]}x where x in DELIM,.Q.an}\ncancast:{nw:x$\"\";if[not x in\"BXCS\";nw:(min 0#;max 0#;::)@\\:nw];$[not any nw in x$(11&count y)#y;$[11<count y;not any nw in x$y;1b];0b]}\n\nread:{[file]data[file;info[file]]}\nread10:{[file]data10[file;info[file]]}\n\ncolhdrs:{[file]\n\t`$nameltrim DELIM vs cleanhdrs first read0(file;0;1+first where 0xa=read1(file;0;WIDTHHDR))}\ndata:{[file;info]\n\t(exec c from info where not t=\" \")xcol(exec t from info;enlist DELIM)0:file}\ndata10:{[file;info]\n\tdata[;info](file;0;1+last 11#where 0xa=read1(file;0;15*WIDTHHDR))}\ninfo0:{[file;onlycols]\n\tcolhdrs:`$nameltrim DELIM vs cleanhdrs first head:read0(file;0;1+last where 0xa=read1(file;0;WIDTHHDR));\n\tloadfmts:(count colhdrs)#\"S\";if[count onlycols;loadfmts[where not colhdrs in onlycols]:\"C\"];\n\tbreaks:where 0xa=read1(file;0;floor(10+READLINES)*WIDTHHDR%count head);\n\tnas:count as:colhdrs xcol(loadfmts;enlist DELIM)0:(file;0;1+last((1+READLINES)&count breaks)#breaks);\n\tinfo:([]c:key flip as;v:value flip as);as:();\n\treserved:key`.q;reserved,:.Q.res;reserved,:`i;\n\tinfo:update res:c in reserved from info;\n\tinfo:update ci:i,t:\"?\",ipa:0b,mdot:0,mw:0,rule:0,gr:0,ndv:0,maybe:0b,empty:0b,j10:0b,j12:0b from info;\n\tinfo:update ci:`s#ci from info;\n\tif[count onlycols;info:update t:\" \",rule:10 from info where not c in onlycols];\n\tinfo:update sdv:{string(distinct x)except`}peach v from info;\n\tinfo:update ndv:count each sdv from info;\n\tinfo:update gr:floor 0.5+100*ndv%nas,mw:{max count each x}peach sdv from info where 0<ndv;\n\tinfo:update t:\"*\",rule:20 from info where mw>.csv.FORCECHARWIDTH; / long values\n\tinfo:update t:\"C \"[.csv.DISCARDEMPTY],rule:30,empty:1b from info where t=\"?\",mw=0; / empty columns\n\tinfo:update dchar:{asc distinct raze x}peach sdv from info where t=\"?\";\n\tinfo:update mdot:{max sum each\".\"=x}peach sdv from info where t=\"?\",{\".\"in x}each dchar;\n\tinfo:update t:\"n\",rule:40 from info where t=\"?\",{any x in\"0123456789\"}each dchar; / vaguely numeric..\n\tinfo:update t:\"I\",rule:50,ipa:1b from info where t=\"n\",mw within 7 15,mdot=3,{all x in\".0123456789\"}each dchar,.csv.cancast[\"I\"]peach sdv; / ip-address\n\tinfo:update t:\"J\",rule:60 from info where t=\"n\",mdot=0,{all x in\"+-0123456789\"}each dchar,.csv.cancast[\"J\"]peach sdv;\n\tinfo:update t:\"I\",rule:70 from info where t=\"J\",mw<12,.csv.cancast[\"I\"]peach sdv;\n\tinfo:update t:\"H\",rule:80 from info where t=\"I\",mw<7,.csv.cancast[\"H\"]peach sdv;\n\tinfo:update t:\"F\",rule:90 from info where t=\"n\",mdot<2,mw>1,.csv.cancast[\"F\"]peach sdv;\n\tinfo:update t:\"E\",rule:100,maybe:1b from info where t=\"F\",mw<9;\n\tinfo:update t:\"M\",rule:110,maybe:1b from info where t in\"nIHEF\",mdot<2,mw within 4 7,.csv.cancast[\"M\"]peach sdv;\n\tinfo:update t:\"D\",rule:120,maybe:1b from info where t in\"nI\",mdot in 0 2,mw within 6 11,.csv.cancast[\"D\"]peach sdv;\n\tinfo:update t:\"V\",rule:130,maybe:1b from info where t=\"I\",mw in 5 6,7<count each dchar,{all x like\"*[0-9][0-5][0-9][0-5][0-9]\"}peach sdv,.csv.cancast[\"V\"]peach sdv; / 235959 12345\n\tinfo:update t:\"U\",rule:140,maybe:1b from info where t=\"H\",mw in 3 4,7<count each dchar,{all x like\"*[0-9][0-5][0-9]\"}peach sdv,.csv.cancast[\"U\"]peach sdv; /2359\n\tinfo:update t:\"U\",rule:150,maybe:0b from info where t=\"n\",mw in 4 5,mdot=0,{all x like\"*[0-9]:[0-5][0-9]\"}peach sdv,.csv.cancast[\"U\"]peach sdv;\n\tinfo:update t:\"T\",rule:160,maybe:0b from info where t=\"n\",mw within 7 12,mdot<2,{all x like\"*[0-9]:[0-5][0-9]:[0-5][0-9]*\"}peach sdv,.csv.cancast[\"T\"]peach sdv;\n\tinfo:update t:\"V\",rule:170,maybe:0b from info where t=\"T\",mw in 7 8,mdot=0,.csv.cancast[\"V\"]peach sdv;\n\tinfo:update t:\"T\",rule:180,maybe:1b from info where t in\"EF\",mw within 7 10,mdot=1,{all x like\"*[0-9][0-5][0-9][0-5][0-9].*\"}peach sdv,.csv.cancast[\"T\"]peach sdv;\n\tinfo:update t:\"Z\",rule:190,maybe:0b from info where t=\"n\",mw within 11 24,mdot<4,.csv.cancast[\"Z\"]peach sdv;\n\tinfo:update t:\"P\",rule:200,maybe:1b from info where t=\"n\",mw within 12 29,mdot<4,{all x like\"[12]*\"}peach sdv,.csv.cancast[\"P\"]peach sdv;\n\tinfo:update t:\"N\",rule:210,maybe:1b from info where t=\"n\",mw within 3 28,mdot=1,.csv.cancast[\"N\"]peach sdv;\n\tinfo:update t:\"?\",rule:220,maybe:0b from info where t=\"n\"; / reset remaining maybe numeric\n\tinfo:update t:\"C\",rule:230,maybe:0b from info where t=\"?\",mw=1; / char\n\tinfo:update t:\"B\",rule:240,maybe:0b from info where t in\"HC\",mw=1,mdot=0,{$[all x in\"01tTfFyYnN\";(any\"0fFnN\"in x)and any\"1tTyY\"in x;0b]}each dchar; / boolean\n\tinfo:update t:\"B\",rule:250,maybe:1b from info where t in\"HC\",mw=1,mdot=0,{all x in\"01tTfFyYnN\"}each dchar; / boolean\n\tinfo:update t:\"X\",rule:260,maybe:0b from info where t=\"?\",mw=2,{$[all x in\"0123456789abcdefABCDEF\";(any .Q.n in x)and any\"abcdefABCDEF\"in x;0b]}each dchar; /hex\n\tinfo:update t:\"S\",rule:270,maybe:1b from info where t=\"?\",mw<.csv.SYMMAXWIDTH,mw>1,gr<.csv.SYMMAXGR; / symbols (max width permitting)\n\tinfo:update t:\"*\",rule:280,maybe:0b from info where t=\"?\"; / the rest as strings\n\t/ flag those S/* columns which could be encoded to integers (.Q.j10/x10/j12/x12) to avoid symbols\n\tinfo:update j12:1b from info where t in\"S*\",mw<13,{all x in .Q.nA}each dchar;\n\tinfo:update j10:1b from info where t in\"S*\",mw<11,{all x in .Q.b6}each dchar;\n\tselect c,ci,t,maybe,empty,res,j10,j12,ipa,mw,mdot,rule,gr,ndv,dchar from info}\ninfo:info0[;()] / by default don't restrict columns\ninfolike:{[file;pattern] info0[file;{x where x like y}[lower colhdrs[file];pattern]]} / .csv.infolike[file;\"*time\"]\n\n\\d .\n/ DATA:()\nbulkload:{[file;info]\n\tif[not`DATA in system\"v\";'`DATA.not.defined];\n\tif[count DATA;'`DATA.not.empty];\n\tloadhdrs:exec c from info where not t=\" \";loadfmts:exec t from info;\n\t.csv.fs2[{[file;loadhdrs;loadfmts] `DATA insert $[count DATA;flip loadhdrs!(loadfmts;.csv.DELIM)0:file;loadhdrs xcol(loadfmts;enlist .csv.DELIM)0:file]}[file;loadhdrs;loadfmts]];\n\tcount DATA}\n@[.:;\"\\\\l csvutil.custom.q\";::]; / save your custom settings in csvutil.custom.q to override those set at the beginning of the file\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME type defined:</strong> <code>text/x-q</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/q/q.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(\"q\",function(config){\n  var indentUnit=config.indentUnit,\n      curPunc,\n      keywords=buildRE([\"abs\",\"acos\",\"aj\",\"aj0\",\"all\",\"and\",\"any\",\"asc\",\"asin\",\"asof\",\"atan\",\"attr\",\"avg\",\"avgs\",\"bin\",\"by\",\"ceiling\",\"cols\",\"cor\",\"cos\",\"count\",\"cov\",\"cross\",\"csv\",\"cut\",\"delete\",\"deltas\",\"desc\",\"dev\",\"differ\",\"distinct\",\"div\",\"do\",\"each\",\"ej\",\"enlist\",\"eval\",\"except\",\"exec\",\"exit\",\"exp\",\"fby\",\"fills\",\"first\",\"fkeys\",\"flip\",\"floor\",\"from\",\"get\",\"getenv\",\"group\",\"gtime\",\"hclose\",\"hcount\",\"hdel\",\"hopen\",\"hsym\",\"iasc\",\"idesc\",\"if\",\"ij\",\"in\",\"insert\",\"inter\",\"inv\",\"key\",\"keys\",\"last\",\"like\",\"list\",\"lj\",\"load\",\"log\",\"lower\",\"lsq\",\"ltime\",\"ltrim\",\"mavg\",\"max\",\"maxs\",\"mcount\",\"md5\",\"mdev\",\"med\",\"meta\",\"min\",\"mins\",\"mmax\",\"mmin\",\"mmu\",\"mod\",\"msum\",\"neg\",\"next\",\"not\",\"null\",\"or\",\"over\",\"parse\",\"peach\",\"pj\",\"plist\",\"prd\",\"prds\",\"prev\",\"prior\",\"rand\",\"rank\",\"ratios\",\"raze\",\"read0\",\"read1\",\"reciprocal\",\"reverse\",\"rload\",\"rotate\",\"rsave\",\"rtrim\",\"save\",\"scan\",\"select\",\"set\",\"setenv\",\"show\",\"signum\",\"sin\",\"sqrt\",\"ss\",\"ssr\",\"string\",\"sublist\",\"sum\",\"sums\",\"sv\",\"system\",\"tables\",\"tan\",\"til\",\"trim\",\"txf\",\"type\",\"uj\",\"ungroup\",\"union\",\"update\",\"upper\",\"upsert\",\"value\",\"var\",\"view\",\"views\",\"vs\",\"wavg\",\"where\",\"where\",\"while\",\"within\",\"wj\",\"wj1\",\"wsum\",\"xasc\",\"xbar\",\"xcol\",\"xcols\",\"xdesc\",\"xexp\",\"xgroup\",\"xkey\",\"xlog\",\"xprev\",\"xrank\"]),\n      E=/[|/&^!+:\\\\\\-*%$=~#;@><,?_\\'\\\"\\[\\(\\]\\)\\s{}]/;\n  function buildRE(w){return new RegExp(\"^(\"+w.join(\"|\")+\")$\");}\n  function tokenBase(stream,state){\n    var sol=stream.sol(),c=stream.next();\n    curPunc=null;\n    if(sol)\n      if(c==\"/\")\n        return(state.tokenize=tokenLineComment)(stream,state);\n      else if(c==\"\\\\\"){\n        if(stream.eol()||/\\s/.test(stream.peek()))\n          return stream.skipToEnd(),/^\\\\\\s*$/.test(stream.current())?(state.tokenize=tokenCommentToEOF)(stream, state):state.tokenize=tokenBase,\"comment\";\n        else\n          return state.tokenize=tokenBase,\"builtin\";\n      }\n    if(/\\s/.test(c))\n      return stream.peek()==\"/\"?(stream.skipToEnd(),\"comment\"):\"whitespace\";\n    if(c=='\"')\n      return(state.tokenize=tokenString)(stream,state);\n    if(c=='`')\n      return stream.eatWhile(/[A-Z|a-z|\\d|_|:|\\/|\\.]/),\"symbol\";\n    if((\".\"==c&&/\\d/.test(stream.peek()))||/\\d/.test(c)){\n      var t=null;\n      stream.backUp(1);\n      if(stream.match(/^\\d{4}\\.\\d{2}(m|\\.\\d{2}([D|T](\\d{2}(:\\d{2}(:\\d{2}(\\.\\d{1,9})?)?)?)?)?)/)\n      || stream.match(/^\\d+D(\\d{2}(:\\d{2}(:\\d{2}(\\.\\d{1,9})?)?)?)/)\n      || stream.match(/^\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,9})?)?/)\n      || stream.match(/^\\d+[ptuv]{1}/))\n        t=\"temporal\";\n      else if(stream.match(/^0[NwW]{1}/)\n      || stream.match(/^0x[\\d|a-f|A-F]*/)\n      || stream.match(/^[0|1]+[b]{1}/)\n      || stream.match(/^\\d+[chijn]{1}/)\n      || stream.match(/-?\\d*(\\.\\d*)?(e[+\\-]?\\d+)?(e|f)?/))\n        t=\"number\";\n      return(t&&(!(c=stream.peek())||E.test(c)))?t:(stream.next(),\"error\");\n    }\n    if(/[A-Z|a-z]|\\./.test(c))\n      return stream.eatWhile(/[A-Z|a-z|\\.|_|\\d]/),keywords.test(stream.current())?\"keyword\":\"variable\";\n    if(/[|/&^!+:\\\\\\-*%$=~#;@><\\.,?_\\']/.test(c))\n      return null;\n    if(/[{}\\(\\[\\]\\)]/.test(c))\n      return null;\n    return\"error\";\n  }\n  function tokenLineComment(stream,state){\n    return stream.skipToEnd(),/\\/\\s*$/.test(stream.current())?(state.tokenize=tokenBlockComment)(stream,state):(state.tokenize=tokenBase),\"comment\";\n  }\n  function tokenBlockComment(stream,state){\n    var f=stream.sol()&&stream.peek()==\"\\\\\";\n    stream.skipToEnd();\n    if(f&&/^\\\\\\s*$/.test(stream.current()))\n      state.tokenize=tokenBase;\n    return\"comment\";\n  }\n  function tokenCommentToEOF(stream){return stream.skipToEnd(),\"comment\";}\n  function tokenString(stream,state){\n    var escaped=false,next,end=false;\n    while((next=stream.next())){\n      if(next==\"\\\"\"&&!escaped){end=true;break;}\n      escaped=!escaped&&next==\"\\\\\";\n    }\n    if(end)state.tokenize=tokenBase;\n    return\"string\";\n  }\n  function pushContext(state,type,col){state.context={prev:state.context,indent:state.indent,col:col,type:type};}\n  function popContext(state){state.indent=state.context.indent;state.context=state.context.prev;}\n  return{\n    startState:function(){\n      return{tokenize:tokenBase,\n             context:null,\n             indent:0,\n             col:0};\n    },\n    token:function(stream,state){\n      if(stream.sol()){\n        if(state.context&&state.context.align==null)\n          state.context.align=false;\n        state.indent=stream.indentation();\n      }\n      //if (stream.eatSpace()) return null;\n      var style=state.tokenize(stream,state);\n      if(style!=\"comment\"&&state.context&&state.context.align==null&&state.context.type!=\"pattern\"){\n        state.context.align=true;\n      }\n      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(/[\\]\\}\\)]/.test(curPunc)){\n        while(state.context&&state.context.type==\"pattern\")popContext(state);\n        if(state.context&&curPunc==state.context.type)popContext(state);\n      }\n      else if(curPunc==\".\"&&state.context&&state.context.type==\"pattern\")popContext(state);\n      else if(/atom|string|variable/.test(style)&&state.context){\n        if(/[\\}\\]]/.test(state.context.type))\n          pushContext(state,\"pattern\",stream.column());\n        else if(state.context.type==\"pattern\"&&!state.context.align){\n          state.context.align=true;\n          state.context.col=stream.column();\n        }\n      }\n      return style;\n    },\n    indent:function(state,textAfter){\n      var firstChar=textAfter&&textAfter.charAt(0);\n      var context=state.context;\n      if(/[\\]\\}]/.test(firstChar))\n        while (context&&context.type==\"pattern\")context=context.prev;\n      var closing=context&&firstChar==context.type;\n      if(!context)\n        return 0;\n      else if(context.type==\"pattern\")\n        return context.col;\n      else if(context.align)\n        return context.col+(closing?0:1);\n      else\n        return context.indent+(closing?0:indentUnit);\n    }\n  };\n});\nCodeMirror.defineMIME(\"text/x-q\",\"q\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/r/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: R mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"r.js\"></script>\n<style>\n      .CodeMirror { border-top: 1px solid silver; border-bottom: 1px solid silver; }\n      .cm-s-default span.cm-semi { color: blue; font-weight: bold; }\n      .cm-s-default span.cm-dollar { color: orange; font-weight: bold; }\n      .cm-s-default span.cm-arrow { color: brown; }\n      .cm-s-default span.cm-arg-is { color: brown; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">R</a>\n  </ul>\n</div>\n\n<article>\n<h2>R mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# Code from http://www.mayin.org/ajayshah/KB/R/\n\n# FIRST LEARN ABOUT LISTS --\nX = list(height=5.4, weight=54)\nprint(\"Use default printing --\")\nprint(X)\nprint(\"Accessing individual elements --\")\ncat(\"Your height is \", X$height, \" and your weight is \", X$weight, \"\\n\")\n\n# FUNCTIONS --\nsquare <- function(x) {\n  return(x*x)\n}\ncat(\"The square of 3 is \", square(3), \"\\n\")\n\n                 # default value of the arg is set to 5.\ncube <- function(x=5) {\n  return(x*x*x);\n}\ncat(\"Calling cube with 2 : \", cube(2), \"\\n\")    # will give 2^3\ncat(\"Calling cube        : \", cube(), \"\\n\")     # will default to 5^3.\n\n# LEARN ABOUT FUNCTIONS THAT RETURN MULTIPLE OBJECTS --\npowers <- function(x) {\n  parcel = list(x2=x*x, x3=x*x*x, x4=x*x*x*x);\n  return(parcel);\n}\n\nX = powers(3);\nprint(\"Showing powers of 3 --\"); print(X);\n\n# WRITING THIS COMPACTLY (4 lines instead of 7)\n\npowerful <- function(x) {\n  return(list(x2=x*x, x3=x*x*x, x4=x*x*x*x));\n}\nprint(\"Showing powers of 3 --\"); print(powerful(3));\n\n# In R, the last expression in a function is, by default, what is\n# returned. So you could equally just say:\npowerful <- function(x) {list(x2=x*x, x3=x*x*x, x4=x*x*x*x)}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rsrc</code>.</p>\n\n    <p>Development of the CodeMirror R mode was kindly sponsored\n    by <a href=\"https://twitter.com/ubalo\">Ubalo</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/r/r.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(\"r\", function(config) {\n  function wordObj(str) {\n    var words = str.split(\" \"), res = {};\n    for (var i = 0; i < words.length; ++i) res[words[i]] = true;\n    return res;\n  }\n  var atoms = wordObj(\"NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_\");\n  var builtins = wordObj(\"list quote bquote eval return call parse deparse\");\n  var keywords = wordObj(\"if else repeat while function for in next break\");\n  var blockkeywords = wordObj(\"if else repeat while function for\");\n  var opChars = /[+\\-*\\/^<>=!&|~$:]/;\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    var ch = stream.next();\n    if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"0\" && stream.eat(\"x\")) {\n      stream.eatWhile(/[\\da-f]/i);\n      return \"number\";\n    } else if (ch == \".\" && stream.eat(/\\d/)) {\n      stream.match(/\\d*(?:e[+\\-]?\\d+)?/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/\\d*(?:\\.\\d+)?(?:e[+\\-]\\d+)?L?/);\n      return \"number\";\n    } else if (ch == \"'\" || ch == '\"') {\n      state.tokenize = tokenString(ch);\n      return \"string\";\n    } else if (ch == \".\" && stream.match(/.[.\\d]+/)) {\n      return \"keyword\";\n    } else if (/[\\w\\.]/.test(ch) && ch != \"_\") {\n      stream.eatWhile(/[\\w\\.]/);\n      var word = stream.current();\n      if (atoms.propertyIsEnumerable(word)) return \"atom\";\n      if (keywords.propertyIsEnumerable(word)) {\n        // Block keywords start new blocks, except 'else if', which only starts\n        // one new block for the 'if', no block for the 'else'.\n        if (blockkeywords.propertyIsEnumerable(word) &&\n            !stream.match(/\\s*if(\\s+|$)/, false))\n          curPunc = \"block\";\n        return \"keyword\";\n      }\n      if (builtins.propertyIsEnumerable(word)) return \"builtin\";\n      return \"variable\";\n    } else if (ch == \"%\") {\n      if (stream.skipTo(\"%\")) stream.next();\n      return \"variable-2\";\n    } else if (ch == \"<\" && stream.eat(\"-\")) {\n      return \"arrow\";\n    } else if (ch == \"=\" && state.ctx.argList) {\n      return \"arg-is\";\n    } else if (opChars.test(ch)) {\n      if (ch == \"$\") return \"dollar\";\n      stream.eatWhile(opChars);\n      return \"operator\";\n    } else if (/[\\(\\){}\\[\\];]/.test(ch)) {\n      curPunc = ch;\n      if (ch == \";\") return \"semi\";\n      return null;\n    } else {\n      return null;\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      if (stream.eat(\"\\\\\")) {\n        var ch = stream.next();\n        if (ch == \"x\") stream.match(/^[a-f0-9]{2}/i);\n        else if ((ch == \"u\" || ch == \"U\") && stream.eat(\"{\") && stream.skipTo(\"}\")) stream.next();\n        else if (ch == \"u\") stream.match(/^[a-f0-9]{4}/i);\n        else if (ch == \"U\") stream.match(/^[a-f0-9]{8}/i);\n        else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);\n        return \"string-2\";\n      } else {\n        var next;\n        while ((next = stream.next()) != null) {\n          if (next == quote) { state.tokenize = tokenBase; break; }\n          if (next == \"\\\\\") { stream.backUp(1); break; }\n        }\n        return \"string\";\n      }\n    };\n  }\n\n  function push(state, type, stream) {\n    state.ctx = {type: type,\n                 indent: state.indent,\n                 align: null,\n                 column: stream.column(),\n                 prev: state.ctx};\n  }\n  function pop(state) {\n    state.indent = state.ctx.indent;\n    state.ctx = state.ctx.prev;\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: tokenBase,\n              ctx: {type: \"top\",\n                    indent: -config.indentUnit,\n                    align: false},\n              indent: 0,\n              afterIdent: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.ctx.align == null) state.ctx.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (style != \"comment\" && state.ctx.align == null) state.ctx.align = true;\n\n      var ctype = state.ctx.type;\n      if ((curPunc == \";\" || curPunc == \"{\" || curPunc == \"}\") && ctype == \"block\") pop(state);\n      if (curPunc == \"{\") push(state, \"}\", stream);\n      else if (curPunc == \"(\") {\n        push(state, \")\", stream);\n        if (state.afterIdent) state.ctx.argList = true;\n      }\n      else if (curPunc == \"[\") push(state, \"]\", stream);\n      else if (curPunc == \"block\") push(state, \"block\", stream);\n      else if (curPunc == ctype) pop(state);\n      state.afterIdent = style == \"variable\" || style == \"keyword\";\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,\n          closing = firstChar == ctx.type;\n      if (ctx.type == \"block\") return ctx.indent + (firstChar == \"{\" ? 0 : config.indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indent + (closing ? 0 : config.indentUnit);\n    },\n\n    lineComment: \"#\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rsrc\", \"r\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rpm/changes/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: RPM changes mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n    <link rel=\"stylesheet\" href=\"../../../lib/codemirror.css\">\n    <script src=\"../../../lib/codemirror.js\"></script>\n    <script src=\"changes.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../../index.html\">Home</a>\n    <li><a href=\"../../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">RPM changes</a>\n  </ul>\n</div>\n\n<article>\n<h2>RPM changes mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n-------------------------------------------------------------------\nTue Oct 18 13:58:40 UTC 2011 - misterx@example.com\n\n- Update to r60.3\n- Fixes bug in the reflect package\n  * disallow Interface method on Value obtained via unexported name\n\n-------------------------------------------------------------------\nThu Oct  6 08:14:24 UTC 2011 - misterx@example.com\n\n- Update to r60.2\n- Fixes memory leak in certain map types\n\n-------------------------------------------------------------------\nWed Oct  5 14:34:10 UTC 2011 - misterx@example.com\n\n- Tweaks for gdb debugging\n- go.spec changes:\n  - move %go_arch definition to %prep section\n  - pass correct location of go specific gdb pretty printer and\n    functions to cpp as HOST_EXTRA_CFLAGS macro\n  - install go gdb functions & printer\n- gdb-printer.patch\n  - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go\n    gdb functions and pretty printer\n</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"changes\"},\n        lineNumbers: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rpm-changes</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rpm/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: RPM changes mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"rpm.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">RPM</a>\n  </ul>\n</div>\n\n<article>\n<h2>RPM changes mode</h2>\n\n    <div><textarea id=\"code\" name=\"code\">\n-------------------------------------------------------------------\nTue Oct 18 13:58:40 UTC 2011 - misterx@example.com\n\n- Update to r60.3\n- Fixes bug in the reflect package\n  * disallow Interface method on Value obtained via unexported name\n\n-------------------------------------------------------------------\nThu Oct  6 08:14:24 UTC 2011 - misterx@example.com\n\n- Update to r60.2\n- Fixes memory leak in certain map types\n\n-------------------------------------------------------------------\nWed Oct  5 14:34:10 UTC 2011 - misterx@example.com\n\n- Tweaks for gdb debugging\n- go.spec changes:\n  - move %go_arch definition to %prep section\n  - pass correct location of go specific gdb pretty printer and\n    functions to cpp as HOST_EXTRA_CFLAGS macro\n  - install go gdb functions & printer\n- gdb-printer.patch\n  - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go\n    gdb functions and pretty printer\n</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"rpm-changes\"},\n        lineNumbers: true,\n        indentUnit: 4\n      });\n    </script>\n\n<h2>RPM spec mode</h2>\n\n    <div><textarea id=\"code2\" name=\"code2\">\n#\n# spec file for package minidlna\n#\n# Copyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>\n#\n# All modifications and additions to the file contributed by third parties\n# remain the property of their copyright owners, unless otherwise agreed\n# upon. The license for this file, and modifications and additions to the\n# file, is the same license as for the pristine package itself (unless the\n# license for the pristine package is not an Open Source License, in which\n# case the license is the MIT License). An \"Open Source License\" is a\n# license that conforms to the Open Source Definition (Version 1.9)\n# published by the Open Source Initiative.\n\n\nName:           libupnp6\nVersion:        1.6.13\nRelease:        0\nSummary:        Portable Universal Plug and Play (UPnP) SDK\nGroup:          System/Libraries\nLicense:        BSD-3-Clause\nUrl:            http://sourceforge.net/projects/pupnp/\nSource0:        http://downloads.sourceforge.net/pupnp/libupnp-%{version}.tar.bz2\nBuildRoot:      %{_tmppath}/%{name}-%{version}-build\n\n%description\nThe portable Universal Plug and Play (UPnP) SDK provides support for building\nUPnP-compliant control points, devices, and bridges on several operating\nsystems.\n\n%package -n libupnp-devel\nSummary:        Portable Universal Plug and Play (UPnP) SDK\nGroup:          Development/Libraries/C and C++\nProvides:       pkgconfig(libupnp)\nRequires:       %{name} = %{version}\n\n%description -n libupnp-devel\nThe portable Universal Plug and Play (UPnP) SDK provides support for building\nUPnP-compliant control points, devices, and bridges on several operating\nsystems.\n\n%prep\n%setup -n libupnp-%{version}\n\n%build\n%configure --disable-static\nmake %{?_smp_mflags}\n\n%install\n%makeinstall\nfind %{buildroot} -type f -name '*.la' -exec rm -f {} ';'\n\n%post -p /sbin/ldconfig\n\n%postun -p /sbin/ldconfig\n\n%files\n%defattr(-,root,root,-)\n%doc ChangeLog NEWS README TODO\n%{_libdir}/libixml.so.*\n%{_libdir}/libthreadutil.so.*\n%{_libdir}/libupnp.so.*\n\n%files -n libupnp-devel\n%defattr(-,root,root,-)\n%{_libdir}/pkgconfig/libupnp.pc\n%{_libdir}/libixml.so\n%{_libdir}/libthreadutil.so\n%{_libdir}/libupnp.so\n%{_includedir}/upnp/\n\n%changelog</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code2\"), {\n        mode: {name: \"rpm-spec\"},\n        lineNumbers: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rpm-spec</code>, <code>text/x-rpm-changes</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rpm/rpm.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(\"rpm-changes\", function() {\n  var headerSeperator = /^-+$/;\n  var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\\d{1,2} \\d{2}:\\d{2}(:\\d{2})? [A-Z]{3,4} \\d{4} - /;\n  var simpleEmail = /^[\\w+.-]+@[\\w.-]+/;\n\n  return {\n    token: function(stream) {\n      if (stream.sol()) {\n        if (stream.match(headerSeperator)) { return 'tag'; }\n        if (stream.match(headerLine)) { return 'tag'; }\n      }\n      if (stream.match(simpleEmail)) { return 'string'; }\n      stream.next();\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rpm-changes\", \"rpm-changes\");\n\n// Quick and dirty spec file highlighting\n\nCodeMirror.defineMode(\"rpm-spec\", function() {\n  var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;\n\n  var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\\(\\w+\\))?|Obsoletes|Conflicts|Recommends|Source\\d*|Patch\\d*|ExclusiveArch|NoSource|Supplements):/;\n  var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;\n  var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros\n  var control_flow_simple = /^%(else|endif)/; // rpm control flow macros\n  var operators = /^(\\!|\\?|\\<\\=|\\<|\\>\\=|\\>|\\=\\=|\\&\\&|\\|\\|)/; // operators in control flow macros\n\n  return {\n    startState: function () {\n        return {\n          controlFlow: false,\n          macroParameters: false,\n          section: false\n        };\n    },\n    token: function (stream, state) {\n      var ch = stream.peek();\n      if (ch == \"#\") { stream.skipToEnd(); return \"comment\"; }\n\n      if (stream.sol()) {\n        if (stream.match(preamble)) { return \"preamble\"; }\n        if (stream.match(section)) { return \"section\"; }\n      }\n\n      if (stream.match(/^\\$\\w+/)) { return \"def\"; } // Variables like '$RPM_BUILD_ROOT'\n      if (stream.match(/^\\$\\{\\w+\\}/)) { return \"def\"; } // Variables like '${RPM_BUILD_ROOT}'\n\n      if (stream.match(control_flow_simple)) { return \"keyword\"; }\n      if (stream.match(control_flow_complex)) {\n        state.controlFlow = true;\n        return \"keyword\";\n      }\n      if (state.controlFlow) {\n        if (stream.match(operators)) { return \"operator\"; }\n        if (stream.match(/^(\\d+)/)) { return \"number\"; }\n        if (stream.eol()) { state.controlFlow = false; }\n      }\n\n      if (stream.match(arch)) { return \"number\"; }\n\n      // Macros like '%make_install' or '%attr(0775,root,root)'\n      if (stream.match(/^%[\\w]+/)) {\n        if (stream.match(/^\\(/)) { state.macroParameters = true; }\n        return \"macro\";\n      }\n      if (state.macroParameters) {\n        if (stream.match(/^\\d+/)) { return \"number\";}\n        if (stream.match(/^\\)/)) {\n          state.macroParameters = false;\n          return \"macro\";\n        }\n      }\n      if (stream.match(/^%\\{\\??[\\w \\-]+\\}/)) { return \"macro\"; } // Macros like '%{defined fedora}'\n\n      //TODO: Include bash script sub-parser (CodeMirror supports that)\n      stream.next();\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rpm-spec\", \"rpm-spec\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rst/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: reStructuredText mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/mode/overlay.js\"></script>\n<script src=\"rst.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">reStructuredText</a>\n  </ul>\n</div>\n\n<article>\n<h2>reStructuredText mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n.. This is an excerpt from Sphinx documentation: http://sphinx.pocoo.org/_sources/rest.txt\n\n.. highlightlang:: rest\n\n.. _rst-primer:\n\nreStructuredText Primer\n=======================\n\nThis section is a brief introduction to reStructuredText (reST) concepts and\nsyntax, intended to provide authors with enough information to author documents\nproductively.  Since reST was designed to be a simple, unobtrusive markup\nlanguage, this will not take too long.\n\n.. seealso::\n\n   The authoritative `reStructuredText User Documentation\n   &lt;http://docutils.sourceforge.net/rst.html&gt;`_.  The \"ref\" links in this\n   document link to the description of the individual constructs in the reST\n   reference.\n\n\nParagraphs\n----------\n\nThe paragraph (:duref:`ref &lt;paragraphs&gt;`) is the most basic block in a reST\ndocument.  Paragraphs are simply chunks of text separated by one or more blank\nlines.  As in Python, indentation is significant in reST, so all lines of the\nsame paragraph must be left-aligned to the same level of indentation.\n\n\n.. _inlinemarkup:\n\nInline markup\n-------------\n\nThe standard reST inline markup is quite simple: use\n\n* one asterisk: ``*text*`` for emphasis (italics),\n* two asterisks: ``**text**`` for strong emphasis (boldface), and\n* backquotes: ````text```` for code samples.\n\nIf asterisks or backquotes appear in running text and could be confused with\ninline markup delimiters, they have to be escaped with a backslash.\n\nBe aware of some restrictions of this markup:\n\n* it may not be nested,\n* content may not start or end with whitespace: ``* text*`` is wrong,\n* it must be separated from surrounding text by non-word characters.  Use a\n  backslash escaped space to work around that: ``thisis\\ *one*\\ word``.\n\nThese restrictions may be lifted in future versions of the docutils.\n\nreST also allows for custom \"interpreted text roles\"', which signify that the\nenclosed text should be interpreted in a specific way.  Sphinx uses this to\nprovide semantic markup and cross-referencing of identifiers, as described in\nthe appropriate section.  The general syntax is ``:rolename:`content```.\n\nStandard reST provides the following roles:\n\n* :durole:`emphasis` -- alternate spelling for ``*emphasis*``\n* :durole:`strong` -- alternate spelling for ``**strong**``\n* :durole:`literal` -- alternate spelling for ````literal````\n* :durole:`subscript` -- subscript text\n* :durole:`superscript` -- superscript text\n* :durole:`title-reference` -- for titles of books, periodicals, and other\n  materials\n\nSee :ref:`inline-markup` for roles added by Sphinx.\n\n\nLists and Quote-like blocks\n---------------------------\n\nList markup (:duref:`ref &lt;bullet-lists&gt;`) is natural: just place an asterisk at\nthe start of a paragraph and indent properly.  The same goes for numbered lists;\nthey can also be autonumbered using a ``#`` sign::\n\n   * This is a bulleted list.\n   * It has two items, the second\n     item uses two lines.\n\n   1. This is a numbered list.\n   2. It has two items too.\n\n   #. This is a numbered list.\n   #. It has two items too.\n\n\nNested lists are possible, but be aware that they must be separated from the\nparent list items by blank lines::\n\n   * this is\n   * a list\n\n     * with a nested list\n     * and some subitems\n\n   * and here the parent list continues\n\nDefinition lists (:duref:`ref &lt;definition-lists&gt;`) are created as follows::\n\n   term (up to a line of text)\n      Definition of the term, which must be indented\n\n      and can even consist of multiple paragraphs\n\n   next term\n      Description.\n\nNote that the term cannot have more than one line of text.\n\nQuoted paragraphs (:duref:`ref &lt;block-quotes&gt;`) are created by just indenting\nthem more than the surrounding paragraphs.\n\nLine blocks (:duref:`ref &lt;line-blocks&gt;`) are a way of preserving line breaks::\n\n   | These lines are\n   | broken exactly like in\n   | the source file.\n\nThere are also several more special blocks available:\n\n* field lists (:duref:`ref &lt;field-lists&gt;`)\n* option lists (:duref:`ref &lt;option-lists&gt;`)\n* quoted literal blocks (:duref:`ref &lt;quoted-literal-blocks&gt;`)\n* doctest blocks (:duref:`ref &lt;doctest-blocks&gt;`)\n\n\nSource Code\n-----------\n\nLiteral code blocks (:duref:`ref &lt;literal-blocks&gt;`) are introduced by ending a\nparagraph with the special marker ``::``.  The literal block must be indented\n(and, like all paragraphs, separated from the surrounding ones by blank lines)::\n\n   This is a normal text paragraph. The next paragraph is a code sample::\n\n      It is not processed in any way, except\n      that the indentation is removed.\n\n      It can span multiple lines.\n\n   This is a normal text paragraph again.\n\nThe handling of the ``::`` marker is smart:\n\n* If it occurs as a paragraph of its own, that paragraph is completely left\n  out of the document.\n* If it is preceded by whitespace, the marker is removed.\n* If it is preceded by non-whitespace, the marker is replaced by a single\n  colon.\n\nThat way, the second sentence in the above example's first paragraph would be\nrendered as \"The next paragraph is a code sample:\".\n\n\n.. _rst-tables:\n\nTables\n------\n\nTwo forms of tables are supported.  For *grid tables* (:duref:`ref\n&lt;grid-tables&gt;`), you have to \"paint\" the cell grid yourself.  They look like\nthis::\n\n   +------------------------+------------+----------+----------+\n   | Header row, column 1   | Header 2   | Header 3 | Header 4 |\n   | (header rows optional) |            |          |          |\n   +========================+============+==========+==========+\n   | body row 1, column 1   | column 2   | column 3 | column 4 |\n   +------------------------+------------+----------+----------+\n   | body row 2             | ...        | ...      |          |\n   +------------------------+------------+----------+----------+\n\n*Simple tables* (:duref:`ref &lt;simple-tables&gt;`) are easier to write, but\nlimited: they must contain more than one row, and the first column cannot\ncontain multiple lines.  They look like this::\n\n   =====  =====  =======\n   A      B      A and B\n   =====  =====  =======\n   False  False  False\n   True   False  False\n   False  True   False\n   True   True   True\n   =====  =====  =======\n\n\nHyperlinks\n----------\n\nExternal links\n^^^^^^^^^^^^^^\n\nUse ```Link text &lt;http://example.com/&gt;`_`` for inline web links.  If the link\ntext should be the web address, you don't need special markup at all, the parser\nfinds links and mail addresses in ordinary text.\n\nYou can also separate the link and the target definition (:duref:`ref\n&lt;hyperlink-targets&gt;`), like this::\n\n   This is a paragraph that contains `a link`_.\n\n   .. _a link: http://example.com/\n\n\nInternal links\n^^^^^^^^^^^^^^\n\nInternal linking is done via a special reST role provided by Sphinx, see the\nsection on specific markup, :ref:`ref-role`.\n\n\nSections\n--------\n\nSection headers (:duref:`ref &lt;sections&gt;`) are created by underlining (and\noptionally overlining) the section title with a punctuation character, at least\nas long as the text::\n\n   =================\n   This is a heading\n   =================\n\nNormally, there are no heading levels assigned to certain characters as the\nstructure is determined from the succession of headings.  However, for the\nPython documentation, this convention is used which you may follow:\n\n* ``#`` with overline, for parts\n* ``*`` with overline, for chapters\n* ``=``, for sections\n* ``-``, for subsections\n* ``^``, for subsubsections\n* ``\"``, for paragraphs\n\nOf course, you are free to use your own marker characters (see the reST\ndocumentation), and use a deeper nesting level, but keep in mind that most\ntarget formats (HTML, LaTeX) have a limited supported nesting depth.\n\n\nExplicit Markup\n---------------\n\n\"Explicit markup\" (:duref:`ref &lt;explicit-markup-blocks&gt;`) is used in reST for\nmost constructs that need special handling, such as footnotes,\nspecially-highlighted paragraphs, comments, and generic directives.\n\nAn explicit markup block begins with a line starting with ``..`` followed by\nwhitespace and is terminated by the next paragraph at the same level of\nindentation.  (There needs to be a blank line between explicit markup and normal\nparagraphs.  This may all sound a bit complicated, but it is intuitive enough\nwhen you write it.)\n\n\n.. _directives:\n\nDirectives\n----------\n\nA directive (:duref:`ref &lt;directives&gt;`) is a generic block of explicit markup.\nBesides roles, it is one of the extension mechanisms of reST, and Sphinx makes\nheavy use of it.\n\nDocutils supports the following directives:\n\n* Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,\n  :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,\n  :dudir:`tip`, :dudir:`warning` and the generic :dudir:`admonition`.\n  (Most themes style only \"note\" and \"warning\" specially.)\n\n* Images:\n\n  - :dudir:`image` (see also Images_ below)\n  - :dudir:`figure` (an image with caption and optional legend)\n\n* Additional body elements:\n\n  - :dudir:`contents` (a local, i.e. for the current file only, table of\n    contents)\n  - :dudir:`container` (a container with a custom class, useful to generate an\n    outer ``&lt;div&gt;`` in HTML)\n  - :dudir:`rubric` (a heading without relation to the document sectioning)\n  - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)\n  - :dudir:`parsed-literal` (literal block that supports inline markup)\n  - :dudir:`epigraph` (a block quote with optional attribution line)\n  - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own\n    class attribute)\n  - :dudir:`compound` (a compound paragraph)\n\n* Special tables:\n\n  - :dudir:`table` (a table with title)\n  - :dudir:`csv-table` (a table generated from comma-separated values)\n  - :dudir:`list-table` (a table generated from a list of lists)\n\n* Special directives:\n\n  - :dudir:`raw` (include raw target-format markup)\n  - :dudir:`include` (include reStructuredText from another file)\n    -- in Sphinx, when given an absolute include file path, this directive takes\n    it as relative to the source directory\n  - :dudir:`class` (assign a class attribute to the next element) [1]_\n\n* HTML specifics:\n\n  - :dudir:`meta` (generation of HTML ``&lt;meta&gt;`` tags)\n  - :dudir:`title` (override document title)\n\n* Influencing markup:\n\n  - :dudir:`default-role` (set a new default role)\n  - :dudir:`role` (create a new role)\n\n  Since these are only per-file, better use Sphinx' facilities for setting the\n  :confval:`default_role`.\n\nDo *not* use the directives :dudir:`sectnum`, :dudir:`header` and\n:dudir:`footer`.\n\nDirectives added by Sphinx are described in :ref:`sphinxmarkup`.\n\nBasically, a directive consists of a name, arguments, options and content. (Keep\nthis terminology in mind, it is used in the next chapter describing custom\ndirectives.)  Looking at this example, ::\n\n   .. function:: foo(x)\n                 foo(y, z)\n      :module: some.module.name\n\n      Return a line of text input from the user.\n\n``function`` is the directive name.  It is given two arguments here, the\nremainder of the first line and the second line, as well as one option\n``module`` (as you can see, options are given in the lines immediately following\nthe arguments and indicated by the colons).  Options must be indented to the\nsame level as the directive content.\n\nThe directive content follows after a blank line and is indented relative to the\ndirective start.\n\n\nImages\n------\n\nreST supports an image directive (:dudir:`ref &lt;image&gt;`), used like so::\n\n   .. image:: gnu.png\n      (options)\n\nWhen used within Sphinx, the file name given (here ``gnu.png``) must either be\nrelative to the source file, or absolute which means that they are relative to\nthe top source directory.  For example, the file ``sketch/spam.rst`` could refer\nto the image ``images/spam.png`` as ``../images/spam.png`` or\n``/images/spam.png``.\n\nSphinx will automatically copy image files over to a subdirectory of the output\ndirectory on building (e.g. the ``_static`` directory for HTML output.)\n\nInterpretation of image size options (``width`` and ``height``) is as follows:\nif the size has no unit or the unit is pixels, the given size will only be\nrespected for output channels that support pixels (i.e. not in LaTeX output).\nOther units (like ``pt`` for points) will be used for HTML and LaTeX output.\n\nSphinx extends the standard docutils behavior by allowing an asterisk for the\nextension::\n\n   .. image:: gnu.*\n\nSphinx then searches for all images matching the provided pattern and determines\ntheir type.  Each builder then chooses the best image out of these candidates.\nFor instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`\nand :file:`gnu.png` existed in the source tree, the LaTeX builder would choose\nthe former, while the HTML builder would prefer the latter.\n\n.. versionchanged:: 0.4\n   Added the support for file names ending in an asterisk.\n\n.. versionchanged:: 0.6\n   Image paths can now be absolute.\n\n\nFootnotes\n---------\n\nFor footnotes (:duref:`ref &lt;footnotes&gt;`), use ``[#name]_`` to mark the footnote\nlocation, and add the footnote body at the bottom of the document after a\n\"Footnotes\" rubric heading, like so::\n\n   Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_\n\n   .. rubric:: Footnotes\n\n   .. [#f1] Text of the first footnote.\n   .. [#f2] Text of the second footnote.\n\nYou can also explicitly number the footnotes (``[1]_``) or use auto-numbered\nfootnotes without names (``[#]_``).\n\n\nCitations\n---------\n\nStandard reST citations (:duref:`ref &lt;citations&gt;`) are supported, with the\nadditional feature that they are \"global\", i.e. all citations can be referenced\nfrom all files.  Use them like so::\n\n   Lorem ipsum [Ref]_ dolor sit amet.\n\n   .. [Ref] Book or article reference, URL or whatever.\n\nCitation usage is similar to footnote usage, but with a label that is not\nnumeric or begins with ``#``.\n\n\nSubstitutions\n-------------\n\nreST supports \"substitutions\" (:duref:`ref &lt;substitution-definitions&gt;`), which\nare pieces of text and/or markup referred to in the text by ``|name|``.  They\nare defined like footnotes with explicit markup blocks, like this::\n\n   .. |name| replace:: replacement *text*\n\nor this::\n\n   .. |caution| image:: warning.png\n                :alt: Warning!\n\nSee the :duref:`reST reference for substitutions &lt;substitution-definitions&gt;`\nfor details.\n\nIf you want to use some substitutions for all documents, put them into\n:confval:`rst_prolog` or put them into a separate file and include it into all\ndocuments you want to use them in, using the :rst:dir:`include` directive.  (Be\nsure to give the include file a file name extension differing from that of other\nsource files, to avoid Sphinx finding it as a standalone document.)\n\nSphinx defines some default substitutions, see :ref:`default-substitutions`.\n\n\nComments\n--------\n\nEvery explicit markup block which isn't a valid markup construct (like the\nfootnotes above) is regarded as a comment (:duref:`ref &lt;comments&gt;`).  For\nexample::\n\n   .. This is a comment.\n\nYou can indent text after a comment start to form multiline comments::\n\n   ..\n      This whole indented block\n      is a comment.\n\n      Still in the comment.\n\n\nSource encoding\n---------------\n\nSince the easiest way to include special characters like em dashes or copyright\nsigns in reST is to directly write them as Unicode characters, one has to\nspecify an encoding.  Sphinx assumes source files to be encoded in UTF-8 by\ndefault; you can change this with the :confval:`source_encoding` config value.\n\n\nGotchas\n-------\n\nThere are some problems one commonly runs into while authoring reST documents:\n\n* **Separation of inline markup:** As said above, inline markup spans must be\n  separated from the surrounding text by non-word characters, you have to use a\n  backslash-escaped space to get around that.  See `the reference\n  &lt;http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup&gt;`_\n  for the details.\n\n* **No nested inline markup:** Something like ``*see :func:`foo`*`` is not\n  possible.\n\n\n.. rubric:: Footnotes\n\n.. [1] When the default domain contains a :rst:dir:`class` directive, this directive\n       will be shadowed.  Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n      });\n    </script>\n    <p>\n        The <code>python</code> mode will be used for highlighting blocks\n        containing Python/IPython terminal sessions: blocks starting with\n        <code>&gt;&gt;&gt;</code> (for Python) or <code>In [num]:</code> (for\n        IPython).\n\n        Further, the <code>stex</code> mode will be used for highlighting\n        blocks containing LaTex code.\n    </p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rst/rst.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\"), require(\"../python/python\"), require(\"../stex/stex\"), require(\"../../addon/mode/overlay\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../python/python\", \"../stex/stex\", \"../../addon/mode/overlay\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode('rst', function (config, options) {\n\n  var rx_strong = /^\\*\\*[^\\*\\s](?:[^\\*]*[^\\*\\s])?\\*\\*/;\n  var rx_emphasis = /^\\*[^\\*\\s](?:[^\\*]*[^\\*\\s])?\\*/;\n  var rx_literal = /^``[^`\\s](?:[^`]*[^`\\s])``/;\n\n  var rx_number = /^(?:[\\d]+(?:[\\.,]\\d+)*)/;\n  var rx_positive = /^(?:\\s\\+[\\d]+(?:[\\.,]\\d+)*)/;\n  var rx_negative = /^(?:\\s\\-[\\d]+(?:[\\.,]\\d+)*)/;\n\n  var rx_uri_protocol = \"[Hh][Tt][Tt][Pp][Ss]?://\";\n  var rx_uri_domain = \"(?:[\\\\d\\\\w.-]+)\\\\.(?:\\\\w{2,6})\";\n  var rx_uri_path = \"(?:/[\\\\d\\\\w\\\\#\\\\%\\\\&\\\\-\\\\.\\\\,\\\\/\\\\:\\\\=\\\\?\\\\~]+)*\";\n  var rx_uri = new RegExp(\"^\" + rx_uri_protocol + rx_uri_domain + rx_uri_path);\n\n  var overlay = {\n    token: function (stream) {\n\n      if (stream.match(rx_strong) && stream.match (/\\W+|$/, false))\n        return 'strong';\n      if (stream.match(rx_emphasis) && stream.match (/\\W+|$/, false))\n        return 'em';\n      if (stream.match(rx_literal) && stream.match (/\\W+|$/, false))\n        return 'string-2';\n      if (stream.match(rx_number))\n        return 'number';\n      if (stream.match(rx_positive))\n        return 'positive';\n      if (stream.match(rx_negative))\n        return 'negative';\n      if (stream.match(rx_uri))\n        return 'link';\n\n      while (stream.next() != null) {\n        if (stream.match(rx_strong, false)) break;\n        if (stream.match(rx_emphasis, false)) break;\n        if (stream.match(rx_literal, false)) break;\n        if (stream.match(rx_number, false)) break;\n        if (stream.match(rx_positive, false)) break;\n        if (stream.match(rx_negative, false)) break;\n        if (stream.match(rx_uri, false)) break;\n      }\n\n      return null;\n    }\n  };\n\n  var mode = CodeMirror.getMode(\n    config, options.backdrop || 'rst-base'\n  );\n\n  return CodeMirror.overlayMode(mode, overlay, true); // combine\n}, 'python', 'stex');\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\nCodeMirror.defineMode('rst-base', function (config) {\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function format(string) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    return string.replace(/{(\\d+)}/g, function (match, n) {\n      return typeof args[n] != 'undefined' ? args[n] : match;\n    });\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  var mode_python = CodeMirror.getMode(config, 'python');\n  var mode_stex = CodeMirror.getMode(config, 'stex');\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  var SEPA = \"\\\\s+\";\n  var TAIL = \"(?:\\\\s*|\\\\W|$)\",\n  rx_TAIL = new RegExp(format('^{0}', TAIL));\n\n  var NAME =\n    \"(?:[^\\\\W\\\\d_](?:[\\\\w!\\\"#$%&'()\\\\*\\\\+,\\\\-\\\\.\\/:;<=>\\\\?]*[^\\\\W_])?)\",\n  rx_NAME = new RegExp(format('^{0}', NAME));\n  var NAME_WWS =\n    \"(?:[^\\\\W\\\\d_](?:[\\\\w\\\\s!\\\"#$%&'()\\\\*\\\\+,\\\\-\\\\.\\/:;<=>\\\\?]*[^\\\\W_])?)\";\n  var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);\n\n  var TEXT1 = \"(?:[^\\\\s\\\\|](?:[^\\\\|]*[^\\\\s\\\\|])?)\";\n  var TEXT2 = \"(?:[^\\\\`]+)\",\n  rx_TEXT2 = new RegExp(format('^{0}', TEXT2));\n\n  var rx_section = new RegExp(\n    \"^([!'#$%&\\\"()*+,-./:;<=>?@\\\\[\\\\\\\\\\\\]^_`{|}~])\\\\1{3,}\\\\s*$\");\n  var rx_explicit = new RegExp(\n    format('^\\\\.\\\\.{0}', SEPA));\n  var rx_link = new RegExp(\n    format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL));\n  var rx_directive = new RegExp(\n    format('^{0}::{1}', REF_NAME, TAIL));\n  var rx_substitution = new RegExp(\n    format('^\\\\|{0}\\\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL));\n  var rx_footnote = new RegExp(\n    format('^\\\\[(?:\\\\d+|#{0}?|\\\\*)]{1}', REF_NAME, TAIL));\n  var rx_citation = new RegExp(\n    format('^\\\\[{0}\\\\]{1}', REF_NAME, TAIL));\n\n  var rx_substitution_ref = new RegExp(\n    format('^\\\\|{0}\\\\|', TEXT1));\n  var rx_footnote_ref = new RegExp(\n    format('^\\\\[(?:\\\\d+|#{0}?|\\\\*)]_', REF_NAME));\n  var rx_citation_ref = new RegExp(\n    format('^\\\\[{0}\\\\]_', REF_NAME));\n  var rx_link_ref1 = new RegExp(\n    format('^{0}__?', REF_NAME));\n  var rx_link_ref2 = new RegExp(\n    format('^`{0}`_', TEXT2));\n\n  var rx_role_pre = new RegExp(\n    format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL));\n  var rx_role_suf = new RegExp(\n    format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL));\n  var rx_role = new RegExp(\n    format('^:{0}:{1}', NAME, TAIL));\n\n  var rx_directive_name = new RegExp(format('^{0}', REF_NAME));\n  var rx_directive_tail = new RegExp(format('^::{0}', TAIL));\n  var rx_substitution_text = new RegExp(format('^\\\\|{0}\\\\|', TEXT1));\n  var rx_substitution_sepa = new RegExp(format('^{0}', SEPA));\n  var rx_substitution_name = new RegExp(format('^{0}', REF_NAME));\n  var rx_substitution_tail = new RegExp(format('^::{0}', TAIL));\n  var rx_link_head = new RegExp(\"^_\");\n  var rx_link_name = new RegExp(format('^{0}|_', REF_NAME));\n  var rx_link_tail = new RegExp(format('^:{0}', TAIL));\n\n  var rx_verbatim = new RegExp('^::\\\\s*$');\n  var rx_examples = new RegExp('^\\\\s+(?:>>>|In \\\\[\\\\d+\\\\]:)\\\\s');\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function to_normal(stream, state) {\n    var token = null;\n\n    if (stream.sol() && stream.match(rx_examples, false)) {\n      change(state, to_mode, {\n        mode: mode_python, local: CodeMirror.startState(mode_python)\n      });\n    } else if (stream.sol() && stream.match(rx_explicit)) {\n      change(state, to_explicit);\n      token = 'meta';\n    } else if (stream.sol() && stream.match(rx_section)) {\n      change(state, to_normal);\n      token = 'header';\n    } else if (phase(state) == rx_role_pre ||\n               stream.match(rx_role_pre, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_normal, context(rx_role_pre, 1));\n        stream.match(/^:/);\n        token = 'meta';\n        break;\n      case 1:\n        change(state, to_normal, context(rx_role_pre, 2));\n        stream.match(rx_NAME);\n        token = 'keyword';\n\n        if (stream.current().match(/^(?:math|latex)/)) {\n          state.tmp_stex = true;\n        }\n        break;\n      case 2:\n        change(state, to_normal, context(rx_role_pre, 3));\n        stream.match(/^:`/);\n        token = 'meta';\n        break;\n      case 3:\n        if (state.tmp_stex) {\n          state.tmp_stex = undefined; state.tmp = {\n            mode: mode_stex, local: CodeMirror.startState(mode_stex)\n          };\n        }\n\n        if (state.tmp) {\n          if (stream.peek() == '`') {\n            change(state, to_normal, context(rx_role_pre, 4));\n            state.tmp = undefined;\n            break;\n          }\n\n          token = state.tmp.mode.token(stream, state.tmp.local);\n          break;\n        }\n\n        change(state, to_normal, context(rx_role_pre, 4));\n        stream.match(rx_TEXT2);\n        token = 'string';\n        break;\n      case 4:\n        change(state, to_normal, context(rx_role_pre, 5));\n        stream.match(/^`/);\n        token = 'meta';\n        break;\n      case 5:\n        change(state, to_normal, context(rx_role_pre, 6));\n        stream.match(rx_TAIL);\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (phase(state) == rx_role_suf ||\n               stream.match(rx_role_suf, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_normal, context(rx_role_suf, 1));\n        stream.match(/^`/);\n        token = 'meta';\n        break;\n      case 1:\n        change(state, to_normal, context(rx_role_suf, 2));\n        stream.match(rx_TEXT2);\n        token = 'string';\n        break;\n      case 2:\n        change(state, to_normal, context(rx_role_suf, 3));\n        stream.match(/^`:/);\n        token = 'meta';\n        break;\n      case 3:\n        change(state, to_normal, context(rx_role_suf, 4));\n        stream.match(rx_NAME);\n        token = 'keyword';\n        break;\n      case 4:\n        change(state, to_normal, context(rx_role_suf, 5));\n        stream.match(/^:/);\n        token = 'meta';\n        break;\n      case 5:\n        change(state, to_normal, context(rx_role_suf, 6));\n        stream.match(rx_TAIL);\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (phase(state) == rx_role || stream.match(rx_role, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_normal, context(rx_role, 1));\n        stream.match(/^:/);\n        token = 'meta';\n        break;\n      case 1:\n        change(state, to_normal, context(rx_role, 2));\n        stream.match(rx_NAME);\n        token = 'keyword';\n        break;\n      case 2:\n        change(state, to_normal, context(rx_role, 3));\n        stream.match(/^:/);\n        token = 'meta';\n        break;\n      case 3:\n        change(state, to_normal, context(rx_role, 4));\n        stream.match(rx_TAIL);\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (phase(state) == rx_substitution_ref ||\n               stream.match(rx_substitution_ref, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_normal, context(rx_substitution_ref, 1));\n        stream.match(rx_substitution_text);\n        token = 'variable-2';\n        break;\n      case 1:\n        change(state, to_normal, context(rx_substitution_ref, 2));\n        if (stream.match(/^_?_?/)) token = 'link';\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (stream.match(rx_footnote_ref)) {\n      change(state, to_normal);\n      token = 'quote';\n    } else if (stream.match(rx_citation_ref)) {\n      change(state, to_normal);\n      token = 'quote';\n    } else if (stream.match(rx_link_ref1)) {\n      change(state, to_normal);\n      if (!stream.peek() || stream.peek().match(/^\\W$/)) {\n        token = 'link';\n      }\n    } else if (phase(state) == rx_link_ref2 ||\n               stream.match(rx_link_ref2, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        if (!stream.peek() || stream.peek().match(/^\\W$/)) {\n          change(state, to_normal, context(rx_link_ref2, 1));\n        } else {\n          stream.match(rx_link_ref2);\n        }\n        break;\n      case 1:\n        change(state, to_normal, context(rx_link_ref2, 2));\n        stream.match(/^`/);\n        token = 'link';\n        break;\n      case 2:\n        change(state, to_normal, context(rx_link_ref2, 3));\n        stream.match(rx_TEXT2);\n        break;\n      case 3:\n        change(state, to_normal, context(rx_link_ref2, 4));\n        stream.match(/^`_/);\n        token = 'link';\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (stream.match(rx_verbatim)) {\n      change(state, to_verbatim);\n    }\n\n    else {\n      if (stream.next()) change(state, to_normal);\n    }\n\n    return token;\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function to_explicit(stream, state) {\n    var token = null;\n\n    if (phase(state) == rx_substitution ||\n        stream.match(rx_substitution, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_explicit, context(rx_substitution, 1));\n        stream.match(rx_substitution_text);\n        token = 'variable-2';\n        break;\n      case 1:\n        change(state, to_explicit, context(rx_substitution, 2));\n        stream.match(rx_substitution_sepa);\n        break;\n      case 2:\n        change(state, to_explicit, context(rx_substitution, 3));\n        stream.match(rx_substitution_name);\n        token = 'keyword';\n        break;\n      case 3:\n        change(state, to_explicit, context(rx_substitution, 4));\n        stream.match(rx_substitution_tail);\n        token = 'meta';\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (phase(state) == rx_directive ||\n               stream.match(rx_directive, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_explicit, context(rx_directive, 1));\n        stream.match(rx_directive_name);\n        token = 'keyword';\n\n        if (stream.current().match(/^(?:math|latex)/))\n          state.tmp_stex = true;\n        else if (stream.current().match(/^python/))\n          state.tmp_py = true;\n        break;\n      case 1:\n        change(state, to_explicit, context(rx_directive, 2));\n        stream.match(rx_directive_tail);\n        token = 'meta';\n\n        if (stream.match(/^latex\\s*$/) || state.tmp_stex) {\n          state.tmp_stex = undefined; change(state, to_mode, {\n            mode: mode_stex, local: CodeMirror.startState(mode_stex)\n          });\n        }\n        break;\n      case 2:\n        change(state, to_explicit, context(rx_directive, 3));\n        if (stream.match(/^python\\s*$/) || state.tmp_py) {\n          state.tmp_py = undefined; change(state, to_mode, {\n            mode: mode_python, local: CodeMirror.startState(mode_python)\n          });\n        }\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (phase(state) == rx_link || stream.match(rx_link, false)) {\n\n      switch (stage(state)) {\n      case 0:\n        change(state, to_explicit, context(rx_link, 1));\n        stream.match(rx_link_head);\n        stream.match(rx_link_name);\n        token = 'link';\n        break;\n      case 1:\n        change(state, to_explicit, context(rx_link, 2));\n        stream.match(rx_link_tail);\n        token = 'meta';\n        break;\n      default:\n        change(state, to_normal);\n      }\n    } else if (stream.match(rx_footnote)) {\n      change(state, to_normal);\n      token = 'quote';\n    } else if (stream.match(rx_citation)) {\n      change(state, to_normal);\n      token = 'quote';\n    }\n\n    else {\n      stream.eatSpace();\n      if (stream.eol()) {\n        change(state, to_normal);\n      } else {\n        stream.skipToEnd();\n        change(state, to_comment);\n        token = 'comment';\n      }\n    }\n\n    return token;\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function to_comment(stream, state) {\n    return as_block(stream, state, 'comment');\n  }\n\n  function to_verbatim(stream, state) {\n    return as_block(stream, state, 'meta');\n  }\n\n  function as_block(stream, state, token) {\n    if (stream.eol() || stream.eatSpace()) {\n      stream.skipToEnd();\n      return token;\n    } else {\n      change(state, to_normal);\n      return null;\n    }\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function to_mode(stream, state) {\n\n    if (state.ctx.mode && state.ctx.local) {\n\n      if (stream.sol()) {\n        if (!stream.eatSpace()) change(state, to_normal);\n        return null;\n      }\n\n      return state.ctx.mode.token(stream, state.ctx.local);\n    }\n\n    change(state, to_normal);\n    return null;\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  function context(phase, stage, mode, local) {\n    return {phase: phase, stage: stage, mode: mode, local: local};\n  }\n\n  function change(state, tok, ctx) {\n    state.tok = tok;\n    state.ctx = ctx || {};\n  }\n\n  function stage(state) {\n    return state.ctx.stage || 0;\n  }\n\n  function phase(state) {\n    return state.ctx.phase;\n  }\n\n  ///////////////////////////////////////////////////////////////////////////\n  ///////////////////////////////////////////////////////////////////////////\n\n  return {\n    startState: function () {\n      return {tok: to_normal, ctx: context(undefined, 0)};\n    },\n\n    copyState: function (state) {\n      var ctx = state.ctx, tmp = state.tmp;\n      if (ctx.local)\n        ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)};\n      if (tmp)\n        tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)};\n      return {tok: state.tok, ctx: ctx, tmp: tmp};\n    },\n\n    innerMode: function (state) {\n      return state.tmp      ? {state: state.tmp.local, mode: state.tmp.mode}\n      : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode}\n      : null;\n    },\n\n    token: function (stream, state) {\n      return state.tok(stream, state);\n    }\n  };\n}, 'python', 'stex');\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\nCodeMirror.defineMIME('text/x-rst', 'rst');\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ruby/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Ruby mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"ruby.js\"></script>\n<style>\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .cm-s-default span.cm-arrow { color: red; }\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Ruby</a>\n  </ul>\n</div>\n\n<article>\n<h2>Ruby mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html\n#\n# This program evaluates polynomials.  It first asks for the coefficients\n# of a polynomial, which must be entered on one line, highest-order first.\n# It then requests values of x and will compute the value of the poly for\n# each x.  It will repeatly ask for x values, unless you the user enters\n# a blank line.  It that case, it will ask for another polynomial.  If the\n# user types quit for either input, the program immediately exits.\n#\n\n#\n# Function to evaluate a polynomial at x.  The polynomial is given\n# as a list of coefficients, from the greatest to the least.\ndef polyval(x, coef)\n    sum = 0\n    coef = coef.clone           # Don't want to destroy the original\n    while true\n        sum += coef.shift       # Add and remove the next coef\n        break if coef.empty?    # If no more, done entirely.\n        sum *= x                # This happens the right number of times.\n    end\n    return sum\nend\n\n#\n# Function to read a line containing a list of integers and return\n# them as an array of integers.  If the string conversion fails, it\n# throws TypeError.  If the input line is the word 'quit', then it\n# converts it to an end-of-file exception\ndef readints(prompt)\n    # Read a line\n    print prompt\n    line = readline.chomp\n    raise EOFError.new if line == 'quit' # You can also use a real EOF.\n\n    # Go through each item on the line, converting each one and adding it\n    # to retval.\n    retval = [ ]\n    for str in line.split(/\\s+/)\n        if str =~ /^\\-?\\d+$/\n            retval.push(str.to_i)\n        else\n            raise TypeError.new\n        end\n    end\n\n    return retval\nend\n\n#\n# Take a coeff and an exponent and return the string representation, ignoring\n# the sign of the coefficient.\ndef term_to_str(coef, exp)\n    ret = \"\"\n\n    # Show coeff, unless it's 1 or at the right\n    coef = coef.abs\n    ret = coef.to_s     unless coef == 1 && exp > 0\n    ret += \"x\" if exp > 0                               # x if exponent not 0\n    ret += \"^\" + exp.to_s if exp > 1                    # ^exponent, if > 1.\n\n    return ret\nend\n\n#\n# Create a string of the polynomial in sort-of-readable form.\ndef polystr(p)\n    # Get the exponent of first coefficient, plus 1.\n    exp = p.length\n\n    # Assign exponents to each term, making pairs of coeff and exponent,\n    # Then get rid of the zero terms.\n    p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }\n\n    # If there's nothing left, it's a zero\n    return \"0\" if p.empty?\n\n    # *** Now p is a non-empty list of [ coef, exponent ] pairs. ***\n\n    # Convert the first term, preceded by a \"-\" if it's negative.\n    result = (if p[0][0] < 0 then \"-\" else \"\" end) + term_to_str(*p[0])\n\n    # Convert the rest of the terms, in each case adding the appropriate\n    # + or - separating them.\n    for term in p[1...p.length]\n        # Add the separator then the rep. of the term.\n        result += (if term[0] < 0 then \" - \" else \" + \" end) +\n                term_to_str(*term)\n    end\n\n    return result\nend\n\n#\n# Run until some kind of endfile.\nbegin\n    # Repeat until an exception or quit gets us out.\n    while true\n        # Read a poly until it works.  An EOF will except out of the\n        # program.\n        print \"\\n\"\n        begin\n            poly = readints(\"Enter a polynomial coefficients: \")\n        rescue TypeError\n            print \"Try again.\\n\"\n            retry\n        end\n        break if poly.empty?\n\n        # Read and evaluate x values until the user types a blank line.\n        # Again, an EOF will except out of the pgm.\n        while true\n            # Request an integer.\n            print \"Enter x value or blank line: \"\n            x = readline.chomp\n            break if x == ''\n            raise EOFError.new if x == 'quit'\n\n            # If it looks bad, let's try again.\n            if x !~ /^\\-?\\d+$/\n                print \"That doesn't look like an integer.  Please try again.\\n\"\n                next\n            end\n\n            # Convert to an integer and print the result.\n            x = x.to_i\n            print \"p(x) = \", polystr(poly), \"\\n\"\n            print \"p(\", x, \") = \", polyval(x, poly), \"\\n\"\n        end\n    end\nrescue EOFError\n    print \"\\n=== EOF ===\\n\"\nrescue Interrupt, SignalException\n    print \"\\n=== Interrupted ===\\n\"\nelse\n    print \"--- Bye ---\\n\"\nend\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-ruby\",\n        matchBrackets: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>\n\n    <p>Development of the CodeMirror Ruby mode was kindly sponsored\n    by <a href=\"http://ubalo.com/\">Ubalo</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ruby/ruby.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(\"ruby\", function(config) {\n  function wordObj(words) {\n    var o = {};\n    for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n    return o;\n  }\n  var keywords = wordObj([\n    \"alias\", \"and\", \"BEGIN\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"defined?\", \"do\", \"else\",\n    \"elsif\", \"END\", \"end\", \"ensure\", \"false\", \"for\", \"if\", \"in\", \"module\", \"next\", \"not\", \"or\",\n    \"redo\", \"rescue\", \"retry\", \"return\", \"self\", \"super\", \"then\", \"true\", \"undef\", \"unless\",\n    \"until\", \"when\", \"while\", \"yield\", \"nil\", \"raise\", \"throw\", \"catch\", \"fail\", \"loop\", \"callcc\",\n    \"caller\", \"lambda\", \"proc\", \"public\", \"protected\", \"private\", \"require\", \"load\",\n    \"require_relative\", \"extend\", \"autoload\", \"__END__\", \"__FILE__\", \"__LINE__\", \"__dir__\"\n  ]);\n  var indentWords = wordObj([\"def\", \"class\", \"case\", \"for\", \"while\", \"module\", \"then\",\n                             \"catch\", \"loop\", \"proc\", \"begin\"]);\n  var dedentWords = wordObj([\"end\", \"until\"]);\n  var matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\"};\n  var curPunc;\n\n  function chain(newtok, stream, state) {\n    state.tokenize.push(newtok);\n    return newtok(stream, state);\n  }\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    if (stream.sol() && stream.match(\"=begin\") && stream.eol()) {\n      state.tokenize.push(readBlockComment);\n      return \"comment\";\n    }\n    if (stream.eatSpace()) return null;\n    var ch = stream.next(), m;\n    if (ch == \"`\" || ch == \"'\" || ch == '\"') {\n      return chain(readQuoted(ch, \"string\", ch == '\"' || ch == \"`\"), stream, state);\n    } else if (ch == \"/\") {\n      var currentIndex = stream.current().length;\n      if (stream.skipTo(\"/\")) {\n        var search_till = stream.current().length;\n        stream.backUp(stream.current().length - currentIndex);\n        var balance = 0;  // balance brackets\n        while (stream.current().length < search_till) {\n          var chchr = stream.next();\n          if (chchr == \"(\") balance += 1;\n          else if (chchr == \")\") balance -= 1;\n          if (balance < 0) break;\n        }\n        stream.backUp(stream.current().length - currentIndex);\n        if (balance == 0)\n          return chain(readQuoted(ch, \"string-2\", true), stream, state);\n      }\n      return \"operator\";\n    } else if (ch == \"%\") {\n      var style = \"string\", embed = true;\n      if (stream.eat(\"s\")) style = \"atom\";\n      else if (stream.eat(/[WQ]/)) style = \"string\";\n      else if (stream.eat(/[r]/)) style = \"string-2\";\n      else if (stream.eat(/[wxq]/)) { style = \"string\"; embed = false; }\n      var delim = stream.eat(/[^\\w\\s=]/);\n      if (!delim) return \"operator\";\n      if (matching.propertyIsEnumerable(delim)) delim = matching[delim];\n      return chain(readQuoted(delim, style, embed, true), stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"<\" && (m = stream.match(/^<-?[\\`\\\"\\']?([a-zA-Z_?]\\w*)[\\`\\\"\\']?(?:;|$)/))) {\n      return chain(readHereDoc(m[1]), stream, state);\n    } else if (ch == \"0\") {\n      if (stream.eat(\"x\")) stream.eatWhile(/[\\da-fA-F]/);\n      else if (stream.eat(\"b\")) stream.eatWhile(/[01]/);\n      else stream.eatWhile(/[0-7]/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+\\-]?[\\d_]+)?/);\n      return \"number\";\n    } else if (ch == \"?\") {\n      while (stream.match(/^\\\\[CM]-/)) {}\n      if (stream.eat(\"\\\\\")) stream.eatWhile(/\\w/);\n      else stream.next();\n      return \"string\";\n    } else if (ch == \":\") {\n      if (stream.eat(\"'\")) return chain(readQuoted(\"'\", \"atom\", false), stream, state);\n      if (stream.eat('\"')) return chain(readQuoted('\"', \"atom\", true), stream, state);\n\n      // :> :>> :< :<< are valid symbols\n      if (stream.eat(/[\\<\\>]/)) {\n        stream.eat(/[\\<\\>]/);\n        return \"atom\";\n      }\n\n      // :+ :- :/ :* :| :& :! are valid symbols\n      if (stream.eat(/[\\+\\-\\*\\/\\&\\|\\:\\!]/)) {\n        return \"atom\";\n      }\n\n      // Symbols can't start by a digit\n      if (stream.eat(/[a-zA-Z$@_\\xa1-\\uffff]/)) {\n        stream.eatWhile(/[\\w$\\xa1-\\uffff]/);\n        // Only one ? ! = is allowed and only as the last character\n        stream.eat(/[\\?\\!\\=]/);\n        return \"atom\";\n      }\n      return \"operator\";\n    } else if (ch == \"@\" && stream.match(/^@?[a-zA-Z_\\xa1-\\uffff]/)) {\n      stream.eat(\"@\");\n      stream.eatWhile(/[\\w\\xa1-\\uffff]/);\n      return \"variable-2\";\n    } else if (ch == \"$\") {\n      if (stream.eat(/[a-zA-Z_]/)) {\n        stream.eatWhile(/[\\w]/);\n      } else if (stream.eat(/\\d/)) {\n        stream.eat(/\\d/);\n      } else {\n        stream.next(); // Must be a special global like $: or $!\n      }\n      return \"variable-3\";\n    } else if (/[a-zA-Z_\\xa1-\\uffff]/.test(ch)) {\n      stream.eatWhile(/[\\w\\xa1-\\uffff]/);\n      stream.eat(/[\\?\\!]/);\n      if (stream.eat(\":\")) return \"atom\";\n      return \"ident\";\n    } else if (ch == \"|\" && (state.varList || state.lastTok == \"{\" || state.lastTok == \"do\")) {\n      curPunc = \"|\";\n      return null;\n    } else if (/[\\(\\)\\[\\]{}\\\\;]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    } else if (ch == \"-\" && stream.eat(\">\")) {\n      return \"arrow\";\n    } else if (/[=+\\-\\/*:\\.^%<>~|]/.test(ch)) {\n      var more = stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n      if (ch == \".\" && !more) curPunc = \".\";\n      return \"operator\";\n    } else {\n      return null;\n    }\n  }\n\n  function tokenBaseUntilBrace(depth) {\n    if (!depth) depth = 1;\n    return function(stream, state) {\n      if (stream.peek() == \"}\") {\n        if (depth == 1) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        } else {\n          state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1);\n        }\n      } else if (stream.peek() == \"{\") {\n        state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1);\n      }\n      return tokenBase(stream, state);\n    };\n  }\n  function tokenBaseOnce() {\n    var alreadyCalled = false;\n    return function(stream, state) {\n      if (alreadyCalled) {\n        state.tokenize.pop();\n        return state.tokenize[state.tokenize.length-1](stream, state);\n      }\n      alreadyCalled = true;\n      return tokenBase(stream, state);\n    };\n  }\n  function readQuoted(quote, style, embed, unescaped) {\n    return function(stream, state) {\n      var escaped = false, ch;\n\n      if (state.context.type === 'read-quoted-paused') {\n        state.context = state.context.prev;\n        stream.eat(\"}\");\n      }\n\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && (unescaped || !escaped)) {\n          state.tokenize.pop();\n          break;\n        }\n        if (embed && ch == \"#\" && !escaped) {\n          if (stream.eat(\"{\")) {\n            if (quote == \"}\") {\n              state.context = {prev: state.context, type: 'read-quoted-paused'};\n            }\n            state.tokenize.push(tokenBaseUntilBrace());\n            break;\n          } else if (/[@\\$]/.test(stream.peek())) {\n            state.tokenize.push(tokenBaseOnce());\n            break;\n          }\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return style;\n    };\n  }\n  function readHereDoc(phrase) {\n    return function(stream, state) {\n      if (stream.match(phrase)) state.tokenize.pop();\n      else stream.skipToEnd();\n      return \"string\";\n    };\n  }\n  function readBlockComment(stream, state) {\n    if (stream.sol() && stream.match(\"=end\") && stream.eol())\n      state.tokenize.pop();\n    stream.skipToEnd();\n    return \"comment\";\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: [tokenBase],\n              indented: 0,\n              context: {type: \"top\", indented: -config.indentUnit},\n              continuedLine: false,\n              lastTok: null,\n              varList: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) state.indented = stream.indentation();\n      var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;\n      var thisTok = curPunc;\n      if (style == \"ident\") {\n        var word = stream.current();\n        style = state.lastTok == \".\" ? \"property\"\n          : keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n          : /^[A-Z]/.test(word) ? \"tag\"\n          : (state.lastTok == \"def\" || state.lastTok == \"class\" || state.varList) ? \"def\"\n          : \"variable\";\n        if (style == \"keyword\") {\n          thisTok = word;\n          if (indentWords.propertyIsEnumerable(word)) kwtype = \"indent\";\n          else if (dedentWords.propertyIsEnumerable(word)) kwtype = \"dedent\";\n          else if ((word == \"if\" || word == \"unless\") && stream.column() == stream.indentation())\n            kwtype = \"indent\";\n          else if (word == \"do\" && state.context.indented < state.indented)\n            kwtype = \"indent\";\n        }\n      }\n      if (curPunc || (style && style != \"comment\")) state.lastTok = thisTok;\n      if (curPunc == \"|\") state.varList = !state.varList;\n\n      if (kwtype == \"indent\" || /[\\(\\[\\{]/.test(curPunc))\n        state.context = {prev: state.context, type: curPunc || style, indented: state.indented};\n      else if ((kwtype == \"dedent\" || /[\\)\\]\\}]/.test(curPunc)) && state.context.prev)\n        state.context = state.context.prev;\n\n      if (stream.eol())\n        state.continuedLine = (curPunc == \"\\\\\" || style == \"operator\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0);\n      var ct = state.context;\n      var closing = ct.type == matching[firstChar] ||\n        ct.type == \"keyword\" && /^(?:end|until|else|elsif|when|rescue)\\b/.test(textAfter);\n      return ct.indented + (closing ? 0 : config.indentUnit) +\n        (state.continuedLine ? config.indentUnit : 0);\n    },\n\n    electricChars: \"}de\", // enD and rescuE\n    lineComment: \"#\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ruby\", \"ruby\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/ruby/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"ruby\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"divide_equal_operator\",\n     \"[variable bar] [operator /=] [variable foo]\");\n\n  MT(\"divide_equal_operator_no_spacing\",\n     \"[variable foo][operator /=][number 42]\");\n\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rust/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Rust mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"rust.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Rust</a>\n  </ul>\n</div>\n\n<article>\n<h2>Rust mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n// Demo code.\n\ntype foo<T> = int;\nenum bar {\n    some(int, foo<float>),\n    none\n}\n\nfn check_crate(x: int) {\n    let v = 10;\n    alt foo {\n      1 to 3 {\n        print_foo();\n        if x {\n            blah() + 10;\n        }\n      }\n      (x, y) { \"bye\" }\n      _ { \"hi\" }\n    }\n}\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rustsrc</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/rust/rust.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(\"rust\", function() {\n  var indentUnit = 4, altIndentUnit = 2;\n  var valKeywords = {\n    \"if\": \"if-style\", \"while\": \"if-style\", \"loop\": \"else-style\", \"else\": \"else-style\",\n    \"do\": \"else-style\", \"ret\": \"else-style\", \"fail\": \"else-style\",\n    \"break\": \"atom\", \"cont\": \"atom\", \"const\": \"let\", \"resource\": \"fn\",\n    \"let\": \"let\", \"fn\": \"fn\", \"for\": \"for\", \"alt\": \"alt\", \"iface\": \"iface\",\n    \"impl\": \"impl\", \"type\": \"type\", \"enum\": \"enum\", \"mod\": \"mod\",\n    \"as\": \"op\", \"true\": \"atom\", \"false\": \"atom\", \"assert\": \"op\", \"check\": \"op\",\n    \"claim\": \"op\", \"native\": \"ignore\", \"unsafe\": \"ignore\", \"import\": \"else-style\",\n    \"export\": \"else-style\", \"copy\": \"op\", \"log\": \"op\", \"log_err\": \"op\",\n    \"use\": \"op\", \"bind\": \"op\", \"self\": \"atom\", \"struct\": \"enum\"\n  };\n  var typeKeywords = function() {\n    var keywords = {\"fn\": \"fn\", \"block\": \"fn\", \"obj\": \"obj\"};\n    var atoms = \"bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char\".split(\" \");\n    for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = \"atom\";\n    return keywords;\n  }();\n  var operatorChar = /[+\\-*&%=<>!?|\\.@]/;\n\n  // Tokenizer\n\n  // Used as scratch variable to communicate multiple values without\n  // consing up tons of objects.\n  var tcat, content;\n  function r(tc, style) {\n    tcat = tc;\n    return style;\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"') {\n      state.tokenize = tokenString;\n      return state.tokenize(stream, state);\n    }\n    if (ch == \"'\") {\n      tcat = \"atom\";\n      if (stream.eat(\"\\\\\")) {\n        if (stream.skipTo(\"'\")) { stream.next(); return \"string\"; }\n        else { return \"error\"; }\n      } else {\n        stream.next();\n        return stream.eat(\"'\") ? \"string\" : \"error\";\n      }\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"/\")) { stream.skipToEnd(); return \"comment\"; }\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment(1);\n        return state.tokenize(stream, state);\n      }\n    }\n    if (ch == \"#\") {\n      if (stream.eat(\"[\")) { tcat = \"open-attr\"; return null; }\n      stream.eatWhile(/\\w/);\n      return r(\"macro\", \"meta\");\n    }\n    if (ch == \":\" && stream.match(\":<\")) {\n      return r(\"op\", null);\n    }\n    if (ch.match(/\\d/) || (ch == \".\" && stream.eat(/\\d/))) {\n      var flp = false;\n      if (!stream.match(/^x[\\da-f]+/i) && !stream.match(/^b[01]+/)) {\n        stream.eatWhile(/\\d/);\n        if (stream.eat(\".\")) { flp = true; stream.eatWhile(/\\d/); }\n        if (stream.match(/^e[+\\-]?\\d+/i)) { flp = true; }\n      }\n      if (flp) stream.match(/^f(?:32|64)/);\n      else stream.match(/^[ui](?:8|16|32|64)/);\n      return r(\"atom\", \"number\");\n    }\n    if (ch.match(/[()\\[\\]{}:;,]/)) return r(ch, null);\n    if (ch == \"-\" && stream.eat(\">\")) return r(\"->\", null);\n    if (ch.match(operatorChar)) {\n      stream.eatWhile(operatorChar);\n      return r(\"op\", null);\n    }\n    stream.eatWhile(/\\w/);\n    content = stream.current();\n    if (stream.match(/^::\\w/)) {\n      stream.backUp(1);\n      return r(\"prefix\", \"variable-2\");\n    }\n    if (state.keywords.propertyIsEnumerable(content))\n      return r(state.keywords[content], content.match(/true|false/) ? \"atom\" : \"keyword\");\n    return r(\"name\", \"variable\");\n  }\n\n  function tokenString(stream, state) {\n    var ch, escaped = false;\n    while (ch = stream.next()) {\n      if (ch == '\"' && !escaped) {\n        state.tokenize = tokenBase;\n        return r(\"atom\", \"string\");\n      }\n      escaped = !escaped && ch == \"\\\\\";\n    }\n    // Hack to not confuse the parser when a string is split in\n    // pieces.\n    return r(\"op\", \"string\");\n  }\n\n  function tokenComment(depth) {\n    return function(stream, state) {\n      var lastCh = null, ch;\n      while (ch = stream.next()) {\n        if (ch == \"/\" && lastCh == \"*\") {\n          if (depth == 1) {\n            state.tokenize = tokenBase;\n            break;\n          } else {\n            state.tokenize = tokenComment(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n        if (ch == \"*\" && lastCh == \"/\") {\n          state.tokenize = tokenComment(depth + 1);\n          return state.tokenize(stream, state);\n        }\n        lastCh = ch;\n      }\n      return \"comment\";\n    };\n  }\n\n  // Parser\n\n  var cx = {state: null, stream: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = {indented: state.indented, column: cx.stream.column(),\n                       type: type, prev: state.lexical, info: info};\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  function typecx() { cx.state.keywords = typeKeywords; }\n  function valcx() { cx.state.keywords = valKeywords; }\n  poplex.lex = typecx.lex = valcx.lex = true;\n\n  function commasep(comb, end) {\n    function more(type) {\n      if (type == \",\") return cont(comb, more);\n      if (type == end) return cont();\n      return cont(more);\n    }\n    return function(type) {\n      if (type == end) return cont();\n      return pass(comb, more);\n    };\n  }\n\n  function stat_of(comb, tag) {\n    return cont(pushlex(\"stat\", tag), comb, poplex, block);\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    if (type == \"let\") return stat_of(letdef1, \"let\");\n    if (type == \"fn\") return stat_of(fndef);\n    if (type == \"type\") return cont(pushlex(\"stat\"), tydef, endstatement, poplex, block);\n    if (type == \"enum\") return stat_of(enumdef);\n    if (type == \"mod\") return stat_of(mod);\n    if (type == \"iface\") return stat_of(iface);\n    if (type == \"impl\") return stat_of(impl);\n    if (type == \"open-attr\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex);\n    if (type == \"ignore\" || type.match(/[\\]\\);,]/)) return cont(block);\n    return pass(pushlex(\"stat\"), expression, poplex, endstatement, block);\n  }\n  function endstatement(type) {\n    if (type == \";\") return cont();\n    return pass();\n  }\n  function expression(type) {\n    if (type == \"atom\" || type == \"name\") return cont(maybeop);\n    if (type == \"{\") return cont(pushlex(\"}\"), exprbrace, poplex);\n    if (type.match(/[\\[\\(]/)) return matchBrackets(type, expression);\n    if (type.match(/[\\]\\)\\};,]/)) return pass();\n    if (type == \"if-style\") return cont(expression, expression);\n    if (type == \"else-style\" || type == \"op\") return cont(expression);\n    if (type == \"for\") return cont(pattern, maybetype, inop, expression, expression);\n    if (type == \"alt\") return cont(expression, altbody);\n    if (type == \"fn\") return cont(fndef);\n    if (type == \"macro\") return cont(macro);\n    return cont();\n  }\n  function maybeop(type) {\n    if (content == \".\") return cont(maybeprop);\n    if (content == \"::<\"){return cont(typarams, maybeop);}\n    if (type == \"op\" || content == \":\") return cont(expression);\n    if (type == \"(\" || type == \"[\") return matchBrackets(type, expression);\n    return pass();\n  }\n  function maybeprop() {\n    if (content.match(/^\\w+$/)) {cx.marked = \"variable\"; return cont(maybeop);}\n    return pass(expression);\n  }\n  function exprbrace(type) {\n    if (type == \"op\") {\n      if (content == \"|\") return cont(blockvars, poplex, pushlex(\"}\", \"block\"), block);\n      if (content == \"||\") return cont(poplex, pushlex(\"}\", \"block\"), block);\n    }\n    if (content == \"mutable\" || (content.match(/^\\w+$/) && cx.stream.peek() == \":\"\n                                 && !cx.stream.match(\"::\", false)))\n      return pass(record_of(expression));\n    return pass(block);\n  }\n  function record_of(comb) {\n    function ro(type) {\n      if (content == \"mutable\" || content == \"with\") {cx.marked = \"keyword\"; return cont(ro);}\n      if (content.match(/^\\w*$/)) {cx.marked = \"variable\"; return cont(ro);}\n      if (type == \":\") return cont(comb, ro);\n      if (type == \"}\") return cont();\n      return cont(ro);\n    }\n    return ro;\n  }\n  function blockvars(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(blockvars);}\n    if (type == \"op\" && content == \"|\") return cont();\n    return cont(blockvars);\n  }\n\n  function letdef1(type) {\n    if (type.match(/[\\]\\)\\};]/)) return cont();\n    if (content == \"=\") return cont(expression, letdef2);\n    if (type == \",\") return cont(letdef1);\n    return pass(pattern, maybetype, letdef1);\n  }\n  function letdef2(type) {\n    if (type.match(/[\\]\\)\\};,]/)) return pass(letdef1);\n    else return pass(expression, letdef2);\n  }\n  function maybetype(type) {\n    if (type == \":\") return cont(typecx, rtype, valcx);\n    return pass();\n  }\n  function inop(type) {\n    if (type == \"name\" && content == \"in\") {cx.marked = \"keyword\"; return cont();}\n    return pass();\n  }\n  function fndef(type) {\n    if (content == \"@\" || content == \"~\") {cx.marked = \"keyword\"; return cont(fndef);}\n    if (type == \"name\") {cx.marked = \"def\"; return cont(fndef);}\n    if (content == \"<\") return cont(typarams, fndef);\n    if (type == \"{\") return pass(expression);\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(argdef, \")\"), poplex, fndef);\n    if (type == \"->\") return cont(typecx, rtype, valcx, fndef);\n    if (type == \";\") return cont();\n    return cont(fndef);\n  }\n  function tydef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(tydef);}\n    if (content == \"<\") return cont(typarams, tydef);\n    if (content == \"=\") return cont(typecx, rtype, valcx);\n    return cont(tydef);\n  }\n  function enumdef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(enumdef);}\n    if (content == \"<\") return cont(typarams, enumdef);\n    if (content == \"=\") return cont(typecx, rtype, valcx, endstatement);\n    if (type == \"{\") return cont(pushlex(\"}\"), typecx, enumblock, valcx, poplex);\n    return cont(enumdef);\n  }\n  function enumblock(type) {\n    if (type == \"}\") return cont();\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(rtype, \")\"), poplex, enumblock);\n    if (content.match(/^\\w+$/)) cx.marked = \"def\";\n    return cont(enumblock);\n  }\n  function mod(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(mod);}\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function iface(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(iface);}\n    if (content == \"<\") return cont(typarams, iface);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function impl(type) {\n    if (content == \"<\") return cont(typarams, impl);\n    if (content == \"of\" || content == \"for\") {cx.marked = \"keyword\"; return cont(rtype, impl);}\n    if (type == \"name\") {cx.marked = \"def\"; return cont(impl);}\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function typarams() {\n    if (content == \">\") return cont();\n    if (content == \",\") return cont(typarams);\n    if (content == \":\") return cont(rtype, typarams);\n    return pass(rtype, typarams);\n  }\n  function argdef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(argdef);}\n    if (type == \":\") return cont(typecx, rtype, valcx);\n    return pass();\n  }\n  function rtype(type) {\n    if (type == \"name\") {cx.marked = \"variable-3\"; return cont(rtypemaybeparam); }\n    if (content == \"mutable\") {cx.marked = \"keyword\"; return cont(rtype);}\n    if (type == \"atom\") return cont(rtypemaybeparam);\n    if (type == \"op\" || type == \"obj\") return cont(rtype);\n    if (type == \"fn\") return cont(fntype);\n    if (type == \"{\") return cont(pushlex(\"{\"), record_of(rtype), poplex);\n    return matchBrackets(type, rtype);\n  }\n  function rtypemaybeparam() {\n    if (content == \"<\") return cont(typarams);\n    return pass();\n  }\n  function fntype(type) {\n    if (type == \"(\") return cont(pushlex(\"(\"), commasep(rtype, \")\"), poplex, fntype);\n    if (type == \"->\") return cont(rtype);\n    return pass();\n  }\n  function pattern(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(patternmaybeop);}\n    if (type == \"atom\") return cont(patternmaybeop);\n    if (type == \"op\") return cont(pattern);\n    if (type.match(/[\\]\\)\\};,]/)) return pass();\n    return matchBrackets(type, pattern);\n  }\n  function patternmaybeop(type) {\n    if (type == \"op\" && content == \".\") return cont();\n    if (content == \"to\") {cx.marked = \"keyword\"; return cont(pattern);}\n    else return pass();\n  }\n  function altbody(type) {\n    if (type == \"{\") return cont(pushlex(\"}\", \"alt\"), altblock1, poplex);\n    return pass();\n  }\n  function altblock1(type) {\n    if (type == \"}\") return cont();\n    if (type == \"|\") return cont(altblock1);\n    if (content == \"when\") {cx.marked = \"keyword\"; return cont(expression, altblock2);}\n    if (type.match(/[\\]\\);,]/)) return cont(altblock1);\n    return pass(pattern, altblock2);\n  }\n  function altblock2(type) {\n    if (type == \"{\") return cont(pushlex(\"}\", \"alt\"), block, poplex, altblock1);\n    else return pass(altblock1);\n  }\n\n  function macro(type) {\n    if (type.match(/[\\[\\(\\{]/)) return matchBrackets(type, expression);\n    return pass();\n  }\n  function matchBrackets(type, comb) {\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(comb, \"]\"), poplex);\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(comb, \")\"), poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(comb, \"}\"), poplex);\n    return cont();\n  }\n\n  function parse(state, stream, style) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n\n    while (true) {\n      var combinator = cc.length ? cc.pop() : block;\n      if (combinator(tcat)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        return cx.marked || style;\n      }\n    }\n  }\n\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        cc: [],\n        lexical: {indented: -indentUnit, column: 0, type: \"top\", align: false},\n        keywords: valKeywords,\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      tcat = content = null;\n      var style = state.tokenize(stream, state);\n      if (style == \"comment\") return style;\n      if (!state.lexical.hasOwnProperty(\"align\"))\n        state.lexical.align = true;\n      if (tcat == \"prefix\") return style;\n      if (!content) content = stream.current();\n      return parse(state, stream, style);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,\n          type = lexical.type, closing = firstChar == type;\n      if (type == \"stat\") return lexical.indented + indentUnit;\n      if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      return lexical.indented + (closing ? 0 : (lexical.info == \"alt\" ? altIndentUnit : indentUnit));\n    },\n\n    electricChars: \"{}\",\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\",\n    fold: \"brace\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rustsrc\", \"rust\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sass/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Sass mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"sass.js\"></script>\n<style>.CodeMirror {border: 1px solid #ddd; font-size:12px; height: 400px}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Sass</a>\n  </ul>\n</div>\n\n<article>\n<h2>Sass mode</h2>\n<form><textarea id=\"code\" name=\"code\">// Variable Definitions\n\n$page-width:    800px\n$sidebar-width: 200px\n$primary-color: #eeeeee\n\n// Global Attributes\n\nbody\n  font:\n    family: sans-serif\n    size: 30em\n    weight: bold\n\n// Scoped Styles\n\n#contents\n  width: $page-width\n  #sidebar\n    float: right\n    width: $sidebar-width\n  #main\n    width: $page-width - $sidebar-width\n    background: $primary-color\n    h2\n      color: blue\n\n#footer\n  height: 200px\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers : true,\n        matchBrackets : true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-sass</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sass/sass.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(\"sass\", function(config) {\n  function tokenRegexp(words) {\n    return new RegExp(\"^\" + words.join(\"|\"));\n  }\n\n  var keywords = [\"true\", \"false\", \"null\", \"auto\"];\n  var keywordsRegexp = new RegExp(\"^\" + keywords.join(\"|\"));\n\n  var operators = [\"\\\\(\", \"\\\\)\", \"=\", \">\", \"<\", \"==\", \">=\", \"<=\", \"\\\\+\", \"-\",\n                   \"\\\\!=\", \"/\", \"\\\\*\", \"%\", \"and\", \"or\", \"not\", \";\",\"\\\\{\",\"\\\\}\",\":\"];\n  var opRegexp = tokenRegexp(operators);\n\n  var pseudoElementsRegexp = /^::?[a-zA-Z_][\\w\\-]*/;\n\n  function urlTokens(stream, state) {\n    var ch = stream.peek();\n\n    if (ch === \")\") {\n      stream.next();\n      state.tokenizer = tokenBase;\n      return \"operator\";\n    } else if (ch === \"(\") {\n      stream.next();\n      stream.eatSpace();\n\n      return \"operator\";\n    } else if (ch === \"'\" || ch === '\"') {\n      state.tokenizer = buildStringTokenizer(stream.next());\n      return \"string\";\n    } else {\n      state.tokenizer = buildStringTokenizer(\")\", false);\n      return \"string\";\n    }\n  }\n  function comment(indentation, multiLine) {\n    return function(stream, state) {\n      if (stream.sol() && stream.indentation() <= indentation) {\n        state.tokenizer = tokenBase;\n        return tokenBase(stream, state);\n      }\n\n      if (multiLine && stream.skipTo(\"*/\")) {\n        stream.next();\n        stream.next();\n        state.tokenizer = tokenBase;\n      } else {\n        stream.skipToEnd();\n      }\n\n      return \"comment\";\n    };\n  }\n\n  function buildStringTokenizer(quote, greedy) {\n    if (greedy == null) { greedy = true; }\n\n    function stringTokenizer(stream, state) {\n      var nextChar = stream.next();\n      var peekChar = stream.peek();\n      var previousChar = stream.string.charAt(stream.pos-2);\n\n      var endingString = ((nextChar !== \"\\\\\" && peekChar === quote) || (nextChar === quote && previousChar !== \"\\\\\"));\n\n      if (endingString) {\n        if (nextChar !== quote && greedy) { stream.next(); }\n        state.tokenizer = tokenBase;\n        return \"string\";\n      } else if (nextChar === \"#\" && peekChar === \"{\") {\n        state.tokenizer = buildInterpolationTokenizer(stringTokenizer);\n        stream.next();\n        return \"operator\";\n      } else {\n        return \"string\";\n      }\n    }\n\n    return stringTokenizer;\n  }\n\n  function buildInterpolationTokenizer(currentTokenizer) {\n    return function(stream, state) {\n      if (stream.peek() === \"}\") {\n        stream.next();\n        state.tokenizer = currentTokenizer;\n        return \"operator\";\n      } else {\n        return tokenBase(stream, state);\n      }\n    };\n  }\n\n  function indent(state) {\n    if (state.indentCount == 0) {\n      state.indentCount++;\n      var lastScopeOffset = state.scopes[0].offset;\n      var currentOffset = lastScopeOffset + config.indentUnit;\n      state.scopes.unshift({ offset:currentOffset });\n    }\n  }\n\n  function dedent(state) {\n    if (state.scopes.length == 1) return;\n\n    state.scopes.shift();\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.peek();\n\n    // Comment\n    if (stream.match(\"/*\")) {\n      state.tokenizer = comment(stream.indentation(), true);\n      return state.tokenizer(stream, state);\n    }\n    if (stream.match(\"//\")) {\n      state.tokenizer = comment(stream.indentation(), false);\n      return state.tokenizer(stream, state);\n    }\n\n    // Interpolation\n    if (stream.match(\"#{\")) {\n      state.tokenizer = buildInterpolationTokenizer(tokenBase);\n      return \"operator\";\n    }\n\n    // Strings\n    if (ch === '\"' || ch === \"'\") {\n      stream.next();\n      state.tokenizer = buildStringTokenizer(ch);\n      return \"string\";\n    }\n\n    if(!state.cursorHalf){// state.cursorHalf === 0\n    // first half i.e. before : for key-value pairs\n    // including selectors\n\n      if (ch === \".\") {\n        stream.next();\n        if (stream.match(/^[\\w-]+/)) {\n          indent(state);\n          return \"atom\";\n        } else if (stream.peek() === \"#\") {\n          indent(state);\n          return \"atom\";\n        }\n      }\n\n      if (ch === \"#\") {\n        stream.next();\n        // ID selectors\n        if (stream.match(/^[\\w-]+/)) {\n          indent(state);\n          return \"atom\";\n        }\n        if (stream.peek() === \"#\") {\n          indent(state);\n          return \"atom\";\n        }\n      }\n\n      // Variables\n      if (ch === \"$\") {\n        stream.next();\n        stream.eatWhile(/[\\w-]/);\n        return \"variable-2\";\n      }\n\n      // Numbers\n      if (stream.match(/^-?[0-9\\.]+/))\n        return \"number\";\n\n      // Units\n      if (stream.match(/^(px|em|in)\\b/))\n        return \"unit\";\n\n      if (stream.match(keywordsRegexp))\n        return \"keyword\";\n\n      if (stream.match(/^url/) && stream.peek() === \"(\") {\n        state.tokenizer = urlTokens;\n        return \"atom\";\n      }\n\n      if (ch === \"=\") {\n        // Match shortcut mixin definition\n        if (stream.match(/^=[\\w-]+/)) {\n          indent(state);\n          return \"meta\";\n        }\n      }\n\n      if (ch === \"+\") {\n        // Match shortcut mixin definition\n        if (stream.match(/^\\+[\\w-]+/)){\n          return \"variable-3\";\n        }\n      }\n\n      if(ch === \"@\"){\n        if(stream.match(/@extend/)){\n          if(!stream.match(/\\s*[\\w]/))\n            dedent(state);\n        }\n      }\n\n\n      // Indent Directives\n      if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {\n        indent(state);\n        return \"meta\";\n      }\n\n      // Other Directives\n      if (ch === \"@\") {\n        stream.next();\n        stream.eatWhile(/[\\w-]/);\n        return \"meta\";\n      }\n\n      if (stream.eatWhile(/[\\w-]/)){\n        if(stream.match(/ *: *[\\w-\\+\\$#!\\(\"']/,false)){\n          return \"propery\";\n        }\n        else if(stream.match(/ *:/,false)){\n          indent(state);\n          state.cursorHalf = 1;\n          return \"atom\";\n        }\n        else if(stream.match(/ *,/,false)){\n          return \"atom\";\n        }\n        else{\n          indent(state);\n          return \"atom\";\n        }\n      }\n\n      if(ch === \":\"){\n        if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element\n          return \"keyword\";\n        }\n        stream.next();\n        state.cursorHalf=1;\n        return \"operator\";\n      }\n\n    } // cursorHalf===0 ends here\n    else{\n\n      if (ch === \"#\") {\n        stream.next();\n        // Hex numbers\n        if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){\n          if(!stream.peek()){\n            state.cursorHalf = 0;\n          }\n          return \"number\";\n        }\n      }\n\n      // Numbers\n      if (stream.match(/^-?[0-9\\.]+/)){\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"number\";\n      }\n\n      // Units\n      if (stream.match(/^(px|em|in)\\b/)){\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"unit\";\n      }\n\n      if (stream.match(keywordsRegexp)){\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"keyword\";\n      }\n\n      if (stream.match(/^url/) && stream.peek() === \"(\") {\n        state.tokenizer = urlTokens;\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"atom\";\n      }\n\n      // Variables\n      if (ch === \"$\") {\n        stream.next();\n        stream.eatWhile(/[\\w-]/);\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"variable-3\";\n      }\n\n      // bang character for !important, !default, etc.\n      if (ch === \"!\") {\n        stream.next();\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return stream.match(/^[\\w]+/) ? \"keyword\": \"operator\";\n      }\n\n      if (stream.match(opRegexp)){\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"operator\";\n      }\n\n      // attributes\n      if (stream.eatWhile(/[\\w-]/)) {\n        if(!stream.peek()){\n          state.cursorHalf = 0;\n        }\n        return \"attribute\";\n      }\n\n      //stream.eatSpace();\n      if(!stream.peek()){\n        state.cursorHalf = 0;\n        return null;\n      }\n\n    } // else ends here\n\n    if (stream.match(opRegexp))\n      return \"operator\";\n\n    // If we haven't returned by now, we move 1 character\n    // and return an error\n    stream.next();\n    return null;\n  }\n\n  function tokenLexer(stream, state) {\n    if (stream.sol()) state.indentCount = 0;\n    var style = state.tokenizer(stream, state);\n    var current = stream.current();\n\n    if (current === \"@return\" || current === \"}\"){\n      dedent(state);\n    }\n\n    if (style !== null) {\n      var startOfToken = stream.pos - current.length;\n\n      var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);\n\n      var newScopes = [];\n\n      for (var i = 0; i < state.scopes.length; i++) {\n        var scope = state.scopes[i];\n\n        if (scope.offset <= withCurrentIndent)\n          newScopes.push(scope);\n      }\n\n      state.scopes = newScopes;\n    }\n\n\n    return style;\n  }\n\n  return {\n    startState: function() {\n      return {\n        tokenizer: tokenBase,\n        scopes: [{offset: 0, type: \"sass\"}],\n        indentCount: 0,\n        cursorHalf: 0,  // cursor half tells us if cursor lies after (1)\n                        // or before (0) colon (well... more or less)\n        definedVars: [],\n        definedMixins: []\n      };\n    },\n    token: function(stream, state) {\n      var style = tokenLexer(stream, state);\n\n      state.lastToken = { style: style, content: stream.current() };\n\n      return style;\n    },\n\n    indent: function(state) {\n      return state.scopes[0].offset;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-sass\", \"sass\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/scheme/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Scheme mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"scheme.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Scheme</a>\n  </ul>\n</div>\n\n<article>\n<h2>Scheme mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n; See if the input starts with a given symbol.\n(define (match-symbol input pattern)\n  (cond ((null? (remain input)) #f)\n\t((eqv? (car (remain input)) pattern) (r-cdr input))\n\t(else #f)))\n\n; Allow the input to start with one of a list of patterns.\n(define (match-or input pattern)\n  (cond ((null? pattern) #f)\n\t((match-pattern input (car pattern)))\n\t(else (match-or input (cdr pattern)))))\n\n; Allow a sequence of patterns.\n(define (match-seq input pattern)\n  (if (null? pattern)\n      input\n      (let ((match (match-pattern input (car pattern))))\n\t(if match (match-seq match (cdr pattern)) #f))))\n\n; Match with the pattern but no problem if it does not match.\n(define (match-opt input pattern)\n  (let ((match (match-pattern input (car pattern))))\n    (if match match input)))\n\n; Match anything (other than '()), until pattern is found. The rather\n; clumsy form of requiring an ending pattern is needed to decide where\n; the end of the match is. If none is given, this will match the rest\n; of the sentence.\n(define (match-any input pattern)\n  (cond ((null? (remain input)) #f)\n\t((null? pattern) (f-cons (remain input) (clear-remain input)))\n\t(else\n\t (let ((accum-any (collector)))\n\t   (define (match-pattern-any input pattern)\n\t     (cond ((null? (remain input)) #f)\n\t\t   (else (accum-any (car (remain input)))\n\t\t\t (cond ((match-pattern (r-cdr input) pattern))\n\t\t\t       (else (match-pattern-any (r-cdr input) pattern))))))\n\t   (let ((retval (match-pattern-any input (car pattern))))\n\t     (if retval\n\t\t (f-cons (accum-any) retval)\n\t\t #f))))))\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/scheme/scheme.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Author: Koh Zi Han, based on implementation by Koh Zi Chun\n */\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(\"scheme\", function () {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\";\n    var INDENT_WORD_SKIP = 2;\n\n    function makeKeywords(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\n    var keywords = makeKeywords(\"λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?\");\n    var indentKeys = makeKeywords(\"define let letrec let* lambda\");\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\\/[01]+#*)?i|[-+]?[01]+#*(?:\\/[01]+#*)?@[-+]?[01]+#*(?:\\/[01]+#*)?|[-+]?[01]+#*(?:\\/[01]+#*)?[-+](?:[01]+#*(?:\\/[01]+#*)?)?i|[-+]?[01]+#*(?:\\/[01]+#*)?)(?=[()\\s;\"]|$)/i);\n    var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?)(?=[()\\s;\"]|$)/i);\n    var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\\da-f]+#*(?:\\/[\\da-f]+#*)?i|[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?@[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?|[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?[-+](?:[\\da-f]+#*(?:\\/[\\da-f]+#*)?)?i|[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?)(?=[()\\s;\"]|$)/i);\n    var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)i|[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)@[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)|[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)[-+](?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)?i|(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*))(?=[()\\s;\"]|$)/i);\n\n    function isBinaryNumber (stream) {\n        return stream.match(binaryMatcher);\n    }\n\n    function isOctalNumber (stream) {\n        return stream.match(octalMatcher);\n    }\n\n    function isDecimalNumber (stream, backup) {\n        if (backup === true) {\n            stream.backUp(1);\n        }\n        return stream.match(decimalMatcher);\n    }\n\n    function isHexNumber (stream) {\n        return stream.match(hexMatcher);\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false,\n                sExprComment: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in scheme-string mode\n                    break;\n                case \"comment\": // comment parsing mode\n                    var next, maybeEnd = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"#\" && maybeEnd) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        maybeEnd = (next == \"|\");\n                    }\n                    returnType = COMMENT;\n                    break;\n                case \"s-expr-comment\": // s-expr commenting mode\n                    state.mode = false;\n                    if(stream.peek() == \"(\" || stream.peek() == \"[\"){\n                        // actually start scheme s-expr commenting mode\n                        state.sExprComment = 0;\n                    }else{\n                        // if not we just comment the entire of the next token\n                        stream.eatWhile(/[^/s]/); // eat non spaces\n                        returnType = COMMENT;\n                        break;\n                    }\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n\n                    } else if (ch == \"'\") {\n                        returnType = ATOM;\n                    } else if (ch == '#') {\n                        if (stream.eat(\"|\")) {                    // Multi-line comment\n                            state.mode = \"comment\"; // toggle to comment mode\n                            returnType = COMMENT;\n                        } else if (stream.eat(/[tf]/i)) {            // #t/#f (atom)\n                            returnType = ATOM;\n                        } else if (stream.eat(';')) {                // S-Expr comment\n                            state.mode = \"s-expr-comment\";\n                            returnType = COMMENT;\n                        } else {\n                            var numTest = null, hasExactness = false, hasRadix = true;\n                            if (stream.eat(/[ei]/i)) {\n                                hasExactness = true;\n                            } else {\n                                stream.backUp(1);       // must be radix specifier\n                            }\n                            if (stream.match(/^#b/i)) {\n                                numTest = isBinaryNumber;\n                            } else if (stream.match(/^#o/i)) {\n                                numTest = isOctalNumber;\n                            } else if (stream.match(/^#x/i)) {\n                                numTest = isHexNumber;\n                            } else if (stream.match(/^#d/i)) {\n                                numTest = isDecimalNumber;\n                            } else if (stream.match(/^[-+0-9.]/, false)) {\n                                hasRadix = false;\n                                numTest = isDecimalNumber;\n                            // re-consume the intial # if all matches failed\n                            } else if (!hasExactness) {\n                                stream.eat('#');\n                            }\n                            if (numTest != null) {\n                                if (hasRadix && !hasExactness) {\n                                    // consume optional exactness after radix\n                                    stream.match(/^#[ei]/i);\n                                }\n                                if (numTest(stream))\n                                    returnType = NUMBER;\n                            }\n                        }\n                    } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal\n                        returnType = NUMBER;\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (ch == \"(\" || ch == \"[\") {\n                      var keyWord = ''; var indentTemp = stream.column(), letter;\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        while ((letter = stream.eat(/[^\\s\\(\\[\\;\\)\\]]/)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word\n\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation 1 space after\n                                pushStack(state, indentTemp + 1, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        if(typeof state.sExprComment == \"number\") state.sExprComment++;\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : \"[\")) {\n                            popStack(state);\n\n                            if(typeof state.sExprComment == \"number\"){\n                                if(--state.sExprComment == 0){\n                                    returnType = COMMENT; // final closing bracket\n                                    state.sExprComment = false; // turn off s-expr commenting mode\n                                }\n                            }\n                        }\n                    } else {\n                        stream.eatWhile(/[\\w\\$_\\-!$%&*+\\.\\/:<=>?@\\^~]/);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else returnType = \"variable\";\n                    }\n            }\n            return (typeof state.sExprComment == \"number\") ? COMMENT : returnType;\n        },\n\n        indent: function (state) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        },\n\n        lineComment: \";;\"\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-scheme\", \"scheme\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/shell/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Shell mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=stylesheet href=../../lib/codemirror.css>\n<script src=../../lib/codemirror.js></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=shell.js></script>\n<style type=text/css>\n  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Shell</a>\n  </ul>\n</div>\n\n<article>\n<h2>Shell mode</h2>\n\n\n<textarea id=code>\n#!/bin/bash\n\n# clone the repository\ngit clone http://github.com/garden/tree\n\n# generate HTTPS credentials\ncd tree\nopenssl genrsa -aes256 -out https.key 1024\nopenssl req -new -nodes -key https.key -out https.csr\nopenssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt\ncp https.key{,.orig}\nopenssl rsa -in https.key.orig -out https.key\n\n# start the server in HTTPS mode\ncd web\nsudo node ../server.js 443 'yes' &gt;&gt; ../node.log &amp;\n\n# here is how to stop the server\nfor pid in `ps aux | grep 'node ../server.js' | awk '{print $2}'` ; do\n  sudo kill -9 $pid 2&gt; /dev/null\ndone\n\nexit 0</textarea>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById('code'), {\n    mode: 'shell',\n    lineNumbers: true,\n    matchBrackets: true\n  });\n</script>\n\n<p><strong>MIME types defined:</strong> <code>text/x-sh</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/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));\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) {\n    return function(stream, state) {\n      var next, end = false, escaped = false;\n      while ((next = stream.next()) != null) {\n        if (next === quote && !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        escaped = !escaped && next === '\\\\';\n      }\n      if (end || !escaped) {\n        state.tokens.shift();\n      }\n      return (quote === '`' || quote === ')' ? 'quote' : 'string');\n    };\n  };\n\n  var tokenDollar = function(stream, state) {\n    if (state.tokens.length > 1) stream.eat('$');\n    var ch = stream.next(), hungry = /\\w/;\n    if (ch === '{') hungry = /[^}]/;\n    if (ch === '(') {\n      state.tokens[0] = tokenString(')');\n      return tokenize(stream, state);\n    }\n    if (!/\\d/.test(ch)) {\n      stream.eatWhile(hungry);\n      stream.eat('}');\n    }\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    lineComment: '#',\n    fold: \"brace\"\n  };\n});\n\nCodeMirror.defineMIME('text/x-sh', 'shell');\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/shell/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({}, \"shell\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"var\",\n     \"text [def $var] text\");\n  MT(\"varBraces\",\n     \"text[def ${var}]text\");\n  MT(\"varVar\",\n     \"text [def $a$b] text\");\n  MT(\"varBracesVarBraces\",\n     \"text[def ${a}${b}]text\");\n\n  MT(\"singleQuotedVar\",\n     \"[string 'text $var text']\");\n  MT(\"singleQuotedVarBraces\",\n     \"[string 'text ${var} text']\");\n\n  MT(\"doubleQuotedVar\",\n     '[string \"text ][def $var][string  text\"]');\n  MT(\"doubleQuotedVarBraces\",\n     '[string \"text][def ${var}][string text\"]');\n  MT(\"doubleQuotedVarPunct\",\n     '[string \"text ][def $@][string  text\"]');\n  MT(\"doubleQuotedVarVar\",\n     '[string \"][def $a$b][string \"]');\n  MT(\"doubleQuotedVarBracesVarBraces\",\n     '[string \"][def ${a}${b}][string \"]');\n\n  MT(\"notAString\",\n     \"text\\\\'text\");\n  MT(\"escapes\",\n     \"outside\\\\'\\\\\\\"\\\\`\\\\\\\\[string \\\"inside\\\\`\\\\'\\\\\\\"\\\\\\\\`\\\\$notAVar\\\"]outside\\\\$\\\\(notASubShell\\\\)\");\n\n  MT(\"subshell\",\n     \"[builtin echo] [quote $(whoami)] s log, stardate [quote `date`].\");\n  MT(\"doubleQuotedSubshell\",\n     \"[builtin echo] [string \\\"][quote $(whoami)][string 's log, stardate `date`.\\\"]\");\n\n  MT(\"hashbang\",\n     \"[meta #!/bin/bash]\");\n  MT(\"comment\",\n     \"text [comment # Blurb]\");\n\n  MT(\"numbers\",\n     \"[number 0] [number 1] [number 2]\");\n  MT(\"keywords\",\n     \"[keyword while] [atom true]; [keyword do]\",\n     \"  [builtin sleep] [number 3]\",\n     \"[keyword done]\");\n  MT(\"options\",\n     \"[builtin ls] [attribute -l] [attribute --human-readable]\");\n  MT(\"operator\",\n     \"[def var][operator =]value\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sieve/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Sieve (RFC5228) mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"sieve.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Sieve (RFC5228)</a>\n  </ul>\n</div>\n\n<article>\n<h2>Sieve (RFC5228) mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n#\n# Example Sieve Filter\n# Declare any optional features or extension used by the script\n#\n\nrequire [\"fileinto\", \"reject\"];\n\n#\n# Reject any large messages (note that the four leading dots get\n# \"stuffed\" to three)\n#\nif size :over 1M\n{\n  reject text:\nPlease do not send me large attachments.\nPut your file on a server and send me the URL.\nThank you.\n.... Fred\n.\n;\n  stop;\n}\n\n#\n# Handle messages from known mailing lists\n# Move messages from IETF filter discussion list to filter folder\n#\nif header :is \"Sender\" \"owner-ietf-mta-filters@imc.org\"\n{\n  fileinto \"filter\";  # move to \"filter\" folder\n}\n#\n# Keep all messages to or from people in my company\n#\nelsif address :domain :is [\"From\", \"To\"] \"example.com\"\n{\n  keep;               # keep in \"In\" folder\n}\n\n#\n# Try and catch unsolicited email.  If a message is not to me,\n# or it contains a subject known to be spam, file it away.\n#\nelsif anyof (not address :all :contains\n               [\"To\", \"Cc\", \"Bcc\"] \"me@example.com\",\n             header :matches \"subject\"\n               [\"*make*money*fast*\", \"*university*dipl*mas*\"])\n{\n  # If message header does not contain my address,\n  # it's from a list.\n  fileinto \"spam\";   # move to \"spam\" folder\n}\nelse\n{\n  # Move all other (non-company) mail to \"personal\"\n  # folder.\n  fileinto \"personal\";\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>application/sieve</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sieve/sieve.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(\"sieve\", function(config) {\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\n  var keywords = words(\"if elsif else stop require\");\n  var atoms = words(\"true false not\");\n  var indentUnit = config.indentUnit;\n\n  function tokenBase(stream, state) {\n\n    var ch = stream.next();\n    if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n\n    if (ch === '#') {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n\n    if (ch == \"\\\"\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n\n    if (ch == \"(\") {\n      state._indent.push(\"(\");\n      // add virtual angel wings so that editor behaves...\n      // ...more sane incase of broken brackets\n      state._indent.push(\"{\");\n      return null;\n    }\n\n    if (ch === \"{\") {\n      state._indent.push(\"{\");\n      return null;\n    }\n\n    if (ch == \")\")  {\n      state._indent.pop();\n      state._indent.pop();\n    }\n\n    if (ch === \"}\") {\n      state._indent.pop();\n      return null;\n    }\n\n    if (ch == \",\")\n      return null;\n\n    if (ch == \";\")\n      return null;\n\n\n    if (/[{}\\(\\),;]/.test(ch))\n      return null;\n\n    // 1*DIGIT \"K\" / \"M\" / \"G\"\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\d]/);\n      stream.eat(/[KkMmGg]/);\n      return \"number\";\n    }\n\n    // \":\" (ALPHA / \"_\") *(ALPHA / DIGIT / \"_\")\n    if (ch == \":\") {\n      stream.eatWhile(/[a-zA-Z_]/);\n      stream.eatWhile(/[a-zA-Z0-9_]/);\n\n      return \"operator\";\n    }\n\n    stream.eatWhile(/\\w/);\n    var cur = stream.current();\n\n    // \"text:\" *(SP / HTAB) (hash-comment / CRLF)\n    // *(multiline-literal / multiline-dotstart)\n    // \".\" CRLF\n    if ((cur == \"text\") && stream.eat(\":\"))\n    {\n      state.tokenize = tokenMultiLineString;\n      return \"string\";\n    }\n\n    if (keywords.propertyIsEnumerable(cur))\n      return \"keyword\";\n\n    if (atoms.propertyIsEnumerable(cur))\n      return \"atom\";\n\n    return null;\n  }\n\n  function tokenMultiLineString(stream, state)\n  {\n    state._multiLineString = true;\n    // the first line is special it may contain a comment\n    if (!stream.sol()) {\n      stream.eatSpace();\n\n      if (stream.peek() == \"#\") {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n\n      stream.skipToEnd();\n      return \"string\";\n    }\n\n    if ((stream.next() == \".\")  && (stream.eol()))\n    {\n      state._multiLineString = false;\n      state.tokenize = tokenBase;\n    }\n\n    return \"string\";\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return \"string\";\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              _indent: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace())\n        return null;\n\n      return (state.tokenize || tokenBase)(stream, state);;\n    },\n\n    indent: function(state, _textAfter) {\n      var length = state._indent.length;\n      if (_textAfter && (_textAfter[0] == \"}\"))\n        length--;\n\n      if (length <0)\n        length = 0;\n\n      return length * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/sieve\", \"sieve\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/slim/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: SLIM mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/ambiance.css\">\n<script src=\"https://code.jquery.com/jquery-1.11.1.min.js\"></script>\n<script src=\"https://code.jquery.com/ui/1.11.0/jquery-ui.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../htmlembedded/htmlembedded.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"../coffeescript/coffeescript.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../ruby/ruby.js\"></script>\n<script src=\"../markdown/markdown.js\"></script>\n<script src=\"slim.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">SLIM</a>\n  </ul>\n</div>\n\n<article>\n  <h2>SLIM mode</h2>\n  <form><textarea id=\"code\" name=\"code\">\nbody\n  table\n    - for user in users\n      td id=\"user_#{user.id}\" class=user.role\n        a href=user_action(user, :edit) Edit #{user.name}\n        a href=(path_to_user user) = user.name\nbody\n  h1(id=\"logo\") = page_logo\n  h2[id=\"tagline\" class=\"small tagline\"] = page_tagline\n\nh2[id=\"tagline\"\n   class=\"small tagline\"] = page_tagline\n\nh1 id = \"logo\" = page_logo\nh2 [ id = \"tagline\" ] = page_tagline\n\n/ comment\n  second line\n/! html comment\n   second line\n<!-- html comment -->\n<a href=\"#{'hello' if set}\">link</a>\na.slim href=\"work\" disabled=false running==:atom Text <b>bold</b>\n.clazz data-id=\"test\" == 'hello' unless quark\n | Text mode #{12}\n   Second line\n= x ||= :ruby_atom\n#menu.left\n  - @env.each do |x|\n    li: a = x\n*@dyntag attr=\"val\"\n.first *{:class => [:second, :third]} Text\n.second class=[\"text\",\"more\"]\n.third class=:text,:symbol\n\n  </textarea></form>\n  <script>\n    var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n      lineNumbers: true,\n      theme: \"ambiance\",\n      mode: \"application/x-slim\"\n    });\n    $('.CodeMirror').resizable({\n      resize: function() {\n        editor.setSize($(this).width(), $(this).height());\n        //editor.refresh();\n      }\n    });\n  </script>\n\n  <p><strong>MIME types defined:</strong> <code>application/x-slim</code>.</p>\n\n  <p>\n    <strong>Parsing/Highlighting Tests:</strong>\n    <a href=\"../../test/index.html#slim_*\">normal</a>,\n    <a href=\"../../test/index.html#verbose,slim_*\">verbose</a>.\n  </p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/slim/slim.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"), require(\"../htmlmixed/htmlmixed\"), require(\"../ruby/ruby\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\", \"../ruby/ruby\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\n  CodeMirror.defineMode(\"slim\", function(config) {\n    var htmlMode = CodeMirror.getMode(config, {name: \"htmlmixed\"});\n    var rubyMode = CodeMirror.getMode(config, \"ruby\");\n    var modes = { html: htmlMode, ruby: rubyMode };\n    var embedded = {\n      ruby: \"ruby\",\n      javascript: \"javascript\",\n      css: \"text/css\",\n      sass: \"text/x-sass\",\n      scss: \"text/x-scss\",\n      less: \"text/x-less\",\n      styl: \"text/x-styl\", // no highlighting so far\n      coffee: \"coffeescript\",\n      asciidoc: \"text/x-asciidoc\",\n      markdown: \"text/x-markdown\",\n      textile: \"text/x-textile\", // no highlighting so far\n      creole: \"text/x-creole\", // no highlighting so far\n      wiki: \"text/x-wiki\", // no highlighting so far\n      mediawiki: \"text/x-mediawiki\", // no highlighting so far\n      rdoc: \"text/x-rdoc\", // no highlighting so far\n      builder: \"text/x-builder\", // no highlighting so far\n      nokogiri: \"text/x-nokogiri\", // no highlighting so far\n      erb: \"application/x-erb\"\n    };\n    var embeddedRegexp = function(map){\n      var arr = [];\n      for(var key in map) arr.push(key);\n      return new RegExp(\"^(\"+arr.join('|')+\"):\");\n    }(embedded);\n\n    var styleMap = {\n      \"commentLine\": \"comment\",\n      \"slimSwitch\": \"operator special\",\n      \"slimTag\": \"tag\",\n      \"slimId\": \"attribute def\",\n      \"slimClass\": \"attribute qualifier\",\n      \"slimAttribute\": \"attribute\",\n      \"slimSubmode\": \"keyword special\",\n      \"closeAttributeTag\": null,\n      \"slimDoctype\": null,\n      \"lineContinuation\": null\n    };\n    var closing = {\n      \"{\": \"}\",\n      \"[\": \"]\",\n      \"(\": \")\"\n    };\n\n    var nameStartChar = \"_a-zA-Z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\";\n    var nameChar = nameStartChar + \"\\\\-0-9\\xB7\\u0300-\\u036F\\u203F-\\u2040\";\n    var nameRegexp = new RegExp(\"^[:\"+nameStartChar+\"](?::[\"+nameChar+\"]|[\"+nameChar+\"]*)\");\n    var attributeNameRegexp = new RegExp(\"^[:\"+nameStartChar+\"][:\\\\.\"+nameChar+\"]*(?=\\\\s*=)\");\n    var wrappedAttributeNameRegexp = new RegExp(\"^[:\"+nameStartChar+\"][:\\\\.\"+nameChar+\"]*\");\n    var classNameRegexp = /^\\.-?[_a-zA-Z]+[\\w\\-]*/;\n    var classIdRegexp = /^#[_a-zA-Z]+[\\w\\-]*/;\n\n    function backup(pos, tokenize, style) {\n      var restore = function(stream, state) {\n        state.tokenize = tokenize;\n        if (stream.pos < pos) {\n          stream.pos = pos;\n          return style;\n        }\n        return state.tokenize(stream, state);\n      };\n      return function(stream, state) {\n        state.tokenize = restore;\n        return tokenize(stream, state);\n      };\n    }\n\n    function maybeBackup(stream, state, pat, offset, style) {\n      var cur = stream.current();\n      var idx = cur.search(pat);\n      if (idx > -1) {\n        state.tokenize = backup(stream.pos, state.tokenize, style);\n        stream.backUp(cur.length - idx - offset);\n      }\n      return style;\n    }\n\n    function continueLine(state, column) {\n      state.stack = {\n        parent: state.stack,\n        style: \"continuation\",\n        indented: column,\n        tokenize: state.line\n      };\n      state.line = state.tokenize;\n    }\n    function finishContinue(state) {\n      if (state.line == state.tokenize) {\n        state.line = state.stack.tokenize;\n        state.stack = state.stack.parent;\n      }\n    }\n\n    function lineContinuable(column, tokenize) {\n      return function(stream, state) {\n        finishContinue(state);\n        if (stream.match(/^\\\\$/)) {\n          continueLine(state, column);\n          return \"lineContinuation\";\n        }\n        var style = tokenize(stream, state);\n        if (stream.eol() && stream.current().match(/(?:^|[^\\\\])(?:\\\\\\\\)*\\\\$/)) {\n          stream.backUp(1);\n        }\n        return style;\n      };\n    }\n    function commaContinuable(column, tokenize) {\n      return function(stream, state) {\n        finishContinue(state);\n        var style = tokenize(stream, state);\n        if (stream.eol() && stream.current().match(/,$/)) {\n          continueLine(state, column);\n        }\n        return style;\n      };\n    }\n\n    function rubyInQuote(endQuote, tokenize) {\n      // TODO: add multi line support\n      return function(stream, state) {\n        var ch = stream.peek();\n        if (ch == endQuote && state.rubyState.tokenize.length == 1) {\n          // step out of ruby context as it seems to complete processing all the braces\n          stream.next();\n          state.tokenize = tokenize;\n          return \"closeAttributeTag\";\n        } else {\n          return ruby(stream, state);\n        }\n      };\n    }\n    function startRubySplat(tokenize) {\n      var rubyState;\n      var runSplat = function(stream, state) {\n        if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) {\n          stream.backUp(1);\n          if (stream.eatSpace()) {\n            state.rubyState = rubyState;\n            state.tokenize = tokenize;\n            return tokenize(stream, state);\n          }\n          stream.next();\n        }\n        return ruby(stream, state);\n      };\n      return function(stream, state) {\n        rubyState = state.rubyState;\n        state.rubyState = rubyMode.startState();\n        state.tokenize = runSplat;\n        return ruby(stream, state);\n      };\n    }\n\n    function ruby(stream, state) {\n      return rubyMode.token(stream, state.rubyState);\n    }\n\n    function htmlLine(stream, state) {\n      if (stream.match(/^\\\\$/)) {\n        return \"lineContinuation\";\n      }\n      return html(stream, state);\n    }\n    function html(stream, state) {\n      if (stream.match(/^#\\{/)) {\n        state.tokenize = rubyInQuote(\"}\", state.tokenize);\n        return null;\n      }\n      return maybeBackup(stream, state, /[^\\\\]#\\{/, 1, htmlMode.token(stream, state.htmlState));\n    }\n\n    function startHtmlLine(lastTokenize) {\n      return function(stream, state) {\n        var style = htmlLine(stream, state);\n        if (stream.eol()) state.tokenize = lastTokenize;\n        return style;\n      };\n    }\n\n    function startHtmlMode(stream, state, offset) {\n      state.stack = {\n        parent: state.stack,\n        style: \"html\",\n        indented: stream.column() + offset, // pipe + space\n        tokenize: state.line\n      };\n      state.line = state.tokenize = html;\n      return null;\n    }\n\n    function comment(stream, state) {\n      stream.skipToEnd();\n      return state.stack.style;\n    }\n\n    function commentMode(stream, state) {\n      state.stack = {\n        parent: state.stack,\n        style: \"comment\",\n        indented: state.indented + 1,\n        tokenize: state.line\n      };\n      state.line = comment;\n      return comment(stream, state);\n    }\n\n    function attributeWrapper(stream, state) {\n      if (stream.eat(state.stack.endQuote)) {\n        state.line = state.stack.line;\n        state.tokenize = state.stack.tokenize;\n        state.stack = state.stack.parent;\n        return null;\n      }\n      if (stream.match(wrappedAttributeNameRegexp)) {\n        state.tokenize = attributeWrapperAssign;\n        return \"slimAttribute\";\n      }\n      stream.next();\n      return null;\n    }\n    function attributeWrapperAssign(stream, state) {\n      if (stream.match(/^==?/)) {\n        state.tokenize = attributeWrapperValue;\n        return null;\n      }\n      return attributeWrapper(stream, state);\n    }\n    function attributeWrapperValue(stream, state) {\n      var ch = stream.peek();\n      if (ch == '\"' || ch == \"\\'\") {\n        state.tokenize = readQuoted(ch, \"string\", true, false, attributeWrapper);\n        stream.next();\n        return state.tokenize(stream, state);\n      }\n      if (ch == '[') {\n        return startRubySplat(attributeWrapper)(stream, state);\n      }\n      if (stream.match(/^(true|false|nil)\\b/)) {\n        state.tokenize = attributeWrapper;\n        return \"keyword\";\n      }\n      return startRubySplat(attributeWrapper)(stream, state);\n    }\n\n    function startAttributeWrapperMode(state, endQuote, tokenize) {\n      state.stack = {\n        parent: state.stack,\n        style: \"wrapper\",\n        indented: state.indented + 1,\n        tokenize: tokenize,\n        line: state.line,\n        endQuote: endQuote\n      };\n      state.line = state.tokenize = attributeWrapper;\n      return null;\n    }\n\n    function sub(stream, state) {\n      if (stream.match(/^#\\{/)) {\n        state.tokenize = rubyInQuote(\"}\", state.tokenize);\n        return null;\n      }\n      var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize);\n      subStream.pos = stream.pos - state.stack.indented;\n      subStream.start = stream.start - state.stack.indented;\n      subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented;\n      subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented;\n      var style = state.subMode.token(subStream, state.subState);\n      stream.pos = subStream.pos + state.stack.indented;\n      return style;\n    }\n    function firstSub(stream, state) {\n      state.stack.indented = stream.column();\n      state.line = state.tokenize = sub;\n      return state.tokenize(stream, state);\n    }\n\n    function createMode(mode) {\n      var query = embedded[mode];\n      var spec = CodeMirror.mimeModes[query];\n      if (spec) {\n        return CodeMirror.getMode(config, spec);\n      }\n      var factory = CodeMirror.modes[query];\n      if (factory) {\n        return factory(config, {name: query});\n      }\n      return CodeMirror.getMode(config, \"null\");\n    }\n\n    function getMode(mode) {\n      if (!modes.hasOwnProperty(mode)) {\n        return modes[mode] = createMode(mode);\n      }\n      return modes[mode];\n    }\n\n    function startSubMode(mode, state) {\n      var subMode = getMode(mode);\n      var subState = subMode.startState && subMode.startState();\n\n      state.subMode = subMode;\n      state.subState = subState;\n\n      state.stack = {\n        parent: state.stack,\n        style: \"sub\",\n        indented: state.indented + 1,\n        tokenize: state.line\n      };\n      state.line = state.tokenize = firstSub;\n      return \"slimSubmode\";\n    }\n\n    function doctypeLine(stream, _state) {\n      stream.skipToEnd();\n      return \"slimDoctype\";\n    }\n\n    function startLine(stream, state) {\n      var ch = stream.peek();\n      if (ch == '<') {\n        return (state.tokenize = startHtmlLine(state.tokenize))(stream, state);\n      }\n      if (stream.match(/^[|']/)) {\n        return startHtmlMode(stream, state, 1);\n      }\n      if (stream.match(/^\\/(!|\\[\\w+])?/)) {\n        return commentMode(stream, state);\n      }\n      if (stream.match(/^(-|==?[<>]?)/)) {\n        state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby));\n        return \"slimSwitch\";\n      }\n      if (stream.match(/^doctype\\b/)) {\n        state.tokenize = doctypeLine;\n        return \"keyword\";\n      }\n\n      var m = stream.match(embeddedRegexp);\n      if (m) {\n        return startSubMode(m[1], state);\n      }\n\n      return slimTag(stream, state);\n    }\n\n    function slim(stream, state) {\n      if (state.startOfLine) {\n        return startLine(stream, state);\n      }\n      return slimTag(stream, state);\n    }\n\n    function slimTag(stream, state) {\n      if (stream.eat('*')) {\n        state.tokenize = startRubySplat(slimTagExtras);\n        return null;\n      }\n      if (stream.match(nameRegexp)) {\n        state.tokenize = slimTagExtras;\n        return \"slimTag\";\n      }\n      return slimClass(stream, state);\n    }\n    function slimTagExtras(stream, state) {\n      if (stream.match(/^(<>?|><?)/)) {\n        state.tokenize = slimClass;\n        return null;\n      }\n      return slimClass(stream, state);\n    }\n    function slimClass(stream, state) {\n      if (stream.match(classIdRegexp)) {\n        state.tokenize = slimClass;\n        return \"slimId\";\n      }\n      if (stream.match(classNameRegexp)) {\n        state.tokenize = slimClass;\n        return \"slimClass\";\n      }\n      return slimAttribute(stream, state);\n    }\n    function slimAttribute(stream, state) {\n      if (stream.match(/^([\\[\\{\\(])/)) {\n        return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute);\n      }\n      if (stream.match(attributeNameRegexp)) {\n        state.tokenize = slimAttributeAssign;\n        return \"slimAttribute\";\n      }\n      if (stream.peek() == '*') {\n        stream.next();\n        state.tokenize = startRubySplat(slimContent);\n        return null;\n      }\n      return slimContent(stream, state);\n    }\n    function slimAttributeAssign(stream, state) {\n      if (stream.match(/^==?/)) {\n        state.tokenize = slimAttributeValue;\n        return null;\n      }\n      // should never happen, because of forward lookup\n      return slimAttribute(stream, state);\n    }\n\n    function slimAttributeValue(stream, state) {\n      var ch = stream.peek();\n      if (ch == '\"' || ch == \"\\'\") {\n        state.tokenize = readQuoted(ch, \"string\", true, false, slimAttribute);\n        stream.next();\n        return state.tokenize(stream, state);\n      }\n      if (ch == '[') {\n        return startRubySplat(slimAttribute)(stream, state);\n      }\n      if (ch == ':') {\n        return startRubySplat(slimAttributeSymbols)(stream, state);\n      }\n      if (stream.match(/^(true|false|nil)\\b/)) {\n        state.tokenize = slimAttribute;\n        return \"keyword\";\n      }\n      return startRubySplat(slimAttribute)(stream, state);\n    }\n    function slimAttributeSymbols(stream, state) {\n      stream.backUp(1);\n      if (stream.match(/^[^\\s],(?=:)/)) {\n        state.tokenize = startRubySplat(slimAttributeSymbols);\n        return null;\n      }\n      stream.next();\n      return slimAttribute(stream, state);\n    }\n    function readQuoted(quote, style, embed, unescaped, nextTokenize) {\n      return function(stream, state) {\n        finishContinue(state);\n        var fresh = stream.current().length == 0;\n        if (stream.match(/^\\\\$/, fresh)) {\n          if (!fresh) return style;\n          continueLine(state, state.indented);\n          return \"lineContinuation\";\n        }\n        if (stream.match(/^#\\{/, fresh)) {\n          if (!fresh) return style;\n          state.tokenize = rubyInQuote(\"}\", state.tokenize);\n          return null;\n        }\n        var escaped = false, ch;\n        while ((ch = stream.next()) != null) {\n          if (ch == quote && (unescaped || !escaped)) {\n            state.tokenize = nextTokenize;\n            break;\n          }\n          if (embed && ch == \"#\" && !escaped) {\n            if (stream.eat(\"{\")) {\n              stream.backUp(2);\n              break;\n            }\n          }\n          escaped = !escaped && ch == \"\\\\\";\n        }\n        if (stream.eol() && escaped) {\n          stream.backUp(1);\n        }\n        return style;\n      };\n    }\n    function slimContent(stream, state) {\n      if (stream.match(/^==?/)) {\n        state.tokenize = ruby;\n        return \"slimSwitch\";\n      }\n      if (stream.match(/^\\/$/)) { // tag close hint\n        state.tokenize = slim;\n        return null;\n      }\n      if (stream.match(/^:/)) { // inline tag\n        state.tokenize = slimTag;\n        return \"slimSwitch\";\n      }\n      startHtmlMode(stream, state, 0);\n      return state.tokenize(stream, state);\n    }\n\n    var mode = {\n      // default to html mode\n      startState: function() {\n        var htmlState = htmlMode.startState();\n        var rubyState = rubyMode.startState();\n        return {\n          htmlState: htmlState,\n          rubyState: rubyState,\n          stack: null,\n          last: null,\n          tokenize: slim,\n          line: slim,\n          indented: 0\n        };\n      },\n\n      copyState: function(state) {\n        return {\n          htmlState : CodeMirror.copyState(htmlMode, state.htmlState),\n          rubyState: CodeMirror.copyState(rubyMode, state.rubyState),\n          subMode: state.subMode,\n          subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState),\n          stack: state.stack,\n          last: state.last,\n          tokenize: state.tokenize,\n          line: state.line\n        };\n      },\n\n      token: function(stream, state) {\n        if (stream.sol()) {\n          state.indented = stream.indentation();\n          state.startOfLine = true;\n          state.tokenize = state.line;\n          while (state.stack && state.stack.indented > state.indented && state.last != \"slimSubmode\") {\n            state.line = state.tokenize = state.stack.tokenize;\n            state.stack = state.stack.parent;\n            state.subMode = null;\n            state.subState = null;\n          }\n        }\n        if (stream.eatSpace()) return null;\n        var style = state.tokenize(stream, state);\n        state.startOfLine = false;\n        if (style) state.last = style;\n        return styleMap.hasOwnProperty(style) ? styleMap[style] : style;\n      },\n\n      blankLine: function(state) {\n        if (state.subMode && state.subMode.blankLine) {\n          return state.subMode.blankLine(state.subState);\n        }\n      },\n\n      innerMode: function(state) {\n        if (state.subMode) return {state: state.subState, mode: state.subMode};\n        return {state: state, mode: mode};\n      }\n\n      //indent: function(state) {\n      //  return state.indented;\n      //}\n    };\n    return mode;\n  }, \"htmlmixed\", \"ruby\");\n\n  CodeMirror.defineMIME(\"text/x-slim\", \"slim\");\n  CodeMirror.defineMIME(\"application/x-slim\", \"slim\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/slim/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, \"slim\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  // Requires at least one media query\n  MT(\"elementName\",\n     \"[tag h1] Hey There\");\n\n  MT(\"oneElementPerLine\",\n     \"[tag h1] Hey There .h2\");\n\n  MT(\"idShortcut\",\n     \"[attribute&def #test] Hey There\");\n\n  MT(\"tagWithIdShortcuts\",\n     \"[tag h1][attribute&def #test] Hey There\");\n\n  MT(\"classShortcut\",\n     \"[attribute&qualifier .hello] Hey There\");\n\n  MT(\"tagWithIdAndClassShortcuts\",\n     \"[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There\");\n\n  MT(\"docType\",\n     \"[keyword doctype] xml\");\n\n  MT(\"comment\",\n     \"[comment / Hello WORLD]\");\n\n  MT(\"notComment\",\n     \"[tag h1] This is not a / comment \");\n\n  MT(\"attributes\",\n     \"[tag a]([attribute title]=[string \\\"test\\\"]) [attribute href]=[string \\\"link\\\"]}\");\n\n  MT(\"multiLineAttributes\",\n     \"[tag a]([attribute title]=[string \\\"test\\\"]\",\n     \"  ) [attribute href]=[string \\\"link\\\"]}\");\n\n  MT(\"htmlCode\",\n     \"[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]\");\n\n  MT(\"rubyBlock\",\n     \"[operator&special =][variable-2 @item]\");\n\n  MT(\"selectorRubyBlock\",\n     \"[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]\");\n\n  MT(\"nestedRubyBlock\",\n      \"[tag a]\",\n      \"  [operator&special =][variable puts] [string \\\"test\\\"]\");\n\n  MT(\"multilinePlaintext\",\n      \"[tag p]\",\n      \"  | Hello,\",\n      \"    World\");\n\n  MT(\"multilineRuby\",\n      \"[tag p]\",\n      \"  [comment /# this is a comment]\",\n      \"     [comment and this is a comment too]\",\n      \"  | Date/Time\",\n      \"  [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]\",\n      \"  [tag strong][operator&special =] [variable now]\",\n      \"  [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \\\"December 31, 2006\\\"])\",\n      \"     [operator&special =][string \\\"Happy\\\"]\",\n      \"     [operator&special =][string \\\"Belated\\\"]\",\n      \"     [operator&special =][string \\\"Birthday\\\"]\");\n\n  MT(\"multilineComment\",\n      \"[comment /]\",\n      \"  [comment Multiline]\",\n      \"  [comment Comment]\");\n\n  MT(\"hamlAfterRubyTag\",\n    \"[attribute&qualifier .block]\",\n    \"  [tag strong][operator&special =] [variable now]\",\n    \"  [attribute&qualifier .test]\",\n    \"     [operator&special =][variable now]\",\n    \"  [attribute&qualifier .right]\");\n\n  MT(\"stretchedRuby\",\n     \"[operator&special =] [variable puts] [string \\\"Hello\\\"],\",\n     \"   [string \\\"World\\\"]\");\n\n  MT(\"interpolationInHashAttribute\",\n     \"[tag div]{[attribute id] = [string \\\"]#{[variable test]}[string _]#{[variable ting]}[string \\\"]} test\");\n\n  MT(\"interpolationInHTMLAttribute\",\n     \"[tag div]([attribute title]=[string \\\"]#{[variable test]}[string _]#{[variable ting]()}[string \\\"]) Test\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smalltalk/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Smalltalk mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"smalltalk.js\"></script>\n<style>\n      .CodeMirror {border: 2px solid #dee; border-right-width: 10px;}\n      .CodeMirror-gutter {border: none; background: #dee;}\n      .CodeMirror-gutter pre {color: white; font-weight: bold;}\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Smalltalk</a>\n  </ul>\n</div>\n\n<article>\n<h2>Smalltalk mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n\"\n    This is a test of the Smalltalk code\n\"\nSeaside.WAComponent subclass: #MyCounter [\n    | count |\n    MyCounter class &gt;&gt; canBeRoot [ ^true ]\n\n    initialize [\n        super initialize.\n        count := 0.\n    ]\n    states [ ^{ self } ]\n    renderContentOn: html [\n        html heading: count.\n        html anchor callback: [ count := count + 1 ]; with: '++'.\n        html space.\n        html anchor callback: [ count := count - 1 ]; with: '--'.\n    ]\n]\n\nMyCounter registerAsApplication: 'mycounter'\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-stsrc\",\n        indentUnit: 4\n      });\n    </script>\n\n    <p>Simple Smalltalk mode.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-stsrc</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smalltalk/smalltalk.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('smalltalk', function(config) {\n\n  var specialChars = /[+\\-\\/\\\\*~<>=@%|&?!.,:;^]/;\n  var keywords = /true|false|nil|self|super|thisContext/;\n\n  var Context = function(tokenizer, parent) {\n    this.next = tokenizer;\n    this.parent = parent;\n  };\n\n  var Token = function(name, context, eos) {\n    this.name = name;\n    this.context = context;\n    this.eos = eos;\n  };\n\n  var State = function() {\n    this.context = new Context(next, null);\n    this.expectVariable = true;\n    this.indentation = 0;\n    this.userIndentationDelta = 0;\n  };\n\n  State.prototype.userIndent = function(indentation) {\n    this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;\n  };\n\n  var next = function(stream, context, state) {\n    var token = new Token(null, context, false);\n    var aChar = stream.next();\n\n    if (aChar === '\"') {\n      token = nextComment(stream, new Context(nextComment, context));\n\n    } else if (aChar === '\\'') {\n      token = nextString(stream, new Context(nextString, context));\n\n    } else if (aChar === '#') {\n      if (stream.peek() === '\\'') {\n        stream.next();\n        token = nextSymbol(stream, new Context(nextSymbol, context));\n      } else {\n        if (stream.eatWhile(/[^\\s.{}\\[\\]()]/))\n          token.name = 'string-2';\n        else\n          token.name = 'meta';\n      }\n\n    } else if (aChar === '$') {\n      if (stream.next() === '<') {\n        stream.eatWhile(/[^\\s>]/);\n        stream.next();\n      }\n      token.name = 'string-2';\n\n    } else if (aChar === '|' && state.expectVariable) {\n      token.context = new Context(nextTemporaries, context);\n\n    } else if (/[\\[\\]{}()]/.test(aChar)) {\n      token.name = 'bracket';\n      token.eos = /[\\[{(]/.test(aChar);\n\n      if (aChar === '[') {\n        state.indentation++;\n      } else if (aChar === ']') {\n        state.indentation = Math.max(0, state.indentation - 1);\n      }\n\n    } else if (specialChars.test(aChar)) {\n      stream.eatWhile(specialChars);\n      token.name = 'operator';\n      token.eos = aChar !== ';'; // ; cascaded message expression\n\n    } else if (/\\d/.test(aChar)) {\n      stream.eatWhile(/[\\w\\d]/);\n      token.name = 'number';\n\n    } else if (/[\\w_]/.test(aChar)) {\n      stream.eatWhile(/[\\w\\d_]/);\n      token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;\n\n    } else {\n      token.eos = state.expectVariable;\n    }\n\n    return token;\n  };\n\n  var nextComment = function(stream, context) {\n    stream.eatWhile(/[^\"]/);\n    return new Token('comment', stream.eat('\"') ? context.parent : context, true);\n  };\n\n  var nextString = function(stream, context) {\n    stream.eatWhile(/[^']/);\n    return new Token('string', stream.eat('\\'') ? context.parent : context, false);\n  };\n\n  var nextSymbol = function(stream, context) {\n    stream.eatWhile(/[^']/);\n    return new Token('string-2', stream.eat('\\'') ? context.parent : context, false);\n  };\n\n  var nextTemporaries = function(stream, context) {\n    var token = new Token(null, context, false);\n    var aChar = stream.next();\n\n    if (aChar === '|') {\n      token.context = context.parent;\n      token.eos = true;\n\n    } else {\n      stream.eatWhile(/[^|]/);\n      token.name = 'variable';\n    }\n\n    return token;\n  };\n\n  return {\n    startState: function() {\n      return new State;\n    },\n\n    token: function(stream, state) {\n      state.userIndent(stream.indentation());\n\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      var token = state.context.next(stream, state.context, state);\n      state.context = token.context;\n      state.expectVariable = token.eos;\n\n      return token.name;\n    },\n\n    blankLine: function(state) {\n      state.userIndent(0);\n    },\n\n    indent: function(state, textAfter) {\n      var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;\n      return (state.indentation + i) * config.indentUnit;\n    },\n\n    electricChars: ']'\n  };\n\n});\n\nCodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smarty/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Smarty mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"smarty.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Smarty</a>\n  </ul>\n</div>\n\n<article>\n<h2>Smarty mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n{extends file=\"parent.tpl\"}\n{include file=\"template.tpl\"}\n\n{* some example Smarty content *}\n{if isset($name) && $name == 'Blog'}\n  This is a {$var}.\n  {$integer = 451}, {$array[] = \"a\"}, {$stringvar = \"string\"}\n  {assign var='bob' value=$var.prop}\n{elseif $name == $foo}\n  {function name=menu level=0}\n    {foreach $data as $entry}\n      {if is_array($entry)}\n        - {$entry@key}\n        {menu data=$entry level=$level+1}\n      {else}\n        {$entry}\n      {/if}\n    {/foreach}\n  {/function}\n{/if}</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"smarty\"\n      });\n    </script>\n\n    <br />\n\n\t<h3>Smarty 2, custom delimiters</h3>\n    <form><textarea id=\"code2\" name=\"code2\">\n{--extends file=\"parent.tpl\"--}\n{--include file=\"template.tpl\"--}\n\n{--* some example Smarty content *--}\n{--if isset($name) && $name == 'Blog'--}\n  This is a {--$var--}.\n  {--$integer = 451--}, {--$array[] = \"a\"--}, {--$stringvar = \"string\"--}\n  {--assign var='bob' value=$var.prop--}\n{--elseif $name == $foo--}\n  {--function name=menu level=0--}\n    {--foreach $data as $entry--}\n      {--if is_array($entry)--}\n        - {--$entry@key--}\n        {--menu data=$entry level=$level+1--}\n      {--else--}\n        {--$entry--}\n      {--/if--}\n    {--/foreach--}\n  {--/function--}\n{--/if--}</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code2\"), {\n        lineNumbers: true,\n        mode: {\n          name: \"smarty\",\n          leftDelimiter: \"{--\",\n          rightDelimiter: \"--}\"\n        }\n      });\n    </script>\n\n\t<br />\n\n\t<h3>Smarty 3</h3>\n\n\t<textarea id=\"code3\" name=\"code3\">\nNested tags {$foo={counter one=1 two={inception}}+3} are now valid in Smarty 3.\n\n<script>\nfunction test() {\n\tconsole.log(\"Smarty 3 permits single curly braces followed by whitespace to NOT slip into Smarty mode.\");\n}\n</script>\n\n{assign var=foo value=[1,2,3]}\n{assign var=foo value=['y'=>'yellow','b'=>'blue']}\n{assign var=foo value=[1,[9,8],3]}\n\n{$foo=$bar+2} {* a comment *}\n{$foo.bar=1}  {* another comment *}\n{$foo = myfunct(($x+$y)*3)}\n{$foo = strlen($bar)}\n{$foo.bar.baz=1}, {$foo[]=1}\n\nSmarty \"dot\" syntax (note: embedded {} are used to address ambiguities):\n\n{$foo.a.b.c}      => $foo['a']['b']['c']\n{$foo.a.$b.c}     => $foo['a'][$b]['c']\n{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c']\n{$foo.a.{$b.c}}   => $foo['a'][$b['c']]\n\n{$object->method1($x)->method2($y)}</textarea>\n\n\t<script>\n\t\tvar editor = CodeMirror.fromTextArea(document.getElementById(\"code3\"), {\n\t\t\tlineNumbers: true,\n\t\t\tmode: \"smarty\",\n\t\t\tsmartyVersion: 3\n\t\t});\n\t</script>\n\n\n    <p>A plain text/Smarty version 2 or 3 mode, which allows for custom delimiter tags.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-smarty</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smarty/smarty.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Smarty 2 and 3 mode.\n */\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(\"smarty\", function(config) {\n  \"use strict\";\n\n  // our default settings; check to see if they're overridden\n  var settings = {\n    rightDelimiter: '}',\n    leftDelimiter: '{',\n    smartyVersion: 2 // for backward compatibility\n  };\n  if (config.hasOwnProperty(\"leftDelimiter\")) {\n    settings.leftDelimiter = config.leftDelimiter;\n  }\n  if (config.hasOwnProperty(\"rightDelimiter\")) {\n    settings.rightDelimiter = config.rightDelimiter;\n  }\n  if (config.hasOwnProperty(\"smartyVersion\") && config.smartyVersion === 3) {\n    settings.smartyVersion = 3;\n  }\n\n  var keyFunctions = [\"debug\", \"extends\", \"function\", \"include\", \"literal\"];\n  var last;\n  var regs = {\n    operatorChars: /[+\\-*&%=<>!?]/,\n    validIdentifier: /[a-zA-Z0-9_]/,\n    stringChar: /['\"]/\n  };\n\n  var helpers = {\n    cont: function(style, lastType) {\n      last = lastType;\n      return style;\n    },\n    chain: function(stream, state, parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n  };\n\n\n  // our various parsers\n  var parsers = {\n\n    // the main tokenizer\n    tokenizer: function(stream, state) {\n      if (stream.match(settings.leftDelimiter, true)) {\n        if (stream.eat(\"*\")) {\n          return helpers.chain(stream, state, parsers.inBlock(\"comment\", \"*\" + settings.rightDelimiter));\n        } else {\n          // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode\n          state.depth++;\n          var isEol = stream.eol();\n          var isFollowedByWhitespace = /\\s/.test(stream.peek());\n          if (settings.smartyVersion === 3 && settings.leftDelimiter === \"{\" && (isEol || isFollowedByWhitespace)) {\n            state.depth--;\n            return null;\n          } else {\n            state.tokenize = parsers.smarty;\n            last = \"startTag\";\n            return \"tag\";\n          }\n        }\n      } else {\n        stream.next();\n        return null;\n      }\n    },\n\n    // parsing Smarty content\n    smarty: function(stream, state) {\n      if (stream.match(settings.rightDelimiter, true)) {\n        if (settings.smartyVersion === 3) {\n          state.depth--;\n          if (state.depth <= 0) {\n            state.tokenize = parsers.tokenizer;\n          }\n        } else {\n          state.tokenize = parsers.tokenizer;\n        }\n        return helpers.cont(\"tag\", null);\n      }\n\n      if (stream.match(settings.leftDelimiter, true)) {\n        state.depth++;\n        return helpers.cont(\"tag\", \"startTag\");\n      }\n\n      var ch = stream.next();\n      if (ch == \"$\") {\n        stream.eatWhile(regs.validIdentifier);\n        return helpers.cont(\"variable-2\", \"variable\");\n      } else if (ch == \"|\") {\n        return helpers.cont(\"operator\", \"pipe\");\n      } else if (ch == \".\") {\n        return helpers.cont(\"operator\", \"property\");\n      } else if (regs.stringChar.test(ch)) {\n        state.tokenize = parsers.inAttribute(ch);\n        return helpers.cont(\"string\", \"string\");\n      } else if (regs.operatorChars.test(ch)) {\n        stream.eatWhile(regs.operatorChars);\n        return helpers.cont(\"operator\", \"operator\");\n      } else if (ch == \"[\" || ch == \"]\") {\n        return helpers.cont(\"bracket\", \"bracket\");\n      } else if (ch == \"(\" || ch == \")\") {\n        return helpers.cont(\"bracket\", \"operator\");\n      } else if (/\\d/.test(ch)) {\n        stream.eatWhile(/\\d/);\n        return helpers.cont(\"number\", \"number\");\n      } else {\n\n        if (state.last == \"variable\") {\n          if (ch == \"@\") {\n            stream.eatWhile(regs.validIdentifier);\n            return helpers.cont(\"property\", \"property\");\n          } else if (ch == \"|\") {\n            stream.eatWhile(regs.validIdentifier);\n            return helpers.cont(\"qualifier\", \"modifier\");\n          }\n        } else if (state.last == \"pipe\") {\n          stream.eatWhile(regs.validIdentifier);\n          return helpers.cont(\"qualifier\", \"modifier\");\n        } else if (state.last == \"whitespace\") {\n          stream.eatWhile(regs.validIdentifier);\n          return helpers.cont(\"attribute\", \"modifier\");\n        } if (state.last == \"property\") {\n          stream.eatWhile(regs.validIdentifier);\n          return helpers.cont(\"property\", null);\n        } else if (/\\s/.test(ch)) {\n          last = \"whitespace\";\n          return null;\n        }\n\n        var str = \"\";\n        if (ch != \"/\") {\n          str += ch;\n        }\n        var c = null;\n        while (c = stream.eat(regs.validIdentifier)) {\n          str += c;\n        }\n        for (var i=0, j=keyFunctions.length; i<j; i++) {\n          if (keyFunctions[i] == str) {\n            return helpers.cont(\"keyword\", \"keyword\");\n          }\n        }\n        if (/\\s/.test(ch)) {\n          return null;\n        }\n        return helpers.cont(\"tag\", \"tag\");\n      }\n    },\n\n    inAttribute: function(quote) {\n      return function(stream, state) {\n        var prevChar = null;\n        var currChar = null;\n        while (!stream.eol()) {\n          currChar = stream.peek();\n          if (stream.next() == quote && prevChar !== '\\\\') {\n            state.tokenize = parsers.smarty;\n            break;\n          }\n          prevChar = currChar;\n        }\n        return \"string\";\n      };\n    },\n\n    inBlock: function(style, terminator) {\n      return function(stream, state) {\n        while (!stream.eol()) {\n          if (stream.match(terminator)) {\n            state.tokenize = parsers.tokenizer;\n            break;\n          }\n          stream.next();\n        }\n        return style;\n      };\n    }\n  };\n\n\n  // the public API for CodeMirror\n  return {\n    startState: function() {\n      return {\n        tokenize: parsers.tokenizer,\n        mode: \"smarty\",\n        last: null,\n        depth: 0\n      };\n    },\n    token: function(stream, state) {\n      var style = state.tokenize(stream, state);\n      state.last = last;\n      return style;\n    },\n    electricChars: \"\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-smarty\", \"smarty\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smartymixed/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Smarty mixed mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../mode/xml/xml.js\"></script>\n<script src=\"../../mode/javascript/javascript.js\"></script>\n<script src=\"../../mode/css/css.js\"></script>\n<script src=\"../../mode/htmlmixed/htmlmixed.js\"></script>\n<script src=\"../../mode/smarty/smarty.js\"></script>\n<script src=\"../../mode/smartymixed/smartymixed.js\"></script>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Smarty mixed</a>\n  </ul>\n</div>\n\n<article>\n<h2>Smarty mixed mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n{**\n* @brief Smarty mixed mode\n* @author 郑保乐\n* @date 29.06.2013\n*}\n<html>\n<head>\n  <title>{$title|htmlspecialchars|truncate:30}</title>\n</head>\n<body class=\"{$bodyclass}\">\n  {* Multiline smarty\n  * comment, no {$variables} here\n  *}\n  {literal}\n  {literal} is just an HTML text.\n  <script type=\"text/javascript\">//<![CDATA[\n    var a = {$just_a_normal_js_object : \"value\"};\n    var myCodeMirror = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n      mode           : \"smartymixed\",\n      tabSize        : 2,\n      indentUnit     : 2,\n      indentWithTabs : false,\n      lineNumbers    : true,\n      smartyVersion  : 3\n    });\n    // ]]>\n  </script>\n  <style>\n    /* CSS content\n    {$no_smarty} */\n    .some-class { font-weight: bolder; color: \"orange\"; }\n  </style>\n  {/literal}\n\n  {extends file=\"parent.tpl\"}\n  {include file=\"template.tpl\"}\n\n  {* some example Smarty content *}\n  {if isset($name) && $name == 'Blog'}\n    This is a {$var}.\n    {$integer = 4511}, {$array[] = \"a\"}, {$stringvar = \"string\"}\n    {$integer = 4512} {$array[] = \"a\"} {$stringvar = \"string\"}\n    {assign var='bob' value=$var.prop}\n  {elseif $name == $foo}\n    {function name=menu level=0}\n    {foreach $data as $entry}\n      {if is_array($entry)}\n      - {$entry@key}\n      {menu data=$entry level=$level+1}\n      {else}\n      {$entry}\n      {* One\n      * Two\n      * Three\n      *}\n      {/if}\n    {/foreach}\n    {/function}\n  {/if}\n  </body>\n  <!-- R.O. -->\n</html>\n</textarea></form>\n\n    <script type=\"text/javascript\">\n      var myCodeMirror = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode           : \"smartymixed\",\n        tabSize        : 2,\n        indentUnit     : 2,\n        indentWithTabs : false,\n        lineNumbers    : true,\n        smartyVersion  : 3,\n        matchBrackets  : true,\n      });\n    </script>\n\n    <p>The Smarty mixed mode depends on the Smarty and HTML mixed modes. HTML\n    mixed mode itself depends on XML, JavaScript, and CSS modes.</p>\n\n    <p>It takes the same options, as Smarty and HTML mixed modes.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-smarty</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/smartymixed/smartymixed.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n* @file smartymixed.js\n* @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)\n* @author 郑保乐\n* @version 3.0\n* @date 05.07.2013\n*/\n\n// Warning: Don't base other modes on this one. This here is a\n// terrible way to write a mixed mode.\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"), require(\"../htmlmixed/htmlmixed\"), require(\"../smarty/smarty\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\", \"../smarty/smarty\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode(\"smartymixed\", function(config) {\n  var htmlMixedMode = CodeMirror.getMode(config, \"htmlmixed\");\n  var smartyMode = CodeMirror.getMode(config, \"smarty\");\n\n  var settings = {\n    rightDelimiter: '}',\n    leftDelimiter: '{'\n  };\n\n  if (config.hasOwnProperty(\"leftDelimiter\")) {\n    settings.leftDelimiter = config.leftDelimiter;\n  }\n  if (config.hasOwnProperty(\"rightDelimiter\")) {\n    settings.rightDelimiter = config.rightDelimiter;\n  }\n\n  function reEsc(str) { return str.replace(/[^\\s\\w]/g, \"\\\\$&\"); }\n\n  var reLeft = reEsc(settings.leftDelimiter), reRight = reEsc(settings.rightDelimiter);\n  var regs = {\n    smartyComment: new RegExp(\"^\" + reRight + \"\\\\*\"),\n    literalOpen: new RegExp(reLeft + \"literal\" + reRight),\n    literalClose: new RegExp(reLeft + \"\\/literal\" + reRight),\n    hasLeftDelimeter: new RegExp(\".*\" + reLeft),\n    htmlHasLeftDelimeter: new RegExp(\"[^<>]*\" + reLeft)\n  };\n\n  var helpers = {\n    chain: function(stream, state, parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    },\n\n    cleanChain: function(stream, state, parser) {\n      state.tokenize = null;\n      state.localState = null;\n      state.localMode = null;\n      return (typeof parser == \"string\") ? (parser ? parser : null) : parser(stream, state);\n    },\n\n    maybeBackup: function(stream, pat, style) {\n      var cur = stream.current();\n      var close = cur.search(pat),\n      m;\n      if (close > - 1) stream.backUp(cur.length - close);\n      else if (m = cur.match(/<\\/?$/)) {\n        stream.backUp(cur.length);\n        if (!stream.match(pat, false)) stream.match(cur[0]);\n      }\n      return style;\n    }\n  };\n\n  var parsers = {\n    html: function(stream, state) {\n      var htmlTagName = state.htmlMixedState.htmlState.context && state.htmlMixedState.htmlState.context.tagName\n        ? state.htmlMixedState.htmlState.context.tagName\n        : null;\n\n      if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && htmlTagName === null) {\n        state.tokenize = parsers.smarty;\n        state.localMode = smartyMode;\n        state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, \"\"));\n        return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));\n      } else if (!state.inLiteral && stream.match(settings.leftDelimiter, false)) {\n        state.tokenize = parsers.smarty;\n        state.localMode = smartyMode;\n        state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, \"\"));\n        return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));\n      }\n      return htmlMixedMode.token(stream, state.htmlMixedState);\n    },\n\n    smarty: function(stream, state) {\n      if (stream.match(settings.leftDelimiter, false)) {\n        if (stream.match(regs.smartyComment, false)) {\n          return helpers.chain(stream, state, parsers.inBlock(\"comment\", \"*\" + settings.rightDelimiter));\n        }\n      } else if (stream.match(settings.rightDelimiter, false)) {\n        stream.eat(settings.rightDelimiter);\n        state.tokenize = parsers.html;\n        state.localMode = htmlMixedMode;\n        state.localState = state.htmlMixedState;\n        return \"tag\";\n      }\n\n      return helpers.maybeBackup(stream, settings.rightDelimiter, smartyMode.token(stream, state.localState));\n    },\n\n    inBlock: function(style, terminator) {\n      return function(stream, state) {\n        while (!stream.eol()) {\n          if (stream.match(terminator)) {\n            helpers.cleanChain(stream, state, \"\");\n            break;\n          }\n          stream.next();\n        }\n        return style;\n      };\n    }\n  };\n\n  return {\n    startState: function() {\n      var state = htmlMixedMode.startState();\n      return {\n        token: parsers.html,\n        localMode: null,\n        localState: null,\n        htmlMixedState: state,\n        tokenize: null,\n        inLiteral: false\n      };\n    },\n\n    copyState: function(state) {\n      var local = null, tok = (state.tokenize || state.token);\n      if (state.localState) {\n        local = CodeMirror.copyState((tok != parsers.html ? smartyMode : htmlMixedMode), state.localState);\n      }\n      return {\n        token: state.token,\n        tokenize: state.tokenize,\n        localMode: state.localMode,\n        localState: local,\n        htmlMixedState: CodeMirror.copyState(htmlMixedMode, state.htmlMixedState),\n        inLiteral: state.inLiteral\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.match(settings.leftDelimiter, false)) {\n        if (!state.inLiteral && stream.match(regs.literalOpen, true)) {\n          state.inLiteral = true;\n          return \"keyword\";\n        } else if (state.inLiteral && stream.match(regs.literalClose, true)) {\n          state.inLiteral = false;\n          return \"keyword\";\n        }\n      }\n      if (state.inLiteral && state.localState != state.htmlMixedState) {\n        state.tokenize = parsers.html;\n        state.localMode = htmlMixedMode;\n        state.localState = state.htmlMixedState;\n      }\n\n      var style = (state.tokenize || state.token)(stream, state);\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.localMode == smartyMode\n          || (state.inLiteral && !state.localMode)\n         || regs.hasLeftDelimeter.test(textAfter)) {\n        return CodeMirror.Pass;\n      }\n      return htmlMixedMode.indent(state.htmlMixedState, textAfter);\n    },\n\n    innerMode: function(state) {\n      return {\n        state: state.localState || state.htmlMixedState,\n        mode: state.localMode || htmlMixedMode\n      };\n    }\n  };\n}, \"htmlmixed\", \"smarty\");\n\nCodeMirror.defineMIME(\"text/x-smarty\", \"smartymixed\");\n// vim: et ts=2 sts=2 sw=2\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/solr/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Solr mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"solr.js\"></script>\n<style type=\"text/css\">\n  .CodeMirror {\n    border-top: 1px solid black;\n    border-bottom: 1px solid black;\n  }\n\n  .CodeMirror .cm-operator {\n    color: orange;\n  }\n</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Solr</a>\n  </ul>\n</div>\n\n<article>\n  <h2>Solr mode</h2>\n\n  <div>\n    <textarea id=\"code\" name=\"code\">author:Camus\n\ntitle:\"The Rebel\" and author:Camus\n\nphilosophy:Existentialism -author:Kierkegaard\n\nhardToSpell:Dostoevsky~\n\npublished:[194* TO 1960] and author:(Sartre or \"Simone de Beauvoir\")</textarea>\n  </div>\n\n  <script>\n    var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n      mode: 'solr',\n      lineNumbers: true\n    });\n  </script>\n\n  <p><strong>MIME types defined:</strong> <code>text/x-solr</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/solr/solr.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(\"solr\", function() {\n  \"use strict\";\n\n  var isStringChar = /[^\\s\\|\\!\\+\\-\\*\\?\\~\\^\\&\\:\\(\\)\\[\\]\\{\\}\\^\\\"\\\\]/;\n  var isOperatorChar = /[\\|\\!\\+\\-\\*\\?\\~\\^\\&]/;\n  var isOperatorString = /^(OR|AND|NOT|TO)$/i;\n\n  function isNumber(word) {\n    return parseFloat(word, 10).toString() === word;\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) break;\n        escaped = !escaped && next == \"\\\\\";\n      }\n\n      if (!escaped) state.tokenize = tokenBase;\n      return \"string\";\n    };\n  }\n\n  function tokenOperator(operator) {\n    return function(stream, state) {\n      var style = \"operator\";\n      if (operator == \"+\")\n        style += \" positive\";\n      else if (operator == \"-\")\n        style += \" negative\";\n      else if (operator == \"|\")\n        stream.eat(/\\|/);\n      else if (operator == \"&\")\n        stream.eat(/\\&/);\n      else if (operator == \"^\")\n        style += \" boost\";\n\n      state.tokenize = tokenBase;\n      return style;\n    };\n  }\n\n  function tokenWord(ch) {\n    return function(stream, state) {\n      var word = ch;\n      while ((ch = stream.peek()) && ch.match(isStringChar) != null) {\n        word += stream.next();\n      }\n\n      state.tokenize = tokenBase;\n      if (isOperatorString.test(word))\n        return \"operator\";\n      else if (isNumber(word))\n        return \"number\";\n      else if (stream.peek() == \":\")\n        return \"field\";\n      else\n        return \"string\";\n    };\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"')\n      state.tokenize = tokenString(ch);\n    else if (isOperatorChar.test(ch))\n      state.tokenize = tokenOperator(ch);\n    else if (isStringChar.test(ch))\n      state.tokenize = tokenWord(ch);\n\n    return (state.tokenize != tokenBase) ? state.tokenize(stream, state) : null;\n  }\n\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      return state.tokenize(stream, state);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-solr\", \"solr\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/soy/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Soy (Closure Template) mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../javascript/javascript.js\"></script>\n<script src=\"../css/css.js\"></script>\n<script src=\"soy.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Soy (Closure Template)</a>\n  </ul>\n</div>\n\n<article>\n<h2>Soy (Closure Template) mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n{namespace example}\n\n/**\n * Says hello to the world.\n */\n{template .helloWorld}\n  {@param name: string}\n  {@param? score: number}\n  Hello <b>{$name}</b>!\n  <div>\n    {if $score}\n      <em>{$score} points</em>\n    {else}\n      no score\n    {/if}\n  </div>\n{/template}\n\n{template .alertHelloWorld kind=\"js\"}\n  alert('Hello World');\n{/template}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-soy\",\n        indentUnit: 2,\n        indentWithTabs: false\n      });\n    </script>\n\n    <p>A mode for <a href=\"https://developers.google.com/closure/templates/\">Closure Templates</a> (Soy).</p>\n    <p><strong>MIME type defined:</strong> <code>text/x-soy</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/soy/soy.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\"), require(\"../htmlmixed/htmlmixed\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  var indentingTags = [\"template\", \"literal\", \"msg\", \"fallbackmsg\", \"let\", \"if\", \"elseif\",\n                       \"else\", \"switch\", \"case\", \"default\", \"foreach\", \"ifempty\", \"for\",\n                       \"call\", \"param\", \"deltemplate\", \"delcall\", \"log\"];\n\n  CodeMirror.defineMode(\"soy\", function(config) {\n    var textMode = CodeMirror.getMode(config, \"text/plain\");\n    var modes = {\n      html: CodeMirror.getMode(config, {name: \"text/html\", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}),\n      attributes: textMode,\n      text: textMode,\n      uri: textMode,\n      css: CodeMirror.getMode(config, \"text/css\"),\n      js: CodeMirror.getMode(config, {name: \"text/javascript\", statementIndent: 2 * config.indentUnit})\n    };\n\n    function last(array) {\n      return array[array.length - 1];\n    }\n\n    function tokenUntil(stream, state, untilRegExp) {\n      var oldString = stream.string;\n      var match = untilRegExp.exec(oldString.substr(stream.pos));\n      if (match) {\n        // We don't use backUp because it backs up just the position, not the state.\n        // This uses an undocumented API.\n        stream.string = oldString.substr(0, stream.pos + match.index);\n      }\n      var result = stream.hideFirstChars(state.indent, function() {\n        return state.localMode.token(stream, state.localState);\n      });\n      stream.string = oldString;\n      return result;\n    }\n\n    return {\n      startState: function() {\n        return {\n          kind: [],\n          kindTag: [],\n          soyState: [],\n          indent: 0,\n          localMode: modes.html,\n          localState: CodeMirror.startState(modes.html)\n        };\n      },\n\n      copyState: function(state) {\n        return {\n          tag: state.tag, // Last seen Soy tag.\n          kind: state.kind.concat([]), // Values of kind=\"\" attributes.\n          kindTag: state.kindTag.concat([]), // Opened tags with kind=\"\" attributes.\n          soyState: state.soyState.concat([]),\n          indent: state.indent, // Indentation of the following line.\n          localMode: state.localMode,\n          localState: CodeMirror.copyState(state.localMode, state.localState)\n        };\n      },\n\n      token: function(stream, state) {\n        var match;\n\n        switch (last(state.soyState)) {\n          case \"comment\":\n            if (stream.match(/^.*?\\*\\//)) {\n              state.soyState.pop();\n            } else {\n              stream.skipToEnd();\n            }\n            return \"comment\";\n\n          case \"variable\":\n            if (stream.match(/^}/)) {\n              state.indent -= 2 * config.indentUnit;\n              state.soyState.pop();\n              return \"variable-2\";\n            }\n            stream.next();\n            return null;\n\n          case \"tag\":\n            if (stream.match(/^\\/?}/)) {\n              if (state.tag == \"/template\" || state.tag == \"/deltemplate\") state.indent = 0;\n              else state.indent -= (stream.current() == \"/}\" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit;\n              state.soyState.pop();\n              return \"keyword\";\n            } else if (stream.match(/^(\\w+)(?==)/)) {\n              if (stream.current() == \"kind\" && (match = stream.match(/^=\"([^\"]+)/, false))) {\n                var kind = match[1];\n                state.kind.push(kind);\n                state.kindTag.push(state.tag);\n                state.localMode = modes[kind] || modes.html;\n                state.localState = CodeMirror.startState(state.localMode);\n              }\n              return \"attribute\";\n            } else if (stream.match(/^\"/)) {\n              state.soyState.push(\"string\");\n              return \"string\";\n            }\n            stream.next();\n            return null;\n\n          case \"literal\":\n            if (stream.match(/^(?=\\{\\/literal})/)) {\n              state.indent -= config.indentUnit;\n              state.soyState.pop();\n              return this.token(stream, state);\n            }\n            return tokenUntil(stream, state, /\\{\\/literal}/);\n\n          case \"string\":\n            if (stream.match(/^.*?\"/)) {\n              state.soyState.pop();\n            } else {\n              stream.skipToEnd();\n            }\n            return \"string\";\n        }\n\n        if (stream.match(/^\\/\\*/)) {\n          state.soyState.push(\"comment\");\n          return \"comment\";\n        } else if (stream.match(stream.sol() ? /^\\s*\\/\\/.*/ : /^\\s+\\/\\/.*/)) {\n          return \"comment\";\n        } else if (stream.match(/^\\{\\$\\w*/)) {\n          state.indent += 2 * config.indentUnit;\n          state.soyState.push(\"variable\");\n          return \"variable-2\";\n        } else if (stream.match(/^\\{literal}/)) {\n          state.indent += config.indentUnit;\n          state.soyState.push(\"literal\");\n          return \"keyword\";\n        } else if (match = stream.match(/^\\{([\\/@\\\\]?\\w*)/)) {\n          if (match[1] != \"/switch\")\n            state.indent += (/^(\\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != \"switch\" ? 1 : 2) * config.indentUnit;\n          state.tag = match[1];\n          if (state.tag == \"/\" + last(state.kindTag)) {\n            // We found the tag that opened the current kind=\"\".\n            state.kind.pop();\n            state.kindTag.pop();\n            state.localMode = modes[last(state.kind)] || modes.html;\n            state.localState = CodeMirror.startState(state.localMode);\n          }\n          state.soyState.push(\"tag\");\n          return \"keyword\";\n        }\n\n        return tokenUntil(stream, state, /\\{|\\s+\\/\\/|\\/\\*/);\n      },\n\n      indent: function(state, textAfter) {\n        var indent = state.indent, top = last(state.soyState);\n        if (top == \"comment\") return CodeMirror.Pass;\n\n        if (top == \"literal\") {\n          if (/^\\{\\/literal}/.test(textAfter)) indent -= config.indentUnit;\n        } else {\n          if (/^\\s*\\{\\/(template|deltemplate)\\b/.test(textAfter)) return 0;\n          if (/^\\{(\\/|(fallbackmsg|elseif|else|ifempty)\\b)/.test(textAfter)) indent -= config.indentUnit;\n          if (state.tag != \"switch\" && /^\\{(case|default)\\b/.test(textAfter)) indent -= config.indentUnit;\n          if (/^\\{\\/switch\\b/.test(textAfter)) indent -= config.indentUnit;\n        }\n        if (indent && state.localMode.indent)\n          indent += state.localMode.indent(state.localState, textAfter);\n        return indent;\n      },\n\n      innerMode: function(state) {\n        if (state.soyState.length && last(state.soyState) != \"literal\") return null;\n        else return {state: state.localState, mode: state.localMode};\n      },\n\n      electricInput: /^\\s*\\{(\\/|\\/template|\\/deltemplate|\\/switch|fallbackmsg|elseif|else|case|default|ifempty|\\/literal\\})$/,\n      lineComment: \"//\",\n      blockCommentStart: \"/*\",\n      blockCommentEnd: \"*/\",\n      blockCommentContinue: \" * \",\n      fold: \"indent\"\n    };\n  }, \"htmlmixed\");\n\n  CodeMirror.registerHelper(\"hintWords\", \"soy\", indentingTags.concat(\n      [\"delpackage\", \"namespace\", \"alias\", \"print\", \"css\", \"debugger\"]));\n\n  CodeMirror.defineMIME(\"text/x-soy\", \"soy\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sparql/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: SPARQL mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"sparql.js\"></script>\n<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">SPARQL</a>\n  </ul>\n</div>\n\n<article>\n<h2>SPARQL mode</h2>\n<form><textarea id=\"code\" name=\"code\">\nPREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>\nPREFIX dc: &lt;http://purl.org/dc/elements/1.1/>\nPREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>\nPREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#>\n\n# Comment!\n\nSELECT ?given ?family\nWHERE {\n  {\n    ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .\n    ?annot dc:creator ?c .\n    OPTIONAL {?c foaf:givenName ?given ;\n                 foaf:familyName ?family }\n  } UNION {\n    ?c !foaf:knows/foaf:knows? ?thing.\n    ?thing rdfs\n  } MINUS {\n    ?thing rdfs:label \"剛柔流\"@jp\n  }\n  FILTER isBlank(?c)\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"application/sparql-query\",\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>application/sparql-query</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sparql/sparql.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(\"sparql\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n                        \"iri\", \"uri\", \"bnode\", \"count\", \"sum\", \"min\", \"max\", \"avg\", \"sample\",\n                        \"group_concat\", \"rand\", \"abs\", \"ceil\", \"floor\", \"round\", \"concat\", \"substr\", \"strlen\",\n                        \"replace\", \"ucase\", \"lcase\", \"encode_for_uri\", \"contains\", \"strstarts\", \"strends\",\n                        \"strbefore\", \"strafter\", \"year\", \"month\", \"day\", \"hours\", \"minutes\", \"seconds\",\n                        \"timezone\", \"tz\", \"now\", \"uuid\", \"struuid\", \"md5\", \"sha1\", \"sha256\", \"sha384\",\n                        \"sha512\", \"coalesce\", \"if\", \"strlang\", \"strdt\", \"isnumeric\", \"regex\", \"exists\",\n                        \"isblank\", \"isliteral\", \"a\"]);\n  var keywords = wordRegexp([\"base\", \"prefix\", \"select\", \"distinct\", \"reduced\", \"construct\", \"describe\",\n                             \"ask\", \"from\", \"named\", \"where\", \"order\", \"limit\", \"offset\", \"filter\", \"optional\",\n                             \"graph\", \"by\", \"asc\", \"desc\", \"as\", \"having\", \"undef\", \"values\", \"group\",\n                             \"minus\", \"in\", \"not\", \"service\", \"silent\", \"using\", \"insert\", \"delete\", \"union\",\n                             \"true\", \"false\", \"with\",\n                             \"data\", \"copy\", \"to\", \"move\", \"add\", \"create\", \"drop\", \"clear\", \"load\"]);\n  var operatorChars = /[*+\\-<>=&|\\^\\/!\\?]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"$\" || ch == \"?\") {\n      if(ch == \"?\" && stream.match(/\\s/, false)){\n        return \"operator\";\n      }\n      stream.match(/^[\\w\\d]*/);\n      return \"variable-2\";\n    }\n    else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return \"bracket\";\n    }\n    else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return \"operator\";\n    }\n    else if (ch == \":\") {\n      stream.eatWhile(/[\\w\\d\\._\\-]/);\n      return \"atom\";\n    }\n    else if (ch == \"@\") {\n      stream.eatWhile(/[a-z\\d\\-]/i);\n      return \"meta\";\n    }\n    else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if (stream.eat(\":\")) {\n        stream.eatWhile(/[\\w\\d_\\-]/);\n        return \"atom\";\n      }\n      var word = stream.current();\n      if (ops.test(word))\n        return \"builtin\";\n      else if (keywords.test(word))\n        return \"keyword\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      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 (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"application/sparql-query\", \"sparql\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/spreadsheet/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Spreadsheet mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"spreadsheet.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Spreadsheet</a>\n  </ul>\n</div>\n\n<article>\n  <h2>Spreadsheet mode</h2>\n  <form><textarea id=\"code\" name=\"code\">=IF(A1:B2, TRUE, FALSE) / 100</textarea></form>\n\n  <script>\n    var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n      lineNumbers: true,\n      matchBrackets: true,\n      extraKeys: {\"Tab\":  \"indentAuto\"}\n    });\n  </script>\n\n  <p><strong>MIME types defined:</strong> <code>text/x-spreadsheet</code>.</p>\n\n  <h3>The Spreadsheet Mode</h3>\n  <p> Created by <a href=\"https://github.com/robertleeplummerjr\">Robert Plummer</a></p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/spreadsheet/spreadsheet.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  CodeMirror.defineMode(\"spreadsheet\", function () {\n    return {\n      startState: function () {\n        return {\n          stringType: null,\n          stack: []\n        };\n      },\n      token: function (stream, state) {\n        if (!stream) return;\n\n        //check for state changes\n        if (state.stack.length === 0) {\n          //strings\n          if ((stream.peek() == '\"') || (stream.peek() == \"'\")) {\n            state.stringType = stream.peek();\n            stream.next(); // Skip quote\n            state.stack.unshift(\"string\");\n          }\n        }\n\n        //return state\n        //stack has\n        switch (state.stack[0]) {\n        case \"string\":\n          while (state.stack[0] === \"string\" && !stream.eol()) {\n            if (stream.peek() === state.stringType) {\n              stream.next(); // Skip quote\n              state.stack.shift(); // Clear flag\n            } else if (stream.peek() === \"\\\\\") {\n              stream.next();\n              stream.next();\n            } else {\n              stream.match(/^.[^\\\\\\\"\\']*/);\n            }\n          }\n          return \"string\";\n\n        case \"characterClass\":\n          while (state.stack[0] === \"characterClass\" && !stream.eol()) {\n            if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./)))\n              state.stack.shift();\n          }\n          return \"operator\";\n        }\n\n        var peek = stream.peek();\n\n        //no stack\n        switch (peek) {\n        case \"[\":\n          stream.next();\n          state.stack.unshift(\"characterClass\");\n          return \"bracket\";\n        case \":\":\n          stream.next();\n          return \"operator\";\n        case \"\\\\\":\n          if (stream.match(/\\\\[a-z]+/)) return \"string-2\";\n          else return null;\n        case \".\":\n        case \",\":\n        case \";\":\n        case \"*\":\n        case \"-\":\n        case \"+\":\n        case \"^\":\n        case \"<\":\n        case \"/\":\n        case \"=\":\n          stream.next();\n          return \"atom\";\n        case \"$\":\n          stream.next();\n          return \"builtin\";\n        }\n\n        if (stream.match(/\\d+/)) {\n          if (stream.match(/^\\w+/)) return \"error\";\n          return \"number\";\n        } else if (stream.match(/^[a-zA-Z_]\\w*/)) {\n          if (stream.match(/(?=[\\(.])/, false)) return \"keyword\";\n          return \"variable-2\";\n        } else if ([\"[\", \"]\", \"(\", \")\", \"{\", \"}\"].indexOf(peek) != -1) {\n          stream.next();\n          return \"bracket\";\n        } else if (!stream.eatSpace()) {\n          stream.next();\n        }\n        return null;\n      }\n    };\n  });\n\n  CodeMirror.defineMIME(\"text/x-spreadsheet\", \"spreadsheet\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sql/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: SQL Mode for CodeMirror</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\" />\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"sql.js\"></script>\n<link rel=\"stylesheet\" href=\"../../addon/hint/show-hint.css\" />\n<script src=\"../../addon/hint/show-hint.js\"></script>\n<script src=\"../../addon/hint/sql-hint.js\"></script>\n<style>\n.CodeMirror {\n    border-top: 1px solid black;\n    border-bottom: 1px solid black;\n}\n        </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">SQL Mode for CodeMirror</a>\n  </ul>\n</div>\n\n<article>\n<h2>SQL Mode for CodeMirror</h2>\n<form>\n            <textarea id=\"code\" name=\"code\">-- SQL Mode for CodeMirror\nSELECT SQL_NO_CACHE DISTINCT\n\t\t@var1 AS `val1`, @'val2', @global.'sql_mode',\n\t\t1.1 AS `float_val`, .14 AS `another_float`, 0.09e3 AS `int_with_esp`,\n\t\t0xFA5 AS `hex`, x'fa5' AS `hex2`, 0b101 AS `bin`, b'101' AS `bin2`,\n\t\tDATE '1994-01-01' AS `sql_date`, { T \"1994-01-01\" } AS `odbc_date`,\n\t\t'my string', _utf8'your string', N'her string',\n        TRUE, FALSE, UNKNOWN\n\tFROM DUAL\n\t-- space needed after '--'\n\t# 1 line comment\n\t/* multiline\n\tcomment! */\n\tLIMIT 1 OFFSET 0;\n</textarea>\n            </form>\n            <p><strong>MIME types defined:</strong>\n            <code><a href=\"?mime=text/x-sql\">text/x-sql</a></code>,\n            <code><a href=\"?mime=text/x-mysql\">text/x-mysql</a></code>,\n            <code><a href=\"?mime=text/x-mariadb\">text/x-mariadb</a></code>,\n            <code><a href=\"?mime=text/x-cassandra\">text/x-cassandra</a></code>,\n            <code><a href=\"?mime=text/x-plsql\">text/x-plsql</a></code>,\n            <code><a href=\"?mime=text/x-mssql\">text/x-mssql</a></code>,\n            <code><a href=\"?mime=text/x-hive\">text/x-hive</a></code>.\n        </p>\n<script>\nwindow.onload = function() {\n  var mime = 'text/x-mariadb';\n  // get mime type\n  if (window.location.href.indexOf('mime=') > -1) {\n    mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);\n  }\n  window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {\n    mode: mime,\n    indentWithTabs: true,\n    smartIndent: true,\n    lineNumbers: true,\n    matchBrackets : true,\n    autofocus: true,\n    extraKeys: {\"Ctrl-Space\": \"autocomplete\"},\n    hintOptions: {tables: {\n      users: {name: null, score: null, birthDate: null},\n      countries: {name: null, population: null, size: null}\n    }}\n  });\n};\n</script>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/sql/sql.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(\"sql\", function(config, parserConfig) {\n  \"use strict\";\n\n  var client         = parserConfig.client || {},\n      atoms          = parserConfig.atoms || {\"false\": true, \"true\": true, \"null\": true},\n      builtin        = parserConfig.builtin || {},\n      keywords       = parserConfig.keywords || {},\n      operatorChars  = parserConfig.operatorChars || /^[*+\\-%<>!=&|~^]/,\n      support        = parserConfig.support || {},\n      hooks          = parserConfig.hooks || {},\n      dateSQL        = parserConfig.dateSQL || {\"date\" : true, \"time\" : true, \"timestamp\" : true};\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n    // call hooks from the mime type\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n\n    if (support.hexNumber == true &&\n      ((ch == \"0\" && stream.match(/^[xX][0-9a-fA-F]+/))\n      || (ch == \"x\" || ch == \"X\") && stream.match(/^'[0-9a-fA-F]+'/))) {\n      // hex\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/hexadecimal-literals.html\n      return \"number\";\n    } else if (support.binaryNumber == true &&\n      (((ch == \"b\" || ch == \"B\") && stream.match(/^'[01]+'/))\n      || (ch == \"0\" && stream.match(/^b[01]+/)))) {\n      // bitstring\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/bit-field-literals.html\n      return \"number\";\n    } else if (ch.charCodeAt(0) > 47 && ch.charCodeAt(0) < 58) {\n      // numbers\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/number-literals.html\n          stream.match(/^[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?/);\n      support.decimallessFloat == true && stream.eat('.');\n      return \"number\";\n    } else if (ch == \"?\" && (stream.eatSpace() || stream.eol() || stream.eat(\";\"))) {\n      // placeholders\n      return \"variable-3\";\n    } else if (ch == \"'\" || (ch == '\"' && support.doubleQuote)) {\n      // strings\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    } else if ((((support.nCharCast == true && (ch == \"n\" || ch == \"N\"))\n        || (support.charsetCast == true && ch == \"_\" && stream.match(/[a-z][a-z0-9]*/i)))\n        && (stream.peek() == \"'\" || stream.peek() == '\"'))) {\n      // charset casting: _utf8'str', N'str', n'str'\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html\n      return \"keyword\";\n    } else if (/^[\\(\\),\\;\\[\\]]/.test(ch)) {\n      // no highlightning\n      return null;\n    } else if (support.commentSlashSlash && ch == \"/\" && stream.eat(\"/\")) {\n      // 1-line comment\n      stream.skipToEnd();\n      return \"comment\";\n    } else if ((support.commentHash && ch == \"#\")\n        || (ch == \"-\" && stream.eat(\"-\") && (!support.commentSpaceRequired || stream.eat(\" \")))) {\n      // 1-line comments\n      // ref: https://kb.askmonty.org/en/comment-syntax/\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"/\" && stream.eat(\"*\")) {\n      // multi-line comments\n      // ref: https://kb.askmonty.org/en/comment-syntax/\n      state.tokenize = tokenComment;\n      return state.tokenize(stream, state);\n    } else if (ch == \".\") {\n      // .1 for 0.1\n      if (support.zerolessFloat == true && stream.match(/^(?:\\d+(?:e[+-]?\\d+)?)/i)) {\n        return \"number\";\n      }\n      // .table_name (ODBC)\n      // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html\n      if (support.ODBCdotTable == true && stream.match(/^[a-zA-Z_]+/)) {\n        return \"variable-2\";\n      }\n    } else if (operatorChars.test(ch)) {\n      // operators\n      stream.eatWhile(operatorChars);\n      return null;\n    } else if (ch == '{' &&\n        (stream.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/) || stream.match(/^( )*(d|D|t|T|ts|TS)( )*\"[^\"]*\"( )*}/))) {\n      // dates (weird ODBC syntax)\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html\n      return \"number\";\n    } else {\n      stream.eatWhile(/^[_\\w\\d]/);\n      var word = stream.current().toLowerCase();\n      // dates (standard SQL syntax)\n      // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html\n      if (dateSQL.hasOwnProperty(word) && (stream.match(/^( )+'[^']*'/) || stream.match(/^( )+\"[^\"]*\"/)))\n        return \"number\";\n      if (atoms.hasOwnProperty(word)) return \"atom\";\n      if (builtin.hasOwnProperty(word)) return \"builtin\";\n      if (keywords.hasOwnProperty(word)) return \"keyword\";\n      if (client.hasOwnProperty(word)) return \"string-2\";\n      return null;\n    }\n  }\n\n  // 'string', with char specified in quote escaped by '\\'\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n  function tokenComment(stream, state) {\n    while (true) {\n      if (stream.skipTo(\"*\")) {\n        stream.next();\n        if (stream.eat(\"/\")) {\n          state.tokenize = tokenBase;\n          break;\n        }\n      } else {\n        stream.skipToEnd();\n        break;\n      }\n    }\n    return \"comment\";\n  }\n\n  function pushContext(stream, state, type) {\n    state.context = {\n      prev: state.context,\n      indent: stream.indentation(),\n      col: stream.column(),\n      type: type\n    };\n  }\n\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: tokenBase, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null)\n          state.context.align = false;\n      }\n      if (stream.eatSpace()) return null;\n\n      var style = state.tokenize(stream, state);\n      if (style == \"comment\") return style;\n\n      if (state.context && state.context.align == null)\n        state.context.align = true;\n\n      var tok = stream.current();\n      if (tok == \"(\")\n        pushContext(stream, state, \")\");\n      else if (tok == \"[\")\n        pushContext(stream, state, \"]\");\n      else if (state.context && state.context.type == tok)\n        popContext(state);\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var cx = state.context;\n      if (!cx) return 0;\n      var closing = textAfter.charAt(0) == cx.type;\n      if (cx.align) return cx.col + (closing ? 0 : 1);\n      else return cx.indent + (closing ? 0 : config.indentUnit);\n    },\n\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: support.commentSlashSlash ? \"//\" : support.commentHash ? \"#\" : null\n  };\n});\n\n(function() {\n  \"use strict\";\n\n  // `identifier`\n  function hookIdentifier(stream) {\n    // MySQL/MariaDB identifiers\n    // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html\n    var ch;\n    while ((ch = stream.next()) != null) {\n      if (ch == \"`\" && !stream.eat(\"`\")) return \"variable-2\";\n    }\n    stream.backUp(stream.current().length - 1);\n    return stream.eatWhile(/\\w/) ? \"variable-2\" : null;\n  }\n\n  // variable token\n  function hookVar(stream) {\n    // variables\n    // @@prefix.varName @varName\n    // varName can be quoted with ` or ' or \"\n    // ref: http://dev.mysql.com/doc/refman/5.5/en/user-variables.html\n    if (stream.eat(\"@\")) {\n      stream.match(/^session\\./);\n      stream.match(/^local\\./);\n      stream.match(/^global\\./);\n    }\n\n    if (stream.eat(\"'\")) {\n      stream.match(/^.*'/);\n      return \"variable-2\";\n    } else if (stream.eat('\"')) {\n      stream.match(/^.*\"/);\n      return \"variable-2\";\n    } else if (stream.eat(\"`\")) {\n      stream.match(/^.*`/);\n      return \"variable-2\";\n    } else if (stream.match(/^[0-9a-zA-Z$\\.\\_]+/)) {\n      return \"variable-2\";\n    }\n    return null;\n  };\n\n  // short client keyword token\n  function hookClient(stream) {\n    // \\N means NULL\n    // ref: http://dev.mysql.com/doc/refman/5.5/en/null-values.html\n    if (stream.eat(\"N\")) {\n        return \"atom\";\n    }\n    // \\g, etc\n    // ref: http://dev.mysql.com/doc/refman/5.5/en/mysql-commands.html\n    return stream.match(/^[a-zA-Z.#!?]/) ? \"variable-2\" : null;\n  }\n\n  // these keywords are used by all SQL dialects (however, a mode can still overwrite it)\n  var sqlKeywords = \"alter and as asc between by count create delete desc distinct drop from having in insert into is join like not on or order select set table union update values where \";\n\n  // turn a space-separated list into an array\n  function set(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\n  // A generic SQL Mode. It's not a standard, it just try to support what is generally supported\n  CodeMirror.defineMIME(\"text/x-sql\", {\n    name: \"sql\",\n    keywords: set(sqlKeywords + \"begin\"),\n    builtin: set(\"bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric\"),\n    atoms: set(\"false true null unknown\"),\n    operatorChars: /^[*+\\-%<>!=]/,\n    dateSQL: set(\"date time timestamp\"),\n    support: set(\"ODBCdotTable doubleQuote binaryNumber hexNumber\")\n  });\n\n  CodeMirror.defineMIME(\"text/x-mssql\", {\n    name: \"sql\",\n    client: set(\"charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee\"),\n    keywords: set(sqlKeywords + \"begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered\"),\n    builtin: set(\"bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table \"),\n    atoms: set(\"false true null unknown\"),\n    operatorChars: /^[*+\\-%<>!=]/,\n    dateSQL: set(\"date datetimeoffset datetime2 smalldatetime datetime time\"),\n    hooks: {\n      \"@\":   hookVar\n    }\n  });\n\n  CodeMirror.defineMIME(\"text/x-mysql\", {\n    name: \"sql\",\n    client: set(\"charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee\"),\n    keywords: set(sqlKeywords + \"accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat\"),\n    builtin: set(\"bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric\"),\n    atoms: set(\"false true null unknown\"),\n    operatorChars: /^[*+\\-%<>!=&|^]/,\n    dateSQL: set(\"date time timestamp\"),\n    support: set(\"ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired\"),\n    hooks: {\n      \"@\":   hookVar,\n      \"`\":   hookIdentifier,\n      \"\\\\\":  hookClient\n    }\n  });\n\n  CodeMirror.defineMIME(\"text/x-mariadb\", {\n    name: \"sql\",\n    client: set(\"charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee\"),\n    keywords: set(sqlKeywords + \"accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat\"),\n    builtin: set(\"bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric\"),\n    atoms: set(\"false true null unknown\"),\n    operatorChars: /^[*+\\-%<>!=&|^]/,\n    dateSQL: set(\"date time timestamp\"),\n    support: set(\"ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired\"),\n    hooks: {\n      \"@\":   hookVar,\n      \"`\":   hookIdentifier,\n      \"\\\\\":  hookClient\n    }\n  });\n\n  // the query language used by Apache Cassandra is called CQL, but this mime type\n  // is called Cassandra to avoid confusion with Contextual Query Language\n  CodeMirror.defineMIME(\"text/x-cassandra\", {\n    name: \"sql\",\n    client: { },\n    keywords: set(\"use select from using consistency where limit first reversed first and in insert into values using consistency ttl update set delete truncate begin batch apply create keyspace with columnfamily primary key index on drop alter type add any one quorum all local_quorum each_quorum\"),\n    builtin: set(\"ascii bigint blob boolean counter decimal double float int text timestamp uuid varchar varint\"),\n    atoms: set(\"false true\"),\n    operatorChars: /^[<>=]/,\n    dateSQL: { },\n    support: set(\"commentSlashSlash decimallessFloat\"),\n    hooks: { }\n  });\n\n  // this is based on Peter Raganitsch's 'plsql' mode\n  CodeMirror.defineMIME(\"text/x-plsql\", {\n    name:       \"sql\",\n    client:     set(\"appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap\"),\n    keywords:   set(\"abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work\"),\n    builtin:    set(\"abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml\"),\n    operatorChars: /^[*+\\-%<>!=~]/,\n    dateSQL:    set(\"date time timestamp\"),\n    support:    set(\"doubleQuote nCharCast zerolessFloat binaryNumber hexNumber\")\n  });\n\n  // Created to support specific hive keywords\n  CodeMirror.defineMIME(\"text/x-hive\", {\n    name: \"sql\",\n    keywords: set(\"select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with\"),\n    builtin: set(\"bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype\"),\n    atoms: set(\"false true null unknown\"),\n    operatorChars: /^[*+\\-%<>!=]/,\n    dateSQL: set(\"date timestamp\"),\n    support: set(\"ODBCdotTable doubleQuote binaryNumber hexNumber\")\n  });\n}());\n\n});\n\n/*\n  How Properties of Mime Types are used by SQL Mode\n  =================================================\n\n  keywords:\n    A list of keywords you want to be highlighted.\n  builtin:\n    A list of builtin types you want to be highlighted (if you want types to be of class \"builtin\" instead of \"keyword\").\n  operatorChars:\n    All characters that must be handled as operators.\n  client:\n    Commands parsed and executed by the client (not the server).\n  support:\n    A list of supported syntaxes which are not common, but are supported by more than 1 DBMS.\n    * ODBCdotTable: .tableName\n    * zerolessFloat: .1\n    * doubleQuote\n    * nCharCast: N'string'\n    * charsetCast: _utf8'string'\n    * commentHash: use # char for comments\n    * commentSlashSlash: use // for comments\n    * commentSpaceRequired: require a space after -- for comments\n  atoms:\n    Keywords that must be highlighted as atoms,. Some DBMS's support more atoms than others:\n    UNKNOWN, INFINITY, UNDERFLOW, NaN...\n  dateSQL:\n    Used for date/time SQL standard syntax, because not all DBMS's support same temporal types.\n*/\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/stex/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: sTeX mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"stex.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">sTeX</a>\n  </ul>\n</div>\n\n<article>\n<h2>sTeX mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n\\begin{module}[id=bbt-size]\n\\importmodule[balanced-binary-trees]{balanced-binary-trees}\n\\importmodule[\\KWARCslides{dmath/en/cardinality}]{cardinality}\n\n\\begin{frame}\n  \\frametitle{Size Lemma for Balanced Trees}\n  \\begin{itemize}\n  \\item\n    \\begin{assertion}[id=size-lemma,type=lemma]\n    Let $G=\\tup{V,E}$ be a \\termref[cd=binary-trees]{balanced binary tree}\n    of \\termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set\n     $\\defeq{\\livar{V}i}{\\setst{\\inset{v}{V}}{\\gdepth{v} = i}}$ of\n    \\termref[cd=graphs-intro,name=node]{nodes} at\n    \\termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has\n    \\termref[cd=cardinality,name=cardinality]{cardinality} $\\power2i$.\n   \\end{assertion}\n  \\item\n    \\begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}\n      \\begin{spfcases}{We have to consider two cases}\n        \\begin{spfcase}{$i=0$}\n          \\begin{spfstep}[display=flow]\n            then $\\livar{V}i=\\set{\\livar{v}r}$, where $\\livar{v}r$ is the root, so\n            $\\eq{\\card{\\livar{V}0},\\card{\\set{\\livar{v}r}},1,\\power20}$.\n          \\end{spfstep}\n        \\end{spfcase}\n        \\begin{spfcase}{$i>0$}\n          \\begin{spfstep}[display=flow]\n           then $\\livar{V}{i-1}$ contains $\\power2{i-1}$ vertexes\n           \\begin{justification}[method=byIH](IH)\\end{justification}\n          \\end{spfstep}\n          \\begin{spfstep}\n           By the \\begin{justification}[method=byDef]definition of a binary\n              tree\\end{justification}, each $\\inset{v}{\\livar{V}{i-1}}$ is a leaf or has\n            two children that are at depth $i$.\n          \\end{spfstep}\n          \\begin{spfstep}\n           As $G$ is \\termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\\gdepth{G}=n>i$, $\\livar{V}{i-1}$ cannot contain\n            leaves.\n          \\end{spfstep}\n          \\begin{spfstep}[type=conclusion]\n           Thus $\\eq{\\card{\\livar{V}i},{\\atimes[cdot]{2,\\card{\\livar{V}{i-1}}}},{\\atimes[cdot]{2,\\power2{i-1}}},\\power2i}$.\n          \\end{spfstep}\n        \\end{spfcase}\n      \\end{spfcases}\n    \\end{sproof}\n  \\item\n    \\begin{assertion}[id=fbbt,type=corollary]\n      A fully balanced tree of depth $d$ has $\\power2{d+1}-1$ nodes.\n    \\end{assertion}\n  \\item\n      \\begin{sproof}[for=fbbt,id=fbbt-pf]{}\n        \\begin{spfstep}\n          Let $\\defeq{G}{\\tup{V,E}}$ be a fully balanced tree\n        \\end{spfstep}\n        \\begin{spfstep}\n          Then $\\card{V}=\\Sumfromto{i}1d{\\power2i}= \\power2{d+1}-1$.\n        \\end{spfstep}\n      \\end{sproof}\n    \\end{itemize}\n  \\end{frame}\n\\begin{note}\n  \\begin{omtext}[type=conclusion,for=binary-tree]\n    This shows that balanced binary trees grow in breadth very quickly, a consequence of\n    this is that they are very shallow (and this compute very fast), which is the essence of\n    the next result.\n  \\end{omtext}\n\\end{note}\n\\end{module}\n\n%%% Local Variables:\n%%% mode: LaTeX\n%%% TeX-master: \"all\"\n%%% End: \\end{document}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#stex_*\">normal</a>,  <a href=\"../../test/index.html#verbose,stex_*\">verbose</a>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/stex/stex.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\n * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)\n * Licence: MIT\n */\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  CodeMirror.defineMode(\"stex\", function() {\n    \"use strict\";\n\n    function pushCommand(state, command) {\n      state.cmdState.push(command);\n    }\n\n    function peekCommand(state) {\n      if (state.cmdState.length > 0) {\n        return state.cmdState[state.cmdState.length - 1];\n      } else {\n        return null;\n      }\n    }\n\n    function popCommand(state) {\n      var plug = state.cmdState.pop();\n      if (plug) {\n        plug.closeBracket();\n      }\n    }\n\n    // returns the non-default plugin closest to the end of the list\n    function getMostPowerful(state) {\n      var context = state.cmdState;\n      for (var i = context.length - 1; i >= 0; i--) {\n        var plug = context[i];\n        if (plug.name == \"DEFAULT\") {\n          continue;\n        }\n        return plug;\n      }\n      return { styleIdentifier: function() { return null; } };\n    }\n\n    function addPluginPattern(pluginName, cmdStyle, styles) {\n      return function () {\n        this.name = pluginName;\n        this.bracketNo = 0;\n        this.style = cmdStyle;\n        this.styles = styles;\n        this.argument = null;   // \\begin and \\end have arguments that follow. These are stored in the plugin\n\n        this.styleIdentifier = function() {\n          return this.styles[this.bracketNo - 1] || null;\n        };\n        this.openBracket = function() {\n          this.bracketNo++;\n          return \"bracket\";\n        };\n        this.closeBracket = function() {};\n      };\n    }\n\n    var plugins = {};\n\n    plugins[\"importmodule\"] = addPluginPattern(\"importmodule\", \"tag\", [\"string\", \"builtin\"]);\n    plugins[\"documentclass\"] = addPluginPattern(\"documentclass\", \"tag\", [\"\", \"atom\"]);\n    plugins[\"usepackage\"] = addPluginPattern(\"usepackage\", \"tag\", [\"atom\"]);\n    plugins[\"begin\"] = addPluginPattern(\"begin\", \"tag\", [\"atom\"]);\n    plugins[\"end\"] = addPluginPattern(\"end\", \"tag\", [\"atom\"]);\n\n    plugins[\"DEFAULT\"] = function () {\n      this.name = \"DEFAULT\";\n      this.style = \"tag\";\n\n      this.styleIdentifier = this.openBracket = this.closeBracket = function() {};\n    };\n\n    function setState(state, f) {\n      state.f = f;\n    }\n\n    // called when in a normal (no environment) context\n    function normal(source, state) {\n      var plug;\n      // Do we look like '\\command' ?  If so, attempt to apply the plugin 'command'\n      if (source.match(/^\\\\[a-zA-Z@]+/)) {\n        var cmdName = source.current().slice(1);\n        plug = plugins[cmdName] || plugins[\"DEFAULT\"];\n        plug = new plug();\n        pushCommand(state, plug);\n        setState(state, beginParams);\n        return plug.style;\n      }\n\n      // escape characters\n      if (source.match(/^\\\\[$&%#{}_]/)) {\n        return \"tag\";\n      }\n\n      // white space control characters\n      if (source.match(/^\\\\[,;!\\/\\\\]/)) {\n        return \"tag\";\n      }\n\n      // find if we're starting various math modes\n      if (source.match(\"\\\\[\")) {\n        setState(state, function(source, state){ return inMathMode(source, state, \"\\\\]\"); });\n        return \"keyword\";\n      }\n      if (source.match(\"$$\")) {\n        setState(state, function(source, state){ return inMathMode(source, state, \"$$\"); });\n        return \"keyword\";\n      }\n      if (source.match(\"$\")) {\n        setState(state, function(source, state){ return inMathMode(source, state, \"$\"); });\n        return \"keyword\";\n      }\n\n      var ch = source.next();\n      if (ch == \"%\") {\n        source.skipToEnd();\n        return \"comment\";\n      } else if (ch == '}' || ch == ']') {\n        plug = peekCommand(state);\n        if (plug) {\n          plug.closeBracket(ch);\n          setState(state, beginParams);\n        } else {\n          return \"error\";\n        }\n        return \"bracket\";\n      } else if (ch == '{' || ch == '[') {\n        plug = plugins[\"DEFAULT\"];\n        plug = new plug();\n        pushCommand(state, plug);\n        return \"bracket\";\n      } else if (/\\d/.test(ch)) {\n        source.eatWhile(/[\\w.%]/);\n        return \"atom\";\n      } else {\n        source.eatWhile(/[\\w\\-_]/);\n        plug = getMostPowerful(state);\n        if (plug.name == 'begin') {\n          plug.argument = source.current();\n        }\n        return plug.styleIdentifier();\n      }\n    }\n\n    function inMathMode(source, state, endModeSeq) {\n      if (source.eatSpace()) {\n        return null;\n      }\n      if (source.match(endModeSeq)) {\n        setState(state, normal);\n        return \"keyword\";\n      }\n      if (source.match(/^\\\\[a-zA-Z@]+/)) {\n        return \"tag\";\n      }\n      if (source.match(/^[a-zA-Z]+/)) {\n        return \"variable-2\";\n      }\n      // escape characters\n      if (source.match(/^\\\\[$&%#{}_]/)) {\n        return \"tag\";\n      }\n      // white space control characters\n      if (source.match(/^\\\\[,;!\\/]/)) {\n        return \"tag\";\n      }\n      // special math-mode characters\n      if (source.match(/^[\\^_&]/)) {\n        return \"tag\";\n      }\n      // non-special characters\n      if (source.match(/^[+\\-<>|=,\\/@!*:;'\"`~#?]/)) {\n        return null;\n      }\n      if (source.match(/^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)/)) {\n        return \"number\";\n      }\n      var ch = source.next();\n      if (ch == \"{\" || ch == \"}\" || ch == \"[\" || ch == \"]\" || ch == \"(\" || ch == \")\") {\n        return \"bracket\";\n      }\n\n      if (ch == \"%\") {\n        source.skipToEnd();\n        return \"comment\";\n      }\n      return \"error\";\n    }\n\n    function beginParams(source, state) {\n      var ch = source.peek(), lastPlug;\n      if (ch == '{' || ch == '[') {\n        lastPlug = peekCommand(state);\n        lastPlug.openBracket(ch);\n        source.eat(ch);\n        setState(state, normal);\n        return \"bracket\";\n      }\n      if (/[ \\t\\r]/.test(ch)) {\n        source.eat(ch);\n        return null;\n      }\n      setState(state, normal);\n      popCommand(state);\n\n      return normal(source, state);\n    }\n\n    return {\n      startState: function() {\n        return {\n          cmdState: [],\n          f: normal\n        };\n      },\n      copyState: function(s) {\n        return {\n          cmdState: s.cmdState.slice(),\n          f: s.f\n        };\n      },\n      token: function(stream, state) {\n        return state.f(stream, state);\n      },\n      blankLine: function(state) {\n        state.f = normal;\n        state.cmdState.length = 0;\n      },\n      lineComment: \"%\"\n    };\n  });\n\n  CodeMirror.defineMIME(\"text/x-stex\", \"stex\");\n  CodeMirror.defineMIME(\"text/x-latex\", \"stex\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/stex/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4}, \"stex\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"word\",\n     \"foo\");\n\n  MT(\"twoWords\",\n     \"foo bar\");\n\n  MT(\"beginEndDocument\",\n     \"[tag \\\\begin][bracket {][atom document][bracket }]\",\n     \"[tag \\\\end][bracket {][atom document][bracket }]\");\n\n  MT(\"beginEndEquation\",\n     \"[tag \\\\begin][bracket {][atom equation][bracket }]\",\n     \"  E=mc^2\",\n     \"[tag \\\\end][bracket {][atom equation][bracket }]\");\n\n  MT(\"beginModule\",\n     \"[tag \\\\begin][bracket {][atom module][bracket }[[]]]\");\n\n  MT(\"beginModuleId\",\n     \"[tag \\\\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]\");\n\n  MT(\"importModule\",\n     \"[tag \\\\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]\");\n\n  MT(\"importModulePath\",\n     \"[tag \\\\importmodule][bracket [[][tag \\\\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]\");\n\n  MT(\"psForPDF\",\n     \"[tag \\\\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]\");\n\n  MT(\"comment\",\n     \"[comment % foo]\");\n\n  MT(\"tagComment\",\n     \"[tag \\\\item][comment % bar]\");\n\n  MT(\"commentTag\",\n     \" [comment % \\\\item]\");\n\n  MT(\"commentLineBreak\",\n     \"[comment %]\",\n     \"foo\");\n\n  MT(\"tagErrorCurly\",\n     \"[tag \\\\begin][error }][bracket {]\");\n\n  MT(\"tagErrorSquare\",\n     \"[tag \\\\item][error ]]][bracket {]\");\n\n  MT(\"commentCurly\",\n     \"[comment % }]\");\n\n  MT(\"tagHash\",\n     \"the [tag \\\\#] key\");\n\n  MT(\"tagNumber\",\n     \"a [tag \\\\$][atom 5] stetson\");\n\n  MT(\"tagPercent\",\n     \"[atom 100][tag \\\\%] beef\");\n\n  MT(\"tagAmpersand\",\n     \"L [tag \\\\&] N\");\n\n  MT(\"tagUnderscore\",\n     \"foo[tag \\\\_]bar\");\n\n  MT(\"tagBracketOpen\",\n     \"[tag \\\\emph][bracket {][tag \\\\{][bracket }]\");\n\n  MT(\"tagBracketClose\",\n     \"[tag \\\\emph][bracket {][tag \\\\}][bracket }]\");\n\n  MT(\"tagLetterNumber\",\n     \"section [tag \\\\S][atom 1]\");\n\n  MT(\"textTagNumber\",\n     \"para [tag \\\\P][atom 2]\");\n\n  MT(\"thinspace\",\n     \"x[tag \\\\,]y\");\n\n  MT(\"thickspace\",\n     \"x[tag \\\\;]y\");\n\n  MT(\"negativeThinspace\",\n     \"x[tag \\\\!]y\");\n\n  MT(\"periodNotSentence\",\n     \"J.\\\\ L.\\\\ is\");\n\n  MT(\"periodSentence\",\n     \"X[tag \\\\@]. The\");\n\n  MT(\"italicCorrection\",\n     \"[bracket {][tag \\\\em] If[tag \\\\/][bracket }] I\");\n\n  MT(\"tagBracket\",\n     \"[tag \\\\newcommand][bracket {][tag \\\\pop][bracket }]\");\n\n  MT(\"inlineMathTagFollowedByNumber\",\n     \"[keyword $][tag \\\\pi][number 2][keyword $]\");\n\n  MT(\"inlineMath\",\n     \"[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\\\sqrt][bracket {][tag \\\\$\\\\alpha][bracket }] = [number 2][keyword $] other text\");\n\n  MT(\"displayMath\",\n     \"More [keyword $$]\\t[variable-2 S][tag ^][variable-2 n][tag \\\\sum] [variable-2 i][keyword $$] other text\");\n\n  MT(\"mathWithComment\",\n     \"[keyword $][variable-2 x] [comment % $]\",\n     \"[variable-2 y][keyword $] other text\");\n\n  MT(\"lineBreakArgument\",\n    \"[tag \\\\\\\\][bracket [[][atom 1cm][bracket ]]]\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tcl/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Tcl mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/night.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"tcl.js\"></script>\n<script src=\"../../addon/scroll/scrollpastend.js\"></script>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Tcl</a>\n  </ul>\n</div>\n\n<article>\n<h2>Tcl mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n##############################################################################################\n##  ##     whois.tcl for eggdrop by Ford_Lawnmower irc.geekshed.net #Script-Help        ##  ##\n##############################################################################################\n## To use this script you must set channel flag +whois (ie .chanset #chan +whois)           ##\n##############################################################################################\n##      ____                __                 ###########################################  ##\n##     / __/___ _ ___ _ ___/ /____ ___   ___   ###########################################  ##\n##    / _/ / _ `// _ `// _  // __// _ \\ / _ \\  ###########################################  ##\n##   /___/ \\_, / \\_, / \\_,_//_/   \\___// .__/  ###########################################  ##\n##        /___/ /___/                 /_/      ###########################################  ##\n##                                             ###########################################  ##\n##############################################################################################\n##  ##                             Start Setup.                                         ##  ##\n##############################################################################################\nnamespace eval whois {\n## change cmdchar to the trigger you want to use                                        ##  ##\n  variable cmdchar \"!\"\n## change command to the word trigger you would like to use.                            ##  ##\n## Keep in mind, This will also change the .chanset +/-command                          ##  ##\n  variable command \"whois\"\n## change textf to the colors you want for the text.                                    ##  ##\n  variable textf \"\\017\\00304\"\n## change tagf to the colors you want for tags:                                         ##  ##\n  variable tagf \"\\017\\002\"\n## Change logo to the logo you want at the start of the line.                           ##  ##\n  variable logo \"\\017\\00304\\002\\[\\00306W\\003hois\\00304\\]\\017\"\n## Change lineout to the results you want. Valid results are channel users modes topic  ##  ##\n  variable lineout \"channel users modes topic\"\n##############################################################################################\n##  ##                           End Setup.                                              ## ##\n##############################################################################################\n  variable channel \"\"\n  setudef flag $whois::command\n  bind pub -|- [string trimleft $whois::cmdchar]${whois::command} whois::list\n  bind raw -|- \"311\" whois::311\n  bind raw -|- \"312\" whois::312\n  bind raw -|- \"319\" whois::319\n  bind raw -|- \"317\" whois::317\n  bind raw -|- \"313\" whois::multi\n  bind raw -|- \"310\" whois::multi\n  bind raw -|- \"335\" whois::multi\n  bind raw -|- \"301\" whois::301\n  bind raw -|- \"671\" whois::multi\n  bind raw -|- \"320\" whois::multi\n  bind raw -|- \"401\" whois::multi\n  bind raw -|- \"318\" whois::318\n  bind raw -|- \"307\" whois::307\n}\nproc whois::311 {from key text} {\n  if {[regexp -- {^[^\\s]+\\s(.+?)\\s(.+?)\\s(.+?)\\s\\*\\s\\:(.+)$} $text wholematch nick ident host realname]} {\n    putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Host:${whois::textf} \\\n        $nick \\(${ident}@${host}\\) ${whois::tagf}Realname:${whois::textf} $realname\"\n  }\n}\nproc whois::multi {from key text} {\n  if {[regexp {\\:(.*)$} $text match $key]} {\n    putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Note:${whois::textf} [subst $$key]\"\n        return 1\n  }\n}\nproc whois::312 {from key text} {\n  regexp {([^\\s]+)\\s\\:} $text match server\n  putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Server:${whois::textf} $server\"\n}\nproc whois::319 {from key text} {\n  if {[regexp {.+\\:(.+)$} $text match channels]} {\n    putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Channels:${whois::textf} $channels\"\n  }\n}\nproc whois::317 {from key text} {\n  if {[regexp -- {.*\\s(\\d+)\\s(\\d+)\\s\\:} $text wholematch idle signon]} {\n    putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Connected:${whois::textf} \\\n        [ctime $signon] ${whois::tagf}Idle:${whois::textf} [duration $idle]\"\n  }\n}\nproc whois::301 {from key text} {\n  if {[regexp {^.+\\s[^\\s]+\\s\\:(.*)$} $text match awaymsg]} {\n    putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Away:${whois::textf} $awaymsg\"\n  }\n}\nproc whois::318 {from key text} {\n  namespace eval whois {\n        variable channel \"\"\n  }\n  variable whois::channel \"\"\n}\nproc whois::307 {from key text} {\n  putserv \"PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Services:${whois::textf} Registered Nick\"\n}\nproc whois::list {nick host hand chan text} {\n  if {[lsearch -exact [channel info $chan] \"+${whois::command}\"] != -1} {\n    namespace eval whois {\n          variable channel \"\"\n        }\n    variable whois::channel $chan\n    putserv \"WHOIS $text\"\n  }\n}\nputlog \"\\002*Loaded* \\017\\00304\\002\\[\\00306W\\003hois\\00304\\]\\017 \\002by \\\nFord_Lawnmower irc.GeekShed.net #Script-Help\"\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"night\",\n        lineNumbers: true,\n        indentUnit: 2,\n        scrollPastEnd: true,\n        mode: \"text/x-tcl\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-tcl</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tcl/tcl.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n//tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara\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(\"tcl\", function() {\n  function parseWords(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  var keywords = parseWords(\"Tcl safe after append array auto_execok auto_import auto_load \" +\n        \"auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror \" +\n        \"binary break catch cd close concat continue dde eof encoding error \" +\n        \"eval exec exit expr fblocked fconfigure fcopy file fileevent filename \" +\n        \"filename flush for foreach format gets glob global history http if \" +\n        \"incr info interp join lappend lindex linsert list llength load lrange \" +\n        \"lreplace lsearch lset lsort memory msgcat namespace open package parray \" +\n        \"pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp \" +\n        \"registry regsub rename resource return scan seek set socket source split \" +\n        \"string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord \" +\n        \"tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest \" +\n        \"tclvars tell time trace unknown unset update uplevel upvar variable \" +\n    \"vwait\");\n    var functions = parseWords(\"if elseif else and not or eq ne in ni for foreach while switch\");\n    var isOperatorChar = /[+\\-*&%=<>!?^\\/\\|]/;\n    function chain(stream, state, f) {\n      state.tokenize = f;\n      return f(stream, state);\n    }\n    function tokenBase(stream, state) {\n      var beforeParams = state.beforeParams;\n      state.beforeParams = false;\n      var ch = stream.next();\n      if ((ch == '\"' || ch == \"'\") && state.inParams)\n        return chain(stream, state, tokenString(ch));\n      else if (/[\\[\\]{}\\(\\),;\\.]/.test(ch)) {\n        if (ch == \"(\" && beforeParams) state.inParams = true;\n        else if (ch == \")\") state.inParams = false;\n          return null;\n      }\n      else if (/\\d/.test(ch)) {\n        stream.eatWhile(/[\\w\\.]/);\n        return \"number\";\n      }\n      else if (ch == \"#\" && stream.eat(\"*\")) {\n        return chain(stream, state, tokenComment);\n      }\n      else if (ch == \"#\" && stream.match(/ *\\[ *\\[/)) {\n        return chain(stream, state, tokenUnparsed);\n      }\n      else if (ch == \"#\" && stream.eat(\"#\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      else if (ch == '\"') {\n        stream.skipTo(/\"/);\n        return \"comment\";\n      }\n      else if (ch == \"$\") {\n        stream.eatWhile(/[$_a-z0-9A-Z\\.{:]/);\n        stream.eatWhile(/}/);\n        state.beforeParams = true;\n        return \"builtin\";\n      }\n      else if (isOperatorChar.test(ch)) {\n        stream.eatWhile(isOperatorChar);\n        return \"comment\";\n      }\n      else {\n        stream.eatWhile(/[\\w\\$_{}\\xa1-\\uffff]/);\n        var word = stream.current().toLowerCase();\n        if (keywords && keywords.propertyIsEnumerable(word))\n          return \"keyword\";\n        if (functions && functions.propertyIsEnumerable(word)) {\n          state.beforeParams = true;\n          return \"keyword\";\n        }\n        return null;\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) {\n          end = true;\n          break;\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end) state.tokenize = tokenBase;\n        return \"string\";\n      };\n    }\n    function tokenComment(stream, state) {\n      var maybeEnd = false, ch;\n      while (ch = stream.next()) {\n        if (ch == \"#\" && maybeEnd) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        maybeEnd = (ch == \"*\");\n      }\n      return \"comment\";\n    }\n    function tokenUnparsed(stream, state) {\n      var maybeEnd = 0, ch;\n      while (ch = stream.next()) {\n        if (ch == \"#\" && maybeEnd == 2) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        if (ch == \"]\")\n          maybeEnd++;\n        else if (ch != \" \")\n          maybeEnd = 0;\n      }\n      return \"meta\";\n    }\n    return {\n      startState: function() {\n        return {\n          tokenize: tokenBase,\n          beforeParams: false,\n          inParams: false\n        };\n      },\n      token: function(stream, state) {\n        if (stream.eatSpace()) return null;\n        return state.tokenize(stream, state);\n      }\n    };\n});\nCodeMirror.defineMIME(\"text/x-tcl\", \"tcl\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/textile/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Textile mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"textile.js\"></script>\n<style>.CodeMirror {background: #f8f8f8;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/marijnh/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=\"active\" href=\"#\">Textile</a>\n  </ul>\n</div>\n\n<article>\n    <h2>Textile mode</h2>\n    <form><textarea id=\"code\" name=\"code\">\nh1. Textile Mode\n\nA paragraph without formatting.\n\np. A simple Paragraph.\n\n\nh2. Phrase Modifiers\n\nHere are some simple phrase modifiers: *strong*, _emphasis_, **bold**, and __italic__.\n\nA ??citation??, -deleted text-, +inserted text+, some ^superscript^, and some ~subscript~.\n\nA %span element% and @code element@\n\nA \"link\":http://example.com, a \"link with (alt text)\":urlAlias\n\n[urlAlias]http://example.com/\n\nAn image: !http://example.com/image.png! and an image with a link: !http://example.com/image.png!:http://example.com\n\nA sentence with a footnote.[123]\n\nfn123. The footnote is defined here.\n\nRegistered(r), Trademark(tm), and Copyright(c)\n\n\nh2. Headers\n\nh1. Top level\nh2. Second level\nh3. Third level\nh4. Fourth level\nh5. Fifth level\nh6. Lowest level\n\n\nh2.  Lists\n\n* An unordered list\n** foo bar\n*** foo bar\n**** foo bar\n** foo bar\n\n# An ordered list\n## foo bar\n### foo bar\n#### foo bar\n## foo bar\n\n- definition list := description\n- another item    := foo bar\n- spanning ines   :=\n                     foo bar\n\n                     foo bar =:\n\n\nh2. Attributes\n\nLayouts and phrase modifiers can be modified with various kinds of attributes: alignment, CSS ID, CSS class names, language, padding, and CSS styles.\n\nh3. Alignment\n\ndiv<. left align\ndiv>. right align\n\nh3. CSS ID and class name\n\nYou are a %(my-id#my-classname) rad% person.\n\nh3. Language\n\np[en_CA]. Strange weather, eh?\n\nh3. Horizontal Padding\n\np(())). 2em left padding, 3em right padding\n\nh3. CSS styling\n\np{background: red}. Fire!\n\n\nh2. Table\n\n|_.              Header 1               |_.      Header 2        |\n|{background:#ddd}. Cell with background|         Normal         |\n|\\2.         Cell spanning 2 columns                             |\n|/2.         Cell spanning 2 rows       |(cell-class). one       |\n|                                                two             |\n|>.                  Right aligned cell |<. Left aligned cell    |\n\n\nh3. A table with attributes:\n\ntable(#prices).\n|Adults|$5|\n|Children|$2|\n\n\nh2. Code blocks\n\nbc.\nfunction factorial(n) {\n    if (n === 0) {\n        return 1;\n    }\n    return n * factorial(n - 1);\n}\n\npre..\n                ,,,,,,\n            o#'9MMHb':'-,o,\n         .oH\":HH$' \"' ' -*R&o,\n        dMMM*\"\"'`'      .oM\"HM?.\n       ,MMM'          \"HLbd< ?&H\\\n      .:MH .\"\\          ` MM  MM&b\n     . \"*H    -        &MMMMMMMMMH:\n     .    dboo        MMMMMMMMMMMM.\n     .   dMMMMMMb      *MMMMMMMMMP.\n     .    MMMMMMMP        *MMMMMP .\n          `#MMMMM           MM6P ,\n       '    `MMMP\"           HM*`,\n        '    :MM             .- ,\n         '.   `#?..  .       ..'\n            -.   .         .-\n              ''-.oo,oo.-''\n\n\\. _(9>\n \\==_)\n  -'=\n\nh2. Temporarily disabling textile markup\n\nnotextile. Don't __touch this!__\n\nSurround text with double-equals to disable textile inline. Example: Use ==*asterisks*== for *strong* text.\n\n\nh2. HTML\n\nSome block layouts are simply textile versions of HTML tags with the same name, like @div@, @pre@, and @p@. HTML tags can also exist on their own line:\n\n<section>\n  <h1>Title</h1>\n  <p>Hello!</p>\n</section>\n\n</textarea></form>\n    <script>\n        var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n            lineNumbers: true,\n            mode: \"text/x-textile\"\n        });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-textile</code>.</p>\n\n    <p><strong>Parsing/Highlighting Tests:</strong> <a href=\"../../test/index.html#textile_*\">normal</a>,  <a href=\"../../test/index.html#verbose,textile_*\">verbose</a>.</p>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/textile/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4}, 'textile');\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT('simpleParagraphs',\n      'Some text.',\n      '',\n      'Some more text.');\n\n  /*\n   * Phrase Modifiers\n   */\n\n  MT('em',\n      'foo [em _bar_]');\n\n  MT('emBoogus',\n      'code_mirror');\n\n  MT('strong',\n      'foo [strong *bar*]');\n\n  MT('strongBogus',\n      '3 * 3 = 9');\n\n  MT('italic',\n      'foo [em __bar__]');\n\n  MT('italicBogus',\n      'code__mirror');\n\n  MT('bold',\n      'foo [strong **bar**]');\n\n  MT('boldBogus',\n      '3 ** 3 = 27');\n\n  MT('simpleLink',\n      '[link \"CodeMirror\":http://codemirror.net]');\n\n  MT('referenceLink',\n      '[link \"CodeMirror\":code_mirror]',\n      'Normal Text.',\n      '[link [[code_mirror]]http://codemirror.net]');\n\n  MT('footCite',\n      'foo bar[qualifier [[1]]]');\n\n  MT('footCiteBogus',\n      'foo bar[[1a2]]');\n\n  MT('special-characters',\n          'Registered [tag (r)], ' +\n          'Trademark [tag (tm)], and ' +\n          'Copyright [tag (c)] 2008');\n\n  MT('cite',\n      \"A book is [keyword ??The Count of Monte Cristo??] by Dumas.\");\n\n  MT('additionAndDeletion',\n      'The news networks declared [negative -Al Gore-] ' +\n        '[positive +George W. Bush+] the winner in Florida.');\n\n  MT('subAndSup',\n      'f(x, n) = log [builtin ~4~] x [builtin ^n^]');\n\n  MT('spanAndCode',\n      'A [quote %span element%] and [atom @code element@]');\n\n  MT('spanBogus',\n      'Percentage 25% is not a span.');\n\n  MT('citeBogus',\n      'Question? is not a citation.');\n\n  MT('codeBogus',\n      'user@example.com');\n\n  MT('subBogus',\n      '~username');\n\n  MT('supBogus',\n      'foo ^ bar');\n\n  MT('deletionBogus',\n      '3 - 3 = 0');\n\n  MT('additionBogus',\n      '3 + 3 = 6');\n\n  MT('image',\n      'An image: [string !http://www.example.com/image.png!]');\n\n  MT('imageWithAltText',\n      'An image: [string !http://www.example.com/image.png (Alt Text)!]');\n\n  MT('imageWithUrl',\n      'An image: [string !http://www.example.com/image.png!:http://www.example.com/]');\n\n  /*\n   * Headers\n   */\n\n  MT('h1',\n      '[header&header-1 h1. foo]');\n\n  MT('h2',\n      '[header&header-2 h2. foo]');\n\n  MT('h3',\n      '[header&header-3 h3. foo]');\n\n  MT('h4',\n      '[header&header-4 h4. foo]');\n\n  MT('h5',\n      '[header&header-5 h5. foo]');\n\n  MT('h6',\n      '[header&header-6 h6. foo]');\n\n  MT('h7Bogus',\n      'h7. foo');\n\n  MT('multipleHeaders',\n      '[header&header-1 h1. Heading 1]',\n      '',\n      'Some text.',\n      '',\n      '[header&header-2 h2. Heading 2]',\n      '',\n      'More text.');\n\n  MT('h1inline',\n      '[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1  baz]');\n\n  /*\n   * Lists\n   */\n\n  MT('ul',\n      'foo',\n      'bar',\n      '',\n      '[variable-2 * foo]',\n      '[variable-2 * bar]');\n\n  MT('ulNoBlank',\n      'foo',\n      'bar',\n      '[variable-2 * foo]',\n      '[variable-2 * bar]');\n\n  MT('ol',\n      'foo',\n      'bar',\n      '',\n      '[variable-2 # foo]',\n      '[variable-2 # bar]');\n\n  MT('olNoBlank',\n      'foo',\n      'bar',\n      '[variable-2 # foo]',\n      '[variable-2 # bar]');\n\n  MT('ulFormatting',\n      '[variable-2 * ][variable-2&em _foo_][variable-2  bar]',\n      '[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]' +\n        '[variable-2&strong *][variable-2  bar]',\n      '[variable-2 * ][variable-2&strong *foo*][variable-2  bar]');\n\n  MT('olFormatting',\n      '[variable-2 # ][variable-2&em _foo_][variable-2  bar]',\n      '[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]' +\n        '[variable-2&strong *][variable-2  bar]',\n      '[variable-2 # ][variable-2&strong *foo*][variable-2  bar]');\n\n  MT('ulNested',\n      '[variable-2 * foo]',\n      '[variable-3 ** bar]',\n      '[keyword *** bar]',\n      '[variable-2 **** bar]',\n      '[variable-3 ** bar]');\n\n  MT('olNested',\n      '[variable-2 # foo]',\n      '[variable-3 ## bar]',\n      '[keyword ### bar]',\n      '[variable-2 #### bar]',\n      '[variable-3 ## bar]');\n\n  MT('ulNestedWithOl',\n      '[variable-2 * foo]',\n      '[variable-3 ## bar]',\n      '[keyword *** bar]',\n      '[variable-2 #### bar]',\n      '[variable-3 ** bar]');\n\n  MT('olNestedWithUl',\n      '[variable-2 # foo]',\n      '[variable-3 ** bar]',\n      '[keyword ### bar]',\n      '[variable-2 **** bar]',\n      '[variable-3 ## bar]');\n\n  MT('definitionList',\n      '[number - coffee := Hot ][number&em _and_][number  black]',\n      '',\n      'Normal text.');\n\n  MT('definitionListSpan',\n      '[number - coffee :=]',\n      '',\n      '[number Hot ][number&em _and_][number  black =:]',\n      '',\n      'Normal text.');\n\n  MT('boo',\n      '[number - dog := woof woof]',\n      '[number - cat := meow meow]',\n      '[number - whale :=]',\n      '[number Whale noises.]',\n      '',\n      '[number Also, ][number&em _splashing_][number . =:]');\n\n  /*\n   * Attributes\n   */\n\n  MT('divWithAttribute',\n      '[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]');\n\n  MT('divWithAttributeAnd2emRightPadding',\n      '[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]');\n\n  MT('divWithClassAndId',\n      '[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]');\n\n  MT('paragraphWithCss',\n      'p[attribute {color:red;}]. foo bar');\n\n  MT('paragraphNestedStyles',\n      'p. [strong *foo ][strong&em _bar_][strong *]');\n\n  MT('paragraphWithLanguage',\n      'p[attribute [[fr]]]. Parlez-vous français?');\n\n  MT('paragraphLeftAlign',\n      'p[attribute <]. Left');\n\n  MT('paragraphRightAlign',\n      'p[attribute >]. Right');\n\n  MT('paragraphRightAlign',\n      'p[attribute =]. Center');\n\n  MT('paragraphJustified',\n      'p[attribute <>]. Justified');\n\n  MT('paragraphWithLeftIndent1em',\n      'p[attribute (]. Left');\n\n  MT('paragraphWithRightIndent1em',\n      'p[attribute )]. Right');\n\n  MT('paragraphWithLeftIndent2em',\n      'p[attribute ((]. Left');\n\n  MT('paragraphWithRightIndent2em',\n      'p[attribute ))]. Right');\n\n  MT('paragraphWithLeftIndent3emRightIndent2em',\n      'p[attribute ((())]. Right');\n\n  MT('divFormatting',\n      '[punctuation div. ][punctuation&strong *foo ]' +\n        '[punctuation&strong&em _bar_][punctuation&strong *]');\n\n  MT('phraseModifierAttributes',\n      'p[attribute (my-class)]. This is a paragraph that has a class and' +\n      ' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]' +\n      ' has an id.');\n\n  MT('linkWithClass',\n      '[link \"(my-class). This is a link with class\":http://redcloth.org]');\n\n  /*\n   * Layouts\n   */\n\n  MT('paragraphLayouts',\n      'p. This is one paragraph.',\n      '',\n      'p. This is another.');\n\n  MT('div',\n      '[punctuation div. foo bar]');\n\n  MT('pre',\n      '[operator pre. Text]');\n\n  MT('bq.',\n      '[bracket bq. foo bar]',\n      '',\n      'Normal text.');\n\n  MT('footnote',\n      '[variable fn123. foo ][variable&strong *bar*]');\n\n  /*\n   * Spanning Layouts\n   */\n\n  MT('bq..ThenParagraph',\n      '[bracket bq.. foo bar]',\n      '',\n      '[bracket More quote.]',\n      'p. Normal Text');\n\n  MT('bq..ThenH1',\n      '[bracket bq.. foo bar]',\n      '',\n      '[bracket More quote.]',\n      '[header&header-1 h1. Header Text]');\n\n  MT('bc..ThenParagraph',\n      '[atom bc.. # Some ruby code]',\n      '[atom obj = {foo: :bar}]',\n      '[atom puts obj]',\n      '',\n      '[atom obj[[:love]] = \"*love*\"]',\n      '[atom puts obj.love.upcase]',\n      '',\n      'p. Normal text.');\n\n  MT('fn1..ThenParagraph',\n      '[variable fn1.. foo bar]',\n      '',\n      '[variable More.]',\n      'p. Normal Text');\n\n  MT('pre..ThenParagraph',\n      '[operator pre.. foo bar]',\n      '',\n      '[operator More.]',\n      'p. Normal Text');\n\n  /*\n   * Tables\n   */\n\n  MT('table',\n      '[variable-3&operator |_. name |_. age|]',\n      '[variable-3 |][variable-3&strong *Walter*][variable-3 |   5  |]',\n      '[variable-3 |Florence|   6  |]',\n      '',\n      'p. Normal text.');\n\n  MT('tableWithAttributes',\n      '[variable-3&operator |_. name |_. age|]',\n      '[variable-3 |][variable-3&attribute /2.][variable-3  Jim |]',\n      '[variable-3 |][variable-3&attribute \\\\2{color: red}.][variable-3  Sam |]');\n\n  /*\n   * HTML\n   */\n\n  MT('html',\n      '[comment <div id=\"wrapper\">]',\n      '[comment <section id=\"introduction\">]',\n      '',\n      '[header&header-1 h1. Welcome]',\n      '',\n      '[variable-2 * Item one]',\n      '[variable-2 * Item two]',\n      '',\n      '[comment <a href=\"http://example.com\">Example</a>]',\n      '',\n      '[comment </section>]',\n      '[comment </div>]');\n\n  MT('inlineHtml',\n      'I can use HTML directly in my [comment <span class=\"youbetcha\">Textile</span>].');\n\n  /*\n   * No-Textile\n   */\n\n  MT('notextile',\n    '[string-2 notextile. *No* formatting]');\n\n  MT('notextileInline',\n      'Use [string-2 ==*asterisks*==] for [strong *strong*] text.');\n\n  MT('notextileWithPre',\n      '[operator pre. *No* formatting]');\n\n  MT('notextileWithSpanningPre',\n      '[operator pre.. *No* formatting]',\n      '',\n      '[operator *No* formatting]');\n\n  /* Only toggling phrases between non-word chars. */\n\n  MT('phrase-in-word',\n     'foo_bar_baz');\n\n  MT('phrase-non-word',\n     '[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]');\n\n  MT('phrase-lone-dash',\n     'foo - bar - baz');\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/textile/textile.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  }\n})(function(CodeMirror) {\n  \"use strict\";\n\n  var TOKEN_STYLES = {\n    addition: \"positive\",\n    attributes: \"attribute\",\n    bold: \"strong\",\n    cite: \"keyword\",\n    code: \"atom\",\n    definitionList: \"number\",\n    deletion: \"negative\",\n    div: \"punctuation\",\n    em: \"em\",\n    footnote: \"variable\",\n    footCite: \"qualifier\",\n    header: \"header\",\n    html: \"comment\",\n    image: \"string\",\n    italic: \"em\",\n    link: \"link\",\n    linkDefinition: \"link\",\n    list1: \"variable-2\",\n    list2: \"variable-3\",\n    list3: \"keyword\",\n    notextile: \"string-2\",\n    pre: \"operator\",\n    p: \"property\",\n    quote: \"bracket\",\n    span: \"quote\",\n    specialChar: \"tag\",\n    strong: \"strong\",\n    sub: \"builtin\",\n    sup: \"builtin\",\n    table: \"variable-3\",\n    tableHeading: \"operator\"\n  };\n\n  function startNewLine(stream, state) {\n    state.mode = Modes.newLayout;\n    state.tableHeading = false;\n\n    if (state.layoutType === \"definitionList\" && state.spanningLayout &&\n        stream.match(RE(\"definitionListEnd\"), false))\n      state.spanningLayout = false;\n  }\n\n  function handlePhraseModifier(stream, state, ch) {\n    if (ch === \"_\") {\n      if (stream.eat(\"_\"))\n        return togglePhraseModifier(stream, state, \"italic\", /__/, 2);\n      else\n        return togglePhraseModifier(stream, state, \"em\", /_/, 1);\n    }\n\n    if (ch === \"*\") {\n      if (stream.eat(\"*\")) {\n        return togglePhraseModifier(stream, state, \"bold\", /\\*\\*/, 2);\n      }\n      return togglePhraseModifier(stream, state, \"strong\", /\\*/, 1);\n    }\n\n    if (ch === \"[\") {\n      if (stream.match(/\\d+\\]/)) state.footCite = true;\n      return tokenStyles(state);\n    }\n\n    if (ch === \"(\") {\n      var spec = stream.match(/^(r|tm|c)\\)/);\n      if (spec)\n        return tokenStylesWith(state, TOKEN_STYLES.specialChar);\n    }\n\n    if (ch === \"<\" && stream.match(/(\\w+)[^>]+>[^<]+<\\/\\1>/))\n      return tokenStylesWith(state, TOKEN_STYLES.html);\n\n    if (ch === \"?\" && stream.eat(\"?\"))\n      return togglePhraseModifier(stream, state, \"cite\", /\\?\\?/, 2);\n\n    if (ch === \"=\" && stream.eat(\"=\"))\n      return togglePhraseModifier(stream, state, \"notextile\", /==/, 2);\n\n    if (ch === \"-\" && !stream.eat(\"-\"))\n      return togglePhraseModifier(stream, state, \"deletion\", /-/, 1);\n\n    if (ch === \"+\")\n      return togglePhraseModifier(stream, state, \"addition\", /\\+/, 1);\n\n    if (ch === \"~\")\n      return togglePhraseModifier(stream, state, \"sub\", /~/, 1);\n\n    if (ch === \"^\")\n      return togglePhraseModifier(stream, state, \"sup\", /\\^/, 1);\n\n    if (ch === \"%\")\n      return togglePhraseModifier(stream, state, \"span\", /%/, 1);\n\n    if (ch === \"@\")\n      return togglePhraseModifier(stream, state, \"code\", /@/, 1);\n\n    if (ch === \"!\") {\n      var type = togglePhraseModifier(stream, state, \"image\", /(?:\\([^\\)]+\\))?!/, 1);\n      stream.match(/^:\\S+/); // optional Url portion\n      return type;\n    }\n    return tokenStyles(state);\n  }\n\n  function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) {\n    var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null;\n    var charAfter = stream.peek();\n    if (state[phraseModifier]) {\n      if ((!charAfter || /\\W/.test(charAfter)) && charBefore && /\\S/.test(charBefore)) {\n        var type = tokenStyles(state);\n        state[phraseModifier] = false;\n        return type;\n      }\n    } else if ((!charBefore || /\\W/.test(charBefore)) && charAfter && /\\S/.test(charAfter) &&\n               stream.match(new RegExp(\"^.*\\\\S\" + closeRE.source + \"(?:\\\\W|$)\"), false)) {\n      state[phraseModifier] = true;\n      state.mode = Modes.attributes;\n    }\n    return tokenStyles(state);\n  };\n\n  function tokenStyles(state) {\n    var disabled = textileDisabled(state);\n    if (disabled) return disabled;\n\n    var styles = [];\n    if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]);\n\n    styles = styles.concat(activeStyles(\n      state, \"addition\", \"bold\", \"cite\", \"code\", \"deletion\", \"em\", \"footCite\",\n      \"image\", \"italic\", \"link\", \"span\", \"strong\", \"sub\", \"sup\", \"table\", \"tableHeading\"));\n\n    if (state.layoutType === \"header\")\n      styles.push(TOKEN_STYLES.header + \"-\" + state.header);\n\n    return styles.length ? styles.join(\" \") : null;\n  }\n\n  function textileDisabled(state) {\n    var type = state.layoutType;\n\n    switch(type) {\n    case \"notextile\":\n    case \"code\":\n    case \"pre\":\n      return TOKEN_STYLES[type];\n    default:\n      if (state.notextile)\n        return TOKEN_STYLES.notextile + (type ? (\" \" + TOKEN_STYLES[type]) : \"\");\n      return null;\n    }\n  }\n\n  function tokenStylesWith(state, extraStyles) {\n    var disabled = textileDisabled(state);\n    if (disabled) return disabled;\n\n    var type = tokenStyles(state);\n    if (extraStyles)\n      return type ? (type + \" \" + extraStyles) : extraStyles;\n    else\n      return type;\n  }\n\n  function activeStyles(state) {\n    var styles = [];\n    for (var i = 1; i < arguments.length; ++i) {\n      if (state[arguments[i]])\n        styles.push(TOKEN_STYLES[arguments[i]]);\n    }\n    return styles;\n  }\n\n  function blankLine(state) {\n    var spanningLayout = state.spanningLayout, type = state.layoutType;\n\n    for (var key in state) if (state.hasOwnProperty(key))\n      delete state[key];\n\n    state.mode = Modes.newLayout;\n    if (spanningLayout) {\n      state.layoutType = type;\n      state.spanningLayout = true;\n    }\n  }\n\n  var REs = {\n    cache: {},\n    single: {\n      bc: \"bc\",\n      bq: \"bq\",\n      definitionList: /- [^(?::=)]+:=+/,\n      definitionListEnd: /.*=:\\s*$/,\n      div: \"div\",\n      drawTable: /\\|.*\\|/,\n      foot: /fn\\d+/,\n      header: /h[1-6]/,\n      html: /\\s*<(?:\\/)?(\\w+)(?:[^>]+)?>(?:[^<]+<\\/\\1>)?/,\n      link: /[^\"]+\":\\S/,\n      linkDefinition: /\\[[^\\s\\]]+\\]\\S+/,\n      list: /(?:#+|\\*+)/,\n      notextile: \"notextile\",\n      para: \"p\",\n      pre: \"pre\",\n      table: \"table\",\n      tableCellAttributes: /[\\/\\\\]\\d+/,\n      tableHeading: /\\|_\\./,\n      tableText: /[^\"_\\*\\[\\(\\?\\+~\\^%@|-]+/,\n      text: /[^!\"_=\\*\\[\\(<\\?\\+~\\^%@-]+/\n    },\n    attributes: {\n      align: /(?:<>|<|>|=)/,\n      selector: /\\([^\\(][^\\)]+\\)/,\n      lang: /\\[[^\\[\\]]+\\]/,\n      pad: /(?:\\(+|\\)+){1,2}/,\n      css: /\\{[^\\}]+\\}/\n    },\n    createRe: function(name) {\n      switch (name) {\n      case \"drawTable\":\n        return REs.makeRe(\"^\", REs.single.drawTable, \"$\");\n      case \"html\":\n        return REs.makeRe(\"^\", REs.single.html, \"(?:\", REs.single.html, \")*\", \"$\");\n      case \"linkDefinition\":\n        return REs.makeRe(\"^\", REs.single.linkDefinition, \"$\");\n      case \"listLayout\":\n        return REs.makeRe(\"^\", REs.single.list, RE(\"allAttributes\"), \"*\\\\s+\");\n      case \"tableCellAttributes\":\n        return REs.makeRe(\"^\", REs.choiceRe(REs.single.tableCellAttributes,\n                                            RE(\"allAttributes\")), \"+\\\\.\");\n      case \"type\":\n        return REs.makeRe(\"^\", RE(\"allTypes\"));\n      case \"typeLayout\":\n        return REs.makeRe(\"^\", RE(\"allTypes\"), RE(\"allAttributes\"),\n                          \"*\\\\.\\\\.?\", \"(\\\\s+|$)\");\n      case \"attributes\":\n        return REs.makeRe(\"^\", RE(\"allAttributes\"), \"+\");\n\n      case \"allTypes\":\n        return REs.choiceRe(REs.single.div, REs.single.foot,\n                            REs.single.header, REs.single.bc, REs.single.bq,\n                            REs.single.notextile, REs.single.pre, REs.single.table,\n                            REs.single.para);\n\n      case \"allAttributes\":\n        return REs.choiceRe(REs.attributes.selector, REs.attributes.css,\n                            REs.attributes.lang, REs.attributes.align, REs.attributes.pad);\n\n      default:\n        return REs.makeRe(\"^\", REs.single[name]);\n      }\n    },\n    makeRe: function() {\n      var pattern = \"\";\n      for (var i = 0; i < arguments.length; ++i) {\n        var arg = arguments[i];\n        pattern += (typeof arg === \"string\") ? arg : arg.source;\n      }\n      return new RegExp(pattern);\n    },\n    choiceRe: function() {\n      var parts = [arguments[0]];\n      for (var i = 1; i < arguments.length; ++i) {\n        parts[i * 2 - 1] = \"|\";\n        parts[i * 2] = arguments[i];\n      }\n\n      parts.unshift(\"(?:\");\n      parts.push(\")\");\n      return REs.makeRe.apply(null, parts);\n    }\n  };\n\n  function RE(name) {\n    return (REs.cache[name] || (REs.cache[name] = REs.createRe(name)));\n  }\n\n  var Modes = {\n    newLayout: function(stream, state) {\n      if (stream.match(RE(\"typeLayout\"), false)) {\n        state.spanningLayout = false;\n        return (state.mode = Modes.blockType)(stream, state);\n      }\n      var newMode;\n      if (!textileDisabled(state)) {\n        if (stream.match(RE(\"listLayout\"), false))\n          newMode = Modes.list;\n        else if (stream.match(RE(\"drawTable\"), false))\n          newMode = Modes.table;\n        else if (stream.match(RE(\"linkDefinition\"), false))\n          newMode = Modes.linkDefinition;\n        else if (stream.match(RE(\"definitionList\")))\n          newMode = Modes.definitionList;\n        else if (stream.match(RE(\"html\"), false))\n          newMode = Modes.html;\n      }\n      return (state.mode = (newMode || Modes.text))(stream, state);\n    },\n\n    blockType: function(stream, state) {\n      var match, type;\n      state.layoutType = null;\n\n      if (match = stream.match(RE(\"type\")))\n        type = match[0];\n      else\n        return (state.mode = Modes.text)(stream, state);\n\n      if (match = type.match(RE(\"header\"))) {\n        state.layoutType = \"header\";\n        state.header = parseInt(match[0][1]);\n      } else if (type.match(RE(\"bq\"))) {\n        state.layoutType = \"quote\";\n      } else if (type.match(RE(\"bc\"))) {\n        state.layoutType = \"code\";\n      } else if (type.match(RE(\"foot\"))) {\n        state.layoutType = \"footnote\";\n      } else if (type.match(RE(\"notextile\"))) {\n        state.layoutType = \"notextile\";\n      } else if (type.match(RE(\"pre\"))) {\n        state.layoutType = \"pre\";\n      } else if (type.match(RE(\"div\"))) {\n        state.layoutType = \"div\";\n      } else if (type.match(RE(\"table\"))) {\n        state.layoutType = \"table\";\n      }\n\n      state.mode = Modes.attributes;\n      return tokenStyles(state);\n    },\n\n    text: function(stream, state) {\n      if (stream.match(RE(\"text\"))) return tokenStyles(state);\n\n      var ch = stream.next();\n      if (ch === '\"')\n        return (state.mode = Modes.link)(stream, state);\n      return handlePhraseModifier(stream, state, ch);\n    },\n\n    attributes: function(stream, state) {\n      state.mode = Modes.layoutLength;\n\n      if (stream.match(RE(\"attributes\")))\n        return tokenStylesWith(state, TOKEN_STYLES.attributes);\n      else\n        return tokenStyles(state);\n    },\n\n    layoutLength: function(stream, state) {\n      if (stream.eat(\".\") && stream.eat(\".\"))\n        state.spanningLayout = true;\n\n      state.mode = Modes.text;\n      return tokenStyles(state);\n    },\n\n    list: function(stream, state) {\n      var match = stream.match(RE(\"list\"));\n      state.listDepth = match[0].length;\n      var listMod = (state.listDepth - 1) % 3;\n      if (!listMod)\n        state.layoutType = \"list1\";\n      else if (listMod === 1)\n        state.layoutType = \"list2\";\n      else\n        state.layoutType = \"list3\";\n\n      state.mode = Modes.attributes;\n      return tokenStyles(state);\n    },\n\n    link: function(stream, state) {\n      state.mode = Modes.text;\n      if (stream.match(RE(\"link\"))) {\n        stream.match(/\\S+/);\n        return tokenStylesWith(state, TOKEN_STYLES.link);\n      }\n      return tokenStyles(state);\n    },\n\n    linkDefinition: function(stream, state) {\n      stream.skipToEnd();\n      return tokenStylesWith(state, TOKEN_STYLES.linkDefinition);\n    },\n\n    definitionList: function(stream, state) {\n      stream.match(RE(\"definitionList\"));\n\n      state.layoutType = \"definitionList\";\n\n      if (stream.match(/\\s*$/))\n        state.spanningLayout = true;\n      else\n        state.mode = Modes.attributes;\n\n      return tokenStyles(state);\n    },\n\n    html: function(stream, state) {\n      stream.skipToEnd();\n      return tokenStylesWith(state, TOKEN_STYLES.html);\n    },\n\n    table: function(stream, state) {\n      state.layoutType = \"table\";\n      return (state.mode = Modes.tableCell)(stream, state);\n    },\n\n    tableCell: function(stream, state) {\n      if (stream.match(RE(\"tableHeading\")))\n        state.tableHeading = true;\n      else\n        stream.eat(\"|\");\n\n      state.mode = Modes.tableCellAttributes;\n      return tokenStyles(state);\n    },\n\n    tableCellAttributes: function(stream, state) {\n      state.mode = Modes.tableText;\n\n      if (stream.match(RE(\"tableCellAttributes\")))\n        return tokenStylesWith(state, TOKEN_STYLES.attributes);\n      else\n        return tokenStyles(state);\n    },\n\n    tableText: function(stream, state) {\n      if (stream.match(RE(\"tableText\")))\n        return tokenStyles(state);\n\n      if (stream.peek() === \"|\") { // end of cell\n        state.mode = Modes.tableCell;\n        return tokenStyles(state);\n      }\n      return handlePhraseModifier(stream, state, stream.next());\n    }\n  };\n\n  CodeMirror.defineMode(\"textile\", function() {\n    return {\n      startState: function() {\n        return { mode: Modes.newLayout };\n      },\n      token: function(stream, state) {\n        if (stream.sol()) startNewLine(stream, state);\n        return state.mode(stream, state);\n      },\n      blankLine: blankLine\n    };\n  });\n\n  CodeMirror.defineMIME(\"text/x-textile\", \"textile\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiddlywiki/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: TiddlyWiki mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"tiddlywiki.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"tiddlywiki.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">TiddlyWiki</a>\n  </ul>\n</div>\n\n<article>\n<h2>TiddlyWiki mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n!TiddlyWiki Formatting\n* Rendered versions can be found at: http://www.tiddlywiki.com/#Reference\n\n|!Option            | !Syntax            |\n|bold font          | ''bold''           |\n|italic type        | //italic//         |\n|underlined text    | __underlined__     |\n|strikethrough text | --strikethrough--  |\n|superscript text   | super^^script^^    |\n|subscript text     | sub~~script~~      |\n|highlighted text   | @@highlighted@@    |\n|preformatted text  | {{{preformatted}}} |\n\n!Block Elements\n<<<\n!Heading 1\n\n!!Heading 2\n\n!!!Heading 3\n\n!!!!Heading 4\n\n!!!!!Heading 5\n<<<\n\n!!Lists\n<<<\n* unordered list, level 1\n** unordered list, level 2\n*** unordered list, level 3\n\n# ordered list, level 1\n## ordered list, level 2\n### unordered list, level 3\n\n; definition list, term\n: definition list, description\n<<<\n\n!!Blockquotes\n<<<\n> blockquote, level 1\n>> blockquote, level 2\n>>> blockquote, level 3\n\n> blockquote\n<<<\n\n!!Preformatted Text\n<<<\n{{{\npreformatted (e.g. code)\n}}}\n<<<\n\n!!Code Sections\n<<<\n{{{\nText style code\n}}}\n\n//{{{\nJS styled code. TiddlyWiki mixed mode should support highlighter switching in the future.\n//}}}\n\n<!--{{{-->\nXML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.\n<!--}}}-->\n<<<\n\n!!Tables\n<<<\n|CssClass|k\n|!heading column 1|!heading column 2|\n|row 1, column 1|row 1, column 2|\n|row 2, column 1|row 2, column 2|\n|>|COLSPAN|\n|ROWSPAN| ... |\n|~| ... |\n|CssProperty:value;...| ... |\n|caption|c\n\n''Annotation:''\n* The {{{>}}} marker creates a \"colspan\", causing the current cell to merge with the one to the right.\n* The {{{~}}} marker creates a \"rowspan\", causing the current cell to merge with the one above.\n<<<\n!!Images /% TODO %/\ncf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]\n\n!Hyperlinks\n* [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler\n** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}\n* [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}\n** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).\n\n!Custom Styling\n* {{{@@CssProperty:value;CssProperty:value;...@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.\n* <html><code>{{customCssClass{...}}}</code></html>\n* raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> ... </html>}}}\n\n!Special Markers\n* {{{<br>}}} forces a manual line break\n* {{{----}}} creates a horizontal ruler\n* [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]\n* [[HTML entities local|HtmlEntities]]\n* {{{<<macroName>>}}} calls the respective [[macro|Macros]]\n* To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.\n* To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{\"\"\"WikiWord\"\"\"}}}.\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'tiddlywiki',\n        lineNumbers: true,\n        matchBrackets: true\n      });\n    </script>\n\n    <p>TiddlyWiki mode supports a single configuration.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-tiddlywiki</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiddlywiki/tiddlywiki.css",
    "content": "span.cm-underlined {\n  text-decoration: underline;\n}\nspan.cm-strikethrough {\n  text-decoration: line-through;\n}\nspan.cm-brace {\n  color: #170;\n  font-weight: bold;\n}\nspan.cm-table {\n  color: blue;\n  font-weight: bold;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiddlywiki/tiddlywiki.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/***\n    |''Name''|tiddlywiki.js|\n    |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|\n    |''Author''|PMario|\n    |''Version''|0.1.7|\n    |''Status''|''stable''|\n    |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|\n    |''Documentation''|http://codemirror.tiddlyspace.com/|\n    |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|\n    |''CoreVersion''|2.5.0|\n    |''Requires''|codemirror.js|\n    |''Keywords''|syntax highlighting color code mirror codemirror|\n    ! Info\n    CoreVersion parameter is needed for TiddlyWiki only!\n***/\n//{{{\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(\"tiddlywiki\", function () {\n  // Tokenizer\n  var textwords = {};\n\n  var keywords = function () {\n    function kw(type) {\n      return { type: type, style: \"macro\"};\n    }\n    return {\n      \"allTags\": kw('allTags'), \"closeAll\": kw('closeAll'), \"list\": kw('list'),\n      \"newJournal\": kw('newJournal'), \"newTiddler\": kw('newTiddler'),\n      \"permaview\": kw('permaview'), \"saveChanges\": kw('saveChanges'),\n      \"search\": kw('search'), \"slider\": kw('slider'),   \"tabs\": kw('tabs'),\n      \"tag\": kw('tag'), \"tagging\": kw('tagging'),       \"tags\": kw('tags'),\n      \"tiddler\": kw('tiddler'), \"timeline\": kw('timeline'),\n      \"today\": kw('today'), \"version\": kw('version'),   \"option\": kw('option'),\n\n      \"with\": kw('with'),\n      \"filter\": kw('filter')\n    };\n  }();\n\n  var isSpaceName = /[\\w_\\-]/i,\n  reHR = /^\\-\\-\\-\\-+$/,                                 // <hr>\n  reWikiCommentStart = /^\\/\\*\\*\\*$/,            // /***\n  reWikiCommentStop = /^\\*\\*\\*\\/$/,             // ***/\n  reBlockQuote = /^<<<$/,\n\n  reJsCodeStart = /^\\/\\/\\{\\{\\{$/,                       // //{{{ js block start\n  reJsCodeStop = /^\\/\\/\\}\\}\\}$/,                        // //}}} js stop\n  reXmlCodeStart = /^<!--\\{\\{\\{-->$/,           // xml block start\n  reXmlCodeStop = /^<!--\\}\\}\\}-->$/,            // xml stop\n\n  reCodeBlockStart = /^\\{\\{\\{$/,                        // {{{ TW text div block start\n  reCodeBlockStop = /^\\}\\}\\}$/,                 // }}} TW text stop\n\n  reUntilCodeStop = /.*?\\}\\}\\}/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n\n  function ret(tp, style, cont) {\n    type = tp;\n    content = cont;\n    return style;\n  }\n\n  function jsTokenBase(stream, state) {\n    var sol = stream.sol(), ch;\n\n    state.block = false;        // indicates the start of a code block.\n\n    ch = stream.peek();         // don't eat, to make matching simpler\n\n    // check start of  blocks\n    if (sol && /[<\\/\\*{}\\-]/.test(ch)) {\n      if (stream.match(reCodeBlockStart)) {\n        state.block = true;\n        return chain(stream, state, twTokenCode);\n      }\n      if (stream.match(reBlockQuote)) {\n        return ret('quote', 'quote');\n      }\n      if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {\n        return ret('code', 'comment');\n      }\n      if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {\n        return ret('code', 'comment');\n      }\n      if (stream.match(reHR)) {\n        return ret('hr', 'hr');\n      }\n    } // sol\n    ch = stream.next();\n\n    if (sol && /[\\/\\*!#;:>|]/.test(ch)) {\n      if (ch == \"!\") { // tw header\n        stream.skipToEnd();\n        return ret(\"header\", \"header\");\n      }\n      if (ch == \"*\") { // tw list\n        stream.eatWhile('*');\n        return ret(\"list\", \"comment\");\n      }\n      if (ch == \"#\") { // tw numbered list\n        stream.eatWhile('#');\n        return ret(\"list\", \"comment\");\n      }\n      if (ch == \";\") { // definition list, term\n        stream.eatWhile(';');\n        return ret(\"list\", \"comment\");\n      }\n      if (ch == \":\") { // definition list, description\n        stream.eatWhile(':');\n        return ret(\"list\", \"comment\");\n      }\n      if (ch == \">\") { // single line quote\n        stream.eatWhile(\">\");\n        return ret(\"quote\", \"quote\");\n      }\n      if (ch == '|') {\n        return ret('table', 'header');\n      }\n    }\n\n    if (ch == '{' && stream.match(/\\{\\{/)) {\n      return chain(stream, state, twTokenCode);\n    }\n\n    // rudimentary html:// file:// link matching. TW knows much more ...\n    if (/[hf]/i.test(ch)) {\n      if (/[ti]/i.test(stream.peek()) && stream.match(/\\b(ttps?|tp|ile):\\/\\/[\\-A-Z0-9+&@#\\/%?=~_|$!:,.;]*[A-Z0-9+&@#\\/%=~_|$]/i)) {\n        return ret(\"link\", \"link\");\n      }\n    }\n    // just a little string indicator, don't want to have the whole string covered\n    if (ch == '\"') {\n      return ret('string', 'string');\n    }\n    if (ch == '~') {    // _no_ CamelCase indicator should be bold\n      return ret('text', 'brace');\n    }\n    if (/[\\[\\]]/.test(ch)) { // check for [[..]]\n      if (stream.peek() == ch) {\n        stream.next();\n        return ret('brace', 'brace');\n      }\n    }\n    if (ch == \"@\") {    // check for space link. TODO fix @@...@@ highlighting\n      stream.eatWhile(isSpaceName);\n      return ret(\"link\", \"link\");\n    }\n    if (/\\d/.test(ch)) {        // numbers\n      stream.eatWhile(/\\d/);\n      return ret(\"number\", \"number\");\n    }\n    if (ch == \"/\") { // tw invisible comment\n      if (stream.eat(\"%\")) {\n        return chain(stream, state, twTokenComment);\n      }\n      else if (stream.eat(\"/\")) { //\n        return chain(stream, state, twTokenEm);\n      }\n    }\n    if (ch == \"_\") { // tw underline\n      if (stream.eat(\"_\")) {\n        return chain(stream, state, twTokenUnderline);\n      }\n    }\n    // strikethrough and mdash handling\n    if (ch == \"-\") {\n      if (stream.eat(\"-\")) {\n        // if strikethrough looks ugly, change CSS.\n        if (stream.peek() != ' ')\n          return chain(stream, state, twTokenStrike);\n        // mdash\n        if (stream.peek() == ' ')\n          return ret('text', 'brace');\n      }\n    }\n    if (ch == \"'\") { // tw bold\n      if (stream.eat(\"'\")) {\n        return chain(stream, state, twTokenStrong);\n      }\n    }\n    if (ch == \"<\") { // tw macro\n      if (stream.eat(\"<\")) {\n        return chain(stream, state, twTokenMacro);\n      }\n    }\n    else {\n      return ret(ch);\n    }\n\n    // core macro handling\n    stream.eatWhile(/[\\w\\$_]/);\n    var word = stream.current(),\n    known = textwords.propertyIsEnumerable(word) && textwords[word];\n\n    return known ? ret(known.type, known.style, word) : ret(\"text\", null, word);\n\n  } // jsTokenBase()\n\n  // tw invisible comment\n  function twTokenComment(stream, state) {\n    var maybeEnd = false,\n    ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"%\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // tw strong / bold\n  function twTokenStrong(stream, state) {\n    var maybeEnd = false,\n    ch;\n    while (ch = stream.next()) {\n      if (ch == \"'\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"'\");\n    }\n    return ret(\"text\", \"strong\");\n  }\n\n  // tw code\n  function twTokenCode(stream, state) {\n    var ch, sb = state.block;\n\n    if (sb && stream.current()) {\n      return ret(\"code\", \"comment\");\n    }\n\n    if (!sb && stream.match(reUntilCodeStop)) {\n      state.tokenize = jsTokenBase;\n      return ret(\"code\", \"comment\");\n    }\n\n    if (sb && stream.sol() && stream.match(reCodeBlockStop)) {\n      state.tokenize = jsTokenBase;\n      return ret(\"code\", \"comment\");\n    }\n\n    ch = stream.next();\n    return (sb) ? ret(\"code\", \"comment\") : ret(\"code\", \"comment\");\n  }\n\n  // tw em / italic\n  function twTokenEm(stream, state) {\n    var maybeEnd = false,\n    ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"/\");\n    }\n    return ret(\"text\", \"em\");\n  }\n\n  // tw underlined text\n  function twTokenUnderline(stream, state) {\n    var maybeEnd = false,\n    ch;\n    while (ch = stream.next()) {\n      if (ch == \"_\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"_\");\n    }\n    return ret(\"text\", \"underlined\");\n  }\n\n  // tw strike through text looks ugly\n  // change CSS if needed\n  function twTokenStrike(stream, state) {\n    var maybeEnd = false, ch;\n\n    while (ch = stream.next()) {\n      if (ch == \"-\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"-\");\n    }\n    return ret(\"text\", \"strikethrough\");\n  }\n\n  // macro\n  function twTokenMacro(stream, state) {\n    var ch, word, known;\n\n    if (stream.current() == '<<') {\n      return ret('brace', 'macro');\n    }\n\n    ch = stream.next();\n    if (!ch) {\n      state.tokenize = jsTokenBase;\n      return ret(ch);\n    }\n    if (ch == \">\") {\n      if (stream.peek() == '>') {\n        stream.next();\n        state.tokenize = jsTokenBase;\n        return ret(\"brace\", \"macro\");\n      }\n    }\n\n    stream.eatWhile(/[\\w\\$_]/);\n    word = stream.current();\n    known = keywords.propertyIsEnumerable(word) && keywords[word];\n\n    if (known) {\n      return ret(known.type, known.style, word);\n    }\n    else {\n      return ret(\"macro\", null, word);\n    }\n  }\n\n  // Interface\n  return {\n    startState: function () {\n      return {\n        tokenize: jsTokenBase,\n        indented: 0,\n        level: 0\n      };\n    },\n\n    token: function (stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    },\n\n    electricChars: \"\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-tiddlywiki\", \"tiddlywiki\");\n});\n\n//}}}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiki/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Tiki wiki mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"tiki.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"tiki.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Tiki wiki</a>\n  </ul>\n</div>\n\n<article>\n<h2>Tiki wiki mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\nHeadings\n!Header 1\n!!Header 2\n!!!Header 3\n!!!!Header 4\n!!!!!Header 5\n!!!!!!Header 6\n\nStyling\n-=titlebar=-\n^^ Box on multi\nlines\nof content^^\n__bold__\n''italic''\n===underline===\n::center::\n--Line Through--\n\nOperators\n~np~No parse~/np~\n\nLink\n[link|desc|nocache]\n\nWiki\n((Wiki))\n((Wiki|desc))\n((Wiki|desc|timeout))\n\nTable\n||row1 col1|row1 col2|row1 col3\nrow2 col1|row2 col2|row2 col3\nrow3 col1|row3 col2|row3 col3||\n\nLists:\n*bla\n**bla-1\n++continue-bla-1\n***bla-2\n++continue-bla-1\n*bla\n+continue-bla\n#bla\n** tra-la-la\n+continue-bla\n#bla\n\nPlugin (standard):\n{PLUGIN(attr=\"my attr\")}\nPlugin Body\n{PLUGIN}\n\nPlugin (inline):\n{plugin attr=\"my attr\"}\n</textarea></div>\n\n<script type=\"text/javascript\">\n\tvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'tiki',\n        lineNumbers: true\n    });\n</script>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiki/tiki.css",
    "content": ".cm-tw-syntaxerror {\n\tcolor: #FFF;\n\tbackground-color: #900;\n}\n\n.cm-tw-deleted {\n\ttext-decoration: line-through;\n}\n\n.cm-tw-header5 {\n\tfont-weight: bold;\n}\n.cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/\n\tpadding-left: 10px;\n}\n\n.cm-tw-box {\n\tborder-top-width: 0px ! important;\n\tborder-style: solid;\n\tborder-width: 1px;\n\tborder-color: inherit;\n}\n\n.cm-tw-underline {\n\ttext-decoration: underline;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tiki/tiki.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('tiki', function(config) {\n  function inBlock(style, terminator, returnTokenizer) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n\n      if (returnTokenizer) state.tokenize = returnTokenizer;\n\n      return style;\n    };\n  }\n\n  function inLine(style) {\n    return function(stream, state) {\n      while(!stream.eol()) {\n        stream.next();\n      }\n      state.tokenize = inText;\n      return style;\n    };\n  }\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var sol = stream.sol();\n    var ch = stream.next();\n\n    //non start of line\n    switch (ch) { //switch is generally much faster than if, so it is used here\n    case \"{\": //plugin\n      stream.eat(\"/\");\n      stream.eatSpace();\n      var tagName = \"\";\n      var c;\n      while ((c = stream.eat(/[^\\s\\u00a0=\\\"\\'\\/?(}]/))) tagName += c;\n      state.tokenize = inPlugin;\n      return \"tag\";\n      break;\n    case \"_\": //bold\n      if (stream.eat(\"_\")) {\n        return chain(inBlock(\"strong\", \"__\", inText));\n      }\n      break;\n    case \"'\": //italics\n      if (stream.eat(\"'\")) {\n        // Italic text\n        return chain(inBlock(\"em\", \"''\", inText));\n      }\n      break;\n    case \"(\":// Wiki Link\n      if (stream.eat(\"(\")) {\n        return chain(inBlock(\"variable-2\", \"))\", inText));\n      }\n      break;\n    case \"[\":// Weblink\n      return chain(inBlock(\"variable-3\", \"]\", inText));\n      break;\n    case \"|\": //table\n      if (stream.eat(\"|\")) {\n        return chain(inBlock(\"comment\", \"||\"));\n      }\n      break;\n    case \"-\":\n      if (stream.eat(\"=\")) {//titleBar\n        return chain(inBlock(\"header string\", \"=-\", inText));\n      } else if (stream.eat(\"-\")) {//deleted\n        return chain(inBlock(\"error tw-deleted\", \"--\", inText));\n      }\n      break;\n    case \"=\": //underline\n      if (stream.match(\"==\")) {\n        return chain(inBlock(\"tw-underline\", \"===\", inText));\n      }\n      break;\n    case \":\":\n      if (stream.eat(\":\")) {\n        return chain(inBlock(\"comment\", \"::\"));\n      }\n      break;\n    case \"^\": //box\n      return chain(inBlock(\"tw-box\", \"^\"));\n      break;\n    case \"~\": //np\n      if (stream.match(\"np~\")) {\n        return chain(inBlock(\"meta\", \"~/np~\"));\n      }\n      break;\n    }\n\n    //start of line types\n    if (sol) {\n      switch (ch) {\n      case \"!\": //header at start of line\n        if (stream.match('!!!!!')) {\n          return chain(inLine(\"header string\"));\n        } else if (stream.match('!!!!')) {\n          return chain(inLine(\"header string\"));\n        } else if (stream.match('!!!')) {\n          return chain(inLine(\"header string\"));\n        } else if (stream.match('!!')) {\n          return chain(inLine(\"header string\"));\n        } else {\n          return chain(inLine(\"header string\"));\n        }\n        break;\n      case \"*\": //unordered list line item, or <li /> at start of line\n      case \"#\": //ordered list line item, or <li /> at start of line\n      case \"+\": //ordered list line item, or <li /> at start of line\n        return chain(inLine(\"tw-listitem bracket\"));\n        break;\n      }\n    }\n\n    //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki\n    return null;\n  }\n\n  var indentUnit = config.indentUnit;\n\n  // Return variables for tokenizers\n  var pluginName, type;\n  function inPlugin(stream, state) {\n    var ch = stream.next();\n    var peek = stream.peek();\n\n    if (ch == \"}\") {\n      state.tokenize = inText;\n      //type = ch == \")\" ? \"endPlugin\" : \"selfclosePlugin\"; inPlugin\n      return \"tag\";\n    } else if (ch == \"(\" || ch == \")\") {\n      return \"bracket\";\n    } else if (ch == \"=\") {\n      type = \"equals\";\n\n      if (peek == \">\") {\n        ch = stream.next();\n        peek = stream.peek();\n      }\n\n      //here we detect values directly after equal character with no quotes\n      if (!/[\\'\\\"]/.test(peek)) {\n        state.tokenize = inAttributeNoQuote();\n      }\n      //end detect values\n\n      return \"operator\";\n    } else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    } else {\n      stream.eatWhile(/[^\\s\\u00a0=\\\"\\'\\/?]/);\n      return \"keyword\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inPlugin;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inAttributeNoQuote() {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        var ch = stream.next();\n        var peek = stream.peek();\n        if (ch == \" \" || ch == \",\" || /[ )}]/.test(peek)) {\n      state.tokenize = inPlugin;\n      break;\n    }\n  }\n  return \"string\";\n};\n                     }\n\nvar curState, setStyle;\nfunction pass() {\n  for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n}\n\nfunction cont() {\n  pass.apply(null, arguments);\n  return true;\n}\n\nfunction pushContext(pluginName, startOfLine) {\n  var noIndent = curState.context && curState.context.noIndent;\n  curState.context = {\n    prev: curState.context,\n    pluginName: pluginName,\n    indent: curState.indented,\n    startOfLine: startOfLine,\n    noIndent: noIndent\n  };\n}\n\nfunction popContext() {\n  if (curState.context) curState.context = curState.context.prev;\n}\n\nfunction element(type) {\n  if (type == \"openPlugin\") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}\n  else if (type == \"closePlugin\") {\n    var err = false;\n    if (curState.context) {\n      err = curState.context.pluginName != pluginName;\n      popContext();\n    } else {\n      err = true;\n    }\n    if (err) setStyle = \"error\";\n    return cont(endcloseplugin(err));\n  }\n  else if (type == \"string\") {\n    if (!curState.context || curState.context.name != \"!cdata\") pushContext(\"!cdata\");\n    if (curState.tokenize == inText) popContext();\n    return cont();\n  }\n  else return cont();\n}\n\nfunction endplugin(startOfLine) {\n  return function(type) {\n    if (\n      type == \"selfclosePlugin\" ||\n        type == \"endPlugin\"\n    )\n      return cont();\n    if (type == \"endPlugin\") {pushContext(curState.pluginName, startOfLine); return cont();}\n    return cont();\n  };\n}\n\nfunction endcloseplugin(err) {\n  return function(type) {\n    if (err) setStyle = \"error\";\n    if (type == \"endPlugin\") return cont();\n    return pass();\n  };\n}\n\nfunction attributes(type) {\n  if (type == \"keyword\") {setStyle = \"attribute\"; return cont(attributes);}\n  if (type == \"equals\") return cont(attvalue, attributes);\n  return pass();\n}\nfunction attvalue(type) {\n  if (type == \"keyword\") {setStyle = \"string\"; return cont();}\n  if (type == \"string\") return cont(attvaluemaybe);\n  return pass();\n}\nfunction attvaluemaybe(type) {\n  if (type == \"string\") return cont(attvaluemaybe);\n  else return pass();\n}\nreturn {\n  startState: function() {\n    return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};\n  },\n  token: function(stream, state) {\n    if (stream.sol()) {\n      state.startOfLine = true;\n      state.indented = stream.indentation();\n    }\n    if (stream.eatSpace()) return null;\n\n    setStyle = type = pluginName = null;\n    var style = state.tokenize(stream, state);\n    if ((style || type) && style != \"comment\") {\n      curState = state;\n      while (true) {\n        var comb = state.cc.pop() || element;\n        if (comb(type || style)) break;\n      }\n    }\n    state.startOfLine = false;\n    return setStyle || style;\n  },\n  indent: function(state, textAfter) {\n    var context = state.context;\n    if (context && context.noIndent) return 0;\n    if (context && /^{\\//.test(textAfter))\n        context = context.prev;\n        while (context && !context.startOfLine)\n          context = context.prev;\n        if (context) return context.indent + indentUnit;\n        else return 0;\n       },\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/tiki\", \"tiki\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/toml/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: TOML Mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"toml.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">TOML Mode</a>\n  </ul>\n</div>\n\n<article>\n<h2>TOML Mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n# This is a TOML document. Boom.\n\ntitle = \"TOML Example\"\n\n[owner]\nname = \"Tom Preston-Werner\"\norganization = \"GitHub\"\nbio = \"GitHub Cofounder &amp; CEO\\nLikes tater tots and beer.\"\ndob = 1979-05-27T07:32:00Z # First class dates? Why not?\n\n[database]\nserver = \"192.168.1.1\"\nports = [ 8001, 8001, 8002 ]\nconnection_max = 5000\nenabled = true\n\n[servers]\n\n  # You can indent as you please. Tabs or spaces. TOML don't care.\n  [servers.alpha]\n  ip = \"10.0.0.1\"\n  dc = \"eqdc10\"\n\n  [servers.beta]\n  ip = \"10.0.0.2\"\n  dc = \"eqdc10\"\n\n[clients]\ndata = [ [\"gamma\", \"delta\"], [1, 2] ]\n\n# Line breaks are OK when inside arrays\nhosts = [\n  \"alpha\",\n  \"omega\"\n]\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"toml\"},\n        lineNumbers: true\n      });\n    </script>\n    <h3>The TOML Mode</h3>\n      <p> Created by Forbes Lindesay.</p>\n    <p><strong>MIME type defined:</strong> <code>text/x-toml</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/toml/toml.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(\"toml\", function () {\n  return {\n    startState: function () {\n      return {\n        inString: false,\n        stringType: \"\",\n        lhs: true,\n        inArray: 0\n      };\n    },\n    token: function (stream, state) {\n      //check for state changes\n      if (!state.inString && ((stream.peek() == '\"') || (stream.peek() == \"'\"))) {\n        state.stringType = stream.peek();\n        stream.next(); // Skip quote\n        state.inString = true; // Update state\n      }\n      if (stream.sol() && state.inArray === 0) {\n        state.lhs = true;\n      }\n      //return state\n      if (state.inString) {\n        while (state.inString && !stream.eol()) {\n          if (stream.peek() === state.stringType) {\n            stream.next(); // Skip quote\n            state.inString = false; // Clear flag\n          } else if (stream.peek() === '\\\\') {\n            stream.next();\n            stream.next();\n          } else {\n            stream.match(/^.[^\\\\\\\"\\']*/);\n          }\n        }\n        return state.lhs ? \"property string\" : \"string\"; // Token style\n      } else if (state.inArray && stream.peek() === ']') {\n        stream.next();\n        state.inArray--;\n        return 'bracket';\n      } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) {\n        stream.next();//skip closing ]\n        // array of objects has an extra open & close []\n        if (stream.peek() === ']') stream.next();\n        return \"atom\";\n      } else if (stream.peek() === \"#\") {\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (stream.eatSpace()) {\n        return null;\n      } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) {\n        return \"property\";\n      } else if (state.lhs && stream.peek() === \"=\") {\n        stream.next();\n        state.lhs = false;\n        return null;\n      } else if (!state.lhs && stream.match(/^\\d\\d\\d\\d[\\d\\-\\:\\.T]*Z/)) {\n        return 'atom'; //date\n      } else if (!state.lhs && (stream.match('true') || stream.match('false'))) {\n        return 'atom';\n      } else if (!state.lhs && stream.peek() === '[') {\n        state.inArray++;\n        stream.next();\n        return 'bracket';\n      } else if (!state.lhs && stream.match(/^\\-?\\d+(?:\\.\\d+)?/)) {\n        return 'number';\n      } else if (!stream.eatSpace()) {\n        stream.next();\n      }\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME('text/x-toml', 'toml');\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tornado/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Tornado template mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/mode/overlay.js\"></script>\n<script src=\"../xml/xml.js\"></script>\n<script src=\"../htmlmixed/htmlmixed.js\"></script>\n<script src=\"tornado.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/marijnh/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Tornado</a>\n  </ul>\n</div>\n\n<article>\n<h2>Tornado template mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n<!doctype html>\n<html>\n    <head>\n        <title>My Tornado web application</title>\n    </head>\n    <body class=\"gray-bg\">\n        <h1>\n            {{ title }}\n        </h1>\n        <ul class=\"my-list\">\n            {% for item in items %}\n                <li>{% item.name %}</li>\n            {% empty %}\n                <li>You have no items in your list.</li>\n            {% end %}\n        </ul>\n    </body>\n</html>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"tornado\",\n        indentUnit: 4,\n        indentWithTabs: true\n      });\n    </script>\n\n    <p>Mode for HTML with embedded Tornado template markup.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-tornado</code></p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/tornado/tornado.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\"), require(\"../htmlmixed/htmlmixed\"),\n        require(\"../../addon/mode/overlay\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"../htmlmixed/htmlmixed\",\n            \"../../addon/mode/overlay\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  CodeMirror.defineMode(\"tornado:inner\", function() {\n    var keywords = [\"and\",\"as\",\"assert\",\"autoescape\",\"block\",\"break\",\"class\",\"comment\",\"context\",\n                    \"continue\",\"datetime\",\"def\",\"del\",\"elif\",\"else\",\"end\",\"escape\",\"except\",\n                    \"exec\",\"extends\",\"false\",\"finally\",\"for\",\"from\",\"global\",\"if\",\"import\",\"in\",\n                    \"include\",\"is\",\"json_encode\",\"lambda\",\"length\",\"linkify\",\"load\",\"module\",\n                    \"none\",\"not\",\"or\",\"pass\",\"print\",\"put\",\"raise\",\"raw\",\"return\",\"self\",\"set\",\n                    \"squeeze\",\"super\",\"true\",\"try\",\"url_escape\",\"while\",\"with\",\"without\",\"xhtml_escape\",\"yield\"];\n    keywords = new RegExp(\"^((\" + keywords.join(\")|(\") + \"))\\\\b\");\n\n    function tokenBase (stream, state) {\n      stream.eatWhile(/[^\\{]/);\n      var ch = stream.next();\n      if (ch == \"{\") {\n        if (ch = stream.eat(/\\{|%|#/)) {\n          state.tokenize = inTag(ch);\n          return \"tag\";\n        }\n      }\n    }\n    function inTag (close) {\n      if (close == \"{\") {\n        close = \"}\";\n      }\n      return function (stream, state) {\n        var ch = stream.next();\n        if ((ch == close) && stream.eat(\"}\")) {\n          state.tokenize = tokenBase;\n          return \"tag\";\n        }\n        if (stream.match(keywords)) {\n          return \"keyword\";\n        }\n        return close == \"#\" ? \"comment\" : \"string\";\n      };\n    }\n    return {\n      startState: function () {\n        return {tokenize: tokenBase};\n      },\n      token: function (stream, state) {\n        return state.tokenize(stream, state);\n      }\n    };\n  });\n\n  CodeMirror.defineMode(\"tornado\", function(config) {\n    var htmlBase = CodeMirror.getMode(config, \"text/html\");\n    var tornadoInner = CodeMirror.getMode(config, \"tornado:inner\");\n    return CodeMirror.overlayMode(htmlBase, tornadoInner);\n  });\n\n  CodeMirror.defineMIME(\"text/x-tornado\", \"tornado\");\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/turtle/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Turtle mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"turtle.js\"></script>\n<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Turtle</a>\n  </ul>\n</div>\n\n<article>\n<h2>Turtle mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n@prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .\n@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\n<http://purl.org/net/bsletten>\n    a foaf:Person;\n    foaf:interest <http://www.w3.org/2000/01/sw/>;\n    foaf:based_near [\n        geo:lat \"34.0736111\" ;\n        geo:lon \"-118.3994444\"\n   ]\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/turtle\",\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/turtle</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/turtle/turtle.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(\"turtle\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([]);\n  var keywords = wordRegexp([\"@prefix\", \"@base\", \"a\"]);\n  var operatorChars = /[*+\\-<>=&|]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return null;\n    }\n    else if (ch == \":\") {\n          return \"operator\";\n        } else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if(stream.peek() == \":\") {\n        return \"variable-3\";\n      } else {\n             var word = stream.current();\n\n             if(keywords.test(word)) {\n                        return \"meta\";\n             }\n\n             if(ch >= \"A\" && ch <= \"Z\") {\n                    return \"comment\";\n                 } else {\n                        return \"keyword\";\n                 }\n      }\n      var word = stream.current();\n      if (ops.test(word))\n        return null;\n      else if (keywords.test(word))\n        return \"meta\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      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 (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    },\n\n    lineComment: \"#\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/turtle\", \"turtle\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/vb/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: VB.NET mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link href=\"http://fonts.googleapis.com/css?family=Inconsolata\" rel=\"stylesheet\" type=\"text/css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"vb.js\"></script>\n<script type=\"text/javascript\" src=\"../../addon/runmode/runmode.js\"></script>\n<style>\n      .CodeMirror {border: 1px solid #aaa; height:210px; height: auto;}\n      .CodeMirror-scroll { overflow-x: auto; overflow-y: hidden;}\n      .CodeMirror pre { font-family: Inconsolata; font-size: 14px}\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">VB.NET</a>\n  </ul>\n</div>\n\n<article>\n<h2>VB.NET mode</h2>\n\n<script type=\"text/javascript\">\nfunction test(golden, text) {\n  var ok = true;\n  var i = 0;\n  function callback(token, style, lineNo, pos){\n\t\t//console.log(String(token) + \" \" + String(style) + \" \" + String(lineNo) + \" \" + String(pos));\n    var result = [String(token), String(style)];\n    if (golden[i][0] != result[0] || golden[i][1] != result[1]){\n      return \"Error, expected: \" + String(golden[i]) + \", got: \" + String(result);\n      ok = false;\n    }\n    i++;\n  }\n  CodeMirror.runMode(text, \"text/x-vb\",callback);\n\n  if (ok) return \"Tests OK\";\n}\nfunction testTypes() {\n  var golden = [['Integer','keyword'],[' ','null'],['Float','keyword']]\n  var text =  \"Integer Float\";\n  return test(golden,text);\n}\nfunction testIf(){\n  var golden = [['If','keyword'],[' ','null'],['True','keyword'],[' ','null'],['End','keyword'],[' ','null'],['If','keyword']];\n  var text = 'If True End If';\n  return test(golden, text);\n}\nfunction testDecl(){\n   var golden = [['Dim','keyword'],[' ','null'],['x','variable'],[' ','null'],['as','keyword'],[' ','null'],['Integer','keyword']];\n   var text = 'Dim x as Integer';\n   return test(golden, text);\n}\nfunction testAll(){\n  var result = \"\";\n\n  result += testTypes() + \"\\n\";\n  result += testIf() + \"\\n\";\n  result += testDecl() + \"\\n\";\n  return result;\n\n}\nfunction initText(editor) {\n  var content = 'Class rocket\\nPrivate quality as Double\\nPublic Sub launch() as String\\nif quality > 0.8\\nlaunch = \"Successful\"\\nElse\\nlaunch = \"Failed\"\\nEnd If\\nEnd sub\\nEnd class\\n';\n  editor.setValue(content);\n  for (var i =0; i< editor.lineCount(); i++) editor.indentLine(i);\n}\nfunction init() {\n    editor = CodeMirror.fromTextArea(document.getElementById(\"solution\"), {\n        lineNumbers: true,\n        mode: \"text/x-vb\",\n        readOnly: false\n    });\n    runTest();\n}\nfunction runTest() {\n\tdocument.getElementById('testresult').innerHTML = testAll();\n  initText(editor);\n\n}\ndocument.body.onload = init;\n</script>\n\n  <div id=\"edit\">\n  <textarea style=\"width:95%;height:200px;padding:5px;\" name=\"solution\" id=\"solution\" ></textarea>\n  </div>\n  <pre id=\"testresult\"></pre>\n  <p>MIME type defined: <code>text/x-vb</code>.</p>\n\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/vb/vb.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(\"vb\", function(conf, parserConf) {\n    var ERRORCLASS = 'error';\n\n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\", \"i\");\n    }\n\n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&\\\\\\\\|\\\\^~<>!]\");\n    var singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\n    var doubleOperators = new RegExp(\"^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\\\*\\\\*))\");\n    var doubleDelimiters = new RegExp(\"^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = new RegExp(\"^((//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n    var identifiers = new RegExp(\"^[_A-Za-z][_A-Za-z0-9]*\");\n\n    var openingKeywords = ['class','module', 'sub','enum','select','while','if','function',  'get','set','property', 'try'];\n    var middleKeywords = ['else','elseif','case', 'catch'];\n    var endKeywords = ['next','loop'];\n\n    var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'in']);\n    var commonkeywords = ['as', 'dim', 'break',  'continue','optional', 'then',  'until',\n                          'goto', 'byval','byref','new','handles','property', 'return',\n                          'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false'];\n    var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single'];\n\n    var keywords = wordRegexp(commonkeywords);\n    var types = wordRegexp(commontypes);\n    var stringPrefixes = '\"';\n\n    var opening = wordRegexp(openingKeywords);\n    var middle = wordRegexp(middleKeywords);\n    var closing = wordRegexp(endKeywords);\n    var doubleClosing = wordRegexp(['end']);\n    var doOpening = wordRegexp(['do']);\n\n    var indentInfo = null;\n\n\n\n\n    function indent(_stream, state) {\n      state.currentIndent++;\n    }\n\n    function dedent(_stream, state) {\n      state.currentIndent--;\n    }\n    // tokenizers\n    function tokenBase(stream, state) {\n        if (stream.eatSpace()) {\n            return null;\n        }\n\n        var ch = stream.peek();\n\n        // Handle Comments\n        if (ch === \"'\") {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n\n        // Handle Number Literals\n        if (stream.match(/^((&H)|(&O))?[0-9\\.a-f]/i, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^\\d*\\.\\d+F?/i)) { floatLiteral = true; }\n            else if (stream.match(/^\\d+\\.\\d*F?/)) { floatLiteral = true; }\n            else if (stream.match(/^\\.\\d+F?/)) { floatLiteral = true; }\n\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(/^&H[0-9a-f]+/i)) { intLiteral = true; }\n            // Octal\n            else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }\n            // Decimal\n            else if (stream.match(/^[1-9]\\d*F?/)) {\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            else 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 null;\n        }\n        if (stream.match(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return null;\n        }\n        if (stream.match(doOpening)) {\n            indent(stream,state);\n            state.doInCurrentLine = true;\n            return 'keyword';\n        }\n        if (stream.match(opening)) {\n            if (! state.doInCurrentLine)\n              indent(stream,state);\n            else\n              state.doInCurrentLine = false;\n            return 'keyword';\n        }\n        if (stream.match(middle)) {\n            return 'keyword';\n        }\n\n        if (stream.match(doubleClosing)) {\n            dedent(stream,state);\n            dedent(stream,state);\n            return 'keyword';\n        }\n        if (stream.match(closing)) {\n            dedent(stream,state);\n            return 'keyword';\n        }\n\n        if (stream.match(types)) {\n            return 'keyword';\n        }\n\n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n\n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n\n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n\n    function tokenStringFactory(delimiter) {\n        var singleline = delimiter.length == 1;\n        var OUTCLASS = 'string';\n\n        return function(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"]/);\n                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            }\n            return OUTCLASS;\n        };\n    }\n\n\n    function tokenLexer(stream, state) {\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = state.tokenize(stream, state);\n            current = stream.current();\n            if (style === 'variable') {\n                return 'variable';\n            } else {\n                return ERRORCLASS;\n            }\n        }\n\n\n        var delimiter_index = '[({'.indexOf(current);\n        if (delimiter_index !== -1) {\n            indent(stream, state );\n        }\n        if (indentInfo === 'dedent') {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        delimiter_index = '])}'.indexOf(current);\n        if (delimiter_index !== -1) {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n\n        return style;\n    }\n\n    var external = {\n        electricChars:\"dDpPtTfFeE \",\n        startState: function() {\n            return {\n              tokenize: tokenBase,\n              lastToken: null,\n              currentIndent: 0,\n              nextLineIndent: 0,\n              doInCurrentLine: false\n\n\n          };\n        },\n\n        token: function(stream, state) {\n            if (stream.sol()) {\n              state.currentIndent += state.nextLineIndent;\n              state.nextLineIndent = 0;\n              state.doInCurrentLine = 0;\n            }\n            var style = tokenLexer(stream, state);\n\n            state.lastToken = {style:style, content: stream.current()};\n\n\n\n            return style;\n        },\n\n        indent: function(state, textAfter) {\n            var trueText = textAfter.replace(/^\\s+|\\s+$/g, '') ;\n            if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);\n            if(state.currentIndent < 0) return 0;\n            return state.currentIndent * conf.indentUnit;\n        }\n\n    };\n    return external;\n});\n\nCodeMirror.defineMIME(\"text/x-vb\", \"vb\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/vbscript/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: VBScript mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"vbscript.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">VBScript</a>\n  </ul>\n</div>\n\n<article>\n<h2>VBScript mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n' Pete Guhl\n' 03-04-2012\n'\n' Basic VBScript support for codemirror2\n\nConst ForReading = 1, ForWriting = 2, ForAppending = 8\n\nCall Sub020_PostBroadcastToUrbanAirship(strUserName, strPassword, intTransmitID, strResponse)\n\nIf Not IsNull(strResponse) AND Len(strResponse) = 0 Then\n\tboolTransmitOkYN = False\nElse\n\t' WScript.Echo \"Oh Happy Day! Oh Happy DAY!\"\n\tboolTransmitOkYN = True\nEnd If\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/vbscript</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/vbscript/vbscript.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/*\nFor extra ASP classic objects, initialize CodeMirror instance with this option:\n    isASP: true\n\nE.G.:\n    var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        isASP: true\n      });\n*/\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(\"vbscript\", function(conf, parserConf) {\n    var ERRORCLASS = 'error';\n\n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\", \"i\");\n    }\n\n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/&\\\\\\\\\\\\^<>=]\");\n    var doubleOperators = new RegExp(\"^((<>)|(<=)|(>=))\");\n    var singleDelimiters = new RegExp('^[\\\\.,]');\n    var brakets = new RegExp('^[\\\\(\\\\)]');\n    var identifiers = new RegExp(\"^[A-Za-z][_A-Za-z0-9]*\");\n\n    var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for'];\n    var middleKeywords = ['else','elseif','case'];\n    var endKeywords = ['next','loop','wend'];\n\n    var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']);\n    var commonkeywords = ['dim', 'redim', 'then',  'until', 'randomize',\n                          'byval','byref','new','property', 'exit', 'in',\n                          'const','private', 'public',\n                          'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me'];\n\n    //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx\n    var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];\n    //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx\n    var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart',\n                        'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject',\n                        'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left',\n                        'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round',\n                        'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp',\n                        'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year'];\n\n    //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx\n    var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare',\n                         'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek',\n                         'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError',\n                         'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2',\n                         'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo',\n                         'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse',\n                         'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray'];\n    //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx\n    var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp'];\n    var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count'];\n    var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit'];\n\n    var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application'];\n    var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response\n                              'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request\n                              'contents', 'staticobjects', //application\n                              'codepage', 'lcid', 'sessionid', 'timeout', //session\n                              'scripttimeout']; //server\n    var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response\n                           'binaryread', //request\n                           'remove', 'removeall', 'lock', 'unlock', //application\n                           'abandon', //session\n                           'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server\n\n    var knownWords = knownMethods.concat(knownProperties);\n\n    builtinObjsWords = builtinObjsWords.concat(builtinConsts);\n\n    if (conf.isASP){\n        builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords);\n        knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties);\n    };\n\n    var keywords = wordRegexp(commonkeywords);\n    var atoms = wordRegexp(atomWords);\n    var builtinFuncs = wordRegexp(builtinFuncsWords);\n    var builtinObjs = wordRegexp(builtinObjsWords);\n    var known = wordRegexp(knownWords);\n    var stringPrefixes = '\"';\n\n    var opening = wordRegexp(openingKeywords);\n    var middle = wordRegexp(middleKeywords);\n    var closing = wordRegexp(endKeywords);\n    var doubleClosing = wordRegexp(['end']);\n    var doOpening = wordRegexp(['do']);\n    var noIndentWords = wordRegexp(['on error resume next', 'exit']);\n    var comment = wordRegexp(['rem']);\n\n\n    function indent(_stream, state) {\n      state.currentIndent++;\n    }\n\n    function dedent(_stream, state) {\n      state.currentIndent--;\n    }\n    // tokenizers\n    function tokenBase(stream, state) {\n        if (stream.eatSpace()) {\n            return 'space';\n            //return null;\n        }\n\n        var ch = stream.peek();\n\n        // Handle Comments\n        if (ch === \"'\") {\n            stream.skipToEnd();\n            return 'comment';\n        }\n        if (stream.match(comment)){\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n\n        // Handle Number Literals\n        if (stream.match(/^((&H)|(&O))?[0-9\\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\\.]+[a-z_]/i, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^\\d*\\.\\d+/i)) { floatLiteral = true; }\n            else if (stream.match(/^\\d+\\.\\d*/)) { floatLiteral = true; }\n            else if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n\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(/^&H[0-9a-f]+/i)) { intLiteral = true; }\n            // Octal\n            else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }\n            // Decimal\n            else if (stream.match(/^[1-9]\\d*F?/)) {\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            else 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(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return null;\n        }\n\n        if (stream.match(brakets)) {\n            return \"bracket\";\n        }\n\n        if (stream.match(noIndentWords)) {\n            state.doInCurrentLine = true;\n\n            return 'keyword';\n        }\n\n        if (stream.match(doOpening)) {\n            indent(stream,state);\n            state.doInCurrentLine = true;\n\n            return 'keyword';\n        }\n        if (stream.match(opening)) {\n            if (! state.doInCurrentLine)\n              indent(stream,state);\n            else\n              state.doInCurrentLine = false;\n\n            return 'keyword';\n        }\n        if (stream.match(middle)) {\n            return 'keyword';\n        }\n\n\n        if (stream.match(doubleClosing)) {\n            dedent(stream,state);\n            dedent(stream,state);\n\n            return 'keyword';\n        }\n        if (stream.match(closing)) {\n            if (! state.doInCurrentLine)\n              dedent(stream,state);\n            else\n              state.doInCurrentLine = false;\n\n            return 'keyword';\n        }\n\n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n\n        if (stream.match(atoms)) {\n            return 'atom';\n        }\n\n        if (stream.match(known)) {\n            return 'variable-2';\n        }\n\n        if (stream.match(builtinFuncs)) {\n            return 'builtin';\n        }\n\n        if (stream.match(builtinObjs)){\n            return 'variable-2';\n        }\n\n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n\n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n\n    function tokenStringFactory(delimiter) {\n        var singleline = delimiter.length == 1;\n        var OUTCLASS = 'string';\n\n        return function(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"]/);\n                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            }\n            return OUTCLASS;\n        };\n    }\n\n\n    function tokenLexer(stream, state) {\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = state.tokenize(stream, state);\n\n            current = stream.current();\n            if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) {\n                if (style === 'builtin' || style === 'keyword') style='variable';\n                if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2';\n\n                return style;\n            } else {\n                return ERRORCLASS;\n            }\n        }\n\n        return style;\n    }\n\n    var external = {\n        electricChars:\"dDpPtTfFeE \",\n        startState: function() {\n            return {\n              tokenize: tokenBase,\n              lastToken: null,\n              currentIndent: 0,\n              nextLineIndent: 0,\n              doInCurrentLine: false,\n              ignoreKeyword: false\n\n\n          };\n        },\n\n        token: function(stream, state) {\n            if (stream.sol()) {\n              state.currentIndent += state.nextLineIndent;\n              state.nextLineIndent = 0;\n              state.doInCurrentLine = 0;\n            }\n            var style = tokenLexer(stream, state);\n\n            state.lastToken = {style:style, content: stream.current()};\n\n            if (style==='space') style=null;\n\n            return style;\n        },\n\n        indent: function(state, textAfter) {\n            var trueText = textAfter.replace(/^\\s+|\\s+$/g, '') ;\n            if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);\n            if(state.currentIndent < 0) return 0;\n            return state.currentIndent * conf.indentUnit;\n        }\n\n    };\n    return external;\n});\n\nCodeMirror.defineMIME(\"text/vbscript\", \"vbscript\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/velocity/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Velocity mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/night.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"velocity.js\"></script>\n<style>.CodeMirror {border: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Velocity</a>\n  </ul>\n</div>\n\n<article>\n<h2>Velocity mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n## Velocity Code Demo\n#*\n   based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )\n   August 2011\n*#\n\n#*\n   This is a multiline comment.\n   This is the second line\n*#\n\n#[[ hello steve\n   This has invalid syntax that would normally need \"poor man's escaping\" like:\n\n   #define()\n\n   ${blah\n]]#\n\n#include( \"disclaimer.txt\" \"opinion.txt\" )\n#include( $foo $bar )\n\n#parse( \"lecorbusier.vm\" )\n#parse( $foo )\n\n#evaluate( 'string with VTL #if(true)will be displayed#end' )\n\n#define( $hello ) Hello $who #end #set( $who = \"World!\") $hello ## displays Hello World!\n\n#foreach( $customer in $customerList )\n\n    $foreach.count $customer.Name\n\n    #if( $foo == ${bar})\n        it's true!\n        #break\n    #{else}\n        it's not!\n        #stop\n    #end\n\n    #if ($foreach.parent.hasNext)\n        $velocityCount\n    #end\n#end\n\n$someObject.getValues(\"this is a string split\n        across lines\")\n\n$someObject(\"This plus $something in the middle\").method(7567).property\n\n#macro( tablerows $color $somelist )\n    #foreach( $something in $somelist )\n        <tr><td bgcolor=$color>$something</td></tr>\n        <tr><td bgcolor=$color>$bodyContent</td></tr>\n    #end\n#end\n\n#tablerows(\"red\" [\"dadsdf\",\"dsa\"])\n#@tablerows(\"red\" [\"dadsdf\",\"dsa\"]) some body content #end\n\n   Variable reference: #set( $monkey = $bill )\n   String literal: #set( $monkey.Friend = 'monica' )\n   Property reference: #set( $monkey.Blame = $whitehouse.Leak )\n   Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )\n   Number literal: #set( $monkey.Number = 123 )\n   Range operator: #set( $monkey.Numbers = [1..3] )\n   Object list: #set( $monkey.Say = [\"Not\", $my, \"fault\"] )\n   Object map: #set( $monkey.Map = {\"banana\" : \"good\", \"roast beef\" : \"bad\"})\n\nThe RHS can also be a simple arithmetic expression, such as:\nAddition: #set( $value = $foo + 1 )\n   Subtraction: #set( $value = $bar - 1 )\n   Multiplication: #set( $value = $foo * $bar )\n   Division: #set( $value = $foo / $bar )\n   Remainder: #set( $value = $foo % $bar )\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"night\",\n        lineNumbers: true,\n        indentUnit: 4,\n        mode: \"text/velocity\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/velocity/velocity.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(\"velocity\", function() {\n    function parseWords(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\n    var keywords = parseWords(\"#end #else #break #stop #[[ #]] \" +\n                              \"#{end} #{else} #{break} #{stop}\");\n    var functions = parseWords(\"#if #elseif #foreach #set #include #parse #macro #define #evaluate \" +\n                               \"#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}\");\n    var specials = parseWords(\"$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent\");\n    var isOperatorChar = /[+\\-*&%=<>!?:\\/|]/;\n\n    function chain(stream, state, f) {\n        state.tokenize = f;\n        return f(stream, state);\n    }\n    function tokenBase(stream, state) {\n        var beforeParams = state.beforeParams;\n        state.beforeParams = false;\n        var ch = stream.next();\n        // start of unparsed string?\n        if ((ch == \"'\") && state.inParams) {\n            state.lastTokenWasBuiltin = false;\n            return chain(stream, state, tokenString(ch));\n        }\n        // start of parsed string?\n        else if ((ch == '\"')) {\n            state.lastTokenWasBuiltin = false;\n            if (state.inString) {\n                state.inString = false;\n                return \"string\";\n            }\n            else if (state.inParams)\n                return chain(stream, state, tokenString(ch));\n        }\n        // is it one of the special signs []{}().,;? Seperator?\n        else if (/[\\[\\]{}\\(\\),;\\.]/.test(ch)) {\n            if (ch == \"(\" && beforeParams)\n                state.inParams = true;\n            else if (ch == \")\") {\n                state.inParams = false;\n                state.lastTokenWasBuiltin = true;\n            }\n            return null;\n        }\n        // start of a number value?\n        else if (/\\d/.test(ch)) {\n            state.lastTokenWasBuiltin = false;\n            stream.eatWhile(/[\\w\\.]/);\n            return \"number\";\n        }\n        // multi line comment?\n        else if (ch == \"#\" && stream.eat(\"*\")) {\n            state.lastTokenWasBuiltin = false;\n            return chain(stream, state, tokenComment);\n        }\n        // unparsed content?\n        else if (ch == \"#\" && stream.match(/ *\\[ *\\[/)) {\n            state.lastTokenWasBuiltin = false;\n            return chain(stream, state, tokenUnparsed);\n        }\n        // single line comment?\n        else if (ch == \"#\" && stream.eat(\"#\")) {\n            state.lastTokenWasBuiltin = false;\n            stream.skipToEnd();\n            return \"comment\";\n        }\n        // variable?\n        else if (ch == \"$\") {\n            stream.eatWhile(/[\\w\\d\\$_\\.{}]/);\n            // is it one of the specials?\n            if (specials && specials.propertyIsEnumerable(stream.current())) {\n                return \"keyword\";\n            }\n            else {\n                state.lastTokenWasBuiltin = true;\n                state.beforeParams = true;\n                return \"builtin\";\n            }\n        }\n        // is it a operator?\n        else if (isOperatorChar.test(ch)) {\n            state.lastTokenWasBuiltin = false;\n            stream.eatWhile(isOperatorChar);\n            return \"operator\";\n        }\n        else {\n            // get the whole word\n            stream.eatWhile(/[\\w\\$_{}@]/);\n            var word = stream.current();\n            // is it one of the listed keywords?\n            if (keywords && keywords.propertyIsEnumerable(word))\n                return \"keyword\";\n            // is it one of the listed functions?\n            if (functions && functions.propertyIsEnumerable(word) ||\n                    (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()==\"(\") &&\n                     !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) {\n                state.beforeParams = true;\n                state.lastTokenWasBuiltin = false;\n                return \"keyword\";\n            }\n            if (state.inString) {\n                state.lastTokenWasBuiltin = false;\n                return \"string\";\n            }\n            if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)==\".\" && state.lastTokenWasBuiltin)\n                return \"builtin\";\n            // default: just a \"word\"\n            state.lastTokenWasBuiltin = false;\n            return null;\n        }\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) {\n                    end = true;\n                    break;\n                }\n                if (quote=='\"' && stream.peek() == '$' && !escaped) {\n                    state.inString = true;\n                    end = true;\n                    break;\n                }\n                escaped = !escaped && next == \"\\\\\";\n            }\n            if (end) state.tokenize = tokenBase;\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 = tokenBase;\n                break;\n            }\n            maybeEnd = (ch == \"*\");\n        }\n        return \"comment\";\n    }\n\n    function tokenUnparsed(stream, state) {\n        var maybeEnd = 0, ch;\n        while (ch = stream.next()) {\n            if (ch == \"#\" && maybeEnd == 2) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            if (ch == \"]\")\n                maybeEnd++;\n            else if (ch != \" \")\n                maybeEnd = 0;\n        }\n        return \"meta\";\n    }\n    // Interface\n\n    return {\n        startState: function() {\n            return {\n                tokenize: tokenBase,\n                beforeParams: false,\n                inParams: false,\n                inString: false,\n                lastTokenWasBuiltin: false\n            };\n        },\n\n        token: function(stream, state) {\n            if (stream.eatSpace()) return null;\n            return state.tokenize(stream, state);\n        },\n        blockCommentStart: \"#*\",\n        blockCommentEnd: \"*#\",\n        lineComment: \"##\",\n        fold: \"velocity\"\n    };\n});\n\nCodeMirror.defineMIME(\"text/velocity\", \"velocity\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/verilog/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Verilog/SystemVerilog mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"../../addon/edit/matchbrackets.js\"></script>\n<script src=\"verilog.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Verilog/SystemVerilog</a>\n  </ul>\n</div>\n\n<article>\n<h2>SystemVerilog mode</h2>\n\n<div><textarea id=\"code\" name=\"code\">\n// Literals\n1'b0\n1'bx\n1'bz\n16'hDC78\n'hdeadbeef\n'b0011xxzz\n1234\n32'd5678\n3.4e6\n-128.7\n\n// Macro definition\n`define BUS_WIDTH = 8;\n\n// Module definition\nmodule block(\n  input                   clk,\n  input                   rst_n,\n  input  [`BUS_WIDTH-1:0] data_in,\n  output [`BUS_WIDTH-1:0] data_out\n);\n\n  always @(posedge clk or negedge rst_n) begin\n\n    if (~rst_n) begin\n      data_out <= 8'b0;\n    end else begin\n      data_out <= data_in;\n    end\n\n    if (~rst_n)\n      data_out <= 8'b0;\n    else\n      data_out <= data_in;\n\n    if (~rst_n)\n      begin\n        data_out <= 8'b0;\n      end\n    else\n      begin\n        data_out <= data_in;\n      end\n\n  end\n\nendmodule\n\n// Class definition\nclass test;\n\n  /**\n   * Sum two integers\n   */\n  function int sum(int a, int b);\n    int result = a + b;\n    string msg = $sformatf(\"%d + %d = %d\", a, b, result);\n    $display(msg);\n    return result;\n  endfunction\n\n  task delay(int num_cycles);\n    repeat(num_cycles) #1;\n  endtask\n\nendclass\n\n</textarea></div>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n    lineNumbers: true,\n    matchBrackets: true,\n    mode: {\n      name: \"verilog\",\n      noIndentKeywords: [\"package\"]\n    }\n  });\n</script>\n\n<p>\nSyntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800).\n<h2>Configuration options:</h2>\n  <ul>\n    <li><strong>noIndentKeywords</strong> - List of keywords which should not cause identation to increase. E.g. [\"package\", \"module\"]. Default: None</li>\n  </ul>\n</p>\n\n<p><strong>MIME types defined:</strong> <code>text/x-verilog</code> and <code>text/x-systemverilog</code>.</p>\n</article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/verilog/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 4}, \"verilog\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"binary_literals\",\n     \"[number 1'b0]\",\n     \"[number 1'b1]\",\n     \"[number 1'bx]\",\n     \"[number 1'bz]\",\n     \"[number 1'bX]\",\n     \"[number 1'bZ]\",\n     \"[number 1'B0]\",\n     \"[number 1'B1]\",\n     \"[number 1'Bx]\",\n     \"[number 1'Bz]\",\n     \"[number 1'BX]\",\n     \"[number 1'BZ]\",\n     \"[number 1'b0]\",\n     \"[number 1'b1]\",\n     \"[number 2'b01]\",\n     \"[number 2'bxz]\",\n     \"[number 2'b11]\",\n     \"[number 2'b10]\",\n     \"[number 2'b1Z]\",\n     \"[number 12'b0101_0101_0101]\",\n     \"[number 1'b 0]\",\n     \"[number 'b0101]\"\n  );\n\n  MT(\"octal_literals\",\n     \"[number 3'o7]\",\n     \"[number 3'O7]\",\n     \"[number 3'so7]\",\n     \"[number 3'SO7]\"\n  );\n\n  MT(\"decimal_literals\",\n     \"[number 0]\",\n     \"[number 1]\",\n     \"[number 7]\",\n     \"[number 123_456]\",\n     \"[number 'd33]\",\n     \"[number 8'd255]\",\n     \"[number 8'D255]\",\n     \"[number 8'sd255]\",\n     \"[number 8'SD255]\",\n     \"[number 32'd123]\",\n     \"[number 32 'd123]\",\n     \"[number 32 'd 123]\"\n  );\n\n  MT(\"hex_literals\",\n     \"[number 4'h0]\",\n     \"[number 4'ha]\",\n     \"[number 4'hF]\",\n     \"[number 4'hx]\",\n     \"[number 4'hz]\",\n     \"[number 4'hX]\",\n     \"[number 4'hZ]\",\n     \"[number 32'hdc78]\",\n     \"[number 32'hDC78]\",\n     \"[number 32 'hDC78]\",\n     \"[number 32'h DC78]\",\n     \"[number 32 'h DC78]\",\n     \"[number 32'h44x7]\",\n     \"[number 32'hFFF?]\"\n  );\n\n  MT(\"real_number_literals\",\n     \"[number 1.2]\",\n     \"[number 0.1]\",\n     \"[number 2394.26331]\",\n     \"[number 1.2E12]\",\n     \"[number 1.2e12]\",\n     \"[number 1.30e-2]\",\n     \"[number 0.1e-0]\",\n     \"[number 23E10]\",\n     \"[number 29E-2]\",\n     \"[number 236.123_763_e-12]\"\n  );\n\n  MT(\"operators\",\n     \"[meta ^]\"\n  );\n\n  MT(\"keywords\",\n     \"[keyword logic]\",\n     \"[keyword logic] [variable foo]\",\n     \"[keyword reg] [variable abc]\"\n  );\n\n  MT(\"variables\",\n     \"[variable _leading_underscore]\",\n     \"[variable _if]\",\n     \"[number 12] [variable foo]\",\n     \"[variable foo] [number 14]\"\n  );\n\n  MT(\"tick_defines\",\n     \"[def `FOO]\",\n     \"[def `foo]\",\n     \"[def `FOO_bar]\"\n  );\n\n  MT(\"system_calls\",\n     \"[meta $display]\",\n     \"[meta $vpi_printf]\"\n  );\n\n  MT(\"line_comment\", \"[comment // Hello world]\");\n\n  // Alignment tests\n  MT(\"align_port_map_style1\",\n     /**\n      * mod mod(.a(a),\n      *         .b(b)\n      *        );\n      */\n     \"[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],\",\n     \"        .[variable b][bracket (][variable b][bracket )]\",\n     \"       [bracket )];\",\n     \"\"\n  );\n\n  MT(\"align_port_map_style2\",\n     /**\n      * mod mod(\n      *     .a(a),\n      *     .b(b)\n      * );\n      */\n     \"[variable mod] [variable mod][bracket (]\",\n     \"    .[variable a][bracket (][variable a][bracket )],\",\n     \"    .[variable b][bracket (][variable b][bracket )]\",\n     \"[bracket )];\",\n     \"\"\n  );\n\n  // Indentation tests\n  MT(\"indent_single_statement_if\",\n      \"[keyword if] [bracket (][variable foo][bracket )]\",\n      \"    [keyword break];\",\n      \"\"\n  );\n\n  MT(\"no_indent_after_single_line_if\",\n      \"[keyword if] [bracket (][variable foo][bracket )] [keyword break];\",\n      \"\"\n  );\n\n  MT(\"indent_after_if_begin_same_line\",\n      \"[keyword if] [bracket (][variable foo][bracket )] [keyword begin]\",\n      \"    [keyword break];\",\n      \"    [keyword break];\",\n      \"[keyword end]\",\n      \"\"\n  );\n\n  MT(\"indent_after_if_begin_next_line\",\n      \"[keyword if] [bracket (][variable foo][bracket )]\",\n      \"    [keyword begin]\",\n      \"        [keyword break];\",\n      \"        [keyword break];\",\n      \"    [keyword end]\",\n      \"\"\n  );\n\n  MT(\"indent_single_statement_if_else\",\n      \"[keyword if] [bracket (][variable foo][bracket )]\",\n      \"    [keyword break];\",\n      \"[keyword else]\",\n      \"    [keyword break];\",\n      \"\"\n  );\n\n  MT(\"indent_if_else_begin_same_line\",\n      \"[keyword if] [bracket (][variable foo][bracket )] [keyword begin]\",\n      \"    [keyword break];\",\n      \"    [keyword break];\",\n      \"[keyword end] [keyword else] [keyword begin]\",\n      \"    [keyword break];\",\n      \"    [keyword break];\",\n      \"[keyword end]\",\n      \"\"\n  );\n\n  MT(\"indent_if_else_begin_next_line\",\n      \"[keyword if] [bracket (][variable foo][bracket )]\",\n      \"    [keyword begin]\",\n      \"        [keyword break];\",\n      \"        [keyword break];\",\n      \"    [keyword end]\",\n      \"[keyword else]\",\n      \"    [keyword begin]\",\n      \"        [keyword break];\",\n      \"        [keyword break];\",\n      \"    [keyword end]\",\n      \"\"\n  );\n\n  MT(\"indent_if_nested_without_begin\",\n      \"[keyword if] [bracket (][variable foo][bracket )]\",\n      \"    [keyword if] [bracket (][variable foo][bracket )]\",\n      \"        [keyword if] [bracket (][variable foo][bracket )]\",\n      \"            [keyword break];\",\n      \"\"\n  );\n\n  MT(\"indent_case\",\n      \"[keyword case] [bracket (][variable state][bracket )]\",\n      \"    [variable FOO]:\",\n      \"        [keyword break];\",\n      \"    [variable BAR]:\",\n      \"        [keyword break];\",\n      \"[keyword endcase]\",\n      \"\"\n  );\n\n  MT(\"unindent_after_end_with_preceding_text\",\n      \"[keyword begin]\",\n      \"    [keyword break]; [keyword end]\",\n      \"\"\n  );\n\n  MT(\"export_function_one_line_does_not_indent\",\n     \"[keyword export] [string \\\"DPI-C\\\"] [keyword function] [variable helloFromSV];\",\n     \"\"\n  );\n\n  MT(\"export_task_one_line_does_not_indent\",\n     \"[keyword export] [string \\\"DPI-C\\\"] [keyword task] [variable helloFromSV];\",\n     \"\"\n  );\n\n  MT(\"export_function_two_lines_indents_properly\",\n    \"[keyword export]\",\n    \"    [string \\\"DPI-C\\\"] [keyword function] [variable helloFromSV];\",\n    \"\"\n  );\n\n  MT(\"export_task_two_lines_indents_properly\",\n    \"[keyword export]\",\n    \"    [string \\\"DPI-C\\\"] [keyword task] [variable helloFromSV];\",\n    \"\"\n  );\n\n  MT(\"import_function_one_line_does_not_indent\",\n    \"[keyword import] [string \\\"DPI-C\\\"] [keyword function] [variable helloFromC];\",\n    \"\"\n  );\n\n  MT(\"import_task_one_line_does_not_indent\",\n    \"[keyword import] [string \\\"DPI-C\\\"] [keyword task] [variable helloFromC];\",\n    \"\"\n  );\n\n  MT(\"import_package_single_line_does_not_indent\",\n    \"[keyword import] [variable p]::[variable x];\",\n    \"[keyword import] [variable p]::[variable y];\",\n    \"\"\n  );\n\n  MT(\"covergoup_with_function_indents_properly\",\n    \"[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];\",\n    \"    [variable c] : [keyword coverpoint] [variable c];\",\n    \"[keyword endgroup]: [variable cg]\",\n    \"\"\n  );\n\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/verilog/verilog.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(\"verilog\", function(config, parserConfig) {\n\n  var indentUnit = config.indentUnit,\n      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n      dontAlignCalls = parserConfig.dontAlignCalls,\n      noIndentKeywords = parserConfig.noIndentKeywords || [],\n      multiLineStrings = parserConfig.multiLineStrings;\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\n  /**\n   * Keywords from IEEE 1800-2012\n   */\n  var keywords = words(\n    \"accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind \" +\n    \"bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config \" +\n    \"const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable \" +\n    \"dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup \" +\n    \"endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask \" +\n    \"enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin \" +\n    \"function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import \" +\n    \"incdir include initial inout input inside instance int integer interconnect interface intersect join join_any \" +\n    \"join_none large let liblist library local localparam logic longint macromodule matches medium modport module \" +\n    \"nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed \" +\n    \"parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup \" +\n    \"pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg \" +\n    \"reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime \" +\n    \"s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify \" +\n    \"specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on \" +\n    \"table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior \" +\n    \"trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void \" +\n    \"wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor\");\n\n  /** Operators from IEEE 1800-2012\n     unary_operator ::=\n       + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~\n     binary_operator ::=\n       + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **\n       | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<\n       | -> | <->\n     inc_or_dec_operator ::= ++ | --\n     unary_module_path_operator ::=\n       ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~\n     binary_module_path_operator ::=\n       == | != | && | || | & | | | ^ | ^~ | ~^\n  */\n  var isOperatorChar = /[\\+\\-\\*\\/!~&|^%=?:]/;\n  var isBracketChar = /[\\[\\]{}()]/;\n\n  var unsignedNumber = /\\d[0-9_]*/;\n  var decimalLiteral = /\\d*\\s*'s?d\\s*\\d[0-9_]*/i;\n  var binaryLiteral = /\\d*\\s*'s?b\\s*[xz01][xz01_]*/i;\n  var octLiteral = /\\d*\\s*'s?o\\s*[xz0-7][xz0-7_]*/i;\n  var hexLiteral = /\\d*\\s*'s?h\\s*[0-9a-fxz?][0-9a-fxz?_]*/i;\n  var realLiteral = /(\\d[\\d_]*(\\.\\d[\\d_]*)?E-?[\\d_]+)|(\\d[\\d_]*\\.\\d[\\d_]*)/i;\n\n  var closingBracketOrWord = /^((\\w+)|[)}\\]])/;\n  var closingBracket = /[)}\\]]/;\n\n  var curPunc;\n  var curKeyword;\n\n  // Block openings which are closed by a matching keyword in the form of (\"end\" + keyword)\n  // E.g. \"task\" => \"endtask\"\n  var blockKeywords = words(\n    \"case checker class clocking config function generate interface module package\" +\n    \"primitive program property specify sequence table task\"\n  );\n\n  // Opening/closing pairs\n  var openClose = {};\n  for (var keyword in blockKeywords) {\n    openClose[keyword] = \"end\" + keyword;\n  }\n  openClose[\"begin\"] = \"end\";\n  openClose[\"casex\"] = \"endcase\";\n  openClose[\"casez\"] = \"endcase\";\n  openClose[\"do\"   ] = \"while\";\n  openClose[\"fork\" ] = \"join;join_any;join_none\";\n  openClose[\"covergroup\"] = \"endgroup\";\n\n  for (var i in noIndentKeywords) {\n    var keyword = noIndentKeywords[i];\n    if (openClose[keyword]) {\n      openClose[keyword] = undefined;\n    }\n  }\n\n  // Keywords which open statements that are ended with a semi-colon\n  var statementKeywords = words(\"always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while\");\n\n  function tokenBase(stream, state) {\n    var ch = stream.peek();\n    if (/[,;:\\.]/.test(ch)) {\n      curPunc = stream.next();\n      return null;\n    }\n    if (isBracketChar.test(ch)) {\n      curPunc = stream.next();\n      return \"bracket\";\n    }\n    // Macros (tick-defines)\n    if (ch == '`') {\n      stream.next();\n      if (stream.eatWhile(/[\\w\\$_]/)) {\n        return \"def\";\n      } else {\n        return null;\n      }\n    }\n    // System calls\n    if (ch == '$') {\n      stream.next();\n      if (stream.eatWhile(/[\\w\\$_]/)) {\n        return \"meta\";\n      } else {\n        return null;\n      }\n    }\n    // Time literals\n    if (ch == '#') {\n      stream.next();\n      stream.eatWhile(/[\\d_.]/);\n      return \"def\";\n    }\n    // Strings\n    if (ch == '\"') {\n      stream.next();\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    // Comments\n    if (ch == \"/\") {\n      stream.next();\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      stream.backUp(1);\n    }\n\n    // Numeric literals\n    if (stream.match(realLiteral) ||\n        stream.match(decimalLiteral) ||\n        stream.match(binaryLiteral) ||\n        stream.match(octLiteral) ||\n        stream.match(hexLiteral) ||\n        stream.match(unsignedNumber) ||\n        stream.match(realLiteral)) {\n      return \"number\";\n    }\n\n    // Operators\n    if (stream.eatWhile(isOperatorChar)) {\n      return \"meta\";\n    }\n\n    // Keywords / plain variables\n    if (stream.eatWhile(/[\\w\\$_]/)) {\n      var cur = stream.current();\n      if (keywords[cur]) {\n        if (openClose[cur]) {\n          curPunc = \"newblock\";\n        }\n        if (statementKeywords[cur]) {\n          curPunc = \"newstatement\";\n        }\n        curKeyword = cur;\n        return \"keyword\";\n      }\n      return \"variable\";\n    }\n\n    stream.next();\n    return null;\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 = tokenBase;\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 = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function 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  }\n  function pushContext(state, col, type) {\n    var indent = state.indented;\n    var c = new Context(indent, col, type, null, state.context);\n    return state.context = c;\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\") {\n      state.indented = state.context.indented;\n    }\n    return state.context = state.context.prev;\n  }\n\n  function isClosing(text, contextClosing) {\n    if (text == contextClosing) {\n      return true;\n    } else {\n      // contextClosing may be mulitple keywords separated by ;\n      var closingKeywords = contextClosing.split(\";\");\n      for (var i in closingKeywords) {\n        if (text == closingKeywords[i]) {\n          return true;\n        }\n      }\n      return false;\n    }\n  }\n\n  function buildElectricInputRegEx() {\n    // Reindentation should occur on any bracket char: {}()[]\n    // or on a match of any of the block closing keywords, at\n    // the end of a line\n    var allClosings = [];\n    for (var i in openClose) {\n      if (openClose[i]) {\n        var closings = openClose[i].split(\";\");\n        for (var j in closings) {\n          allClosings.push(closings[j]);\n        }\n      }\n    }\n    var re = new RegExp(\"[{}()\\\\[\\\\]]|(\" + allClosings.join(\"|\") + \")$\");\n    return re;\n  }\n\n  // Interface\n  return {\n\n    // Regex to force current line to reindent\n    electricInput: buildElectricInputRegEx(),\n\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      };\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 = null;\n      curKeyword = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\" || style == \"variable\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if (curPunc == ctx.type) {\n        popContext(state);\n      }\n      else if ((curPunc == \";\" && ctx.type == \"statement\") ||\n               (ctx.type && isClosing(curKeyword, ctx.type))) {\n        ctx = popContext(state);\n        while (ctx && ctx.type == \"statement\") ctx = popContext(state);\n      }\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 (ctx && ctx.type == \"endcase\" && curPunc == \":\") { pushContext(state, stream.column(), \"statement\"); }\n      else if (curPunc == \"newstatement\") {\n        pushContext(state, stream.column(), \"statement\");\n      } else if (curPunc == \"newblock\") {\n        if (curKeyword == \"function\" && ctx && (ctx.type == \"statement\" || ctx.type == \"endgroup\")) {\n          // The 'function' keyword can appear in some other contexts where it actually does not\n          // indicate a function (import/export DPI and covergroup definitions).\n          // Do nothing in this case\n        } else if (curKeyword == \"task\" && ctx && ctx.type == \"statement\") {\n          // Same thing for task\n        } else {\n          var close = openClose[curKeyword];\n          pushContext(state, stream.column(), close);\n        }\n      }\n\n      state.startOfLine = false;\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 (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = false;\n      var possibleClosing = textAfter.match(closingBracketOrWord);\n      if (possibleClosing) {\n        closing = isClosing(possibleClosing[0], ctx.type);\n      }\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit);\n      else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);\n      else if (ctx.type == \")\" && !closing) return ctx.indented + statementIndentUnit;\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-verilog\", {\n  name: \"verilog\"\n});\nCodeMirror.defineMIME(\"text/x-systemverilog\", {\n  name: \"systemverilog\"\n});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xml/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: XML mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"xml.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">XML</a>\n  </ul>\n</div>\n\n<article>\n<h2>XML mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n&lt;html style=\"color: green\"&gt;\n  &lt;!-- this is a comment --&gt;\n  &lt;head&gt;\n    &lt;title&gt;HTML Example&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what\n    I mean&amp;quot;&lt;/em&gt;... but might not match your style.\n  &lt;/body&gt;\n&lt;/html&gt;\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/html\",\n        lineNumbers: true\n      });\n    </script>\n    <p>The XML mode supports two configuration parameters:</p>\n    <dl>\n      <dt><code>htmlMode (boolean)</code></dt>\n      <dd>This switches the mode to parse HTML instead of XML. This\n      means attributes do not have to be quoted, and some elements\n      (such as <code>br</code>) do not require a closing tag.</dd>\n      <dt><code>alignCDATA (boolean)</code></dt>\n      <dd>Setting this to true will force the opening tag of CDATA\n      blocks to not be indented.</dd>\n    </dl>\n\n    <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xml/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function() {\n  var mode = CodeMirror.getMode({indentUnit: 2}, \"xml\"), mname = \"xml\";\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }\n\n  MT(\"matching\",\n     \"[tag&bracket <][tag top][tag&bracket >]\",\n     \"  text\",\n     \"  [tag&bracket <][tag inner][tag&bracket />]\",\n     \"[tag&bracket </][tag top][tag&bracket >]\");\n\n  MT(\"nonmatching\",\n     \"[tag&bracket <][tag top][tag&bracket >]\",\n     \"  [tag&bracket <][tag inner][tag&bracket />]\",\n     \"  [tag&bracket </][tag&error tip][tag&bracket&error >]\");\n\n  MT(\"doctype\",\n     \"[meta <!doctype foobar>]\",\n     \"[tag&bracket <][tag top][tag&bracket />]\");\n\n  MT(\"cdata\",\n     \"[tag&bracket <][tag top][tag&bracket >]\",\n     \"  [atom <![CDATA[foo]\",\n     \"[atom barbazguh]]]]>]\",\n     \"[tag&bracket </][tag top][tag&bracket >]\");\n\n  // HTML tests\n  mode = CodeMirror.getMode({indentUnit: 2}, \"text/html\");\n\n  MT(\"selfclose\",\n     \"[tag&bracket <][tag html][tag&bracket >]\",\n     \"  [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \\\"/foobar\\\"][tag&bracket >]\",\n     \"[tag&bracket </][tag html][tag&bracket >]\");\n\n  MT(\"list\",\n     \"[tag&bracket <][tag ol][tag&bracket >]\",\n     \"  [tag&bracket <][tag li][tag&bracket >]one\",\n     \"  [tag&bracket <][tag li][tag&bracket >]two\",\n     \"[tag&bracket </][tag ol][tag&bracket >]\");\n\n  MT(\"valueless\",\n     \"[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]\");\n\n  MT(\"pThenArticle\",\n     \"[tag&bracket <][tag p][tag&bracket >]\",\n     \"  foo\",\n     \"[tag&bracket <][tag article][tag&bracket >]bar\");\n\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xml/xml.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(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;\n  var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;\n  if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;\n\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,\n                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,\n                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,\n                      'track': true, 'wbr': true, 'menuitem': true},\n    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,\n                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,\n                       'th': true, 'tr': true},\n    contextGrabbers: {\n      'dd': {'dd': true, 'dt': true},\n      'dt': {'dd': true, 'dt': true},\n      'li': {'li': true},\n      'option': {'option': true, 'optgroup': true},\n      'optgroup': {'optgroup': true},\n      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,\n            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,\n            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,\n            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,\n            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},\n      'rp': {'rp': true, 'rt': true},\n      'rt': {'rp': true, 'rt': true},\n      'tbody': {'tbody': true, 'tfoot': true},\n      'td': {'td': true, 'th': true},\n      'tfoot': {'tbody': true},\n      'th': {'td': true, 'th': true},\n      'thead': {'tbody': true, 'tfoot': true},\n      'tr': {'tr': true}\n    },\n    doNotIndent: {\"pre\": true},\n    allowUnquoted: true,\n    allowMissing: true,\n    caseFold: true\n  } : {\n    autoSelfClosers: {},\n    implicitlyClosed: {},\n    contextGrabbers: {},\n    doNotIndent: {},\n    allowUnquoted: false,\n    allowMissing: false,\n    caseFold: false\n  };\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var type, setStyle;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        } else if (stream.match(\"--\")) {\n          return chain(inBlock(\"comment\", \"-->\"));\n        } else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(doctype(1));\n        } else {\n          return null;\n        }\n      } else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      } else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        state.tokenize = inTag;\n        return \"tag bracket\";\n      }\n    } else if (ch == \"&\") {\n      var ok;\n      if (stream.eat(\"#\")) {\n        if (stream.eat(\"x\")) {\n          ok = stream.eatWhile(/[a-fA-F\\d]/) && stream.eat(\";\");\n        } else {\n          ok = stream.eatWhile(/[\\d]/) && stream.eat(\";\");\n        }\n      } else {\n        ok = stream.eatWhile(/[\\w\\.\\-:]/) && stream.eat(\";\");\n      }\n      return ok ? \"atom\" : \"error\";\n    } else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag bracket\";\n    } else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    } else if (ch == \"<\") {\n      state.tokenize = inText;\n      state.state = baseState;\n      state.tagName = state.tagStart = null;\n      var next = state.tokenize(stream, state);\n      return next ? next + \" tag error\" : \"tag error\";\n    } else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      state.stringStartCol = stream.column();\n      return state.tokenize(stream, state);\n    } else {\n      stream.match(/^[^\\s\\u00a0=<>\\\"\\']*[^\\s\\u00a0=<>\\\"\\'\\/]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    var closure = function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n    closure.isInAttribute = true;\n    return closure;\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n  function doctype(depth) {\n    return function(stream, state) {\n      var ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == \"<\") {\n          state.tokenize = doctype(depth + 1);\n          return state.tokenize(stream, state);\n        } else if (ch == \">\") {\n          if (depth == 1) {\n            state.tokenize = inText;\n            break;\n          } else {\n            state.tokenize = doctype(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n      }\n      return \"meta\";\n    };\n  }\n\n  function Context(state, tagName, startOfLine) {\n    this.prev = state.context;\n    this.tagName = tagName;\n    this.indent = state.indented;\n    this.startOfLine = startOfLine;\n    if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))\n      this.noIndent = true;\n  }\n  function popContext(state) {\n    if (state.context) state.context = state.context.prev;\n  }\n  function maybePopContext(state, nextTagName) {\n    var parentTagName;\n    while (true) {\n      if (!state.context) {\n        return;\n      }\n      parentTagName = state.context.tagName;\n      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n        return;\n      }\n      popContext(state);\n    }\n  }\n\n  function baseState(type, stream, state) {\n    if (type == \"openTag\") {\n      state.tagStart = stream.column();\n      return tagNameState;\n    } else if (type == \"closeTag\") {\n      return closeTagNameState;\n    } else {\n      return baseState;\n    }\n  }\n  function tagNameState(type, stream, state) {\n    if (type == \"word\") {\n      state.tagName = stream.current();\n      setStyle = \"tag\";\n      return attrState;\n    } else {\n      setStyle = \"error\";\n      return tagNameState;\n    }\n  }\n  function closeTagNameState(type, stream, state) {\n    if (type == \"word\") {\n      var tagName = stream.current();\n      if (state.context && state.context.tagName != tagName &&\n          Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))\n        popContext(state);\n      if (state.context && state.context.tagName == tagName) {\n        setStyle = \"tag\";\n        return closeState;\n      } else {\n        setStyle = \"tag error\";\n        return closeStateErr;\n      }\n    } else {\n      setStyle = \"error\";\n      return closeStateErr;\n    }\n  }\n\n  function closeState(type, _stream, state) {\n    if (type != \"endTag\") {\n      setStyle = \"error\";\n      return closeState;\n    }\n    popContext(state);\n    return baseState;\n  }\n  function closeStateErr(type, stream, state) {\n    setStyle = \"error\";\n    return closeState(type, stream, state);\n  }\n\n  function attrState(type, _stream, state) {\n    if (type == \"word\") {\n      setStyle = \"attribute\";\n      return attrEqState;\n    } else if (type == \"endTag\" || type == \"selfcloseTag\") {\n      var tagName = state.tagName, tagStart = state.tagStart;\n      state.tagName = state.tagStart = null;\n      if (type == \"selfcloseTag\" ||\n          Kludges.autoSelfClosers.hasOwnProperty(tagName)) {\n        maybePopContext(state, tagName);\n      } else {\n        maybePopContext(state, tagName);\n        state.context = new Context(state, tagName, tagStart == state.indented);\n      }\n      return baseState;\n    }\n    setStyle = \"error\";\n    return attrState;\n  }\n  function attrEqState(type, stream, state) {\n    if (type == \"equals\") return attrValueState;\n    if (!Kludges.allowMissing) setStyle = \"error\";\n    return attrState(type, stream, state);\n  }\n  function attrValueState(type, stream, state) {\n    if (type == \"string\") return attrContinuedState;\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return attrState;}\n    setStyle = \"error\";\n    return attrState(type, stream, state);\n  }\n  function attrContinuedState(type, stream, state) {\n    if (type == \"string\") return attrContinuedState;\n    return attrState(type, stream, state);\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText,\n              state: baseState,\n              indented: 0,\n              tagName: null, tagStart: null,\n              context: null};\n    },\n\n    token: function(stream, state) {\n      if (!state.tagName && stream.sol())\n        state.indented = stream.indentation();\n\n      if (stream.eatSpace()) return null;\n      type = null;\n      var style = state.tokenize(stream, state);\n      if ((style || type) && style != \"comment\") {\n        setStyle = null;\n        state.state = state.state(type || style, stream, state);\n        if (setStyle)\n          style = setStyle == \"error\" ? style + \" error\" : setStyle;\n      }\n      return style;\n    },\n\n    indent: function(state, textAfter, fullLine) {\n      var context = state.context;\n      // Indent multi-line strings (e.g. css).\n      if (state.tokenize.isInAttribute) {\n        if (state.tagStart == state.indented)\n          return state.stringStartCol + 1;\n        else\n          return state.indented + indentUnit;\n      }\n      if (context && context.noIndent) return CodeMirror.Pass;\n      if (state.tokenize != inTag && state.tokenize != inText)\n        return fullLine ? fullLine.match(/^(\\s*)/)[0].length : 0;\n      // Indent the starts of attribute names.\n      if (state.tagName) {\n        if (multilineTagIndentPastTag)\n          return state.tagStart + state.tagName.length + 2;\n        else\n          return state.tagStart + indentUnit * multilineTagIndentFactor;\n      }\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      var tagAfter = textAfter && /^<(\\/)?([\\w_:\\.-]*)/.exec(textAfter);\n      if (tagAfter && tagAfter[1]) { // Closing tag spotted\n        while (context) {\n          if (context.tagName == tagAfter[2]) {\n            context = context.prev;\n            break;\n          } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {\n            context = context.prev;\n          } else {\n            break;\n          }\n        }\n      } else if (tagAfter) { // Opening tag spotted\n        while (context) {\n          var grabbers = Kludges.contextGrabbers[context.tagName];\n          if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))\n            context = context.prev;\n          else\n            break;\n        }\n      }\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    electricInput: /<\\/[\\s\\w:]+>$/,\n    blockCommentStart: \"<!--\",\n    blockCommentEnd: \"-->\",\n\n    configuration: parserConfig.htmlMode ? \"html\" : \"xml\",\n    helperType: parserConfig.htmlMode ? \"html\" : \"xml\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/xml\", \"xml\");\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/html\"))\n  CodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xquery/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: XQuery mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"../../theme/xq-dark.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"xquery.js\"></script>\n<style type=\"text/css\">\n\t.CodeMirror {\n\t  border-top: 1px solid black; border-bottom: 1px solid black;\n\t  height:400px;\n\t}\n    </style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">XQuery</a>\n  </ul>\n</div>\n\n<article>\n<h2>XQuery mode</h2>\n\n\n<div class=\"cm-s-default\">\n\t<textarea id=\"code\" name=\"code\">\nxquery version &quot;1.0-ml&quot;;\n(: this is\n : a\n   \"comment\" :)\nlet $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;\nlet $joe:=1\nreturn element element {\n\tattribute attribute { 1 },\n\telement test { &#39;a&#39; },\n\tattribute foo { &quot;bar&quot; },\n\tfn:doc()[ foo/@bar eq $let ],\n\t//x }\n\n(: a more 'evil' test :)\n(: Modified Blakeley example (: with nested comment :) ... :)\ndeclare private function local:declare() {()};\ndeclare private function local:private() {()};\ndeclare private function local:function() {()};\ndeclare private function local:local() {()};\nlet $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;\nreturn element element {\n\tattribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\n\tattribute fn:doc { &quot;bar&quot; castable as xs:string },\n\telement text { text { &quot;text&quot; } },\n\tfn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\n\t//fn:doc\n}\n\n\n\nxquery version &quot;1.0-ml&quot;;\n\n(: Copyright 2006-2010 Mark Logic Corporation. :)\n\n(:\n : Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\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 &quot;AS IS&quot; 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\nmodule namespace json = &quot;http://marklogic.com/json&quot;;\ndeclare default function namespace &quot;http://www.w3.org/2005/xpath-functions&quot;;\n\n(: Need to backslash escape any double quotes, backslashes, and newlines :)\ndeclare function json:escape($s as xs:string) as xs:string {\n  let $s := replace($s, &quot;\\\\&quot;, &quot;\\\\\\\\&quot;)\n  let $s := replace($s, &quot;&quot;&quot;&quot;, &quot;\\\\&quot;&quot;&quot;)\n  let $s := replace($s, codepoints-to-string((13, 10)), &quot;\\\\n&quot;)\n  let $s := replace($s, codepoints-to-string(13), &quot;\\\\n&quot;)\n  let $s := replace($s, codepoints-to-string(10), &quot;\\\\n&quot;)\n  return $s\n};\n\ndeclare function json:atomize($x as element()) as xs:string {\n  if (count($x/node()) = 0) then 'null'\n  else if ($x/@type = &quot;number&quot;) then\n    let $castable := $x castable as xs:float or\n                     $x castable as xs:double or\n                     $x castable as xs:decimal\n    return\n    if ($castable) then xs:string($x)\n    else error(concat(&quot;Not a number: &quot;, xdmp:describe($x)))\n  else if ($x/@type = &quot;boolean&quot;) then\n    let $castable := $x castable as xs:boolean\n    return\n    if ($castable) then xs:string(xs:boolean($x))\n    else error(concat(&quot;Not a boolean: &quot;, xdmp:describe($x)))\n  else concat('&quot;', json:escape($x), '&quot;')\n};\n\n(: Print the thing that comes after the colon :)\ndeclare function json:print-value($x as element()) as xs:string {\n  if (count($x/*) = 0) then\n    json:atomize($x)\n  else if ($x/@quote = &quot;true&quot;) then\n    concat('&quot;', json:escape(xdmp:quote($x/node())), '&quot;')\n  else\n    string-join(('{',\n      string-join(for $i in $x/* return json:print-name-value($i), &quot;,&quot;),\n    '}'), &quot;&quot;)\n};\n\n(: Print the name and value both :)\ndeclare function json:print-name-value($x as element()) as xs:string? {\n  let $name := name($x)\n  let $first-in-array :=\n    count($x/preceding-sibling::*[name(.) = $name]) = 0 and\n    (count($x/following-sibling::*[name(.) = $name]) &gt; 0 or $x/@array = &quot;true&quot;)\n  let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) &gt; 0\n  return\n\n  if ($later-in-array) then\n    ()  (: I was handled previously :)\n  else if ($first-in-array) then\n    string-join(('&quot;', json:escape($name), '&quot;:[',\n      string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), &quot;,&quot;),\n    ']'), &quot;&quot;)\n   else\n     string-join(('&quot;', json:escape($name), '&quot;:', json:print-value($x)), &quot;&quot;)\n};\n\n(:~\n  Transforms an XML element into a JSON string representation.  See http://json.org.\n  &lt;p/&gt;\n  Sample usage:\n  &lt;pre&gt;\n    xquery version &quot;1.0-ml&quot;;\n    import module namespace json=&quot;http://marklogic.com/json&quot; at &quot;json.xqy&quot;;\n    json:serialize(&amp;lt;foo&amp;gt;&amp;lt;bar&amp;gt;kid&amp;lt;/bar&amp;gt;&amp;lt;/foo&amp;gt;)\n  &lt;/pre&gt;\n  Sample transformations:\n  &lt;pre&gt;\n  &amp;lt;e/&amp;gt; becomes {&quot;e&quot;:null}\n  &amp;lt;e&amp;gt;text&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;text&quot;}\n  &amp;lt;e&amp;gt;quote &quot; escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;quote \\&quot; escaping&quot;}\n  &amp;lt;e&amp;gt;backslash \\ escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;backslash \\\\ escaping&quot;}\n  &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;text2&amp;lt;/b&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:&quot;text1&quot;,&quot;b&quot;:&quot;text2&quot;}}\n  &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;a&amp;gt;text2&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;,&quot;text2&quot;]}}\n  &amp;lt;e&amp;gt;&amp;lt;a array=&quot;true&quot;&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;]}}\n  &amp;lt;e&amp;gt;&amp;lt;a type=&quot;boolean&quot;&amp;gt;false&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:false}}\n  &amp;lt;e&amp;gt;&amp;lt;a type=&quot;number&quot;&amp;gt;123.5&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:123.5}}\n  &amp;lt;e quote=&quot;true&quot;&amp;gt;&amp;lt;div attrib=&quot;value&quot;/&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;&amp;lt;div attrib=\\&quot;value\\&quot;/&amp;gt;&quot;}\n  &lt;/pre&gt;\n  &lt;p/&gt;\n  Namespace URIs are ignored.  Namespace prefixes are included in the JSON name.\n  &lt;p/&gt;\n  Attributes are ignored, except for the special attribute @array=&quot;true&quot; that\n  indicates the JSON serialization should write the node, even if single, as an\n  array, and the attribute @type that can be set to &quot;boolean&quot; or &quot;number&quot; to\n  dictate the value should be written as that type (unquoted).  There's also\n  an @quote attribute that when set to true writes the inner content as text\n  rather than as structured JSON, useful for sending some XHTML over the\n  wire.\n  &lt;p/&gt;\n  Text nodes within mixed content are ignored.\n\n  @param $x Element node to convert\n  @return String holding JSON serialized representation of $x\n\n  @author 郑保乐\n  @version 1.0.1\n\n  Ported to xquery 1.0-ml; double escaped backslashes in json:escape\n:)\ndeclare function json:serialize($x as element())  as xs:string {\n  string-join(('{', json:print-name-value($x), '}'), &quot;&quot;)\n};\n  </textarea>\n</div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"xq-dark\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p>\n\n    <p>Development of the CodeMirror XQuery mode was sponsored by\n      <a href=\"http://marklogic.com\">MarkLogic</a> and developed by\n      <a href=\"https://twitter.com/mbrevoort\">Mike Brevoort</a>.\n    </p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xquery/test.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// Don't take these too seriously -- the expected results appear to be\n// based on the results of actual runs without any serious manual\n// verification. If a change you made causes them to fail, the test is\n// as likely to wrong as the code.\n\n(function() {\n  var mode = CodeMirror.getMode({tabSize: 4}, \"xquery\");\n  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n\n  MT(\"eviltest\",\n     \"[keyword xquery] [keyword version] [variable &quot;1][keyword .][atom 0][keyword -][variable ml&quot;][def&variable ;]      [comment (: this is       : a          \\\"comment\\\" :)]\",\n     \"      [keyword let] [variable $let] [keyword :=] [variable &lt;x] [variable attr][keyword =][variable &quot;value&quot;&gt;&quot;test&quot;&lt;func&gt][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable &lt;][keyword /][variable func&gt;&lt;][keyword /][variable x&gt;]\",\n     \"      [keyword let] [variable $joe][keyword :=][atom 1]\",\n     \"      [keyword return] [keyword element] [variable element] {\",\n     \"          [keyword attribute] [variable attribute] { [atom 1] },\",\n     \"          [keyword element] [variable test] { [variable &#39;a&#39;] },           [keyword attribute] [variable foo] { [variable &quot;bar&quot;] },\",\n     \"          [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],\",\n     \"          [keyword //][variable x] }                 [comment (: a more 'evil' test :)]\",\n     \"      [comment (: Modified Blakeley example (: with nested comment :) ... :)]\",\n     \"      [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]\",\n     \"      [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]\",\n     \"      [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]\",\n     \"      [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]\",\n     \"      [keyword let] [variable $let] [keyword :=] [variable &lt;let&gt;let] [variable $let] [keyword :=] [variable &quot;let&quot;&lt;][keyword /let][variable &gt;]\",\n     \"      [keyword return] [keyword element] [variable element] {\",\n     \"          [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },\",\n     \"          [keyword attribute] [variable fn:doc] { [variable &quot;bar&quot;] [variable castable] [keyword as] [atom xs:string] },\",\n     \"          [keyword element] [variable text] { [keyword text] { [variable &quot;text&quot;] } },\",\n     \"          [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],\",\n     \"          [keyword //][variable fn:doc]\",\n     \"      }\");\n\n  MT(\"testEmptySequenceKeyword\",\n     \"[string \\\"foo\\\"] [keyword instance] [keyword of] [keyword empty-sequence]()\");\n\n  MT(\"testMultiAttr\",\n     \"[tag <p ][attribute a1]=[string \\\"foo\\\"] [attribute a2]=[string \\\"bar\\\"][tag >][variable hello] [variable world][tag </p>]\");\n\n  MT(\"test namespaced variable\",\n     \"[keyword declare] [keyword namespace] [variable e] [keyword =] [string \\\"http://example.com/ANamespace\\\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]\");\n\n  MT(\"test EQName variable\",\n     \"[keyword declare] [keyword variable] [variable $\\\"http://www.example.com/ns/my\\\":var] [keyword :=] [atom 12][variable ;]\",\n     \"[tag <out>]{[variable $\\\"http://www.example.com/ns/my\\\":var]}[tag </out>]\");\n\n  MT(\"test EQName function\",\n     \"[keyword declare] [keyword function] [def&variable \\\"http://www.example.com/ns/my\\\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {\",\n     \"   [variable $a] [keyword +] [atom 2]\",\n     \"}[variable ;]\",\n     \"[tag <out>]{[def&variable \\\"http://www.example.com/ns/my\\\":fn]([atom 12])}[tag </out>]\");\n\n  MT(\"test EQName function with single quotes\",\n     \"[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {\",\n     \"   [variable $a] [keyword +] [atom 2]\",\n     \"}[variable ;]\",\n     \"[tag <out>]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag </out>]\");\n\n  MT(\"testProcessingInstructions\",\n     \"[def&variable data]([comment&meta <?target content?>]) [keyword instance] [keyword of] [atom xs:string]\");\n\n  MT(\"testQuoteEscapeDouble\",\n     \"[keyword let] [variable $rootfolder] [keyword :=] [string \\\"c:\\\\builds\\\\winnt\\\\HEAD\\\\qa\\\\scripts\\\\\\\"]\",\n     \"[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \\\"keys\\\\\\\"])\");\n})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/xquery/xquery.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(\"xquery\", function() {\n\n  // The keywords object is set to the result of this self executing\n  // function. Each keyword is a property of the keywords object whose\n  // value is {type: atype, style: astyle}\n  var keywords = function(){\n    // conveinence functions used to build keywords object\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\")\n      , B = kw(\"keyword b\")\n      , C = kw(\"keyword c\")\n      , operator = kw(\"operator\")\n      , atom = {type: \"atom\", style: \"atom\"}\n      , punctuation = {type: \"punctuation\", style: null}\n      , qualifier = {type: \"axis_specifier\", style: \"qualifier\"};\n\n    // kwObj is what is return from this function at the end\n    var kwObj = {\n      'if': A, 'switch': A, 'while': A, 'for': A,\n      'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,\n      'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C,\n      'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,\n      ',': punctuation,\n      'null': atom, 'fn:false()': atom, 'fn:true()': atom\n    };\n\n    // a list of 'basic' keywords. For each add a property to kwObj with the value of\n    // {type: basic[i], style: \"keyword\"} e.g. 'after' --> {type: \"after\", style: \"keyword\"}\n    var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',\n    'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',\n    'descending','document','document-node','element','else','eq','every','except','external','following',\n    'following-sibling','follows','for','function','if','import','in','instance','intersect','item',\n    'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',\n    'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',\n    'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',\n    'xquery', 'empty-sequence'];\n    for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i]);};\n\n    // a list of types. For each add a property to kwObj with the value of\n    // {type: \"atom\", style: \"atom\"}\n    var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime',\n    'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary',\n    'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];\n    for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};\n\n    // each operator will add a property to kwObj with value of {type: \"operator\", style: \"keyword\"}\n    var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];\n    for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};\n\n    // each axis_specifiers will add a property to kwObj with value of {type: \"axis_specifier\", style: \"qualifier\"}\n    var axis_specifiers = [\"self::\", \"attribute::\", \"child::\", \"descendant::\", \"descendant-or-self::\", \"parent::\",\n    \"ancestor::\", \"ancestor-or-self::\", \"following::\", \"preceding::\", \"following-sibling::\", \"preceding-sibling::\"];\n    for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };\n\n    return kwObj;\n  }();\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  // the primary mode tokenizer\n  function tokenBase(stream, state) {\n    var ch = stream.next(),\n        mightBeFunction = false,\n        isEQName = isEQNameAhead(stream);\n\n    // an XML tag (if not in some sub, chained tokenizer)\n    if (ch == \"<\") {\n      if(stream.match(\"!--\", true))\n        return chain(stream, state, tokenXMLComment);\n\n      if(stream.match(\"![CDATA\", false)) {\n        state.tokenize = tokenCDATA;\n        return ret(\"tag\", \"tag\");\n      }\n\n      if(stream.match(\"?\", false)) {\n        return chain(stream, state, tokenPreProcessing);\n      }\n\n      var isclose = stream.eat(\"/\");\n      stream.eatSpace();\n      var tagName = \"\", c;\n      while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n\n      return chain(stream, state, tokenTag(tagName, isclose));\n    }\n    // start code block\n    else if(ch == \"{\") {\n      pushStateStack(state,{ type: \"codeblock\"});\n      return ret(\"\", null);\n    }\n    // end code block\n    else if(ch == \"}\") {\n      popStateStack(state);\n      return ret(\"\", null);\n    }\n    // if we're in an XML block\n    else if(isInXmlBlock(state)) {\n      if(ch == \">\")\n        return ret(\"tag\", \"tag\");\n      else if(ch == \"/\" && stream.eat(\">\")) {\n        popStateStack(state);\n        return ret(\"tag\", \"tag\");\n      }\n      else\n        return ret(\"word\", \"variable\");\n    }\n    // if a number\n    else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:E[+\\-]?\\d+)?/);\n      return ret(\"number\", \"atom\");\n    }\n    // comment start\n    else if (ch === \"(\" && stream.eat(\":\")) {\n      pushStateStack(state, { type: \"comment\"});\n      return chain(stream, state, tokenComment);\n    }\n    // quoted string\n    else if (  !isEQName && (ch === '\"' || ch === \"'\"))\n      return chain(stream, state, tokenString(ch));\n    // variable\n    else if(ch === \"$\") {\n      return chain(stream, state, tokenVariable);\n    }\n    // assignment\n    else if(ch ===\":\" && stream.eat(\"=\")) {\n      return ret(\"operator\", \"keyword\");\n    }\n    // open paren\n    else if(ch === \"(\") {\n      pushStateStack(state, { type: \"paren\"});\n      return ret(\"\", null);\n    }\n    // close paren\n    else if(ch === \")\") {\n      popStateStack(state);\n      return ret(\"\", null);\n    }\n    // open paren\n    else if(ch === \"[\") {\n      pushStateStack(state, { type: \"bracket\"});\n      return ret(\"\", null);\n    }\n    // close paren\n    else if(ch === \"]\") {\n      popStateStack(state);\n      return ret(\"\", null);\n    }\n    else {\n      var known = keywords.propertyIsEnumerable(ch) && keywords[ch];\n\n      // if there's a EQName ahead, consume the rest of the string portion, it's likely a function\n      if(isEQName && ch === '\\\"') while(stream.next() !== '\"'){}\n      if(isEQName && ch === '\\'') while(stream.next() !== '\\''){}\n\n      // gobble up a word if the character is not known\n      if(!known) stream.eatWhile(/[\\w\\$_-]/);\n\n      // gobble a colon in the case that is a lib func type call fn:doc\n      var foundColon = stream.eat(\":\");\n\n      // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier\n      // which should get matched as a keyword\n      if(!stream.eat(\":\") && foundColon) {\n        stream.eatWhile(/[\\w\\$_-]/);\n      }\n      // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)\n      if(stream.match(/^[ \\t]*\\(/, false)) {\n        mightBeFunction = true;\n      }\n      // is the word a keyword?\n      var word = stream.current();\n      known = keywords.propertyIsEnumerable(word) && keywords[word];\n\n      // if we think it's a function call but not yet known,\n      // set style to variable for now for lack of something better\n      if(mightBeFunction && !known) known = {type: \"function_call\", style: \"variable def\"};\n\n      // if the previous word was element, attribute, axis specifier, this word should be the name of that\n      if(isInXmlConstructor(state)) {\n        popStateStack(state);\n        return ret(\"word\", \"variable\", word);\n      }\n      // as previously checked, if the word is element,attribute, axis specifier, call it an \"xmlconstructor\" and\n      // push the stack so we know to look for it on the next word\n      if(word == \"element\" || word == \"attribute\" || known.type == \"axis_specifier\") pushStateStack(state, {type: \"xmlconstructor\"});\n\n      // if the word is known, return the details of that else just call this a generic 'word'\n      return known ? ret(known.type, known.style, word) :\n                     ret(\"word\", \"variable\", word);\n    }\n  }\n\n  // handle comments, including nested\n  function tokenComment(stream, state) {\n    var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;\n    while (ch = stream.next()) {\n      if (ch == \")\" && maybeEnd) {\n        if(nestedCount > 0)\n          nestedCount--;\n        else {\n          popStateStack(state);\n          break;\n        }\n      }\n      else if(ch == \":\" && maybeNested) {\n        nestedCount++;\n      }\n      maybeEnd = (ch == \":\");\n      maybeNested = (ch == \"(\");\n    }\n\n    return ret(\"comment\", \"comment\");\n  }\n\n  // tokenizer for string literals\n  // optionally pass a tokenizer function to set state.tokenize back to when finished\n  function tokenString(quote, f) {\n    return function(stream, state) {\n      var ch;\n\n      if(isInString(state) && stream.current() == quote) {\n        popStateStack(state);\n        if(f) state.tokenize = f;\n        return ret(\"string\", \"string\");\n      }\n\n      pushStateStack(state, { type: \"string\", name: quote, tokenize: tokenString(quote, f) });\n\n      // if we're in a string and in an XML block, allow an embedded code block\n      if(stream.match(\"{\", false) && isInXmlAttributeBlock(state)) {\n        state.tokenize = tokenBase;\n        return ret(\"string\", \"string\");\n      }\n\n\n      while (ch = stream.next()) {\n        if (ch ==  quote) {\n          popStateStack(state);\n          if(f) state.tokenize = f;\n          break;\n        }\n        else {\n          // if we're in a string and in an XML block, allow an embedded code block in an attribute\n          if(stream.match(\"{\", false) && isInXmlAttributeBlock(state)) {\n            state.tokenize = tokenBase;\n            return ret(\"string\", \"string\");\n          }\n\n        }\n      }\n\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  // tokenizer for variables\n  function tokenVariable(stream, state) {\n    var isVariableChar = /[\\w\\$_-]/;\n\n    // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote\n    if(stream.eat(\"\\\"\")) {\n      while(stream.next() !== '\\\"'){};\n      stream.eat(\":\");\n    } else {\n      stream.eatWhile(isVariableChar);\n      if(!stream.match(\":=\", false)) stream.eat(\":\");\n    }\n    stream.eatWhile(isVariableChar);\n    state.tokenize = tokenBase;\n    return ret(\"variable\", \"variable\");\n  }\n\n  // tokenizer for XML tags\n  function tokenTag(name, isclose) {\n    return function(stream, state) {\n      stream.eatSpace();\n      if(isclose && stream.eat(\">\")) {\n        popStateStack(state);\n        state.tokenize = tokenBase;\n        return ret(\"tag\", \"tag\");\n      }\n      // self closing tag without attributes?\n      if(!stream.eat(\"/\"))\n        pushStateStack(state, { type: \"tag\", name: name, tokenize: tokenBase});\n      if(!stream.eat(\">\")) {\n        state.tokenize = tokenAttribute;\n        return ret(\"tag\", \"tag\");\n      }\n      else {\n        state.tokenize = tokenBase;\n      }\n      return ret(\"tag\", \"tag\");\n    };\n  }\n\n  // tokenizer for XML attributes\n  function tokenAttribute(stream, state) {\n    var ch = stream.next();\n\n    if(ch == \"/\" && stream.eat(\">\")) {\n      if(isInXmlAttributeBlock(state)) popStateStack(state);\n      if(isInXmlBlock(state)) popStateStack(state);\n      return ret(\"tag\", \"tag\");\n    }\n    if(ch == \">\") {\n      if(isInXmlAttributeBlock(state)) popStateStack(state);\n      return ret(\"tag\", \"tag\");\n    }\n    if(ch == \"=\")\n      return ret(\"\", null);\n    // quoted string\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, tokenString(ch, tokenAttribute));\n\n    if(!isInXmlAttributeBlock(state))\n      pushStateStack(state, { type: \"attribute\", tokenize: tokenAttribute});\n\n    stream.eat(/[a-zA-Z_:]/);\n    stream.eatWhile(/[-a-zA-Z0-9_:.]/);\n    stream.eatSpace();\n\n    // the case where the attribute has not value and the tag was closed\n    if(stream.match(\">\", false) || stream.match(\"/\", false)) {\n      popStateStack(state);\n      state.tokenize = tokenBase;\n    }\n\n    return ret(\"attribute\", \"attribute\");\n  }\n\n  // handle comments, including nested\n  function tokenXMLComment(stream, state) {\n    var ch;\n    while (ch = stream.next()) {\n      if (ch == \"-\" && stream.match(\"->\", true)) {\n        state.tokenize = tokenBase;\n        return ret(\"comment\", \"comment\");\n      }\n    }\n  }\n\n\n  // handle CDATA\n  function tokenCDATA(stream, state) {\n    var ch;\n    while (ch = stream.next()) {\n      if (ch == \"]\" && stream.match(\"]\", true)) {\n        state.tokenize = tokenBase;\n        return ret(\"comment\", \"comment\");\n      }\n    }\n  }\n\n  // handle preprocessing instructions\n  function tokenPreProcessing(stream, state) {\n    var ch;\n    while (ch = stream.next()) {\n      if (ch == \"?\" && stream.match(\">\", true)) {\n        state.tokenize = tokenBase;\n        return ret(\"comment\", \"comment meta\");\n      }\n    }\n  }\n\n\n  // functions to test the current context of the state\n  function isInXmlBlock(state) { return isIn(state, \"tag\"); }\n  function isInXmlAttributeBlock(state) { return isIn(state, \"attribute\"); }\n  function isInXmlConstructor(state) { return isIn(state, \"xmlconstructor\"); }\n  function isInString(state) { return isIn(state, \"string\"); }\n\n  function isEQNameAhead(stream) {\n    // assume we've already eaten a quote (\")\n    if(stream.current() === '\"')\n      return stream.match(/^[^\\\"]+\\\"\\:/, false);\n    else if(stream.current() === '\\'')\n      return stream.match(/^[^\\\"]+\\'\\:/, false);\n    else\n      return false;\n  }\n\n  function isIn(state, type) {\n    return (state.stack.length && state.stack[state.stack.length - 1].type == type);\n  }\n\n  function pushStateStack(state, newState) {\n    state.stack.push(newState);\n  }\n\n  function popStateStack(state) {\n    state.stack.pop();\n    var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize;\n    state.tokenize = reinstateTokenize || tokenBase;\n  }\n\n  // the interface for the mode API\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        cc: [],\n        stack: []\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    },\n\n    blockCommentStart: \"(:\",\n    blockCommentEnd: \":)\"\n\n  };\n\n});\n\nCodeMirror.defineMIME(\"application/xquery\", \"xquery\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/yaml/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: YAML mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"yaml.js\"></script>\n<style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">YAML</a>\n  </ul>\n</div>\n\n<article>\n<h2>YAML mode</h2>\n<form><textarea id=\"code\" name=\"code\">\n--- # Favorite movies\n- Casablanca\n- North by Northwest\n- The Man Who Wasn't There\n--- # Shopping list\n[milk, pumpkin pie, eggs, juice]\n--- # Indented Blocks, common in YAML data files, use indentation and new lines to separate the key: value pairs\n  name: John Smith\n  age: 33\n--- # Inline Blocks, common in YAML data streams, use commas to separate the key: value pairs between braces\n{name: John Smith, age: 33}\n---\nreceipt:     Oz-Ware Purchase Invoice\ndate:        2007-08-06\ncustomer:\n    given:   Dorothy\n    family:  Gale\n\nitems:\n    - part_no:   A4786\n      descrip:   Water Bucket (Filled)\n      price:     1.47\n      quantity:  4\n\n    - part_no:   E1628\n      descrip:   High Heeled \"Ruby\" Slippers\n      size:       8\n      price:     100.27\n      quantity:  1\n\nbill-to:  &id001\n    street: |\n            123 Tornado Alley\n            Suite 16\n    city:   East Centerville\n    state:  KS\n\nship-to:  *id001\n\nspecialDelivery:  >\n    Follow the Yellow Brick\n    Road to the Emerald City.\n    Pay no attention to the\n    man behind the curtain.\n...\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-yaml</code>.</p>\n\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/yaml/yaml.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(\"yaml\", function() {\n\n  var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];\n  var keywordRegex = new RegExp(\"\\\\b((\"+cons.join(\")|(\")+\"))$\", 'i');\n\n  return {\n    token: function(stream, state) {\n      var ch = stream.peek();\n      var esc = state.escaped;\n      state.escaped = false;\n      /* comments */\n      if (ch == \"#\" && (stream.pos == 0 || /\\s/.test(stream.string.charAt(stream.pos - 1)))) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n\n      if (stream.match(/^('([^']|\\\\.)*'?|\"([^\"]|\\\\.)*\"?)/))\n        return \"string\";\n\n      if (state.literal && stream.indentation() > state.keyCol) {\n        stream.skipToEnd(); return \"string\";\n      } else if (state.literal) { state.literal = false; }\n      if (stream.sol()) {\n        state.keyCol = 0;\n        state.pair = false;\n        state.pairStart = false;\n        /* document start */\n        if(stream.match(/---/)) { return \"def\"; }\n        /* document end */\n        if (stream.match(/\\.\\.\\./)) { return \"def\"; }\n        /* array list item */\n        if (stream.match(/\\s*-\\s+/)) { return 'meta'; }\n      }\n      /* inline pairs/lists */\n      if (stream.match(/^(\\{|\\}|\\[|\\])/)) {\n        if (ch == '{')\n          state.inlinePairs++;\n        else if (ch == '}')\n          state.inlinePairs--;\n        else if (ch == '[')\n          state.inlineList++;\n        else\n          state.inlineList--;\n        return 'meta';\n      }\n\n      /* list seperator */\n      if (state.inlineList > 0 && !esc && ch == ',') {\n        stream.next();\n        return 'meta';\n      }\n      /* pairs seperator */\n      if (state.inlinePairs > 0 && !esc && ch == ',') {\n        state.keyCol = 0;\n        state.pair = false;\n        state.pairStart = false;\n        stream.next();\n        return 'meta';\n      }\n\n      /* start of value of a pair */\n      if (state.pairStart) {\n        /* block literals */\n        if (stream.match(/^\\s*(\\||\\>)\\s*/)) { state.literal = true; return 'meta'; };\n        /* references */\n        if (stream.match(/^\\s*(\\&|\\*)[a-z0-9\\._-]+\\b/i)) { return 'variable-2'; }\n        /* numbers */\n        if (state.inlinePairs == 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?$/)) { return 'number'; }\n        if (state.inlinePairs > 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?(?=(,|}))/)) { return 'number'; }\n        /* keywords */\n        if (stream.match(keywordRegex)) { return 'keyword'; }\n      }\n\n      /* pairs (associative arrays) -> key */\n      if (!state.pair && stream.match(/^\\s*(?:[,\\[\\]{}&*!|>'\"%@`][^\\s'\":]|[^,\\[\\]{}#&*!|>'\"%@`])[^#]*?(?=\\s*:($|\\s))/)) {\n        state.pair = true;\n        state.keyCol = stream.indentation();\n        return \"atom\";\n      }\n      if (state.pair && stream.match(/^:\\s*/)) { state.pairStart = true; return 'meta'; }\n\n      /* nothing found, continue */\n      state.pairStart = false;\n      state.escaped = (ch == '\\\\');\n      stream.next();\n      return null;\n    },\n    startState: function() {\n      return {\n        pair: false,\n        pairStart: false,\n        keyCol: 0,\n        inlinePairs: 0,\n        inlineList: 0,\n        literal: false,\n        escaped: false\n      };\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-yaml\", \"yaml\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/z80/index.html",
    "content": "<!doctype html>\n\n<title>CodeMirror: Z80 assembly mode</title>\n<meta charset=\"utf-8\"/>\n<link rel=stylesheet href=\"../../doc/docs.css\">\n\n<link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n<script src=\"../../lib/codemirror.js\"></script>\n<script src=\"z80.js\"></script>\n<style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n<div id=nav>\n  <a href=\"http://codemirror.net\"><h1>CodeMirror</h1><img id=logo src=\"../../doc/logo.png\"></a>\n\n  <ul>\n    <li><a href=\"../../index.html\">Home</a>\n    <li><a href=\"../../doc/manual.html\">Manual</a>\n    <li><a href=\"https://github.com/codemirror/codemirror\">Code</a>\n  </ul>\n  <ul>\n    <li><a href=\"../index.html\">Language modes</a>\n    <li><a class=active href=\"#\">Z80 assembly</a>\n  </ul>\n</div>\n\n<article>\n<h2>Z80 assembly mode</h2>\n\n\n<div><textarea id=\"code\" name=\"code\">\n#include    \"ti83plus.inc\"\n#define     progStart   $9D95\n.org        progStart-2\n.db         $BB,$6D\n    bcall(_ClrLCDFull)\n    ld  HL, 0\n    ld  (PenCol),   HL\n    ld  HL, Message\n    bcall(_PutS) ; Displays the string\n    bcall(_NewLine)\n    ret\nMessage:\n.db         \"Hello world!\",0\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true\n      });\n    </script>\n\n    <p><strong>MIME type defined:</strong> <code>text/x-z80</code>.</p>\n  </article>\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/codemirror/mode/z80/z80.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('z80', function() {\n  var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\\b/i;\n  var keywords2 = /^(call|j[pr]|ret[in]?)\\b/i;\n  var keywords3 = /^b_?(call|jump)\\b/i;\n  var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\\b/i;\n  var variables2 = /^(n?[zc]|p[oe]?|m)\\b/i;\n  var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\\b/i;\n  var numbers = /^([\\da-f]+h|[0-7]+o|[01]+b|\\d+)\\b/i;\n\n  return {\n    startState: function() {\n      return {context: 0};\n    },\n    token: function(stream, state) {\n      if (!stream.column())\n        state.context = 0;\n\n      if (stream.eatSpace())\n        return null;\n\n      var w;\n\n      if (stream.eatWhile(/\\w/)) {\n        w = stream.current();\n\n        if (stream.indentation()) {\n          if (state.context == 1 && variables1.test(w))\n            return 'variable-2';\n\n          if (state.context == 2 && variables2.test(w))\n            return 'variable-3';\n\n          if (keywords1.test(w)) {\n            state.context = 1;\n            return 'keyword';\n          } else if (keywords2.test(w)) {\n            state.context = 2;\n            return 'keyword';\n          } else if (keywords3.test(w)) {\n            state.context = 3;\n            return 'keyword';\n          }\n\n          if (errors.test(w))\n            return 'error';\n        } else if (numbers.test(w)) {\n          return 'number';\n        } else {\n          return null;\n        }\n      } else if (stream.eat(';')) {\n        stream.skipToEnd();\n        return 'comment';\n      } else if (stream.eat('\"')) {\n        while (w = stream.next()) {\n          if (w == '\"')\n            break;\n\n          if (w == '\\\\')\n            stream.next();\n        }\n        return 'string';\n      } else if (stream.eat('\\'')) {\n        if (stream.match(/\\\\?.'/))\n          return 'number';\n      } else if (stream.eat('.') || stream.sol() && stream.eat('#')) {\n        state.context = 4;\n\n        if (stream.eatWhile(/\\w/))\n          return 'def';\n      } else if (stream.eat('$')) {\n        if (stream.eatWhile(/[\\da-f]/i))\n          return 'number';\n      } else if (stream.eat('%')) {\n        if (stream.eatWhile(/[01]/))\n          return 'number';\n      } else {\n        stream.next();\n      }\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-z80\", \"z80\");\n\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/dataTables/dataTables.bootstrap.js",
    "content": "/* Set the defaults for DataTables initialisation */\n$.extend(true, $.fn.dataTable.defaults, {\n    \"sDom\": \"<'row'<'col-sm-6'l><'col-sm-6'f>r>\" + \"t\" + \"<'row'<'col-sm-6'i><'col-sm-6'p>>\",\n    \"oLanguage\": {\n        \"sLengthMenu\": \"每页 _MENU_ 条记录\"\n    }\n});\n\n\n/* Default class modification */\n$.extend($.fn.dataTableExt.oStdClasses, {\n    \"sWrapper\": \"dataTables_wrapper form-inline\",\n    \"sFilterInput\": \"form-control input-sm\",\n    \"sLengthSelect\": \"form-control input-sm\"\n});\n\n// In 1.10 we use the pagination renderers to draw the Bootstrap paging,\n// rather than  custom plug-in\nif ($.fn.dataTable.Api) {\n    $.fn.dataTable.defaults.renderer = 'bootstrap';\n    $.fn.dataTable.ext.renderer.pageButton.bootstrap = function(settings, host, idx, buttons, page, pages) {\n        var api = new $.fn.dataTable.Api(settings);\n        var classes = settings.oClasses;\n        var lang = settings.oLanguage.oPaginate;\n        var btnDisplay, btnClass;\n\n        var attach = function(container, buttons) {\n            var i, ien, node, button;\n            var clickHandler = function(e) {\n                e.preventDefault();\n                if (e.data.action !== 'ellipsis') {\n                    api.page(e.data.action).draw(false);\n                }\n            };\n\n            for (i = 0, ien = buttons.length; i < ien; i++) {\n                button = buttons[i];\n\n                if ($.isArray(button)) {\n                    attach(container, button);\n                } else {\n                    btnDisplay = '';\n                    btnClass = '';\n\n                    switch (button) {\n                        case 'ellipsis':\n                            btnDisplay = '&hellip;';\n                            btnClass = 'disabled';\n                            break;\n\n                        case 'first':\n                            btnDisplay = lang.sFirst;\n                            btnClass = button + (page > 0 ?\n                                '' : ' disabled');\n                            break;\n\n                        case 'previous':\n                            btnDisplay = lang.sPrevious;\n                            btnClass = button + (page > 0 ?\n                                '' : ' disabled');\n                            break;\n\n                        case 'next':\n                            btnDisplay = lang.sNext;\n                            btnClass = button + (page < pages - 1 ?\n                                '' : ' disabled');\n                            break;\n\n                        case 'last':\n                            btnDisplay = lang.sLast;\n                            btnClass = button + (page < pages - 1 ?\n                                '' : ' disabled');\n                            break;\n\n                        default:\n                            btnDisplay = button + 1;\n                            btnClass = page === button ?\n                                'active' : '';\n                            break;\n                    }\n\n                    if (btnDisplay) {\n                        node = $('<li>', {\n                            'class': classes.sPageButton + ' ' + btnClass,\n                            'aria-controls': settings.sTableId,\n                            'tabindex': settings.iTabIndex,\n                            'id': idx === 0 && typeof button === 'string' ? settings.sTableId + '_' + button : null\n                        })\n                            .append($('<a>', {\n                                    'href': '#'\n                                })\n                                .html(btnDisplay)\n                        )\n                            .appendTo(container);\n\n                        settings.oApi._fnBindAction(\n                            node, {\n                                action: button\n                            }, clickHandler\n                        );\n                    }\n                }\n            }\n        };\n\n        attach(\n            $(host).empty().html('<ul class=\"pagination\"/>').children('ul'),\n            buttons\n        );\n    }\n} else {\n    // Integration for 1.9-\n    $.fn.dataTable.defaults.sPaginationType = 'bootstrap';\n\n    /* API method to get paging information */\n    $.fn.dataTableExt.oApi.fnPagingInfo = function(oSettings) {\n        return {\n            \"iStart\": oSettings._iDisplayStart,\n            \"iEnd\": oSettings.fnDisplayEnd(),\n            \"iLength\": oSettings._iDisplayLength,\n            \"iTotal\": oSettings.fnRecordsTotal(),\n            \"iFilteredTotal\": oSettings.fnRecordsDisplay(),\n            \"iPage\": oSettings._iDisplayLength === -1 ? 0 : Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength),\n            \"iTotalPages\": oSettings._iDisplayLength === -1 ? 0 : Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength)\n        };\n    };\n\n    /* Bootstrap style pagination control */\n    $.extend($.fn.dataTableExt.oPagination, {\n        \"bootstrap\": {\n            \"fnInit\": function(oSettings, nPaging, fnDraw) {\n                var oLang = oSettings.oLanguage.oPaginate;\n                var fnClickHandler = function(e) {\n                    e.preventDefault();\n                    if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {\n                        fnDraw(oSettings);\n                    }\n                };\n\n                $(nPaging).append(\n                    '<ul class=\"pagination\">' +\n                    '<li class=\"prev disabled\"><a href=\"#\">&larr; ' + oLang.sPrevious + '</a></li>' +\n                    '<li class=\"next disabled\"><a href=\"#\">' + oLang.sNext + ' &rarr; </a></li>' +\n                    '</ul>'\n                );\n                var els = $('a', nPaging);\n                $(els[0]).bind('click.DT', {\n                    action: \"previous\"\n                }, fnClickHandler);\n                $(els[1]).bind('click.DT', {\n                    action: \"next\"\n                }, fnClickHandler);\n            },\n\n            \"fnUpdate\": function(oSettings, fnDraw) {\n                var iListLength = 5;\n                var oPaging = oSettings.oInstance.fnPagingInfo();\n                var an = oSettings.aanFeatures.p;\n                var i, ien, j, sClass, iStart, iEnd, iHalf = Math.floor(iListLength / 2);\n\n                if (oPaging.iTotalPages < iListLength) {\n                    iStart = 1;\n                    iEnd = oPaging.iTotalPages;\n                } else if (oPaging.iPage <= iHalf) {\n                    iStart = 1;\n                    iEnd = iListLength;\n                } else if (oPaging.iPage >= (oPaging.iTotalPages - iHalf)) {\n                    iStart = oPaging.iTotalPages - iListLength + 1;\n                    iEnd = oPaging.iTotalPages;\n                } else {\n                    iStart = oPaging.iPage - iHalf + 1;\n                    iEnd = iStart + iListLength - 1;\n                }\n\n                for (i = 0, ien = an.length; i < ien; i++) {\n                    // Remove the middle elements\n                    $('li:gt(0)', an[i]).filter(':not(:last)').remove();\n\n                    // Add the new list items and their event handlers\n                    for (j = iStart; j <= iEnd; j++) {\n                        sClass = (j == oPaging.iPage + 1) ? 'class=\"active\"' : '';\n                        $('<li ' + sClass + '><a href=\"#\">' + j + '</a></li>')\n                            .insertBefore($('li:last', an[i])[0])\n                            .bind('click', function(e) {\n                                e.preventDefault();\n                                oSettings._iDisplayStart = (parseInt($('a', this).text(), 10) - 1) * oPaging.iLength;\n                                fnDraw(oSettings);\n                            });\n                    }\n\n                    // Add / remove disabled classes from the static elements\n                    if (oPaging.iPage === 0) {\n                        $('li:first', an[i]).addClass('disabled');\n                    } else {\n                        $('li:first', an[i]).removeClass('disabled');\n                    }\n\n                    if (oPaging.iPage === oPaging.iTotalPages - 1 || oPaging.iTotalPages === 0) {\n                        $('li:last', an[i]).addClass('disabled');\n                    } else {\n                        $('li:last', an[i]).removeClass('disabled');\n                    }\n                }\n            }\n        }\n    });\n}\n\n\n/*\n * TableTools Bootstrap compatibility\n * Required TableTools 2.1+\n */\nif ($.fn.DataTable.TableTools) {\n    // Set the classes that TableTools uses to something suitable for Bootstrap\n    $.extend(true, $.fn.DataTable.TableTools.classes, {\n        \"container\": \"DTTT btn-group\",\n        \"buttons\": {\n            \"normal\": \"btn btn-default\",\n            \"disabled\": \"disabled\"\n        },\n        \"collection\": {\n            \"container\": \"DTTT_dropdown dropdown-menu\",\n            \"buttons\": {\n                \"normal\": \"\",\n                \"disabled\": \"disabled\"\n            }\n        },\n        \"print\": {\n            \"info\": \"DTTT_print_info modal\"\n        },\n        \"select\": {\n            \"row\": \"active\"\n        }\n    });\n\n    // Have the collection use a bootstrap compatible dropdown\n    $.extend(true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {\n        \"collection\": {\n            \"container\": \"ul\",\n            \"button\": \"li\",\n            \"liner\": \"a\"\n        }\n    });\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/dataTables/jquery.dataTables.js",
    "content": "/*! DataTables 1.10.0-dev\n * ©2008-2013 SpryMedia Ltd - datatables.net/license\n */\n\n/**\n * @summary     DataTables\n * @description Paginate, search and order HTML tables\n * @version     1.10.0-dev\n * @file        jquery.dataTables.js\n * @author 郑保乐\n * @contact     www.sprymedia.co.uk/contact\n * @copyright   Copyright 2008-2013 SpryMedia Ltd.\n *\n * This source file is free software, available under the following license:\n *   MIT license - http://datatables.net/license\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 $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_empty,_intVal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/\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( 'datatables', ['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\n\t/**\n\t * DataTables is a plug-in for the jQuery Javascript library. It is a highly\n\t * flexible tool, based upon the foundations of progressive enhancement,\n\t * which will add advanced interaction controls to any HTML table. For a\n\t * full list of features please refer to\n\t * [DataTables.net](href=\"http://datatables.net).\n\t *\n\t * Note that the `DataTable` object is not a global variable but is aliased\n\t * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may\n\t * be  accessed.\n\t *\n\t *  @class\n\t *  @param {object} [init={}] 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 *        \"paginate\": false,\n\t *        \"sort\": false\n\t *      } );\n\t *    } );\n\t */\n\tvar DataTable;\n\n\n\t/*\n\t * It is useful to have variables which are scoped locally so only the\n\t * DataTables functions can access them and they don't leak into global space.\n\t * At the same time these functions are often useful over multiple files in the\n\t * core and API, so we list, or at least document, all variables which are used\n\t * by DataTables as private variables here. This also ensures that there is no\n\t * clashing of variable names and that they can easily referenced for reuse.\n\t */\n\n\n\t// Defined else where\n\t//  _selector_run\n\t//  _selector_opts\n\t//  _selector_first\n\t//  _selector_row_indexes\n\n\tvar _ext; // DataTable.ext\n\tvar _Api; // DataTable.Api\n\tvar _api_register; // DataTable.Api.register\n\tvar _api_registerPlural; // DataTable.Api.registerPlural\n\n\tvar _re_new_lines = /[\\r\\n]/g;\n\tvar _re_html = /<.*?>/g;\n\tvar _re_formatted_numeric = /[',$£€¥%]/g;\n\tvar _re_date_start = /^[\\d\\+\\-a-zA-Z]/;\n\n\n\n\n\tvar _empty = function ( d ) {\n\t\treturn !d || d === '-' ? true : false;\n\t};\n\n\n\tvar _intVal = function ( s ) {\n\t\tvar integer = parseInt( s, 10 );\n\t\treturn !isNaN(integer) && isFinite(s) ? integer : null;\n\t};\n\n\n\tvar _isNumber = function ( d, formatted ) {\n\t\tif ( formatted && typeof d === 'string' ) {\n\t\t\td = d.replace( _re_formatted_numeric, '' );\n\t\t}\n\n\t\treturn !d || d==='-' || (!isNaN( parseFloat(d) ) && isFinite( d ));\n\t};\n\n\n\t// A string without HTML in it can be considered to be HTML still\n\tvar _isHtml = function ( d ) {\n\t\treturn !d || typeof d === 'string';\n\t};\n\n\n\tvar _htmlNumeric = function ( d, formatted ) {\n\t\tif ( _empty( d ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tvar html = _isHtml( d );\n\t\treturn ! html ?\n\t\t\tnull :\n\t\t\t_isNumber( _stripHtml( d ), formatted ) ?\n\t\t\t\ttrue :\n\t\t\t\tnull;\n\t};\n\n\n\tvar _pluck = function ( a, prop, prop2 ) {\n\t\tvar out = [];\n\t\tvar i=0, ien=a.length;\n\n\t\t// Could have the test in the loop for slightly smaller code, but speed\n\t\t// is essential here\n\t\tif ( prop2 !== undefined ) {\n\t\t\tfor ( ; i<ien ; i++ ) {\n\t\t\t\tif ( a[i] && a[i][ prop ] ) {\n\t\t\t\t\tout.push( a[i][ prop ][ prop2 ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor ( ; i<ien ; i++ ) {\n\t\t\t\tif ( a[i] ) {\n\t\t\t\t\tout.push( a[i][ prop ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn out;\n\t};\n\n\n\t// Basically the same as _pluck, but rather than looping over `a` we use `order`\n\t// as the indexes to pick from `a`\n\tvar _pluck_order = function ( a, order, prop, prop2 )\n\t{\n\t\tvar out = [];\n\t\tvar i=0, ien=order.length;\n\n\t\t// Could have the test in the loop for slightly smaller code, but speed\n\t\t// is essential here\n\t\tif ( prop2 !== undefined ) {\n\t\t\tfor ( ; i<ien ; i++ ) {\n\t\t\t\tout.push( a[ order[i] ][ prop ][ prop2 ] );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor ( ; i<ien ; i++ ) {\n\t\t\t\tout.push( a[ order[i] ][ prop ] );\n\t\t\t}\n\t\t}\n\n\t\treturn out;\n\t};\n\n\n\tvar _range = function ( len, start )\n\t{\n\t\tvar out = [];\n\t\tvar end;\n\n\t\tif ( start === undefined ) {\n\t\t\tstart = 0;\n\t\t\tend = len;\n\t\t}\n\t\telse {\n\t\t\tend = start;\n\t\t\tstart = len;\n\t\t}\n\n\t\tfor ( var i=start ; i<end ; i++ ) {\n\t\t\tout.push( i );\n\t\t}\n\n\t\treturn out;\n\t};\n\n\n\tvar _stripHtml = function ( d ) {\n\t\treturn d.replace( _re_html, '' );\n\t};\n\n\n\t/**\n\t * Find the unique elements in a source array.\n\t *\n\t * @param  {array} src Source array\n\t * @return {array} Array of unique items\n\t * @ignore\n\t */\n\tvar _unique = function ( src )\n\t{\n\t\t// A faster unique method is to use object keys to identify used values,\n\t\t// but this doesn't work with arrays or objects, which we must also\n\t\t// consider. See jsperf.com/compare-array-unique-versions/4 for more\n\t\t// information.\n\t\tvar\n\t\t\tout = [],\n\t\t\tval,\n\t\t\ti, ien=src.length,\n\t\t\tj, k=0;\n\n\t\tagain: for ( i=0 ; i<ien ; i++ ) {\n\t\t\tval = src[i];\n\n\t\t\tfor ( j=0 ; j<k ; j++ ) {\n\t\t\t\tif ( out[j] === val ) {\n\t\t\t\t\tcontinue again;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tout.push( val );\n\t\t\tk++;\n\t\t}\n\n\t\treturn out;\n\t};\n\n\n\n\t/**\n\t * Create a mapping object that allows camel case parameters to be looked up\n\t * for their Hungarian counterparts. The mapping is stored in a private\n\t * parameter called `_hungarianMap` which can be accessed on the source object.\n\t *  @param {object} o\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnHungarianMap ( o )\n\t{\n\t\tvar\n\t\t\thungarian = 'a aa ao as b fn i m o s ',\n\t\t\tmatch,\n\t\t\tnewKey,\n\t\t\tmap = {};\n\n\t\t$.each( o, function (key, val) {\n\t\t\tmatch = key.match(/^([^A-Z]+?)([A-Z])/);\n\n\t\t\tif ( match && hungarian.indexOf(match[1]+' ') !== -1 )\n\t\t\t{\n\t\t\t\tnewKey = key.replace( match[0], match[2].toLowerCase() );\n\t\t\t\tmap[ newKey ] = key;\n\n\t\t\t\tif ( match[1] === 'o' )\n\t\t\t\t{\n\t\t\t\t\t_fnHungarianMap( o[key] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\to._hungarianMap = map;\n\t}\n\n\n\t/**\n\t * Convert from camel case parameters to Hungarian, based on a Hungarian map\n\t * created by _fnHungarianMap.\n\t *  @param {object} src The model object which holds all parameters that can be\n\t *    mapped.\n\t *  @param {object} user The object to convert from camel case to Hungarian.\n\t *  @param {boolean} force When set to `true`, properties which already have a\n\t *    Hungarian value in the `user` object will be overwritten. Otherwise they\n\t *    won't be.\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnCamelToHungarian ( src, user, force )\n\t{\n\t\tif ( ! src._hungarianMap )\n\t\t{\n\t\t\t_fnHungarianMap( src );\n\t\t}\n\n\t\tvar hungarianKey;\n\n\t\t$.each( user, function (key, val) {\n\t\t\thungarianKey = src._hungarianMap[ key ];\n\n\t\t\tif ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )\n\t\t\t{\n\t\t\t\tuser[hungarianKey] = user[ key ];\n\n\t\t\t\tif ( hungarianKey.charAt(0) === 'o' )\n\t\t\t\t{\n\t\t\t\t\t_fnCamelToHungarian( src[hungarianKey], user[key] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\n\t/**\n\t * Language compatibility - when certain options are given, and others aren't, we\n\t * need to duplicate the values over, in order to provide backwards compatibility\n\t * with older language files.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnLanguageCompat( oLanguage )\n\t{\n\t\tvar oDefaults = DataTable.defaults.oLanguage;\n\t\tvar zeroRecords = oLanguage.sZeroRecords;\n\n\t\t/* Backwards compatibility - if there is no sEmptyTable given, then use the same as\n\t\t * sZeroRecords - assuming that is given.\n\t\t */\n\t\tif ( !oLanguage.sEmptyTable && zeroRecords &&\n\t\t\toDefaults.sEmptyTable === \"没有数据\" )\n\t\t{\n\t\t\t_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );\n\t\t}\n\n\t\t/* Likewise with loading records */\n\t\tif ( !oLanguage.sLoadingRecords && zeroRecords &&\n\t\t\toDefaults.sLoadingRecords === \"加载中…\" )\n\t\t{\n\t\t\t_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );\n\t\t}\n\t}\n\n\n\t/**\n\t * Map one parameter onto another\n\t *  @param {object} o Object to map\n\t *  @param {*} knew The new parameter name\n\t *  @param {*} old The old parameter name\n\t */\n\tvar _fnCompatMap = function ( o, knew, old ) {\n\t\tif ( o[ knew ] !== undefined ) {\n\t\t\to[ old ] = o[ knew ];\n\t\t}\n\t};\n\n\n\t/**\n\t * Provide backwards compatibility for the main DT options. Note that the new\n\t * options are mapped onto the old parameters, so this is an external interface\n\t * change only.\n\t *  @param {object} init Object to map\n\t */\n\tfunction _fnCompatOpts ( init )\n\t{\n\t\t_fnCompatMap( init, 'ordering',      'bSort' );\n\t\t_fnCompatMap( init, 'orderMulti',    'bSortMulti' );\n\t\t_fnCompatMap( init, 'orderClasses',  'bSortClasses' );\n\t\t_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );\n\t\t_fnCompatMap( init, 'order',         'aaSorting' );\n\t\t_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );\n\t\t_fnCompatMap( init, 'paging',        'bPaginate' );\n\t\t_fnCompatMap( init, 'pagingType',    'sPaginationType' );\n\t\t_fnCompatMap( init, 'pageLength',    'iDisplayLength' );\n\t\t_fnCompatMap( init, 'searching',     'bFilter' );\n\t}\n\n\n\t/**\n\t * Provide backwards compatibility for column options. Note that the new options\n\t * are mapped onto the old parameters, so this is an external interface change\n\t * only.\n\t *  @param {object} init Object to map\n\t */\n\tfunction _fnCompatCols ( init )\n\t{\n\t\t_fnCompatMap( init, 'orderable',     'bSortable' );\n\t\t_fnCompatMap( init, 'orderData',     'aDataSort' );\n\t\t_fnCompatMap( init, 'orderSequence', 'asSorting' );\n\t\t_fnCompatMap( init, 'orderDataType', 'sortDataType' );\n\t}\n\n\n\t/**\n\t * Browser feature detection for capabilities, quirks\n\t *  @param {object} settings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnBrowserDetect( settings )\n\t{\n\t\tvar browser = settings.oBrowser;\n\n\t\t// Scrolling feature / quirks detection\n\t\tvar n = $('<div/>')\n\t\t\t.css( {\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\theight: 1,\n\t\t\t\twidth: 1,\n\t\t\t\toverflow: 'hidden'\n\t\t\t} )\n\t\t\t.append(\n\t\t\t\t$('<div/>')\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: 1,\n\t\t\t\t\t\tleft: 1,\n\t\t\t\t\t\twidth: 100,\n\t\t\t\t\t\toverflow: 'scroll'\n\t\t\t\t\t} )\n\t\t\t\t\t.append(\n\t\t\t\t\t\t$('<div class=\"test\"/>')\n\t\t\t\t\t\t\t.css( {\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\theight: 10\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.appendTo( 'body' );\n\n\t\tvar test = n.find('.test');\n\n\t\t// IE6/7 will oversize a width 100% element inside a scrolling element, to\n\t\t// include the width of the scrollbar, while other browsers ensure the inner\n\t\t// element is contained without forcing scrolling\n\t\tbrowser.bScrollOversize = test[0].offsetWidth === 100;\n\n\t\t// In rtl text layout, some browsers (most, but not all) will place the\n\t\t// scrollbar on the left, rather than the right.\n\t\tbrowser.bScrollbarLeft = test.offset().left !== 1;\n\n\t\tn.remove();\n\t}\n\n\t/**\n\t * Add a column to the list used for the table with default values\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {node} nTh The th element for this column\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAddColumn( oSettings, nTh )\n\t{\n\t\tvar oDefaults = DataTable.defaults.column;\n\t\tvar iCol = oSettings.aoColumns.length;\n\t\tvar oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {\n\t\t\t\"sSortingClass\": oSettings.oClasses.sSortable,\n\t\t\t\"sSortingClassJUI\": oSettings.oClasses.sSortJUI,\n\t\t\t\"nTh\": nTh ? nTh : document.createElement('th'),\n\t\t\t\"sTitle\":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',\n\t\t\t\"aDataSort\": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],\n\t\t\t\"mData\": oDefaults.mData ? oDefaults.mData : iCol\n\t\t} );\n\t\toSettings.aoColumns.push( oCol );\n\n\t\t/* Add a column specific filter */\n\t\tif ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )\n\t\t{\n\t\t\toSettings.aoPreSearchCols[ iCol ] = $.extend( true, {}, DataTable.models.oSearch );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvar oPre = oSettings.aoPreSearchCols[ iCol ];\n\n\t\t\t/* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */\n\t\t\tif ( oPre.bRegex === undefined )\n\t\t\t{\n\t\t\t\toPre.bRegex = true;\n\t\t\t}\n\n\t\t\tif ( oPre.bSmart === undefined )\n\t\t\t{\n\t\t\t\toPre.bSmart = true;\n\t\t\t}\n\n\t\t\tif ( oPre.bCaseInsensitive === undefined )\n\t\t\t{\n\t\t\t\toPre.bCaseInsensitive = true;\n\t\t\t}\n\t\t}\n\n\t\t/* Use the column options function to initialise classes etc */\n\t\t_fnColumnOptions( oSettings, iCol, null );\n\t}\n\n\n\t/**\n\t * Apply options for a column\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iCol column index to consider\n\t *  @param {object} oOptions object with sType, bVisible and bSearchable etc\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnColumnOptions( oSettings, iCol, oOptions )\n\t{\n\t\tvar oCol = oSettings.aoColumns[ iCol ];\n\t\tvar oClasses = oSettings.oClasses;\n\n\t\t/* User specified column options */\n\t\tif ( oOptions !== undefined && oOptions !== null )\n\t\t{\n\t\t\t// Backwards compatibility\n\t\t\t_fnCompatCols( oOptions );\n\n\t\t\t// Map camel case parameters to their Hungarian counterparts\n\t\t\t_fnCamelToHungarian( DataTable.defaults.column, oOptions );\n\n\t\t\t/* Backwards compatibility for mDataProp */\n\t\t\tif ( oOptions.mDataProp !== undefined && !oOptions.mData )\n\t\t\t{\n\t\t\t\toOptions.mData = oOptions.mDataProp;\n\t\t\t}\n\n\t\t\toCol._sManualType = oOptions.sType;\n\n\t\t\t// `class` is a reserved word in Javascript, so we need to provide\n\t\t\t// the ability to use a valid name for the camel case input\n\t\t\tif ( oOptions.className && ! oOptions.sClass )\n\t\t\t{\n\t\t\t\toOptions.sClass = oOptions.className;\n\t\t\t}\n\n\t\t\t$.extend( oCol, oOptions );\n\t\t\t_fnMap( oCol, oOptions, \"sWidth\", \"sWidthOrig\" );\n\n\t\t\t/* iDataSort to be applied (backwards compatibility), but aDataSort will take\n\t\t\t * priority if defined\n\t\t\t */\n\t\t\tif ( typeof oOptions.iDataSort === 'number' )\n\t\t\t{\n\t\t\t\toCol.aDataSort = [ oOptions.iDataSort ];\n\t\t\t}\n\t\t\t_fnMap( oCol, oOptions, \"aDataSort\" );\n\t\t}\n\n\t\t/* Cache the data get and set functions for speed */\n\t\tvar mDataSrc = oCol.mData;\n\t\tvar mData = _fnGetObjectDataFn( mDataSrc );\n\t\tvar mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;\n\n\t\tvar attrTest = function( src ) {\n\t\t\treturn typeof src === 'string' && src.indexOf('@') !== -1;\n\t\t};\n\t\toCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (\n\t\t\tattrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)\n\t\t);\n\n\t\toCol.fnGetData = function (oData, sSpecific) {\n\t\t\tvar innerData = mData( oData, sSpecific );\n\n\t\t\tif ( oCol.mRender && (sSpecific && sSpecific !== '') )\n\t\t\t{\n\t\t\t\treturn mRender( innerData, sSpecific, oData );\n\t\t\t}\n\t\t\treturn innerData;\n\t\t};\n\t\toCol.fnSetData = _fnSetObjectDataFn( mDataSrc );\n\n\t\t/* Feature sorting overrides column specific when off */\n\t\tif ( !oSettings.oFeatures.bSort )\n\t\t{\n\t\t\toCol.bSortable = false;\n\t\t}\n\n\t\t/* Check that the class assignment is correct for sorting */\n\t\tvar bAsc = $.inArray('asc', oCol.asSorting) !== -1;\n\t\tvar bDesc = $.inArray('desc', oCol.asSorting) !== -1;\n\t\tif ( !oCol.bSortable || (!bAsc && !bDesc) )\n\t\t{\n\t\t\toCol.sSortingClass = oClasses.sSortableNone;\n\t\t\toCol.sSortingClassJUI = \"\";\n\t\t}\n\t\telse if ( bAsc && !bDesc )\n\t\t{\n\t\t\toCol.sSortingClass = oClasses.sSortableAsc;\n\t\t\toCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;\n\t\t}\n\t\telse if ( !bAsc && bDesc )\n\t\t{\n\t\t\toCol.sSortingClass = oClasses.sSortableDesc;\n\t\t\toCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;\n\t\t}\n\t}\n\n\n\t/**\n\t * Adjust the table column widths for new data. Note: you would probably want to\n\t * do a redraw after calling this function!\n\t *  @param {object} settings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAdjustColumnSizing ( settings )\n\t{\n\t\t/* Not interested in doing column width calculation if auto-width is disabled */\n\t\tif ( settings.oFeatures.bAutoWidth !== false )\n\t\t{\n\t\t\tvar columns = settings.aoColumns;\n\n\t\t\t_fnCalculateColumnWidths( settings );\n\t\t\tfor ( var i=0 , iLen=columns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tcolumns[i].nTh.style.width = columns[i].sWidth;\n\t\t\t}\n\t\t}\n\n\t\tvar scroll = settings.oScroll;\n\t\tif ( scroll.sY !== '' || scroll.sX !== '')\n\t\t{\n\t\t\t_fnScrollDraw( settings );\n\t\t}\n\n\t\t_fnCallbackFire( settings, null, 'column-sizing', [settings] );\n\t}\n\n\n\t/**\n\t * Covert the index of a visible column to the index in the data array (take account\n\t * of hidden columns)\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iMatch Visible column index to lookup\n\t *  @returns {int} i the data index\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnVisibleToColumnIndex( oSettings, iMatch )\n\t{\n\t\tvar aiVis = _fnGetColumns( oSettings, 'bVisible' );\n\n\t\treturn typeof aiVis[iMatch] === 'number' ?\n\t\t\taiVis[iMatch] :\n\t\t\tnull;\n\t}\n\n\n\t/**\n\t * Covert the index of an index in the data array and convert it to the visible\n\t *   column index (take account of hidden columns)\n\t *  @param {int} iMatch Column index to lookup\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {int} i the data index\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnColumnIndexToVisible( oSettings, iMatch )\n\t{\n\t\tvar aiVis = _fnGetColumns( oSettings, 'bVisible' );\n\t\tvar iPos = $.inArray( iMatch, aiVis );\n\n\t\treturn iPos !== -1 ? iPos : null;\n\t}\n\n\n\t/**\n\t * Get the number of visible columns\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {int} i the number of visible columns\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnVisbleColumns( oSettings )\n\t{\n\t\treturn _fnGetColumns( oSettings, 'bVisible' ).length;\n\t}\n\n\n\t/**\n\t * Get an array of column indexes that match a given property\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {string} sParam Parameter in aoColumns to look for - typically\n\t *    bVisible or bSearchable\n\t *  @returns {array} Array of indexes with matched properties\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetColumns( oSettings, sParam )\n\t{\n\t\tvar a = [];\n\n\t\t$.map( oSettings.aoColumns, function(val, i) {\n\t\t\tif ( val[sParam] ) {\n\t\t\t\ta.push( i );\n\t\t\t}\n\t\t} );\n\n\t\treturn a;\n\t}\n\n\n\tfunction _fnColumnTypes ( settings )\n\t{\n\t\tvar columns = settings.aoColumns;\n\t\tvar data = settings.aoData;\n\t\tvar types = DataTable.ext.type.detect;\n\t\tvar i, ien, j, jen, k, ken;\n\t\tvar col, cell, detectedType, cache;\n\n\t\t// For each column, spin over the\n\t\tfor ( i=0, ien=columns.length ; i<ien ; i++ ) {\n\t\t\tcol = columns[i];\n\t\t\tcache = [];\n\n\t\t\tif ( ! col.sType && col._sManualType ) {\n\t\t\t\tcol.sType = col._sManualType;\n\t\t\t}\n\t\t\telse if ( ! col.sType ) {\n\t\t\t\tfor ( j=0, jen=types.length ; j<jen ; j++ ) {\n\t\t\t\t\tfor ( k=0, ken=data.length ; k<ken ; k++ ) {\n\t\t\t\t\t\t// Use a cache array so we only need to get the type data\n\t\t\t\t\t\t// from the formatter once (when using multiple detectors)\n\t\t\t\t\t\tif ( cache[k] === undefined ) {\n\t\t\t\t\t\t\tcache[k] = _fnGetCellData( settings, k, i, 'type' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdetectedType = types[j]( cache[k] );\n\n\t\t\t\t\t\t// Doesn't match, so break early, since this type can't\n\t\t\t\t\t\t// apply to this column. Also, HTML is a special case since\n\t\t\t\t\t\t// it is so similar to `string`. Just a single match is\n\t\t\t\t\t\t// needed for a column to be html type\n\t\t\t\t\t\tif ( ! detectedType || detectedType === 'html' ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Type is valid for all data points in the column - use this\n\t\t\t\t\t// type\n\t\t\t\t\tif ( detectedType ) {\n\t\t\t\t\t\tcol.sType = detectedType;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fall back - if no type was detected, always use string\n\t\t\t\tif ( ! col.sType ) {\n\t\t\t\t\tcol.sType = 'string';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Take the column definitions and static columns arrays and calculate how\n\t * they relate to column indexes. The callback function will then apply the\n\t * definition found for a column to a suitable configuration object.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {array} aoColDefs The aoColumnDefs array that is to be applied\n\t *  @param {array} aoCols The aoColumns array that defines columns individually\n\t *  @param {function} fn Callback function - takes two parameters, the calculated\n\t *    column index and the definition for that column.\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )\n\t{\n\t\tvar i, iLen, j, jLen, k, kLen, def;\n\n\t\t// Column definitions with aTargets\n\t\tif ( aoColDefs )\n\t\t{\n\t\t\t/* Loop over the definitions array - loop in reverse so first instance has priority */\n\t\t\tfor ( i=aoColDefs.length-1 ; i>=0 ; i-- )\n\t\t\t{\n\t\t\t\tdef = aoColDefs[i];\n\n\t\t\t\t/* Each definition can target multiple columns, as it is an array */\n\t\t\t\tvar aTargets = def.targets !== undefined ?\n\t\t\t\t\tdef.targets :\n\t\t\t\t\tdef.aTargets;\n\n\t\t\t\tif ( ! $.isArray( aTargets ) )\n\t\t\t\t{\n\t\t\t\t\taTargets = [ aTargets ];\n\t\t\t\t}\n\n\t\t\t\tfor ( j=0, jLen=aTargets.length ; j<jLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tif ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Add columns that we don't yet know about */\n\t\t\t\t\t\twhile( oSettings.aoColumns.length <= aTargets[j] )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_fnAddColumn( oSettings );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* Integer, basic index */\n\t\t\t\t\t\tfn( aTargets[j], def );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Negative integer, right to left column counting */\n\t\t\t\t\t\tfn( oSettings.aoColumns.length+aTargets[j], def );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( typeof aTargets[j] === 'string' )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Class name matching on TH element */\n\t\t\t\t\t\tfor ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( aTargets[j] == \"_all\" ||\n\t\t\t\t\t\t\t     $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfn( k, def );\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\t// Statically defined columns array\n\t\tif ( aoCols )\n\t\t{\n\t\t\tfor ( i=0, iLen=aoCols.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tfn( i, aoCols[i] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Add a data array to the table, creating DOM node etc. This is the parallel to\n\t * _fnGatherData, but for adding rows from a Javascript source, rather than a\n\t * DOM source.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {array} aData data array to be added\n\t *  @param {node} [nTr] TR element to add to the table - optional. If not given,\n\t *    DataTables will create a row automatically\n\t *  @param {array} [anTds] Array of TD|TH elements for the row - must be given\n\t *    if nTr is.\n\t *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAddData ( oSettings, aDataIn, nTr, anTds )\n\t{\n\t\t/* Create the object for storing information about this new row */\n\t\tvar iRow = oSettings.aoData.length;\n\t\tvar oData = $.extend( true, {}, DataTable.models.oRow, {\n\t\t\tsrc: nTr ? 'dom' : 'data'\n\t\t} );\n\n\t\toData._aData = aDataIn;\n\t\toSettings.aoData.push( oData );\n\n\t\t/* Create the cells */\n\t\tvar nTd, sThisType;\n\t\tvar columns = oSettings.aoColumns;\n\t\tfor ( var i=0, iLen=columns.length ; i<iLen ; i++ )\n\t\t{\n\t\t\t// When working with a row, the data source object must be populated. In\n\t\t\t// all other cases, the data source object is already populated, so we\n\t\t\t// don't overwrite it, which might break bindings etc\n\t\t\tif ( nTr ) {\n\t\t\t\t_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );\n\t\t\t}\n\t\t\tcolumns[i].sType = null;\n\t\t}\n\n\t\t/* Add to the display array */\n\t\toSettings.aiDisplayMaster.push( iRow );\n\n\t\t/* Create the DOM information */\n\t\tif ( !oSettings.oFeatures.bDeferRender )\n\t\t{\n\t\t\t_fnCreateTr( oSettings, iRow, nTr, anTds );\n\t\t}\n\n\t\treturn iRow;\n\t}\n\n\n\t/**\n\t * Add one or more TR elements to the table. Generally we'd expect to\n\t * use this for reading data from a DOM sourced table, but it could be\n\t * used for an TR element. Note that if a TR is given, it is used (i.e.\n\t * it is not cloned).\n\t *  @param {object} settings dataTables settings object\n\t *  @param {array|node|jQuery} trs The TR element(s) to add to the table\n\t *  @returns {array} Array of indexes for the added rows\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAddTr( settings, trs )\n\t{\n\t\tvar row;\n\n\t\t// Allow an individual node to be passed in\n\t\tif ( ! (trs instanceof $) ) {\n\t\t\ttrs = $(trs);\n\t\t}\n\n\t\treturn trs.map( function (i, el) {\n\t\t\trow = _fnGetRowElements( settings, el );\n\t\t\treturn _fnAddData( settings, row.data, el, row.cells );\n\t\t} );\n\t}\n\n\n\t/**\n\t * Take a TR element and convert it to an index in aoData\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {node} n the TR element to find\n\t *  @returns {int} index if the node is found, null if not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnNodeToDataIndex( oSettings, n )\n\t{\n\t\treturn (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;\n\t}\n\n\n\t/**\n\t * Take a TD element and convert it into a column data index (not the visible index)\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iRow The row number the TD/TH can be found in\n\t *  @param {node} n The TD/TH element to find\n\t *  @returns {int} index if the node is found, -1 if not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnNodeToColumnIndex( oSettings, iRow, n )\n\t{\n\t\treturn $.inArray( n, oSettings.aoData[ iRow ].anCells );\n\t}\n\n\n\t/**\n\t * Get an array of data for a given row from the internal data cache\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iRow aoData row id\n\t *  @param {string} sSpecific data get type ('type' 'filter' 'sort')\n\t *  @param {array} aiColumns Array of column indexes to get data from\n\t *  @returns {array} Data array\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetRowData( oSettings, iRow, sSpecific, aiColumns )\n\t{\n\t\tvar out = [];\n\t\tfor ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tout.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) );\n\t\t}\n\t\treturn out;\n\t}\n\n\n\t/**\n\t * Get the data for a given cell from the internal cache, taking into account data mapping\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iRow aoData row id\n\t *  @param {int} iCol Column index\n\t *  @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')\n\t *  @returns {*} Cell data\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetCellData( oSettings, iRow, iCol, sSpecific )\n\t{\n\t\tvar oCol = oSettings.aoColumns[iCol];\n\t\tvar oData = oSettings.aoData[iRow]._aData;\n\t\tvar sData = oCol.fnGetData( oData, sSpecific );\n\n\t\tif ( sData === undefined )\n\t\t{\n\t\t\tif ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )\n\t\t\t{\n\t\t\t\t_fnLog( oSettings, 0, \"Requested unknown parameter \"+\n\t\t\t\t\t(typeof oCol.mData=='function' ? '{function}' : \"'\"+oCol.mData+\"'\")+\n\t\t\t\t\t\" for row \"+iRow, 4 );\n\t\t\t\toSettings.iDrawError = oSettings.iDraw;\n\t\t\t}\n\t\t\treturn oCol.sDefaultContent;\n\t\t}\n\n\t\t/* When the data source is null, we can use default column data */\n\t\tif ( (sData === oData || sData === null) && oCol.sDefaultContent !== null )\n\t\t{\n\t\t\tsData = oCol.sDefaultContent;\n\t\t}\n\t\telse if ( typeof sData === 'function' )\n\t\t{\n\t\t\t// If the data source is a function, then we run it and use the return\n\t\t\treturn sData();\n\t\t}\n\n\t\tif ( sData === null && sSpecific == 'display' )\n\t\t{\n\t\t\treturn '';\n\t\t}\n\t\treturn sData;\n\t}\n\n\n\t/**\n\t * Set the value for a specific cell, into the internal data cache\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iRow aoData row id\n\t *  @param {int} iCol Column index\n\t *  @param {*} val Value to set\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSetCellData( oSettings, iRow, iCol, val )\n\t{\n\t\tvar oCol = oSettings.aoColumns[iCol];\n\t\tvar oData = oSettings.aoData[iRow]._aData;\n\n\t\toCol.fnSetData( oData, val );\n\t}\n\n\n\t// Private variable that is used to match action syntax in the data property object\n\tvar __reArray = /\\[.*?\\]$/;\n\tvar __reFn = /\\(\\)$/;\n\n\t/**\n\t * Split string on periods, taking into account escaped periods\n\t * @param  {string} str String to split\n\t * @return {array} Split string\n\t */\n\tfunction _fnSplitObjNotation( str )\n\t{\n\t\treturn $.map( str.match(/(\\\\.|[^\\.])+/g), function ( s ) {\n\t\t\treturn s.replace('\\\\.', '.');\n\t\t} );\n\t}\n\n\n\t/**\n\t * Return a function that can be used to get data from a source object, taking\n\t * into account the ability to use nested objects as a source\n\t *  @param {string|int|function} mSource The data source for the object\n\t *  @returns {function} Data get function\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetObjectDataFn( mSource )\n\t{\n\t\tif ( $.isPlainObject( mSource ) )\n\t\t{\n\t\t\t/* Build an object of get functions, and wrap them in a single call */\n\t\t\tvar o = {};\n\t\t\t$.each( mSource, function (key, val) {\n\t\t\t\tif ( val ) {\n\t\t\t\t\to[key] = _fnGetObjectDataFn( val );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\treturn function (data, type, extra) {\n\t\t\t\treturn o[ o[type] !== undefined ? type : '_' ](data, type, extra);\n\t\t\t};\n\t\t}\n\t\telse if ( mSource === null )\n\t\t{\n\t\t\t/* Give an empty string for rendering / sorting etc */\n\t\t\treturn function (data, type) {\n\t\t\t\treturn data;\n\t\t\t};\n\t\t}\n\t\telse if ( typeof mSource === 'function' )\n\t\t{\n\t\t\treturn function (data, type, extra) {\n\t\t\t\treturn mSource( data, type, extra );\n\t\t\t};\n\t\t}\n\t\telse if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||\n\t\t\t      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )\n\t\t{\n\t\t\t/* If there is a . in the source string then the data source is in a\n\t\t\t * nested object so we loop over the data for each level to get the next\n\t\t\t * level down. On each loop we test for undefined, and if found immediately\n\t\t\t * return. This allows entire objects to be missing and sDefaultContent to\n\t\t\t * be used if defined, rather than throwing an error\n\t\t\t */\n\t\t\tvar fetchData = function (data, type, src) {\n\t\t\t\tvar arrayNotation, funcNotation, out, innerSrc;\n\n\t\t\t\tif ( src !== \"\" )\n\t\t\t\t{\n\t\t\t\t\tvar a = _fnSplitObjNotation( src );\n\n\t\t\t\t\tfor ( var i=0, iLen=a.length ; i<iLen ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\t// Check if we are dealing with special notation\n\t\t\t\t\t\tarrayNotation = a[i].match(__reArray);\n\t\t\t\t\t\tfuncNotation = a[i].match(__reFn);\n\n\t\t\t\t\t\tif ( arrayNotation )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Array notation\n\t\t\t\t\t\t\ta[i] = a[i].replace(__reArray, '');\n\n\t\t\t\t\t\t\t// Condition allows simply [] to be passed in\n\t\t\t\t\t\t\tif ( a[i] !== \"\" ) {\n\t\t\t\t\t\t\t\tdata = data[ a[i] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tout = [];\n\n\t\t\t\t\t\t\t// Get the remainder of the nested object to get\n\t\t\t\t\t\t\ta.splice( 0, i+1 );\n\t\t\t\t\t\t\tinnerSrc = a.join('.');\n\n\t\t\t\t\t\t\t// Traverse each entry in the array getting the properties requested\n\t\t\t\t\t\t\tfor ( var j=0, jLen=data.length ; j<jLen ; j++ ) {\n\t\t\t\t\t\t\t\tout.push( fetchData( data[j], type, innerSrc ) );\n\t\t\t\t\t\t\t}\n\n\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// is used to join the strings together, otherwise an array is returned\n\t\t\t\t\t\t\tvar join = arrayNotation[0].substring(1, arrayNotation[0].length-1);\n\t\t\t\t\t\t\tdata = (join===\"\") ? out : out.join(join);\n\n\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// of the source requested, so we exit from the loop\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( funcNotation )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Function call\n\t\t\t\t\t\t\ta[i] = a[i].replace(__reFn, '');\n\t\t\t\t\t\t\tdata = data[ a[i] ]();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( data === null || data[ a[i] ] === undefined )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn undefined;\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\t\t}\n\n\t\t\t\treturn data;\n\t\t\t};\n\n\t\t\treturn function (data, type) {\n\t\t\t\treturn fetchData( data, type, mSource );\n\t\t\t};\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Array or flat object mapping */\n\t\t\treturn function (data, type) {\n\t\t\t\treturn data[mSource];\n\t\t\t};\n\t\t}\n\t}\n\n\n\t/**\n\t * Return a function that can be used to set data from a source object, taking\n\t * into account the ability to use nested objects as a source\n\t *  @param {string|int|function} mSource The data source for the object\n\t *  @returns {function} Data set function\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSetObjectDataFn( mSource )\n\t{\n\t\tif ( $.isPlainObject( mSource ) )\n\t\t{\n\t\t\t/* Unlike get, only the underscore (global) option is used for for\n\t\t\t * setting data since we don't know the type here. This is why an object\n\t\t\t * option is not documented for `mData` (which is read/write), but it is\n\t\t\t * for `mRender` which is read only.\n\t\t\t */\n\t\t\treturn _fnSetObjectDataFn( mSource._ );\n\t\t}\n\t\telse if ( mSource === null )\n\t\t{\n\t\t\t/* Nothing to do when the data source is null */\n\t\t\treturn function (data, val) {};\n\t\t}\n\t\telse if ( typeof mSource === 'function' )\n\t\t{\n\t\t\treturn function (data, val) {\n\t\t\t\tmSource( data, 'set', val );\n\t\t\t};\n\t\t}\n\t\telse if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||\n\t\t\t      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )\n\t\t{\n\t\t\t/* Like the get, we need to get data from a nested object */\n\t\t\tvar setData = function (data, val, src) {\n\t\t\t\tvar a = _fnSplitObjNotation( src ), b;\n\t\t\t\tvar aLast = a[a.length-1];\n\t\t\t\tvar arrayNotation, funcNotation, o, innerSrc;\n\n\t\t\t\tfor ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\t// Check if we are dealing with an array notation request\n\t\t\t\t\tarrayNotation = a[i].match(__reArray);\n\t\t\t\t\tfuncNotation = a[i].match(__reFn);\n\n\t\t\t\t\tif ( arrayNotation )\n\t\t\t\t\t{\n\t\t\t\t\t\ta[i] = a[i].replace(__reArray, '');\n\t\t\t\t\t\tdata[ a[i] ] = [];\n\n\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\tb = a.slice();\n\t\t\t\t\t\tb.splice( 0, i+1 );\n\t\t\t\t\t\tinnerSrc = b.join('.');\n\n\t\t\t\t\t\t// Traverse each entry in the array setting the properties requested\n\t\t\t\t\t\tfor ( var j=0, jLen=val.length ; j<jLen ; j++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\to = {};\n\t\t\t\t\t\t\tsetData( o, val[j], innerSrc );\n\t\t\t\t\t\t\tdata[ a[i] ].push( o );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// The inner call to setData has already traversed through the remainder\n\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\treturn;\n\t\t\t\t\t}\n\t\t\t\t\telse if ( funcNotation )\n\t\t\t\t\t{\n\t\t\t\t\t\t// Function call\n\t\t\t\t\t\ta[i] = a[i].replace(__reFn, '');\n\t\t\t\t\t\tdata = data[ a[i] ]( val );\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the nested object doesn't currently exist - since we are\n\t\t\t\t\t// trying to set the value - create it\n\t\t\t\t\tif ( data[ a[i] ] === null || data[ a[i] ] === undefined )\n\t\t\t\t\t{\n\t\t\t\t\t\tdata[ a[i] ] = {};\n\t\t\t\t\t}\n\t\t\t\t\tdata = data[ a[i] ];\n\t\t\t\t}\n\n\t\t\t\t// Last item in the input - i.e, the actual set\n\t\t\t\tif ( aLast.match(__reFn ) )\n\t\t\t\t{\n\t\t\t\t\t// Function call\n\t\t\t\t\tdata = data[ aLast.replace(__reFn, '') ]( val );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\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[ aLast.replace(__reArray, '') ] = val;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\treturn function (data, val) {\n\t\t\t\treturn setData( data, val, mSource );\n\t\t\t};\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Array or flat object mapping */\n\t\t\treturn function (data, val) {\n\t\t\t\tdata[mSource] = val;\n\t\t\t};\n\t\t}\n\t}\n\n\n\t/**\n\t * Return an array with the full table data\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns array {array} aData Master data array\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetDataMaster ( settings )\n\t{\n\t\treturn _pluck( settings.aoData, '_aData' );\n\t}\n\n\n\t/**\n\t * Nuke the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnClearTable( settings )\n\t{\n\t\tsettings.aoData.length = 0;\n\t\tsettings.aiDisplayMaster.length = 0;\n\t\tsettings.aiDisplay.length = 0;\n\t}\n\n\n\t /**\n\t * Take an array of integers (index array) and remove a target integer (value - not\n\t * the key!)\n\t *  @param {array} a Index array to target\n\t *  @param {int} iTarget value to find\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnDeleteIndex( a, iTarget, splice )\n\t{\n\t\tvar iTargetIndex = -1;\n\n\t\tfor ( var i=0, iLen=a.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tif ( a[i] == iTarget )\n\t\t\t{\n\t\t\t\tiTargetIndex = i;\n\t\t\t}\n\t\t\telse if ( a[i] > iTarget )\n\t\t\t{\n\t\t\t\ta[i]--;\n\t\t\t}\n\t\t}\n\n\t\tif ( iTargetIndex != -1 && splice === undefined )\n\t\t{\n\t\t\ta.splice( iTargetIndex, 1 );\n\t\t}\n\t}\n\n\n\t/**\n\t * Mark cached data as invalid such that a re-read of the data will occur when\n\t * the cached data is next requested. Also update from the data source object.\n\t *\n\t * @param {object} settings DataTables settings object\n\t * @param  {int}    rowIdx   Row index to invalidate\n\t * @memberof DataTable#oApi\n\t *\n\t * @todo For the modularisation of v1.11 this will need to become a callback, so\n\t *   the sort and filter methods can subscribe to it. That will required\n\t *   initialisation options for sorting, which is why it is not already baked in\n\t */\n\tfunction _fnInvalidateRow( settings, rowIdx, src, column )\n\t{\n\t\tvar row = settings.aoData[ rowIdx ];\n\t\tvar i, ien;\n\n\t\t// Are we reading last data from DOM or the data object?\n\t\tif ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {\n\t\t\t// Read the data from the DOM\n\t\t\trow._aData = _fnGetRowElements( settings, row.nTr ).data;\n\t\t}\n\t\telse {\n\t\t\t// Reading from data object, update the DOM\n\t\t\tvar cells = row.anCells;\n\n\t\t\tfor ( i=0, ien=cells.length ; i<ien ; i++ ) {\n\t\t\t\tcells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );\n\t\t\t}\n\t\t}\n\n\t\trow._aSortData = null;\n\t\trow._aFilterData = null;\n\n\t\t// Invalidate the type for a specific column (if given) or all columns since\n\t\t// the data might have changed\n\t\tvar cols = settings.aoColumns;\n\t\tif ( column !== undefined ) {\n\t\t\tcols[ column ].sType = null;\n\t\t}\n\t\telse {\n\t\t\tfor ( i=0, ien=cols.length ; i<ien ; i++ ) {\n\t\t\t\tcols[i].sType = null;\n\t\t\t}\n\t\t}\n\n\t\t// Update DataTables special `DT_*` attributes for the row\n\t\t_fnRowAttributes( row );\n\t}\n\n\n\t/**\n\t * Build a data source object from an HTML row, reading the contents of the\n\t * cells that are in the row.\n\t *\n\t * @param {object} settings DataTables settings object\n\t * @param {node} TR element from which to read data\n\t * @returns {object} Object with two parameters: `data` the data read, in\n\t *   document order, and `cells` and array of nodes (they can be useful to the\n\t *   caller, so rather than needing a second traversal to get them, just return\n\t *   them from here).\n\t * @memberof DataTable#oApi\n\t */\n\tfunction _fnGetRowElements( settings, row )\n\t{\n\t\tvar\n\t\t\td = [],\n\t\t\ttds = [],\n\t\t\ttd = row.firstChild,\n\t\t\tname, col, o, i=0, contents,\n\t\t\tcolumns = settings.aoColumns;\n\n\t\tvar attr = function ( str, data, td  ) {\n\t\t\tif ( typeof str === 'string' ) {\n\t\t\t\tvar idx = str.indexOf('@');\n\n\t\t\t\tif ( idx !== -1 ) {\n\t\t\t\t\tvar src = str.substring( idx+1 );\n\t\t\t\t\to[ '@'+src ] = td.getAttribute( src );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\twhile ( td ) {\n\t\t\tname = td.nodeName.toUpperCase();\n\n\t\t\tif ( name == \"TD\" || name == \"TH\" ) {\n\t\t\t\tcol = columns[i];\n\t\t\t\tcontents = $.trim(td.innerHTML);\n\n\t\t\t\tif ( col && col._bAttrSrc ) {\n\t\t\t\t\to = {\n\t\t\t\t\t\tdisplay: contents\n\t\t\t\t\t};\n\n\t\t\t\t\tattr( col.mData.sort, o, td );\n\t\t\t\t\tattr( col.mData.type, o, td );\n\t\t\t\t\tattr( col.mData.filter, o, td );\n\n\t\t\t\t\td.push( o );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\td.push( contents );\n\t\t\t\t}\n\n\t\t\t\ttds.push( td );\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\ttd = td.nextSibling;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: d,\n\t\t\tcells: tds\n\t\t};\n\t}\n\t/**\n\t * Create a new TR element (and it's TD children) for a row\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {int} iRow Row to consider\n\t *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,\n\t *    DataTables will create a row automatically\n\t *  @param {array} [anTds] Array of TD|TH elements for the row - must be given\n\t *    if nTr is.\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnCreateTr ( oSettings, iRow, nTrIn, anTds )\n\t{\n\t\tvar\n\t\t\trow = oSettings.aoData[iRow],\n\t\t\trowData = row._aData,\n\t\t\tcells = [],\n\t\t\tnTr, nTd, oCol,\n\t\t\ti, iLen;\n\n\t\tif ( row.nTr === null )\n\t\t{\n\t\t\tnTr = nTrIn || document.createElement('tr');\n\n\t\t\trow.nTr = nTr;\n\t\t\trow.anCells = cells;\n\n\t\t\t/* Use a private property on the node to allow reserve mapping from the node\n\t\t\t * to the aoData array for fast look up\n\t\t\t */\n\t\t\tnTr._DT_RowIndex = iRow;\n\n\t\t\t/* Special parameters can be given by the data source to be used on the row */\n\t\t\t_fnRowAttributes( row );\n\n\t\t\t/* Process each column */\n\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\toCol = oSettings.aoColumns[i];\n\n\t\t\t\tnTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );\n\t\t\t\tcells.push( nTd );\n\n\t\t\t\t// Need to create the HTML if new, or if a rendering function is defined\n\t\t\t\tif ( !nTrIn || oCol.mRender || oCol.mData !== i )\n\t\t\t\t{\n\t\t\t\t\tnTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );\n\t\t\t\t}\n\n\t\t\t\t/* Add user defined class */\n\t\t\t\tif ( oCol.sClass !== null )\n\t\t\t\t{\n\t\t\t\t\tnTd.className += ' '+oCol.sClass;\n\t\t\t\t}\n\n\t\t\t\t// Visibility - add or remove as required\n\t\t\t\tif ( oCol.bVisible && ! nTrIn )\n\t\t\t\t{\n\t\t\t\t\tnTr.appendChild( nTd );\n\t\t\t\t}\n\t\t\t\telse if ( ! oCol.bVisible && nTrIn )\n\t\t\t\t{\n\t\t\t\t\tnTd.parentNode.removeChild( nTd );\n\t\t\t\t}\n\n\t\t\t\tif ( oCol.fnCreatedCell )\n\t\t\t\t{\n\t\t\t\t\toCol.fnCreatedCell.call( oSettings.oInstance,\n\t\t\t\t\t\tnTd, _fnGetCellData( oSettings, iRow, i, 'display' ), rowData, iRow, i\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );\n\t\t}\n\t}\n\n\n\t/**\n\t * Add attributes to a row based on the special `DT_*` parameters in a data\n\t * source object.\n\t *  @param {object} DataTables row object for the row to be modified\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnRowAttributes( row )\n\t{\n\t\tvar tr = row.nTr;\n\t\tvar data = row._aData;\n\n\t\tif ( tr ) {\n\t\t\tif ( data.DT_RowId ) {\n\t\t\t\ttr.id = data.DT_RowId;\n\t\t\t}\n\n\t\t\tif ( data.DT_RowClass ) {\n\t\t\t\t// Remove any classes added by DT_RowClass before\n\t\t\t\tvar a = data.DT_RowClass.split(' ');\n\t\t\t\trow.__rowc = row.__rowc ?\n\t\t\t\t\t_unique( row.__rowc.concat( a ) ) :\n\t\t\t\t\ta;\n\n\t\t\t\t$(tr)\n\t\t\t\t\t.removeClass( row.__rowc.join(' ') )\n\t\t\t\t\t.addClass( data.DT_RowClass );\n\t\t\t}\n\n\t\t\tif ( data.DT_RowData ) {\n\t\t\t\t$(tr).data( data.DT_RowData );\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Create the HTML header for the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnBuildHead( oSettings )\n\t{\n\t\tvar i, ien, cell, row, column;\n\t\tvar thead = oSettings.nTHead;\n\t\tvar tfoot = oSettings.nTFoot;\n\t\tvar createHeader = $('th, td', thead).length === 0;\n\t\tvar classes = oSettings.oClasses;\n\t\tvar columns = oSettings.aoColumns;\n\n\t\tif ( createHeader ) {\n\t\t\trow = $('<tr/>').appendTo( thead );\n\t\t}\n\n\t\tfor ( i=0, ien=columns.length ; i<ien ; i++ ) {\n\t\t\tcolumn = columns[i];\n\t\t\tcell = $( column.nTh ).addClass( column.sClass );\n\n\t\t\tif ( createHeader ) {\n\t\t\t\tcell.appendTo( row );\n\t\t\t}\n\n\t\t\t// 1.11 move into sorting\n\t\t\tif ( oSettings.oFeatures.bSort ) {\n\t\t\t\tcell.addClass( column.sSortingClass );\n\n\t\t\t\tif ( column.bSortable !== false ) {\n\t\t\t\t\tcell\n\t\t\t\t\t\t.attr( 'tabindex', oSettings.iTabIndex )\n\t\t\t\t\t\t.attr( 'aria-controls', oSettings.sTableId );\n\n\t\t\t\t\t_fnSortAttachListener( oSettings, column.nTh, i );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( column.sTitle != cell.html() ) {\n\t\t\t\tcell.html( column.sTitle );\n\t\t\t}\n\n\t\t\t_fnRenderer( oSettings, 'header' )(\n\t\t\t\toSettings, cell, column, i, classes\n\t\t\t);\n\t\t}\n\n\t\tif ( createHeader ) {\n\t\t\t_fnDetectHeader( oSettings.aoHeader, thead );\n\t\t}\n\n\t\t/* ARIA role for the rows */\n\t\t$(thead).find('>tr').attr('role', 'row');\n\n\t\t/* Deal with the footer - add classes if required */\n\t\t$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );\n\t\t$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );\n\n\t\t// Cache the footer cells. Note that we only take the cells from the first\n\t\t// row in the footer. If there is more than one row the user wants to\n\t\t// interact with, they need to use the table().foot() method. Note also this\n\t\t// allows cells to be used for multiple columns using colspan\n\t\tif ( tfoot !== null ) {\n\t\t\tvar cells = oSettings.aoFooter[0];\n\n\t\t\tfor ( i=0, ien=cells.length ; i<ien ; i++ ) {\n\t\t\t\tcolumn = columns[i];\n\t\t\t\tcolumn.nTf = cells[i].cell;\n\n\t\t\t\tif ( column.sClass ) {\n\t\t\t\t\t$(column.nTf).addClass( column.sClass );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Draw the header (or footer) element based on the column visibility states. The\n\t * methodology here is to use the layout array from _fnDetectHeader, modified for\n\t * the instantaneous column visibility, to construct the new layout. The grid is\n\t * traversed over cell at a time in a rows x columns grid fashion, although each\n\t * cell insert can cover multiple elements in the grid - which is tracks using the\n\t * aApplied array. Cell inserts in the grid will only occur where there isn't\n\t * already a cell in that position.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param array {objects} aoSource Layout array from _fnDetectHeader\n\t *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnDrawHead( oSettings, aoSource, bIncludeHidden )\n\t{\n\t\tvar i, iLen, j, jLen, k, kLen, n, nLocalTr;\n\t\tvar aoLocal = [];\n\t\tvar aApplied = [];\n\t\tvar iColumns = oSettings.aoColumns.length;\n\t\tvar iRowspan, iColspan;\n\n\t\tif ( ! aoSource )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (  bIncludeHidden === undefined )\n\t\t{\n\t\t\tbIncludeHidden = false;\n\t\t}\n\n\t\t/* Make a copy of the master layout array, but without the visible columns in it */\n\t\tfor ( i=0, iLen=aoSource.length ; i<iLen ; i++ )\n\t\t{\n\t\t\taoLocal[i] = aoSource[i].slice();\n\t\t\taoLocal[i].nTr = aoSource[i].nTr;\n\n\t\t\t/* Remove any columns which are currently hidden */\n\t\t\tfor ( j=iColumns-1 ; j>=0 ; j-- )\n\t\t\t{\n\t\t\t\tif ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )\n\t\t\t\t{\n\t\t\t\t\taoLocal[i].splice( j, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Prep the applied array - it needs an element for each row */\n\t\t\taApplied.push( [] );\n\t\t}\n\n\t\tfor ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tnLocalTr = aoLocal[i].nTr;\n\n\t\t\t/* All cells are going to be replaced, so empty out the row */\n\t\t\tif ( nLocalTr )\n\t\t\t{\n\t\t\t\twhile( (n = nLocalTr.firstChild) )\n\t\t\t\t{\n\t\t\t\t\tnLocalTr.removeChild( n );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )\n\t\t\t{\n\t\t\t\tiRowspan = 1;\n\t\t\t\tiColspan = 1;\n\n\t\t\t\t/* Check to see if there is already a cell (row/colspan) covering our target\n\t\t\t\t * insert point. If there is, then there is nothing to do.\n\t\t\t\t */\n\t\t\t\tif ( aApplied[i][j] === undefined )\n\t\t\t\t{\n\t\t\t\t\tnLocalTr.appendChild( aoLocal[i][j].cell );\n\t\t\t\t\taApplied[i][j] = 1;\n\n\t\t\t\t\t/* Expand the cell to cover as many rows as needed */\n\t\t\t\t\twhile ( aoLocal[i+iRowspan] !== undefined &&\n\t\t\t\t\t        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )\n\t\t\t\t\t{\n\t\t\t\t\t\taApplied[i+iRowspan][j] = 1;\n\t\t\t\t\t\tiRowspan++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Expand the cell to cover as many columns as needed */\n\t\t\t\t\twhile ( aoLocal[i][j+iColspan] !== undefined &&\n\t\t\t\t\t        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Must update the applied array over the rows for the columns */\n\t\t\t\t\t\tfor ( k=0 ; k<iRowspan ; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taApplied[i+k][j+iColspan] = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tiColspan++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Do the actual expansion in the DOM */\n\t\t\t\t\taoLocal[i][j].cell.rowSpan = iRowspan;\n\t\t\t\t\taoLocal[i][j].cell.colSpan = iColspan;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Insert the required TR nodes into the table for display\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnDraw( oSettings )\n\t{\n\t\t/* Provide a pre-callback function which can be used to cancel the draw is false is returned */\n\t\tvar aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );\n\t\tif ( $.inArray( false, aPreDraw ) !== -1 )\n\t\t{\n\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\treturn;\n\t\t}\n\n\t\tvar i, iLen, n;\n\t\tvar anRows = [];\n\t\tvar iRowCount = 0;\n\t\tvar asStripeClasses = oSettings.asStripeClasses;\n\t\tvar iStripes = asStripeClasses.length;\n\t\tvar iOpenRows = oSettings.aoOpenRows.length;\n\t\tvar oLang = oSettings.oLanguage;\n\t\tvar iInitDisplayStart = oSettings.iInitDisplayStart;\n\t\tvar bServerSide = _fnDataSource( oSettings ) == 'ssp';\n\t\tvar aiDisplay = oSettings.aiDisplay;\n\n\t\toSettings.bDrawing = true;\n\n\t\t/* Check and see if we have an initial draw position from state saving */\n\t\tif ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )\n\t\t{\n\t\t\toSettings._iDisplayStart = bServerSide ?\n\t\t\t\tiInitDisplayStart :\n\t\t\t\tiInitDisplayStart >= oSettings.fnRecordsDisplay() ?\n\t\t\t\t\t0 :\n\t\t\t\t\tiInitDisplayStart;\n\n\t\t\toSettings.iInitDisplayStart = -1;\n\t\t}\n\n\t\tvar iDisplayStart = oSettings._iDisplayStart;\n\t\tvar iDisplayEnd = oSettings.fnDisplayEnd();\n\n\t\t/* Server-side processing draw intercept */\n\t\tif ( oSettings.bDeferLoading )\n\t\t{\n\t\t\toSettings.bDeferLoading = false;\n\t\t\toSettings.iDraw++;\n\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t}\n\t\telse if ( !bServerSide )\n\t\t{\n\t\t\toSettings.iDraw++;\n\t\t}\n\t\telse if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif ( aiDisplay.length !== 0 )\n\t\t{\n\t\t\tvar iStart = bServerSide ? 0 : iDisplayStart;\n\t\t\tvar iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;\n\n\t\t\tfor ( var j=iStart ; j<iEnd ; j++ )\n\t\t\t{\n\t\t\t\tvar iDataIndex = aiDisplay[j];\n\t\t\t\tvar aoData = oSettings.aoData[ iDataIndex ];\n\t\t\t\tif ( aoData.nTr === null )\n\t\t\t\t{\n\t\t\t\t\t_fnCreateTr( oSettings, iDataIndex );\n\t\t\t\t}\n\n\t\t\t\tvar nRow = aoData.nTr;\n\n\t\t\t\t/* Remove the old striping classes and then add the new one */\n\t\t\t\tif ( iStripes !== 0 )\n\t\t\t\t{\n\t\t\t\t\tvar sStripe = asStripeClasses[ iRowCount % iStripes ];\n\t\t\t\t\tif ( aoData._sRowStripe != sStripe )\n\t\t\t\t\t{\n\t\t\t\t\t\t$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );\n\t\t\t\t\t\taoData._sRowStripe = sStripe;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Row callback functions - might want to manipulate the row */\n\t\t\t\t_fnCallbackFire( oSettings, 'aoRowCallback', null,\n\t\t\t\t\t[nRow, aoData._aData, iRowCount, j] );\n\n\t\t\t\tanRows.push( nRow );\n\t\t\t\tiRowCount++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Table is empty - create a row with an empty message in it */\n\t\t\tvar sZero = oLang.sZeroRecords;\n\t\t\tif ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )\n\t\t\t{\n\t\t\t\tsZero = oLang.sLoadingRecords;\n\t\t\t}\n\t\t\telse if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )\n\t\t\t{\n\t\t\t\tsZero = oLang.sEmptyTable;\n\t\t\t}\n\n\t\t\tanRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )\n\t\t\t\t.append( $('<td />', {\n\t\t\t\t\t'valign':  'top',\n\t\t\t\t\t'colSpan': _fnVisbleColumns( oSettings ),\n\t\t\t\t\t'class':   oSettings.oClasses.sRowEmpty\n\t\t\t\t} ).html( sZero ) )[0];\n\t\t}\n\n\t\t/* Header and footer callbacks */\n\t\t_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],\n\t\t\t_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );\n\n\t\t_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],\n\t\t\t_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );\n\n\t\tvar body = $(oSettings.nTBody);\n\n\t\tbody.children().detach();\n\t\tbody.append( $(anRows) );\n\n\t\t/* Call all required callback functions for the end of a draw */\n\t\t_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );\n\n\t\t/* Draw is complete, sorting and filtering must be as well */\n\t\toSettings.bSorted = false;\n\t\toSettings.bFiltered = false;\n\t\toSettings.bDrawing = false;\n\t}\n\n\n\t/**\n\t * Redraw the table - taking account of the various features which are enabled\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {boolean} [holdPosition] Keep the current paging position. By default\n\t *    the paging is reset to the first page\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnReDraw( settings, holdPosition )\n\t{\n\t\tvar\n\t\t\tfeatures = settings.oFeatures,\n\t\t\tsort     = features.bSort,\n\t\t\tfilter   = features.bFilter;\n\n\t\tif ( sort ) {\n\t\t\t_fnSort( settings );\n\t\t}\n\n\t\tif ( filter ) {\n\t\t\t_fnFilterComplete( settings, settings.oPreviousSearch );\n\t\t}\n\t\telse {\n\t\t\t// No filtering, so we want to just use the display master\n\t\t\tsettings.aiDisplay = settings.aiDisplayMaster.slice();\n\t\t}\n\n\t\tif ( holdPosition !== true ) {\n\t\t\tsettings._iDisplayStart = 0;\n\t\t}\n\n\t\t_fnDraw( settings );\n\t}\n\n\n\t/**\n\t * Add the options to the page HTML for the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAddOptionsHtml ( oSettings )\n\t{\n\t\t/*\n\t\t * Create a temporary, empty, div which we can later on replace with what we have generated\n\t\t * we do it this way to rendering the 'options' html offline - speed :-)\n\t\t */\n\t\tvar nHolding = $('<div></div>')[0];\n\t\toSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );\n\n\t\t/*\n\t\t * All DataTables are wrapped in a div\n\t\t */\n\t\toSettings.nTableWrapper = $('<div id=\"'+oSettings.sTableId+'_wrapper\" class=\"'+oSettings.oClasses.sWrapper+'\" role=\"grid\"></div>')[0];\n\t\toSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;\n\n\t\t/* Track where we want to insert the option */\n\t\tvar nInsertNode = oSettings.nTableWrapper;\n\n\t\t/* Loop over the user set positioning and place the elements as needed */\n\t\tvar aDom = oSettings.sDom.split('');\n\t\tvar nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;\n\t\tfor ( var i=0 ; i<aDom.length ; i++ )\n\t\t{\n\t\t\tiPushFeature = 0;\n\t\t\tcOption = aDom[i];\n\n\t\t\tif ( cOption == '<' )\n\t\t\t{\n\t\t\t\t/* New container div */\n\t\t\t\tnNewNode = $('<div></div>')[0];\n\n\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\tcNext = aDom[i+1];\n\t\t\t\tif ( cNext == \"'\" || cNext == '\"' )\n\t\t\t\t{\n\t\t\t\t\tsAttr = \"\";\n\t\t\t\t\tj = 2;\n\t\t\t\t\twhile ( aDom[i+j] != cNext )\n\t\t\t\t\t{\n\t\t\t\t\t\tsAttr += aDom[i+j];\n\t\t\t\t\t\tj++;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Replace jQuery UI constants @todo depreciated */\n\t\t\t\t\tif ( sAttr == \"H\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tsAttr = oSettings.oClasses.sJUIHeader;\n\t\t\t\t\t}\n\t\t\t\t\telse if ( sAttr == \"F\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tsAttr = oSettings.oClasses.sJUIFooter;\n\t\t\t\t\t}\n\n\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 * breaks the string into parts and applies them as needed\n\t\t\t\t\t */\n\t\t\t\t\tif ( sAttr.indexOf('.') != -1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tvar aSplit = sAttr.split('.');\n\t\t\t\t\t\tnNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);\n\t\t\t\t\t\tnNewNode.className = aSplit[1];\n\t\t\t\t\t}\n\t\t\t\t\telse if ( sAttr.charAt(0) == \"#\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tnNewNode.id = sAttr.substr(1, sAttr.length-1);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tnNewNode.className = sAttr;\n\t\t\t\t\t}\n\n\t\t\t\t\ti += j; /* Move along the position array */\n\t\t\t\t}\n\n\t\t\t\tnInsertNode.appendChild( nNewNode );\n\t\t\t\tnInsertNode = nNewNode;\n\t\t\t}\n\t\t\telse if ( cOption == '>' )\n\t\t\t{\n\t\t\t\t/* End container div */\n\t\t\t\tnInsertNode = nInsertNode.parentNode;\n\t\t\t}\n\t\t\t// @todo Move options into their own plugins?\n\t\t\telse if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )\n\t\t\t{\n\t\t\t\t/* Length */\n\t\t\t\tnTmp = _fnFeatureHtmlLength( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( cOption == 'f' && oSettings.oFeatures.bFilter )\n\t\t\t{\n\t\t\t\t/* Filter */\n\t\t\t\tnTmp = _fnFeatureHtmlFilter( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( cOption == 'r' && oSettings.oFeatures.bProcessing )\n\t\t\t{\n\t\t\t\t/* pRocessing */\n\t\t\t\tnTmp = _fnFeatureHtmlProcessing( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( cOption == 't' )\n\t\t\t{\n\t\t\t\t/* Table */\n\t\t\t\tnTmp = _fnFeatureHtmlTable( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( cOption ==  'i' && oSettings.oFeatures.bInfo )\n\t\t\t{\n\t\t\t\t/* Info */\n\t\t\t\tnTmp = _fnFeatureHtmlInfo( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( cOption == 'p' && oSettings.oFeatures.bPaginate )\n\t\t\t{\n\t\t\t\t/* Pagination */\n\t\t\t\tnTmp = _fnFeatureHtmlPaginate( oSettings );\n\t\t\t\tiPushFeature = 1;\n\t\t\t}\n\t\t\telse if ( DataTable.ext.feature.length !== 0 )\n\t\t\t{\n\t\t\t\t/* Plug-in features */\n\t\t\t\tvar aoFeatures = DataTable.ext.feature;\n\t\t\t\tfor ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )\n\t\t\t\t{\n\t\t\t\t\tif ( cOption == aoFeatures[k].cFeature )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTmp = aoFeatures[k].fnInit( oSettings );\n\t\t\t\t\t\tif ( nTmp )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Add to the 2D features array */\n\t\t\tif ( iPushFeature == 1 && nTmp !== null )\n\t\t\t{\n\t\t\t\tif ( typeof oSettings.aanFeatures[cOption] !== 'object' )\n\t\t\t\t{\n\t\t\t\t\toSettings.aanFeatures[cOption] = [];\n\t\t\t\t}\n\t\t\t\toSettings.aanFeatures[cOption].push( nTmp );\n\t\t\t\tnInsertNode.appendChild( nTmp );\n\t\t\t}\n\t\t}\n\n\t\t/* Built our DOM structure - replace the holding div with what we want */\n\t\tnHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );\n\t}\n\n\n\t/**\n\t * Use the DOM source to create up an array of header cells. The idea here is to\n\t * create a layout grid (array) of rows x columns, which contains a reference\n\t * to the cell that that point in the grid (regardless of col/rowspan), such that\n\t * any column / row could be removed and the new grid constructed\n\t *  @param array {object} aLayout Array to store the calculated layout in\n\t *  @param {node} nThead The header/footer element for the table\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnDetectHeader ( aLayout, nThead )\n\t{\n\t\tvar nTrs = $(nThead).children('tr');\n\t\tvar nTr, nCell;\n\t\tvar i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;\n\t\tvar bUnique;\n\t\tvar fnShiftCol = function ( a, i, j ) {\n\t\t\tvar k = a[i];\n\t                while ( k[j] ) {\n\t\t\t\tj++;\n\t\t\t}\n\t\t\treturn j;\n\t\t};\n\n\t\taLayout.splice( 0, aLayout.length );\n\n\t\t/* We know how many rows there are in the layout - so prep it */\n\t\tfor ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\n\t\t{\n\t\t\taLayout.push( [] );\n\t\t}\n\n\t\t/* Calculate a layout array */\n\t\tfor ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tnTr = nTrs[i];\n\t\t\tiColumn = 0;\n\n\t\t\t/* For every cell in the row... */\n\t\t\tnCell = nTr.firstChild;\n\t\t\twhile ( nCell ) {\n\t\t\t\tif ( nCell.nodeName.toUpperCase() == \"TD\" ||\n\t\t\t\t     nCell.nodeName.toUpperCase() == \"TH\" )\n\t\t\t\t{\n\t\t\t\t\t/* Get the col and rowspan attributes from the DOM and sanitise them */\n\t\t\t\t\tiColspan = nCell.getAttribute('colspan') * 1;\n\t\t\t\t\tiRowspan = nCell.getAttribute('rowspan') * 1;\n\t\t\t\t\tiColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;\n\t\t\t\t\tiRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;\n\n\t\t\t\t\t/* There might be colspan cells already in this row, so shift our target\n\t\t\t\t\t * accordingly\n\t\t\t\t\t */\n\t\t\t\t\tiColShifted = fnShiftCol( aLayout, i, iColumn );\n\n\t\t\t\t\t/* Cache calculation for unique columns */\n\t\t\t\t\tbUnique = iColspan === 1 ? true : false;\n\n\t\t\t\t\t/* If there is col / rowspan, copy the information into the layout grid */\n\t\t\t\t\tfor ( l=0 ; l<iColspan ; l++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( k=0 ; k<iRowspan ; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taLayout[i+k][iColShifted+l] = {\n\t\t\t\t\t\t\t\t\"cell\": nCell,\n\t\t\t\t\t\t\t\t\"unique\": bUnique\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\taLayout[i+k].nTr = nTr;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnCell = nCell.nextSibling;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Get an array of unique th elements, one for each column\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {node} nHeader automatically detect the layout from this node - optional\n\t *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional\n\t *  @returns array {node} aReturn list of unique th's\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetUniqueThs ( oSettings, nHeader, aLayout )\n\t{\n\t\tvar aReturn = [];\n\t\tif ( !aLayout )\n\t\t{\n\t\t\taLayout = oSettings.aoHeader;\n\t\t\tif ( nHeader )\n\t\t\t{\n\t\t\t\taLayout = [];\n\t\t\t\t_fnDetectHeader( aLayout, nHeader );\n\t\t\t}\n\t\t}\n\n\t\tfor ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tfor ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )\n\t\t\t{\n\t\t\t\tif ( aLayout[i][j].unique &&\n\t\t\t\t\t (!aReturn[j] || !oSettings.bSortCellsTop) )\n\t\t\t\t{\n\t\t\t\t\taReturn[j] = aLayout[i][j].cell;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn aReturn;\n\t}\n\n\n\n\t/**\n\t * Create an Ajax call based on the table's settings, taking into account that\n\t * parameters can have multiple forms, and backwards compatibility.\n\t *\n\t * @param {object} oSettings dataTables settings object\n\t * @param {array} data Data to send to the server, required by\n\t *     DataTables - may be augmented by developer callbacks\n\t * @param {function} fn Callback function to run when data is obtained\n\t */\n\tfunction _fnBuildAjax( oSettings, data, fn )\n\t{\n\t\t// Compatibility with 1.9-, allow fnServerData and event to manipulate\n\t\t_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );\n\n\t\t// Convert to object based for 1.10+ if using the old scheme\n\t\tif ( data && data.__legacy ) {\n\t\t\tvar tmp = {};\n\t\t\tvar rbracket = /(.*?)\\[\\]$/;\n\n\t\t\t$.each( data, function (key, val) {\n\t\t\t\tvar match = val.name.match(rbracket);\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\t// Support for arrays\n\t\t\t\t\tvar name = match[0];\n\n\t\t\t\t\tif ( ! tmp[ name ] ) {\n\t\t\t\t\t\ttmp[ name ] = [];\n\t\t\t\t\t}\n\t\t\t\t\ttmp[ name ].push( val.value );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttmp[val.name] = val.value;\n\t\t\t\t}\n\t\t\t} );\n\t\t\tdata = tmp;\n\t\t}\n\n\t\tvar ajaxData;\n\t\tvar ajax = oSettings.ajax;\n\t\tvar instance = oSettings.oInstance;\n\n\t\tif ( $.isPlainObject( ajax ) && ajax.data )\n\t\t{\n\t\t\tajaxData = ajax.data;\n\n\t\t\tvar newData = $.isFunction( ajaxData ) ?\n\t\t\t\tajaxData( data ) :  // fn can manipulate data or return an object\n\t\t\t\tajaxData;           // object or array to merge\n\n\t\t\t// If the function returned an object, use that alone\n\t\t\tdata = $.isFunction( ajaxData ) && newData ?\n\t\t\t\tnewData :\n\t\t\t\t$.extend( true, data, newData );\n\n\t\t\t// Remove the data property as we've resolved it already and don't want\n\t\t\t// jQuery to do it again (it is restored at the end of the function)\n\t\t\tdelete ajax.data;\n\t\t}\n\n\t\tvar baseAjax = {\n\t\t\t\"data\": data,\n\t\t\t\"success\": function (json) {\n\t\t\t\tvar error = json.error || json.sError;\n\t\t\t\tif ( error ) {\n\t\t\t\t\toSettings.oApi._fnLog( oSettings, 0, error );\n\t\t\t\t}\n\n\t\t\t\toSettings.json = json;\n\t\t\t\t_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );\n\t\t\t\tfn( json );\n\t\t\t},\n\t\t\t\"dataType\": \"json\",\n\t\t\t\"cache\": false,\n\t\t\t\"type\": oSettings.sServerMethod,\n\t\t\t\"error\": function (xhr, error, thrown) {\n\t\t\t\tvar log = oSettings.oApi._fnLog;\n\n\t\t\t\tif ( error == \"parsererror\" ) {\n\t\t\t\t\tlog( oSettings, 0, 'Invalid JSON response', 1 );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlog( oSettings, 0, 'Ajax error', 7 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( oSettings.fnServerData )\n\t\t{\n\t\t\t// DataTables 1.9- compatibility\n\t\t\toSettings.fnServerData.call( instance,\n\t\t\t\toSettings.sAjaxSource, data, fn, oSettings\n\t\t\t);\n\t\t}\n\t\telse if ( oSettings.sAjaxSource || typeof ajax === 'string' )\n\t\t{\n\t\t\t// DataTables 1.9- compatibility\n\t\t\toSettings.jqXHR = $.ajax( $.extend( baseAjax, {\n\t\t\t\turl: ajax || oSettings.sAjaxSource\n\t\t\t} ) );\n\t\t}\n\t\telse if ( $.isFunction( ajax ) )\n\t\t{\n\t\t\t// Is a function - let the caller define what needs to be done\n\t\t\toSettings.jqXHR = ajax.call( instance, data, fn, oSettings );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Object to extend the base settings\n\t\t\toSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );\n\n\t\t\t// Restore for next time around\n\t\t\tajax.data = ajaxData;\n\t\t}\n\t}\n\n\n\t/**\n\t * Update the table using an Ajax call\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {boolean} Block the table drawing or not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAjaxUpdate( oSettings )\n\t{\n\t\tif ( oSettings.bAjaxDataGet )\n\t\t{\n\t\t\toSettings.iDraw++;\n\t\t\t_fnProcessingDisplay( oSettings, true );\n\t\t\tvar iColumns = oSettings.aoColumns.length;\n\t\t\tvar aoData = _fnAjaxParameters( oSettings );\n\n\t\t\t_fnBuildAjax( oSettings, aoData, function(json) {\n\t\t\t\t_fnAjaxUpdateDraw( oSettings, json );\n\t\t\t}, oSettings );\n\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\t/**\n\t * Build up the parameters in an object needed for a server-side processing\n\t * request. Note that this is basically done twice, is different ways - a modern\n\t * method which is used by default in DataTables 1.10 which uses objects and\n\t * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if\n\t * the sAjaxSource option is used in the initialisation, or the legacyAjax\n\t * option is set.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {bool} block the table drawing or not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAjaxParameters( settings )\n\t{\n\t\tvar\n\t\t\tcolumns = settings.aoColumns,\n\t\t\tcolumnCount = columns.length,\n\t\t\tfeatures = settings.oFeatures,\n\t\t\tpreSearch = settings.oPreviousSearch,\n\t\t\tpreColSearch = settings.aoPreSearchCols,\n\t\t\ti, data = [], dataProp, column, columnSearch,\n\t\t\tsort = _fnSortFlatten( settings ),\n\t\t\tdisplayStart = settings._iDisplayStart,\n\t\t\tdisplayLength = features.bPaginate !== false ?\n\t\t\t\tsettings._iDisplayLength :\n\t\t\t\t-1;\n\n\t\tvar param = function ( name, value ) {\n\t\t\tdata.push( { 'name': name, 'value': value } );\n\t\t};\n\n\t\t// DataTables 1.9- compatible method\n\t\tparam( 'sEcho',          settings.iDraw );\n\t\tparam( 'iColumns',       columnCount );\n\t\tparam( 'sColumns',       _pluck( columns, 'sName' ).join(',') );\n\t\tparam( 'iDisplayStart',  displayStart );\n\t\tparam( 'iDisplayLength', displayLength );\n\n\t\t// DataTables 1.10+ method\n\t\tvar d = {\n\t\t\tdraw:    settings.iDraw,\n\t\t\tcolumns: [],\n\t\t\torder:   [],\n\t\t\tstart:   displayStart,\n\t\t\tlength:  displayLength,\n\t\t\tsearch:  {\n\t\t\t\tvalue: preSearch.sSearch,\n\t\t\t\tregex: preSearch.bRegex\n\t\t\t}\n\t\t};\n\n\t\tfor ( i=0 ; i<columnCount ; i++ ) {\n\t\t\tcolumn = columns[i];\n\t\t\tcolumnSearch = preColSearch[i];\n\t\t\tdataProp = typeof column.mData==\"function\" ? 'function' : column.mData ;\n\n\t\t\td.columns.push( {\n\t\t\t\tdata:       dataProp,\n\t\t\t\tname:       column.sName,\n\t\t\t\tsearchable: column.bSearchable,\n\t\t\t\torderable:  column.bSortable,\n\t\t\t\tsearch:     {\n\t\t\t\t\tvalue: columnSearch.sSearch,\n\t\t\t\t\tregex: columnSearch.bRegex\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tparam( \"mDataProp_\"+i, dataProp );\n\n\t\t\tif ( features.bFilter ) {\n\t\t\t\tparam( 'sSearch_'+i,     columnSearch.sSearch );\n\t\t\t\tparam( 'bRegex_'+i,      columnSearch.bRegex );\n\t\t\t\tparam( 'bSearchable_'+i, column.bSearchable );\n\t\t\t}\n\n\t\t\tif ( features.bSort ) {\n\t\t\t\tparam( 'bSortable_'+i, column.bSortable );\n\t\t\t}\n\t\t}\n\n\t\t$.each( sort, function ( i, val ) {\n\t\t\td.order.push( { column: val.col, dir: val.dir } );\n\n\t\t\tparam( 'iSortCol_'+i, val.col );\n\t\t\tparam( 'sSortDir_'+i, val.dir );\n\t\t} );\n\n\t\tif ( features.bFilter ) {\n\t\t\tparam( 'sSearch', preSearch.sSearch );\n\t\t\tparam( 'bRegex', preSearch.bRegex );\n\t\t}\n\n\t\tif ( features.bSort ) {\n\t\t\tparam( 'iSortingCols', sort.length );\n\t\t}\n\n\t\tdata.__legacy = true;\n\t\treturn settings.sAjaxSource || DataTable.ext.legacy.ajax ?\n\t\t\tdata : d;\n\t}\n\n\n\t/**\n\t * Data the data from the server (nuking the old) and redraw the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {object} json json data return from the server.\n\t *  @param {string} json.sEcho Tracking flag for DataTables to match requests\n\t *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering\n\t *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering\n\t *  @param {array} json.aaData The data to display on this page\n\t *  @param {string} [json.sColumns] Column ordering (sName, comma separated)\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnAjaxUpdateDraw ( settings, json )\n\t{\n\t\t// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.\n\t\t// Support both\n\t\tvar compat = function ( old, modern ) {\n\t\t\treturn json[old] !== undefined ? json[old] : json[modern];\n\t\t};\n\n\t\tvar draw            = compat( 'sEcho',                'draw' );\n\t\tvar recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );\n\t\tvar rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );\n\n\t\tif ( draw ) {\n\t\t\t// Protect against out of sequence returns\n\t\t\tif ( draw*1 < settings.iDraw ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettings.iDraw = draw * 1;\n\t\t}\n\n\t\t_fnClearTable( settings );\n\t\tsettings._iRecordsTotal   = parseInt(recordsTotal, 10);\n\t\tsettings._iRecordsDisplay = parseInt(rocordsFiltered, 10);\n\n\t\tvar data = _fnAjaxDataSrc( settings, json );\n\t\tfor ( var i=0, ien=data.length ; i<ien ; i++ ) {\n\t\t\t_fnAddData( settings, data[i] );\n\t\t}\n\t\tsettings.aiDisplay = settings.aiDisplayMaster.slice();\n\n\t\tsettings.bAjaxDataGet = false;\n\t\t_fnDraw( settings );\n\n\t\tif ( ! settings._bInitComplete ) {\n\t\t\t_fnInitComplete( settings, json );\n\t\t}\n\n\t\tsettings.bAjaxDataGet = true;\n\t\t_fnProcessingDisplay( settings, false );\n\t}\n\n\n\t/**\n\t * Get the data from the JSON data source to use for drawing a table. Using\n\t * `_fnGetObjectDataFn` allows the data to be sourced from a property of the\n\t * source object, or from a processing function.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param  {object} json Data source object / array from the server\n\t *  @return {array} Array of data to use\n\t */\n\tfunction _fnAjaxDataSrc ( oSettings, json )\n\t{\n\t\tvar dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?\n\t\t\toSettings.ajax.dataSrc :\n\t\t\toSettings.sAjaxDataProp; // Compatibility with 1.9-.\n\n\t\t// Compatibility with 1.9-. In order to read from aaData, check if the\n\t\t// default has been changed, if not, check for aaData\n\t\tif ( dataSrc === 'data' ) {\n\t\t\treturn json.aaData || json[dataSrc];\n\t\t}\n\n\t\treturn dataSrc !== \"\" ?\n\t\t\t_fnGetObjectDataFn( dataSrc )( json ) :\n\t\t\tjson;\n\t}\n\n\n\t/**\n\t * Generate the node required for filtering text\n\t *  @returns {node} Filter control element\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlFilter ( settings )\n\t{\n\t\tvar classes = settings.oClasses;\n\t\tvar tableId = settings.sTableId;\n\t\tvar previousSearch = settings.oPreviousSearch;\n\t\tvar features = settings.aanFeatures;\n\t\tvar input = '<input type=\"search\" class=\"'+classes.sFilterInput+'\"/>';\n\n\t\tvar str = settings.oLanguage.sSearch;\n\t\tstr = str.match(/_INPUT_/) ?\n\t\t\tstr.replace('_INPUT_', input) :\n\t\t\tstr+input;\n\n\t\tvar filter = $('<div/>', {\n\t\t\t\t'id': ! features.f ? tableId+'_filter' : null,\n\t\t\t\t'class': classes.sFilter\n\t\t\t} )\n\t\t\t.append( $('<label/>' ).append( str ) );\n\n\t\tvar jqFilter = $('input[type=\"search\"]', filter)\n\t\t\t.val( previousSearch.sSearch.replace('\"','&quot;') )\n\t\t\t.bind( 'keyup.DT search.DT input.DT paste.DT cut.DT', function(e) {\n\t\t\t\t/* Update all other filter input elements for the new display */\n\t\t\t\tvar n = features.f;\n\t\t\t\tvar val = !this.value ? \"\" : this.value; // mental IE8 fix :-(\n\n\t\t\t\t/* Now do the filter */\n\t\t\t\tif ( val != previousSearch.sSearch ) {\n\t\t\t\t\t_fnFilterComplete( settings, {\n\t\t\t\t\t\t\"sSearch\": val,\n\t\t\t\t\t\t\"bRegex\": previousSearch.bRegex,\n\t\t\t\t\t\t\"bSmart\": previousSearch.bSmart ,\n\t\t\t\t\t\t\"bCaseInsensitive\": previousSearch.bCaseInsensitive\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Need to redraw, without resorting\n\t\t\t\t\tsettings._iDisplayStart = 0;\n\t\t\t\t\t_fnDraw( settings );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.bind( 'keypress.DT', function(e) {\n\t\t\t\t/* Prevent form submission */\n\t\t\t\tif ( e.keyCode == 13 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.attr('aria-controls', tableId);\n\n\t\t// Update the input elements whenever the table is filtered\n\t\t$(settings.nTable).on( 'filter.DT', function () {\n\t\t\t// IE9 throws an 'unknown error' if document.activeElement is used\n\t\t\t// inside an iframe or frame...\n\t\t\ttry {\n\t\t\t\tif ( jqFilter[0] !== document.activeElement ) {\n\t\t\t\t\tjqFilter.val( previousSearch.sSearch );\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch ( e ) {}\n\t\t} );\n\n\t\treturn filter[0];\n\t}\n\n\n\t/**\n\t * Filter the table using both the global filter and column based filtering\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {object} oSearch search information\n\t *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFilterComplete ( oSettings, oInput, iForce )\n\t{\n\t\tvar oPrevSearch = oSettings.oPreviousSearch;\n\t\tvar aoPrevSearch = oSettings.aoPreSearchCols;\n\t\tvar fnSaveFilter = function ( oFilter ) {\n\t\t\t/* Save the filtering values */\n\t\t\toPrevSearch.sSearch = oFilter.sSearch;\n\t\t\toPrevSearch.bRegex = oFilter.bRegex;\n\t\t\toPrevSearch.bSmart = oFilter.bSmart;\n\t\t\toPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;\n\t\t};\n\n\t\t// Resolve any column types that are unknown due to addition or invalidation\n\t\t// @todo As per sort - can this be moved into an event handler?\n\t\t_fnColumnTypes( oSettings );\n\n\t\t/* In server-side processing all filtering is done by the server, so no point hanging around here */\n\t\tif ( _fnDataSource( oSettings ) != 'ssp' )\n\t\t{\n\t\t\t/* Global filter */\n\t\t\t_fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );\n\t\t\tfnSaveFilter( oInput );\n\n\t\t\t/* Now do the individual column filter */\n\t\t\tfor ( var i=0 ; i<aoPrevSearch.length ; i++ )\n\t\t\t{\n\t\t\t\t_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex,\n\t\t\t\t\taoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );\n\t\t\t}\n\n\t\t\t/* Custom filtering */\n\t\t\t_fnFilterCustom( oSettings );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfnSaveFilter( oInput );\n\t\t}\n\n\t\t/* Tell the draw function we have been filtering */\n\t\toSettings.bFiltered = true;\n\t\t_fnCallbackFire( oSettings, null, 'search', [oSettings] );\n\t}\n\n\n\t/**\n\t * Apply custom filtering functions\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFilterCustom( oSettings )\n\t{\n\t\tvar afnFilters = DataTable.ext.search;\n\t\tvar aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );\n\n\t\tfor ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tvar iCorrector = 0;\n\t\t\tfor ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )\n\t\t\t{\n\t\t\t\tvar iDisIndex = oSettings.aiDisplay[j-iCorrector];\n\t\t\t\tvar bTest = afnFilters[i](\n\t\t\t\t\toSettings,\n\t\t\t\t\t_fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ),\n\t\t\t\t\tiDisIndex\n\t\t\t\t);\n\n\t\t\t\t/* Check if we should use this row based on the filtering function */\n\t\t\t\tif ( !bTest )\n\t\t\t\t{\n\t\t\t\t\toSettings.aiDisplay.splice( j-iCorrector, 1 );\n\t\t\t\t\tiCorrector++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Filter the table on a per-column basis\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {string} sInput string to filter on\n\t *  @param {int} iColumn column to filter\n\t *  @param {bool} bRegex treat search string as a regular expression or not\n\t *  @param {bool} bSmart use smart filtering or not\n\t *  @param {bool} bCaseInsensitive Do case insenstive matching or not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )\n\t{\n\t\tif ( searchStr === '' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar data;\n\t\tvar display = settings.aiDisplay;\n\t\tvar rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );\n\n\t\tfor ( var i=display.length-1 ; i>=0 ; i-- ) {\n\t\t\tdata = settings.aoData[ display[i] ]._aFilterData[ colIdx ];\n\n\t\t\tif ( ! rpSearch.test( data ) ) {\n\t\t\t\tdisplay.splice( i, 1 );\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Filter the data table based on user input and draw the table\n\t *  @param {object} settings dataTables settings object\n\t *  @param {string} input string to filter on\n\t *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)\n\t *  @param {bool} regex treat as a regular expression or not\n\t *  @param {bool} smart perform smart filtering or not\n\t *  @param {bool} caseInsensitive Do case insenstive matching or not\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFilter( settings, input, force, regex, smart, caseInsensitive )\n\t{\n\t\tvar rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );\n\t\tvar prevSearch = settings.oPreviousSearch.sSearch;\n\t\tvar displayMaster = settings.aiDisplayMaster;\n\t\tvar display, invalidated, i;\n\n\t\t// Need to take account of custom filtering functions - always filter\n\t\tif ( DataTable.ext.search.length !== 0 ) {\n\t\t\tforce = true;\n\t\t}\n\n\t\t// Check if any of the rows were invalidated\n\t\tinvalidated = _fnFilterData( settings );\n\n\t\t// If the input is blank - we just want the full data set\n\t\tif ( input.length <= 0 ) {\n\t\t\tsettings.aiDisplay = displayMaster.slice();\n\t\t}\n\t\telse {\n\t\t\t// New search - start from the master array\n\t\t\tif ( invalidated ||\n\t\t\t\t force ||\n\t\t\t\t prevSearch.length > input.length ||\n\t\t\t\t input.indexOf(prevSearch) !== 0 ||\n\t\t\t\t settings.bSorted // On resort, the display master needs to be\n\t\t\t\t                  // re-filtered since indexes will have changed\n\t\t\t) {\n\t\t\t\tsettings.aiDisplay = displayMaster.slice();\n\t\t\t}\n\n\t\t\t// Search the display array\n\t\t\tdisplay = settings.aiDisplay;\n\n\t\t\tfor ( i=display.length-1 ; i>=0 ; i-- ) {\n\t\t\t\tif ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {\n\t\t\t\t\tdisplay.splice( i, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Build a regular expression object suitable for searching a table\n\t *  @param {string} sSearch string to search for\n\t *  @param {bool} bRegex treat as a regular expression or not\n\t *  @param {bool} bSmart perform smart filtering or not\n\t *  @param {bool} bCaseInsensitive Do case insensitive matching or not\n\t *  @returns {RegExp} constructed object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )\n\t{\n\t\tvar asSearch,\n\t\t\tsRegExpString = bRegex ? sSearch : _fnEscapeRegex( sSearch );\n\n\t\tif ( bSmart )\n\t\t{\n\t\t\t/* Generate the regular expression to use. Something along the lines of:\n\t\t\t * ^(?=.*?\\bone\\b)(?=.*?\\btwo\\b)(?=.*?\\bthree\\b).*$\n\t\t\t */\n\t\t\tasSearch = sRegExpString.split( ' ' );\n\t\t\tsRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';\n\t\t}\n\n\t\treturn new RegExp( sRegExpString, bCaseInsensitive ? \"i\" : \"\" );\n\t}\n\n\n\t/**\n\t * scape a string such that it can be used in a regular expression\n\t *  @param {string} sVal string to escape\n\t *  @returns {string} escaped string\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnEscapeRegex ( sVal )\n\t{\n\t\tvar acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\\\', '$', '^', '-' ];\n\t\tvar reReplace = new RegExp( '(\\\\' + acEscape.join('|\\\\') + ')', 'g' );\n\t\treturn sVal.replace(reReplace, '\\\\$1');\n\t}\n\n\n\n\tvar __filter_div = $('<div>')[0];\n\tvar __filter_div_textContent = __filter_div.textContent !== undefined;\n\n\t// Update the filtering data for each row if needed (by invalidation or first run)\n\tfunction _fnFilterData ( settings )\n\t{\n\t\tvar columns = settings.aoColumns;\n\t\tvar column;\n\t\tvar i, j, ien, jen, filterData, cellData, row;\n\t\tvar fomatters = DataTable.ext.type.search;\n\t\tvar wasInvalidated = false;\n\n\t\tfor ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\n\t\t\trow = settings.aoData[i];\n\n\t\t\tif ( ! row._aFilterData ) {\n\t\t\t\tfilterData = [];\n\n\t\t\t\tfor ( j=0, jen=columns.length ; j<jen ; j++ ) {\n\t\t\t\t\tcolumn = columns[j];\n\n\t\t\t\t\tif ( column.bSearchable ) {\n\t\t\t\t\t\tcellData = _fnGetCellData( settings, i, j, 'filter' );\n\n\t\t\t\t\t\tcellData = fomatters[ column.sType ] ?\n\t\t\t\t\t\t\tfomatters[ column.sType ]( cellData ) :\n\t\t\t\t\t\t\tcellData !== null ?\n\t\t\t\t\t\t\t\tcellData :\n\t\t\t\t\t\t\t\t'';\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcellData = '';\n\t\t\t\t\t}\n\n\t\t\t\t\t// If it looks like there is an HTML entity in the string,\n\t\t\t\t\t// attempt to decode it so sorting works as expected. Note that\n\t\t\t\t\t// we could use a single line of jQuery to do this, but the DOM\n\t\t\t\t\t// method used here is much faster http://jsperf.com/html-decode\n\t\t\t\t\tif ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {\n\t\t\t\t\t\t__filter_div.innerHTML = cellData;\n\t\t\t\t\t\tcellData = __filter_div_textContent ?\n\t\t\t\t\t\t\t__filter_div.textContent :\n\t\t\t\t\t\t\t__filter_div.innerText;\n\t\t\t\t\t\tcellData = cellData.replace(/[\\r\\n]/g, '');\n\t\t\t\t\t}\n\n\t\t\t\t\tfilterData.push( cellData );\n\t\t\t\t}\n\n\t\t\t\trow._aFilterData = filterData;\n\t\t\t\trow._sFilterRow = filterData.join('  ');\n\t\t\t\twasInvalidated = true;\n\t\t\t}\n\t\t}\n\n\t\treturn wasInvalidated;\n\t}\n\n\t/**\n\t * Generate the node required for the info display\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {node} Information element\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlInfo ( settings )\n\t{\n\t\tvar\n\t\t\ttid = settings.sTableId,\n\t\t\tnodes = settings.aanFeatures.i,\n\t\t\tn = $('<div/>', {\n\t\t\t\t'class': settings.oClasses.sInfo,\n\t\t\t\t'id': ! nodes ? tid+'_info' : null\n\t\t\t} );\n\n\t\tif ( ! nodes ) {\n\t\t\t// Update display on each draw\n\t\t\tsettings.aoDrawCallback.push( {\n\t\t\t\t\"fn\": _fnUpdateInfo,\n\t\t\t\t\"sName\": \"information\"\n\t\t\t} );\n\n\t\t\tn\n\t\t\t\t.attr( 'role', 'alert' )\n\t\t\t\t.attr( 'aria-live', 'polite' )\n\t\t\t\t.attr( 'aria-relevant', 'all' );\n\n\t\t\t// Table is described by our info div\n\t\t\t$(settings.nTable).attr( 'aria-describedby', tid+'_info' );\n\t\t}\n\n\t\treturn n[0];\n\t}\n\n\n\t/**\n\t * Update the information elements in the display\n\t *  @param {object} settings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnUpdateInfo ( settings )\n\t{\n\t\t/* Show information about the table */\n\t\tvar nodes = settings.aanFeatures.i;\n\t\tif ( nodes.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar\n\t\t\tlang  = settings.oLanguage,\n\t\t\tstart = settings._iDisplayStart+1,\n\t\t\tend   = settings.fnDisplayEnd(),\n\t\t\tmax   = settings.fnRecordsTotal(),\n\t\t\ttotal = settings.fnRecordsDisplay(),\n\t\t\tout   = total ?\n\t\t\t\tlang.sInfo :\n\t\t\t\tlang.sInfoEmpty;\n\n\t\tif ( total !== max ) {\n\t\t\t/* Record set after filtering */\n\t\t\tout += ' ' + lang.sInfoFiltered;\n\t\t}\n\n\t\t// Convert the macros\n\t\tout += lang.sInfoPostFix;\n\t\tout = _fnInfoMacros( settings, out );\n\n\t\tvar callback = lang.fnInfoCallback;\n\t\tif ( callback !== null ) {\n\t\t\tout = callback.call( settings.oInstance,\n\t\t\t\tsettings, start, end, max, total, out\n\t\t\t);\n\t\t}\n\n\t\t$(nodes).html( out );\n\t}\n\n\n\tfunction _fnInfoMacros ( settings, str )\n\t{\n\t\t// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only\n\t\t// internally\n\t\tvar\n\t\t\tformatter  = settings.fnFormatNumber,\n\t\t\tstart      = settings._iDisplayStart+1,\n\t\t\tlen        = settings._iDisplayLength,\n\t\t\tvis        = settings.fnRecordsDisplay(),\n\t\t\tall        = len === -1;\n\n\t\treturn str.\n\t\t\treplace(/_START_/g, formatter.call( settings, start ) ).\n\t\t\treplace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).\n\t\t\treplace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).\n\t\t\treplace(/_TOTAL_/g, formatter.call( settings, vis ) ).\n\t\t\treplace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).\n\t\t\treplace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );\n\t}\n\n\n\n\t/**\n\t * Draw the table for the first time, adding all required features\n\t *  @param {object} settings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnInitialise ( settings )\n\t{\n\t\tvar i, iLen, iAjaxStart=settings.iInitDisplayStart;\n\t\tvar columns = settings.aoColumns, column;\n\t\tvar features = settings.oFeatures;\n\n\t\t/* Ensure that the table data is fully initialised */\n\t\tif ( ! settings.bInitialised ) {\n\t\t\tsetTimeout( function(){ _fnInitialise( settings ); }, 200 );\n\t\t\treturn;\n\t\t}\n\n\t\t/* Show the display HTML options */\n\t\t_fnAddOptionsHtml( settings );\n\n\t\t/* Build and draw the header / footer for the table */\n\t\t_fnBuildHead( settings );\n\t\t_fnDrawHead( settings, settings.aoHeader );\n\t\t_fnDrawHead( settings, settings.aoFooter );\n\n\t\t/* Okay to show that something is going on now */\n\t\t_fnProcessingDisplay( settings, true );\n\n\t\t/* Calculate sizes for columns */\n\t\tif ( features.bAutoWidth ) {\n\t\t\t_fnCalculateColumnWidths( settings );\n\t\t}\n\n\t\tfor ( i=0, iLen=columns.length ; i<iLen ; i++ ) {\n\t\t\tcolumn = columns[i];\n\n\t\t\tif ( column.sWidth ) {\n\t\t\t\tcolumn.nTh.style.width = _fnStringToCss( column.sWidth );\n\t\t\t}\n\t\t}\n\n\t\t// If there is default sorting required - let's do it. The sort function\n\t\t// will do the drawing for us. Otherwise we draw the table regardless of the\n\t\t// Ajax source - this allows the table to look initialised for Ajax sourcing\n\t\t// data (show 'loading' message possibly)\n\t\t_fnReDraw( settings );\n\n\t\t// Server-side processing init complete is done by _fnAjaxUpdateDraw\n\t\tvar dataSrc = _fnDataSource( settings );\n\t\tif ( dataSrc != 'ssp' ) {\n\t\t\t// if there is an ajax source load the data\n\t\t\tif ( dataSrc == 'ajax' ) {\n\t\t\t\t_fnBuildAjax( settings, [], function(json) {\n\t\t\t\t\tvar aData = _fnAjaxDataSrc( settings, json );\n\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\t_fnAddData( settings, aData[i] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Reset the init display for cookie saving. We've already done\n\t\t\t\t\t// a filter, and therefore cleared it before. So we need to make\n\t\t\t\t\t// it appear 'fresh'\n\t\t\t\t\tsettings.iInitDisplayStart = iAjaxStart;\n\n\t\t\t\t\t_fnReDraw( settings );\n\n\t\t\t\t\t_fnProcessingDisplay( settings, false );\n\t\t\t\t\t_fnInitComplete( settings, json );\n\t\t\t\t}, settings );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t_fnProcessingDisplay( settings, false );\n\t\t\t\t_fnInitComplete( settings );\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Draw the table for the first time, adding all required features\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {object} [json] JSON from the server that completed the table, if using Ajax source\n\t *    with client-side processing (optional)\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnInitComplete ( settings, json )\n\t{\n\t\tsettings._bInitComplete = true;\n\n\t\t// On an Ajax load we now have data and therefore want to apply the column\n\t\t// sizing\n\t\tif ( json ) {\n\t\t\t_fnAdjustColumnSizing( settings );\n\t\t}\n\n\t\t_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );\n\t}\n\n\n\tfunction _fnLengthChange ( settings, val )\n\t{\n\t\tvar len = parseInt( val, 10 );\n\t\tsettings._iDisplayLength = len;\n\n\t\t_fnLengthOverflow( settings );\n\n\t\t// Fire length change event\n\t\t_fnCallbackFire( settings, null, 'length', [settings, len] );\n\t}\n\n\n\t/**\n\t * Generate the node required for user display length changing\n\t *  @param {object} settings dataTables settings object\n\t *  @returns {node} Display length feature node\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlLength ( settings )\n\t{\n\t\tvar\n\t\t\tclasses  = settings.oClasses,\n\t\t\ttableId  = settings.sTableId,\n\t\t\tmenu     = settings.aLengthMenu,\n\t\t\td2       = $.isArray( menu[0] ),\n\t\t\tlengths  = d2 ? menu[0] : menu,\n\t\t\tlanguage = d2 ? menu[1] : menu;\n\n\t\tvar select = $('<select/>', {\n\t\t\t'name':          tableId+'_length',\n\t\t\t'aria-controls': tableId,\n\t\t\t'class':         classes.sLengthSelect\n\t\t} );\n\n\t\tfor ( var i=0, ien=lengths.length ; i<ien ; i++ ) {\n\t\t\tselect[0][ i ] = new Option( language[i], lengths[i] );\n\t\t}\n\n\t\tvar div = $('<div><label/></div>').addClass( classes.sLength );\n\t\tif ( ! settings.aanFeatures.l ) {\n\t\t\tdiv[0].id = tableId+'_length';\n\t\t}\n\n\t\t// This split doesn't matter where _MENU_ is, we get three items back from it\n\t\tvar a = settings.oLanguage.sLengthMenu.split(/(_MENU_)/);\n\t\tdiv.children()\n\t\t\t.append( a[0] )\n\t\t\t.append( select )\n\t\t\t.append( a[2] );\n\n\t\tselect\n\t\t\t.val( settings._iDisplayLength )\n\t\t\t.bind( 'change.DT', function(e) {\n\t\t\t\t_fnLengthChange( settings, $(this).val() );\n\t\t\t\t_fnDraw( settings );\n\t\t\t} );\n\n\t\t// Update node value whenever anything changes the table's length\n\t\t$(settings.nTable).bind( 'length', function (e, s, len) {\n\t\t\tselect.val( len );\n\t\t} );\n\n\t\treturn div[0];\n\t}\n\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Note that most of the paging logic is done in\n\t * DataTable.ext.pager\n\t */\n\n\t/**\n\t * Generate the node required for default pagination\n\t *  @param {object} oSettings dataTables settings object\n\t *  @returns {node} Pagination feature node\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlPaginate ( settings )\n\t{\n\t\tvar\n\t\t\ttype   = settings.sPaginationType,\n\t\t\tplugin = DataTable.ext.pager[ type ],\n\t\t\tmodern = typeof plugin === 'function',\n\t\t\tredraw = function( settings ) {\n\t\t\t\t_fnDraw( settings );\n\t\t\t},\n\t\t\tnode = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],\n\t\t\tfeatures = settings.aanFeatures;\n\n\t\tif ( ! modern ) {\n\t\t\tplugin.fnInit( settings, node, redraw );\n\t\t}\n\n\t\t/* Add a draw callback for the pagination on first instance, to update the paging display */\n\t\tif ( ! features.p )\n\t\t{\n\t\t\tnode.id = settings.sTableId+'_paginate';\n\n\t\t\tsettings.aoDrawCallback.push( {\n\t\t\t\t\"fn\": function( settings ) {\n\t\t\t\t\tif ( modern ) {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\tstart      = settings._iDisplayStart,\n\t\t\t\t\t\t\tlen        = settings._iDisplayLength,\n\t\t\t\t\t\t\tvisRecords = settings.fnRecordsDisplay(),\n\t\t\t\t\t\t\tall        = len === -1,\n\t\t\t\t\t\t\tpage = all ? 0 : Math.ceil( start / len ),\n\t\t\t\t\t\t\tpages = all ? 1 : Math.ceil( visRecords / len ),\n\t\t\t\t\t\t\tbuttons = plugin(page, pages),\n\t\t\t\t\t\t\ti, ien;\n\n\t\t\t\t\t\tfor ( i=0, ien=features.p.length ; i<ien ; i++ ) {\n\t\t\t\t\t\t\t_fnRenderer( settings, 'pageButton' )(\n\t\t\t\t\t\t\t\tsettings, features.p[i], i, buttons, page, pages\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\tplugin.fnUpdate( settings, redraw );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"sName\": \"pagination\"\n\t\t\t} );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\n\t/**\n\t * Alter the display settings to change the page\n\t *  @param {object} settings DataTables settings object\n\t *  @param {string|int} action Paging action to take: \"first\", \"previous\",\n\t *    \"next\" or \"last\" or page number to jump to (integer)\n\t *  @param [bool] redraw Automatically draw the update or not\n\t *  @returns {bool} true page has changed, false - no change\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnPageChange ( settings, action, redraw )\n\t{\n\t\tvar\n\t\t\tstart     = settings._iDisplayStart,\n\t\t\tlen       = settings._iDisplayLength,\n\t\t\trecords   = settings.fnRecordsDisplay();\n\n\t\tif ( records === 0 || len === -1 )\n\t\t{\n\t\t\tstart = 0;\n\t\t}\n\t\telse if ( typeof action === \"number\" )\n\t\t{\n\t\t\tstart = action * len;\n\n\t\t\tif ( start > records )\n\t\t\t{\n\t\t\t\tstart = 0;\n\t\t\t}\n\t\t}\n\t\telse if ( action == \"first\" )\n\t\t{\n\t\t\tstart = 0;\n\t\t}\n\t\telse if ( action == \"previous\" )\n\t\t{\n\t\t\tstart = len >= 0 ?\n\t\t\t\tstart - len :\n\t\t\t\t0;\n\n\t\t\tif ( start < 0 )\n\t\t\t{\n\t\t\t  start = 0;\n\t\t\t}\n\t\t}\n\t\telse if ( action == \"next\" )\n\t\t{\n\t\t\tif ( start + len < records )\n\t\t\t{\n\t\t\t\tstart += len;\n\t\t\t}\n\t\t}\n\t\telse if ( action == \"last\" )\n\t\t{\n\t\t\tstart = Math.floor( (records-1) / len) * len;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_fnLog( settings, 0, \"Unknown paging action: \"+action, 5 );\n\t\t}\n\n\t\tvar changed = settings._iDisplayStart !== start;\n\t\tsettings._iDisplayStart = start;\n\n\t\t_fnCallbackFire( settings, null, 'page', [settings] );\n\n\t\tif ( redraw ) {\n\t\t\t_fnDraw( settings );\n\t\t}\n\n\t\treturn changed;\n\t}\n\n\n\n\t/**\n\t * Generate the node required for the processing node\n\t *  @param {object} settings dataTables settings object\n\t *  @returns {node} Processing element\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlProcessing ( settings )\n\t{\n\t\treturn $('<div/>', {\n\t\t\t\t'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,\n\t\t\t\t'class': settings.oClasses.sProcessing\n\t\t\t} )\n\t\t\t.html( settings.oLanguage.sProcessing )\n\t\t\t.insertBefore( settings.nTable )[0];\n\t}\n\n\n\t/**\n\t * Display or hide the processing indicator\n\t *  @param {object} settings dataTables settings object\n\t *  @param {bool} show Show the processing indicator (true) or not (false)\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnProcessingDisplay ( settings, show )\n\t{\n\t\tif ( settings.oFeatures.bProcessing ) {\n\t\t\t$(settings.aanFeatures.r).css( 'visibility', show ? 'visible' : 'hidden' );\n\t\t}\n\n\t\t_fnCallbackFire( settings, null, 'processing', [settings, show] );\n\t}\n\n\t/**\n\t * Add any control elements for the table - specifically scrolling\n\t *  @param {object} settings dataTables settings object\n\t *  @returns {node} Node to add to the DOM\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnFeatureHtmlTable ( settings )\n\t{\n\t\tvar scroll = settings.oScroll;\n\n\t\tif ( scroll.sX === '' && scroll.sY === '' ) {\n\t\t\treturn settings.nTable;\n\t\t}\n\n\t\tvar scrollX = scroll.sX;\n\t\tvar scrollY = scroll.sY;\n\t\tvar classes = settings.oClasses;\n\t\tvar table = $(settings.nTable);\n\t\tvar caption = table.children('caption');\n\t\tvar captionSide = caption.length ? caption[0]._captionSide : null;\n\t\tvar headerClone = $( table[0].cloneNode(false) );\n\t\tvar footerClone = $( table[0].cloneNode(false) );\n\t\tvar footer = table.children('tfoot');\n\t\tvar _div = '<div/>';\n\t\tvar size = function ( s ) {\n\t\t\treturn !s ? null : _fnStringToCss( s );\n\t\t};\n\n\t\tif ( ! footer.length ) {\n\t\t\tfooter = null;\n\t\t}\n\n\t\t/*\n\t\t * The HTML structure that we want to generate in this function is:\n\t\t *  div - scroller\n\t\t *    div - scroll head\n\t\t *      div - scroll head inner\n\t\t *        table - scroll head table\n\t\t *          thead - thead\n\t\t *    div - scroll body\n\t\t *      table - table (master table)\n\t\t *        thead - thead clone for sizing\n\t\t *        tbody - tbody\n\t\t *    div - scroll foot\n\t\t *      div - scroll foot inner\n\t\t *        table - scroll foot table\n\t\t *          tfoot - tfoot\n\t\t */\n\t\tvar scroller = $( _div, { 'class': classes.sScrollWrapper } )\n\t\t\t.append(\n\t\t\t\t$(_div, { 'class': classes.sScrollHead } )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\tposition: 'relative',\n\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\twidth: scrollX ? size(scrollX) : '100%'\n\t\t\t\t\t} )\n\t\t\t\t\t.append(\n\t\t\t\t\t\t$(_div, { 'class': classes.sScrollHeadInner } )\n\t\t\t\t\t\t\t.css( {\n\t\t\t\t\t\t\t\t'box-sizing': 'content-box',\n\t\t\t\t\t\t\t\twidth: scroll.sXInner || '100%'\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t\theaderClone\n\t\t\t\t\t\t\t\t\t.removeAttr('id')\n\t\t\t\t\t\t\t\t\t.css( 'margin-left', 0 )\n\t\t\t\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t\t\t\ttable.children('thead')\n\t\t\t\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\t.append( captionSide === 'top' ? caption : null )\n\t\t\t)\n\t\t\t.append(\n\t\t\t\t$(_div, { 'class': classes.sScrollBody } )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\toverflow: 'auto',\n\t\t\t\t\t\theight: size( scrollY ),\n\t\t\t\t\t\twidth: size( scrollX )\n\t\t\t\t\t} )\n\t\t\t\t\t.append( table )\n\t\t\t);\n\n\t\tif ( footer ) {\n\t\t\tscroller.append(\n\t\t\t\t$(_div, { 'class': classes.sScrollFoot } )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\twidth: scrollX ? size(scrollX) : '100%'\n\t\t\t\t\t} )\n\t\t\t\t\t.append(\n\t\t\t\t\t\t$(_div, { 'class': classes.sScrollFootInner } )\n\t\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t\tfooterClone\n\t\t\t\t\t\t\t\t\t.removeAttr('id')\n\t\t\t\t\t\t\t\t\t.css( 'margin-left', 0 )\n\t\t\t\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t\t\t\ttable.children('tfoot')\n\t\t\t\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\t.append( captionSide === 'bottom' ? caption : null )\n\t\t\t);\n\t\t}\n\n\t\tvar children = scroller.children();\n\t\tvar scrollHead = children[0];\n\t\tvar scrollBody = children[1];\n\t\tvar scrollFoot = footer ? children[2] : null;\n\n\t\t// When the body is scrolled, then we also want to scroll the headers\n\t\tif ( scrollX ) {\n\t\t\t$(scrollBody).scroll( function (e) {\n\t\t\t\tvar scrollLeft = this.scrollLeft;\n\n\t\t\t\tscrollHead.scrollLeft = scrollLeft;\n\n\t\t\t\tif ( footer ) {\n\t\t\t\t\tscrollFoot.scrollLeft = scrollLeft;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tsettings.nScrollHead = scrollHead;\n\t\tsettings.nScrollBody = scrollBody;\n\t\tsettings.nScrollFoot = scrollFoot;\n\n\t\t// On redraw - align columns\n\t\tsettings.aoDrawCallback.push( {\n\t\t\t\"fn\": _fnScrollDraw,\n\t\t\t\"sName\": \"scrolling\"\n\t\t} );\n\n\t\treturn scroller[0];\n\t}\n\n\n\n\t/**\n\t * Update the header, footer and body tables for resizing - i.e. column\n\t * alignment.\n\t *\n\t * Welcome to the most horrible function DataTables. The process that this\n\t * function follows is basically:\n\t *   1. Re-create the table inside the scrolling div\n\t *   2. Take live measurements from the DOM\n\t *   3. Apply the measurements to align the columns\n\t *   4. Clean up\n\t *\n\t *  @param {object} settings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnScrollDraw ( settings )\n\t{\n\t\t// Given that this is such a monster function, a lot of variables are use\n\t\t// to try and keep the minimised size as small as possible\n\t\tvar\n\t\t\tscroll         = settings.oScroll,\n\t\t\tscrollX        = scroll.sX,\n\t\t\tscrollXInner   = scroll.sXInner,\n\t\t\tscrollY        = scroll.sY,\n\t\t\tbarWidth       = scroll.iBarWidth,\n\t\t\tdivHeader      = $(settings.nScrollHead),\n\t\t\tdivHeaderStyle = divHeader[0].style,\n\t\t\tdivHeaderInner = divHeader.children('div'),\n\t\t\tdivHeaderInnerStyle = divHeaderInner[0].style,\n\t\t\tdivHeaderTable = divHeaderInner.children('table'),\n\t\t\tdivBodyEl      = settings.nScrollBody,\n\t\t\tdivBody        = $(divBodyEl),\n\t\t\tdivBodyStyle   = divBodyEl.style,\n\t\t\tdivFooter      = $(settings.nScrollFoot),\n\t\t\tdivFooterInner = divFooter.children('div'),\n\t\t\tdivFooterTable = divFooterInner.children('table'),\n\t\t\theader         = $(settings.nTHead),\n\t\t\ttable          = $(settings.nTable),\n\t\t\ttableEl        = table[0],\n\t\t\ttableStyle     = tableEl.style,\n\t\t\tfooter         = settings.nTFoot ? $(settings.nTFoot) : null,\n\t\t\tbrowser        = settings.oBrowser,\n\t\t\tie67           = browser.bScrollOversize,\n\t\t\theaderTrgEls, footerTrgEls,\n\t\t\theaderSrcEls, footerSrcEls,\n\t\t\theaderCopy, footerCopy,\n\t\t\theaderWidths=[], footerWidths=[],\n\t\t\tidx, correction, sanityWidth,\n\t\t\tzeroOut = function(nSizer) {\n\t\t\t\tvar style = nSizer.style;\n\t\t\t\tstyle.paddingTop = \"0\";\n\t\t\t\tstyle.paddingBottom = \"0\";\n\t\t\t\tstyle.borderTopWidth = \"0\";\n\t\t\t\tstyle.borderBottomWidth = \"0\";\n\t\t\t\tstyle.height = 0;\n\t\t\t};\n\n\t\t/*\n\t\t * 1. Re-create the table inside the scrolling div\n\t\t */\n\n\t\t// Remove the old minimised thead and tfoot elements in the inner table\n\t\ttable.children('thead, tfoot').remove();\n\n\t\t// Clone the current header and footer elements and then place it into the inner table\n\t\theaderCopy = header.clone().prependTo( table );\n\t\theaderTrgEls = header.find('tr'); // original header is in its own table\n\t\theaderSrcEls = headerCopy.find('tr');\n\t\theaderCopy.find('th, td').removeAttr('tabindex');\n\n\t\tif ( footer ) {\n\t\t\tfooterCopy = footer.clone().prependTo( table );\n\t\t\tfooterTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized\n\t\t\tfooterSrcEls = footerCopy.find('tr');\n\t\t}\n\n\n\t\t/*\n\t\t * 2. Take live measurements from the DOM - do not alter the DOM itself!\n\t\t */\n\n\t\t// Remove old sizing and apply the calculated column widths\n\t\t// Get the unique column headers in the newly created (cloned) header. We want to apply the\n\t\t// calculated sizes to this header\n\t\tif ( ! scrollX )\n\t\t{\n\t\t\tdivBodyStyle.width = '100%';\n\t\t\tdivHeader[0].style.width = '100%';\n\t\t}\n\n\t\t$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {\n\t\t\tidx = _fnVisibleToColumnIndex( settings, i );\n\t\t\tel.style.width = settings.aoColumns[idx].sWidth;\n\t\t} );\n\n\t\tif ( footer ) {\n\t\t\t_fnApplyToChildren( function(n) {\n\t\t\t\tn.style.width = \"\";\n\t\t\t}, footerSrcEls );\n\t\t}\n\n\t\t// If scroll collapse is enabled, when we put the headers back into the body for sizing, we\n\t\t// will end up forcing the scrollbar to appear, making our measurements wrong for when we\n\t\t// then hide it (end of this function), so add the header height to the body scroller.\n\t\tif ( scroll.bCollapse && scrollY !== \"\" ) {\n\t\t\tdivBodyStyle.height = (divBody.offsetHeight + header[0].offsetHeight)+\"px\";\n\t\t}\n\n\t\t// Size the table as a whole\n\t\tsanityWidth = table.outerWidth();\n\t\tif ( scrollX === \"\" ) {\n\t\t\t// No x scrolling\n\t\t\ttableStyle.width = \"100%\";\n\n\t\t\t// IE7 will make the width of the table when 100% include the scrollbar\n\t\t\t// - which is shouldn't. When there is a scrollbar we need to take this\n\t\t\t// into account.\n\t\t\tif ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||\n\t\t\t\tdivBody.css('overflow-y') == \"scroll\")\n\t\t\t) {\n\t\t\t\ttableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// x scrolling\n\t\t\tif ( scrollXInner !== \"\" ) {\n\t\t\t\t// x scroll inner has been given - use it\n\t\t\t\ttableStyle.width = _fnStringToCss(scrollXInner);\n\t\t\t}\n\t\t\telse if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {\n\t\t\t\t// There is y-scrolling - try to take account of the y scroll bar\n\t\t\t\ttableStyle.width = _fnStringToCss( sanityWidth-barWidth );\n\t\t\t\tif ( table.outerWidth() > sanityWidth-barWidth ) {\n\t\t\t\t\t// Not possible to take account of it\n\t\t\t\t\ttableStyle.width = _fnStringToCss( sanityWidth );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// When all else fails\n\t\t\t\ttableStyle.width = _fnStringToCss( sanityWidth );\n\t\t\t}\n\t\t}\n\n\t\t// Recalculate the sanity width - now that we've applied the required width,\n\t\t// before it was a temporary variable. This is required because the column\n\t\t// width calculation is done before this table DOM is created.\n\t\tsanityWidth = table.outerWidth();\n\n\t\t// Hidden header should have zero height, so remove padding and borders. Then\n\t\t// set the width based on the real headers\n\n\t\t// Apply all styles in one pass\n\t\t_fnApplyToChildren( zeroOut, headerSrcEls );\n\n\t\t// Read all widths in next pass\n\t\t_fnApplyToChildren( function(nSizer) {\n\t\t\theaderWidths.push( _fnStringToCss( $(nSizer).css('width') ) );\n\t\t}, headerSrcEls );\n\n\t\t// Apply all widths in final pass\n\t\t_fnApplyToChildren( function(nToSize, i) {\n\t\t\tnToSize.style.width = headerWidths[i];\n\t\t}, headerTrgEls );\n\n\t\t$(headerSrcEls).height(0);\n\n\t\t/* Same again with the footer if we have one */\n\t\tif ( footer )\n\t\t{\n\t\t\t_fnApplyToChildren( zeroOut, footerSrcEls );\n\n\t\t\t_fnApplyToChildren( function(nSizer) {\n\t\t\t\tfooterWidths.push( _fnStringToCss( $(nSizer).css('width') ) );\n\t\t\t}, footerSrcEls );\n\n\t\t\t_fnApplyToChildren( function(nToSize, i) {\n\t\t\t\tnToSize.style.width = footerWidths[i];\n\t\t\t}, footerTrgEls );\n\n\t\t\t$(footerSrcEls).height(0);\n\t\t}\n\n\n\t\t/*\n\t\t * 3. Apply the measurements\n\t\t */\n\n\t\t// \"Hide\" the header and footer that we used for the sizing. We want to also fix their width\n\t\t// to what they currently are\n\t\t_fnApplyToChildren( function(nSizer, i) {\n\t\t\tnSizer.innerHTML = \"\";\n\t\t\tnSizer.style.width = headerWidths[i];\n\t\t}, headerSrcEls );\n\n\t\tif ( footer )\n\t\t{\n\t\t\t_fnApplyToChildren( function(nSizer, i) {\n\t\t\t\tnSizer.innerHTML = \"\";\n\t\t\t\tnSizer.style.width = footerWidths[i];\n\t\t\t}, footerSrcEls );\n\t\t}\n\n\t\t// Sanity check that the table is of a sensible width. If not then we are going to get\n\t\t// misalignment - try to prevent this by not allowing the table to shrink below its min width\n\t\tif ( table.outerWidth() < sanityWidth )\n\t\t{\n\t\t\t// The min width depends upon if we have a vertical scrollbar visible or not */\n\t\t\tcorrection = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||\n\t\t\t\tdivBody.css('overflow-y') == \"scroll\")) ?\n\t\t\t\t\tsanityWidth+barWidth :\n\t\t\t\t\tsanityWidth;\n\n\t\t\t// IE6/7 are a law unto themselves...\n\t\t\tif ( ie67 && (divBodyEl.scrollHeight >\n\t\t\t\tdivBodyEl.offsetHeight || divBody.css('overflow-y') == \"scroll\")\n\t\t\t) {\n\t\t\t\ttableStyle.width = _fnStringToCss( correction-barWidth );\n\t\t\t}\n\n\t\t\t// And give the user a warning that we've stopped the table getting too small\n\t\t\tif ( scrollX === \"\" || scrollXInner !== \"\" ) {\n\t\t\t\t_fnLog( settings, 1, 'Possible column misalignment', 6 );\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcorrection = '100%';\n\t\t}\n\n\t\t// Apply to the container elements\n\t\tdivBodyStyle.width = _fnStringToCss( correction );\n\t\tdivHeaderStyle.width = _fnStringToCss( correction );\n\n\t\tif ( footer ) {\n\t\t\tsettings.nScrollFoot.style.width = _fnStringToCss( correction );\n\t\t}\n\n\n\t\t/*\n\t\t * 4. Clean up\n\t\t */\n\t\tif ( ! scrollY ) {\n\t\t\t/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting\n\t\t\t * the scrollbar height from the visible display, rather than adding it on. We need to\n\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 */\n\t\t\tif ( ie67 ) {\n\t\t\t\tdivBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );\n\t\t\t}\n\t\t}\n\n\t\tif ( scrollY && scroll.bCollapse ) {\n\t\t\tdivBodyStyle.height = _fnStringToCss( scrollY );\n\n\t\t\tvar iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?\n\t\t\t\tbarWidth :\n\t\t\t\t0;\n\n\t\t\tif ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {\n\t\t\t\tdivBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );\n\t\t\t}\n\t\t}\n\n\t\t/* Finally set the width's of the header and footer tables */\n\t\tvar iOuterWidth = table.outerWidth();\n\t\tdivHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );\n\t\tdivHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );\n\n\t\t// Figure out if there are scrollbar present - if so then we need a the header and footer to\n\t\t// provide a bit more space to allow \"overflow\" scrolling (i.e. past the scrollbar)\n\t\tvar bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == \"scroll\";\n\t\tvar padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );\n\t\tdivHeaderInnerStyle[ padding ] = bScrolling ? barWidth+\"px\" : \"0px\";\n\n\t\tif ( footer ) {\n\t\t\tdivFooterTable[0].style.width = _fnStringToCss( iOuterWidth );\n\t\t\tdivFooterInner[0].style.width = _fnStringToCss( iOuterWidth );\n\t\t\tdivFooterInner[0].style[padding] = bScrolling ? barWidth+\"px\" : \"0px\";\n\t\t}\n\n\t\t/* Adjust the position of the header in case we loose the y-scrollbar */\n\t\tdivBody.scroll();\n\n\t\t/* If sorting or filtering has occurred, jump the scrolling back to the top */\n\t\tif ( settings.bSorted || settings.bFiltered ) {\n\t\t\tdivBodyEl.scrollTop = 0;\n\t\t}\n\t}\n\n\n\n\t/**\n\t * Apply a given function to the display child nodes of an element array (typically\n\t * TD children of TR rows\n\t *  @param {function} fn Method to apply to the objects\n\t *  @param array {nodes} an1 List of elements to look through for display children\n\t *  @param array {nodes} an2 Another list (identical structure to the first) - optional\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnApplyToChildren( fn, an1, an2 )\n\t{\n\t\tvar index=0, i=0, iLen=an1.length;\n\t\tvar nNode1, nNode2;\n\n\t\twhile ( i < iLen ) {\n\t\t\tnNode1 = an1[i].firstChild;\n\t\t\tnNode2 = an2 ? an2[i].firstChild : null;\n\n\t\t\twhile ( nNode1 ) {\n\t\t\t\tif ( nNode1.nodeType === 1 ) {\n\t\t\t\t\tif ( an2 ) {\n\t\t\t\t\t\tfn( nNode1, nNode2, index );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tfn( nNode1, index );\n\t\t\t\t\t}\n\n\t\t\t\t\tindex++;\n\t\t\t\t}\n\n\t\t\t\tnNode1 = nNode1.nextSibling;\n\t\t\t\tnNode2 = an2 ? nNode2.nextSibling : null;\n\t\t\t}\n\n\t\t\ti++;\n\t\t}\n\t}\n\n\n\n\tvar __re_html_remove = /<.*?>/g;\n\n\n\t/**\n\t * Calculate the width of columns for the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnCalculateColumnWidths ( oSettings )\n\t{\n\t\tvar\n\t\t\ttable = oSettings.nTable,\n\t\t\tcolumns = oSettings.aoColumns,\n\t\t\tscroll = oSettings.oScroll,\n\t\t\tscrollY = scroll.sY,\n\t\t\tscrollX = scroll.sX,\n\t\t\tscrollXInner = scroll.sXInner,\n\t\t\tcolumnCount = columns.length,\n\t\t\tvisibleColumns = _fnGetColumns( oSettings, 'bVisible' ),\n\t\t\theaderCells = $('th', oSettings.nTHead),\n\t\t\ttableWidthAttr = table.getAttribute('width'),\n\t\t\ttableContainer = table.parentNode,\n\t\t\tuserInputs = false,\n\t\t\ti, column, columnIdx, width, outerWidth;\n\n\t\t/* Convert any user input sizes into pixel sizes */\n\t\tfor ( i=0 ; i<visibleColumns.length ; i++ ) {\n\t\t\tcolumn = columns[ visibleColumns[i] ];\n\n\t\t\tif ( column.sWidth !== null ) {\n\t\t\t\tcolumn.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );\n\n\t\t\t\tuserInputs = true;\n\t\t\t}\n\t\t}\n\n\t\t/* If the number of columns in the DOM equals the number that we have to\n\t\t * process in DataTables, then we can use the offsets that are created by\n\t\t * the web- browser. No custom sizes can be set in order for this to happen,\n\t\t * nor scrolling used\n\t\t */\n\t\tif ( ! userInputs && ! scrollX && ! scrollY &&\n\t\t    columnCount == _fnVisbleColumns( oSettings ) &&\n\t\t\tcolumnCount == headerCells.length\n\t\t) {\n\t\t\tfor ( i=0 ; i<columnCount ; i++ ) {\n\t\t\t\tcolumns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Otherwise construct a single row table with the widest node in the\n\t\t\t// data, assign any user defined widths, then insert it into the DOM and\n\t\t\t// allow the browser to do all the hard work of calculating table widths\n\t\t\tvar tmpTable = $( table.cloneNode( false ) )\n\t\t\t\t.css( 'visibility', 'hidden' )\n\t\t\t\t.removeAttr( 'id' )\n\t\t\t\t.append( $(oSettings.nTHead).clone( false ) )\n\t\t\t\t.append( $(oSettings.nTFoot).clone( false ) )\n\t\t\t\t.append( $('<tbody><tr/></tbody>') );\n\n\t\t\t// Remove any assigned widths from the footer (from scrolling)\n\t\t\ttmpTable.find('tfoot th, tfoot td').css('width', '');\n\n\t\t\tvar tr = tmpTable.find( 'tbody tr' );\n\n\t\t\t// Apply custom sizing to the cloned header\n\t\t\theaderCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );\n\n\t\t\tfor ( i=0 ; i<visibleColumns.length ; i++ ) {\n\t\t\t\tcolumn = columns[ visibleColumns[i] ];\n\n\t\t\t\theaderCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?\n\t\t\t\t\t_fnStringToCss( column.sWidthOrig ) :\n\t\t\t\t\t'';\n\t\t\t}\n\n\t\t\t// Find the widest cell for each column and put it into the table\n\t\t\tif ( oSettings.aoData.length ) {\n\t\t\t\tfor ( i=0 ; i<visibleColumns.length ; i++ ) {\n\t\t\t\t\tcolumnIdx = visibleColumns[i];\n\t\t\t\t\tcolumn = columns[ columnIdx ];\n\n\t\t\t\t\t$( _fnGetWidestNode( oSettings, columnIdx ) )\n\t\t\t\t\t\t.clone( false )\n\t\t\t\t\t\t.append( column.sContentPadding )\n\t\t\t\t\t\t.appendTo( tr );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Table has been built, attach to the document so we can work with it\n\t\t\ttmpTable.appendTo( tableContainer );\n\n\t\t\t// When scrolling (X or Y) we want to set the width of the table as\n\t\t\t// appropriate. However, when not scrolling leave the table width as it\n\t\t\t// is. This results in slightly different, but I think correct behaviour\n\t\t\tif ( scrollX && scrollXInner ) {\n\t\t\t\ttmpTable.width( scrollXInner );\n\t\t\t}\n\t\t\telse if ( scrollX ) {\n\t\t\t\ttmpTable.css( 'width', 'auto' );\n\n\t\t\t\tif ( tmpTable.width() < tableContainer.offsetWidth ) {\n\t\t\t\t\ttmpTable.width( tableContainer.offsetWidth );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( scrollY ) {\n\t\t\t\ttmpTable.width( tableContainer.offsetWidth );\n\t\t\t}\n\t\t\telse if ( tableWidthAttr ) {\n\t\t\t\ttmpTable.width( tableWidthAttr );\n\t\t\t}\n\n\t\t\t// Take into account the y scrollbar\n\t\t\t_fnScrollingWidthAdjust( oSettings, tmpTable[0] );\n\n\t\t\t// Browsers need a bit of a hand when a width is assigned to any columns\n\t\t\t// when x-scrolling as they tend to collapse the table to the min-width,\n\t\t\t// even if we sent the column widths. So we need to keep track of what\n\t\t\t// the table width should be by summing the user given values, and the\n\t\t\t// automatic values\n\t\t\tif ( scrollX )\n\t\t\t{\n\t\t\t\tvar total = 0;\n\n\t\t\t\tfor ( i=0 ; i<visibleColumns.length ; i++ ) {\n\t\t\t\t\tcolumn = columns[ visibleColumns[i] ];\n\t\t\t\t\touterWidth = $(headerCells[i]).outerWidth();\n\n\t\t\t\t\ttotal += column.sWidthOrig === null ?\n\t\t\t\t\t\touterWidth :\n\t\t\t\t\t\tparseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();\n\t\t\t\t}\n\n\t\t\t\ttmpTable.width( _fnStringToCss( total ) );\n\t\t\t\ttable.style.width = _fnStringToCss( total );\n\t\t\t}\n\n\t\t\t// Get the width of each column in the constructed table\n\t\t\tfor ( i=0 ; i<visibleColumns.length ; i++ ) {\n\t\t\t\tcolumn = columns[ visibleColumns[i] ];\n\t\t\t\twidth = $(headerCells[i]).width();\n\n\t\t\t\tif ( width ) {\n\t\t\t\t\tcolumn.sWidth = _fnStringToCss( width );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttable.style.width = _fnStringToCss( tmpTable.css('width') );\n\n\t\t\t// Finished with the table - ditch it\n\t\t\ttmpTable.remove();\n\t\t}\n\n\t\t// If there is a width attr, we want to attach an event listener which\n\t\t// allows the table sizing to automatically adjust when the window is\n\t\t// resized. Use the width attr rather than CSS, since we can't know if the\n\t\t// CSS is a relative value or absolute - DOM read is always px.\n\t\tif ( tableWidthAttr ) {\n\t\t\ttable.style.width = _fnStringToCss( tableWidthAttr );\n\n\t\t\tif ( ! oSettings._reszEvt ) {\n\t\t\t\t$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {\n\t\t\t\t\t_fnAdjustColumnSizing( oSettings );\n\t\t\t\t} ) );\n\n\t\t\t\toSettings._reszEvt = true;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tfunction _fnThrottle( fn ) {\n\t\tvar\n\t\t\tfrequency = 200,\n\t\t\tlast,\n\t\t\ttimer;\n\n\t\treturn function () {\n\t\t\tvar\n\t\t\t\tnow = +new Date(),\n\t\t\t\targs = arguments;\n\n\t\t\tif ( last && now < last + frequency ) {\n\t\t\t\tclearTimeout( timer );\n\n\t\t\t\ttimer = setTimeout( function () {\n\t\t\t\t\tlast = now;\n\t\t\t\t\tfn();\n\t\t\t\t}, frequency );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlast = now;\n\t\t\t\tfn();\n\t\t\t}\n\t\t};\n\t}\n\n\n\t/**\n\t * Convert a CSS unit width to pixels (e.g. 2em)\n\t *  @param {string} width width to be converted\n\t *  @param {node} parent parent to get the with for (required for relative widths) - optional\n\t *  @returns {int} width in pixels\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnConvertToWidth ( width, parent )\n\t{\n\t\tif ( ! width ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar n = $('<div/>')\n\t\t\t.css( 'width', _fnStringToCss( width ) )\n\t\t\t.appendTo( parent || document.body );\n\n\t\tvar val = n[0].offsetWidth;\n\t\tn.remove();\n\n\t\treturn val;\n\t}\n\n\n\t/**\n\t * Adjust a table's width to take account of vertical scroll bar\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {node} n table node\n\t *  @memberof DataTable#oApi\n\t */\n\n\tfunction _fnScrollingWidthAdjust ( settings, n )\n\t{\n\t\tvar scroll = settings.oScroll;\n\n\t\tif ( scroll.sX || scroll.sY ) {\n\t\t\t// When y-scrolling only, we want to remove the width of the scroll bar\n\t\t\t// so the table + scroll bar will fit into the area available, otherwise\n\t\t\t// we fix the table at its current size with no adjustment\n\t\t\tvar correction = ! scroll.sX ? scroll.iBarWidth : 0;\n\t\t\tn.style.width = _fnStringToCss( $(n).outerWidth() - correction );\n\t\t}\n\t}\n\n\n\t/**\n\t * Get the widest node\n\t *  @param {object} settings dataTables settings object\n\t *  @param {int} colIdx column of interest\n\t *  @returns {node} widest table node\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetWidestNode( settings, colIdx )\n\t{\n\t\tvar idx = _fnGetMaxLenString( settings, colIdx );\n\t\tif ( idx < 0 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar data = settings.aoData[ idx ];\n\t\treturn ! data.nTr ? // Might not have been created when deferred rendering\n\t\t\t$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :\n\t\t\tdata.anCells[ colIdx ];\n\t}\n\n\n\t/**\n\t * Get the maximum strlen for each data column\n\t *  @param {object} settings dataTables settings object\n\t *  @param {int} colIdx column of interest\n\t *  @returns {string} max string length for each column\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnGetMaxLenString( settings, colIdx )\n\t{\n\t\tvar s, max=-1, maxIdx = -1;\n\n\t\tfor ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\n\t\t\ts = _fnGetCellData( settings, i, colIdx, 'display' )+'';\n\t\t\ts = s.replace( __re_html_remove, '' );\n\n\t\t\tif ( s.length > max ) {\n\t\t\t\tmax = s.length;\n\t\t\t\tmaxIdx = i;\n\t\t\t}\n\t\t}\n\n\t\treturn maxIdx;\n\t}\n\n\n\t/**\n\t * Append a CSS unit (only if required) to a string\n\t *  @param {string} value to css-ify\n\t *  @returns {string} value with css unit\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnStringToCss( s )\n\t{\n\t\tif ( s === null ) {\n\t\t\treturn '0px';\n\t\t}\n\n\t\tif ( typeof s == 'number' ) {\n\t\t\treturn s < 0 ?\n\t\t\t\t'0px' :\n\t\t\t\ts+'px';\n\t\t}\n\n\t\t// Check it has a unit character already\n\t\treturn s.match(/\\d$/) ?\n\t\t\ts+'px' :\n\t\t\ts;\n\t}\n\n\n\t/**\n\t * Get the width of a scroll bar in this browser being used\n\t *  @returns {int} width in pixels\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnScrollBarWidth ()\n\t{\n\t\t// On first run a static variable is set, since this is only needed once.\n\t\t// Subsequent runs will just use the previously calculated value\n\t\tif ( ! DataTable.__scrollbarWidth ) {\n\t\t\tvar inner = $('<p/>').css( {\n\t\t\t\twidth: '100%',\n\t\t\t\theight: 200,\n\t\t\t\tpadding: 0\n\t\t\t} )[0];\n\n\t\t\tvar outer = $('<div/>')\n\t\t\t\t.css( {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop: 0,\n\t\t\t\t\tleft: 0,\n\t\t\t\t\twidth: 200,\n\t\t\t\t\theight: 150,\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t} )\n\t\t\t\t.append( inner )\n\t\t\t\t.appendTo( 'body' );\n\n\t\t\tvar w1 = inner.offsetWidth;\n\t\t\touter.css( 'overflow', 'scroll' );\n\t\t\tvar w2 = inner.offsetWidth;\n\n\t\t\tif ( w1 === w2 ) {\n\t\t\t\tw2 = outer[0].clientWidth;\n\t\t\t}\n\n\t\t\touter.remove();\n\n\t\t\tDataTable.__scrollbarWidth = w1 - w2;\n\t\t}\n\n\t\treturn DataTable.__scrollbarWidth;\n\t}\n\n\n\n\tfunction _fnSortFlatten ( settings )\n\t{\n\t\tvar\n\t\t\ti, iLen, k, kLen,\n\t\t\taSort = [],\n\t\t\taiOrig = [],\n\t\t\taoColumns = settings.aoColumns,\n\t\t\taDataSort, iCol, sType, srcCol,\n\t\t\tfixed = settings.aaSortingFixed,\n\t\t\tfixedObj = $.isPlainObject( fixed ),\n\t\t\tnestedSort = [],\n\t\t\tadd = function ( a ) {\n\t\t\t\tif ( a.length && ! $.isArray( a[0] ) ) {\n\t\t\t\t\t// 1D array\n\t\t\t\t\tnestedSort.push( a );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// 2D array\n\t\t\t\t\tnestedSort.push.apply( nestedSort, a );\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Build the sort array, with pre-fix and post-fix options if they have been\n\t\t// specified\n\t\tif ( $.isArray( fixed ) ) {\n\t\t\tadd( fixed );\n\t\t}\n\n\t\tif ( fixedObj && fixed.pre ) {\n\t\t\tadd( fixed.pre );\n\t\t}\n\n\t\tadd( settings.aaSorting );\n\n\t\tif (fixedObj && fixed.post ) {\n\t\t\tadd( fixed.post );\n\t\t}\n\n\t\tfor ( i=0 ; i<nestedSort.length ; i++ )\n\t\t{\n\t\t\tsrcCol = nestedSort[i][0];\n\t\t\taDataSort = aoColumns[ srcCol ].aDataSort;\n\n\t\t\tfor ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )\n\t\t\t{\n\t\t\t\tiCol = aDataSort[k];\n\t\t\t\tsType = aoColumns[ iCol ].sType || 'string';\n\n\t\t\t\taSort.push( {\n\t\t\t\t\tsrc:       srcCol,\n\t\t\t\t\tcol:       iCol,\n\t\t\t\t\tdir:       nestedSort[i][1],\n\t\t\t\t\tindex:     nestedSort[i][2],\n\t\t\t\t\ttype:      sType,\n\t\t\t\t\tformatter: DataTable.ext.type.order[ sType+\"-pre\" ]\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\treturn aSort;\n\t}\n\n\t/**\n\t * Change the order of the table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t *  @todo This really needs split up!\n\t */\n\tfunction _fnSort ( oSettings )\n\t{\n\t\tvar\n\t\t\ti, ien, iLen, j, jLen, k, kLen,\n\t\t\tsDataType, nTh,\n\t\t\taiOrig = [],\n\t\t\toExtSort = DataTable.ext.type.order,\n\t\t\taoData = oSettings.aoData,\n\t\t\taoColumns = oSettings.aoColumns,\n\t\t\taDataSort, data, iCol, sType, oSort,\n\t\t\tformatters = 0,\n\t\t\tsortCol,\n\t\t\tdisplayMaster = oSettings.aiDisplayMaster,\n\t\t\taSort = _fnSortFlatten( oSettings );\n\n\t\t// Resolve any column types that are unknown due to addition or invalidation\n\t\t// @todo Can this be moved into a 'data-ready' handler which is called when\n\t\t//   data is going to be used in the table?\n\t\t_fnColumnTypes( oSettings );\n\n\t\tfor ( i=0, ien=aSort.length ; i<ien ; i++ ) {\n\t\t\tsortCol = aSort[i];\n\n\t\t\t// Track if we can use the fast sort algorithm\n\t\t\tif ( sortCol.formatter ) {\n\t\t\t\tformatters++;\n\t\t\t}\n\n\t\t\t// Load the data needed for the sort, for each cell\n\t\t\t_fnSortData( oSettings, sortCol.col );\n\t\t}\n\n\t\t/* No sorting required if server-side or no sorting array */\n\t\tif ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )\n\t\t{\n\t\t\t// Create a value - key array of the current row positions such that we can use their\n\t\t\t// current position during the sort, if values match, in order to perform stable sorting\n\t\t\tfor ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {\n\t\t\t\taiOrig[ displayMaster[i] ] = i;\n\t\t\t}\n\n\t\t\t/* Do the sort - here we want multi-column sorting based on a given data source (column)\n\t\t\t * and sorting function (from oSort) in a certain direction. It's reasonably complex to\n\t\t\t * follow on it's own, but this is what we want (example two column sorting):\n\t\t\t *  fnLocalSorting = function(a,b){\n\t\t\t *    var iTest;\n\t\t\t *    iTest = oSort['string-asc']('data11', 'data12');\n\t\t\t *      if (iTest !== 0)\n\t\t\t *        return iTest;\n\t\t\t *    iTest = oSort['numeric-desc']('data21', 'data22');\n\t\t\t *    if (iTest !== 0)\n\t\t\t *      return iTest;\n\t\t\t *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );\n\t\t\t *  }\n\t\t\t * Basically we have a test for each sorting column, if the data in that column is equal,\n\t\t\t * test the next column. If all columns match, then we use a numeric sort on the row\n\t\t\t * positions in the original data array to provide a stable sort.\n\t\t\t *\n\t\t\t * Note - I know it seems excessive to have two sorting methods, but the first is around\n\t\t\t * 15% faster, so the second is only maintained for backwards compatibility with sorting\n\t\t\t * methods which do not have a pre-sort formatting function.\n\t\t\t */\n\t\t\tif ( formatters === aSort.length ) {\n\t\t\t\t// All sort types have formatting functions\n\t\t\t\tdisplayMaster.sort( function ( a, b ) {\n\t\t\t\t\tvar\n\t\t\t\t\t\tx, y, k, test, sort,\n\t\t\t\t\t\tlen=aSort.length,\n\t\t\t\t\t\tdataA = aoData[a]._aSortData,\n\t\t\t\t\t\tdataB = aoData[b]._aSortData;\n\n\t\t\t\t\tfor ( k=0 ; k<len ; k++ ) {\n\t\t\t\t\t\tsort = aSort[k];\n\n\t\t\t\t\t\tx = dataA[ sort.col ];\n\t\t\t\t\t\ty = dataB[ sort.col ];\n\n\t\t\t\t\t\ttest = x<y ? -1 : x>y ? 1 : 0;\n\t\t\t\t\t\tif ( test !== 0 ) {\n\t\t\t\t\t\t\treturn sort.dir === 'asc' ? test : -test;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tx = aiOrig[a];\n\t\t\t\t\ty = aiOrig[b];\n\t\t\t\t\treturn x<y ? -1 : x>y ? 1 : 0;\n\t\t\t\t} );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Depreciated - remove in 1.11 (providing a plug-in option)\n\t\t\t\t// Not all sort types have formatting methods, so we have to call their sorting\n\t\t\t\t// methods.\n\t\t\t\tdisplayMaster.sort( function ( a, b ) {\n\t\t\t\t\tvar\n\t\t\t\t\t\tx, y, k, l, test, sort, fn,\n\t\t\t\t\t\tlen=aSort.length,\n\t\t\t\t\t\tdataA = aoData[a]._aSortData,\n\t\t\t\t\t\tdataB = aoData[b]._aSortData;\n\n\t\t\t\t\tfor ( k=0 ; k<len ; k++ ) {\n\t\t\t\t\t\tsort = aSort[k];\n\n\t\t\t\t\t\tx = dataA[ sort.col ];\n\t\t\t\t\t\ty = dataB[ sort.col ];\n\n\t\t\t\t\t\tfn = oExtSort[ sort.type+\"-\"+sort.dir ] || oExtSort[ \"string-\"+sort.dir ];\n\t\t\t\t\t\ttest = fn( x, y );\n\t\t\t\t\t\tif ( test !== 0 ) {\n\t\t\t\t\t\t\treturn test;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tx = aiOrig[a];\n\t\t\t\t\ty = aiOrig[b];\n\t\t\t\t\treturn x<y ? -1 : x>y ? 1 : 0;\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\t/* Tell the draw function that we have sorted the data */\n\t\toSettings.bSorted = true;\n\t}\n\n\n\tfunction _fnSortAria ( settings )\n\t{\n\t\tvar label;\n\t\tvar nextSort;\n\t\tvar columns = settings.aoColumns;\n\t\tvar aSort = _fnSortFlatten( settings );\n\t\tvar oAria = settings.oLanguage.oAria;\n\n\t\t// ARIA attributes - need to loop all columns, to update all (removing old\n\t\t// attributes as needed)\n\t\tfor ( var i=0, iLen=columns.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tvar col = columns[i];\n\t\t\tvar asSorting = col.asSorting;\n\t\t\tvar sTitle = col.sTitle.replace( /<.*?>/g, \"\" );\n\t\t\tvar jqTh = $(col.nTh).removeAttr('aria-sort');\n\n\t\t\t/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */\n\t\t\tif ( col.bSortable ) {\n\t\t\t\tif ( aSort.length > 0 && aSort[0].col == i ) {\n\t\t\t\t\tjqTh.attr('aria-sort', aSort[0].dir==\"asc\" ? \"ascending\" : \"descending\" );\n\t\t\t\t\tnextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnextSort = asSorting[0];\n\t\t\t\t}\n\n\t\t\t\tlabel = sTitle + ( nextSort === \"asc\" ?\n\t\t\t\t\toAria.sSortAscending :\n\t\t\t\t\toAria.sSortDescending\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlabel = sTitle;\n\t\t\t}\n\n\t\t\tjqTh.attr('aria-label', label);\n\t\t}\n\t}\n\n\n\t/**\n\t * Function to run on user sort request\n\t *  @param {object} settings dataTables settings object\n\t *  @param {node} attachTo node to attach the handler to\n\t *  @param {int} colIdx column sorting index\n\t *  @param {boolean} [append=false] Append the requested sort to the existing\n\t *    sort if true (i.e. multi-column sort)\n\t *  @param {function} [callback] callback function\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSortListener ( settings, colIdx, append, callback )\n\t{\n\t\tvar col = settings.aoColumns[ colIdx ];\n\t\tvar sorting = settings.aaSorting;\n\t\tvar asSorting = col.asSorting;\n\t\tvar nextSortIdx;\n\t\tvar next = function ( a ) {\n\t\t\tvar idx = a._idx;\n\t\t\tif ( idx === undefined ) {\n\t\t\t\tidx = $.inArray( a[1], asSorting );\n\t\t\t}\n\n\t\t\treturn idx+1 >= asSorting.length ? 0 : idx+1;\n\t\t};\n\n\t\t// If appending the sort then we are multi-column sorting\n\t\tif ( append && settings.oFeatures.bSortMulti ) {\n\t\t\t// Are we already doing some kind of sort on this column?\n\t\t\tvar sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );\n\n\t\t\tif ( sortIdx !== -1 ) {\n\t\t\t\t// Yes, modify the sort\n\t\t\t\tnextSortIdx = next( sorting[sortIdx] );\n\n\t\t\t\tsorting[sortIdx][1] = asSorting[ nextSortIdx ];\n\t\t\t\tsorting[sortIdx]._idx = nextSortIdx;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// No sort on this column yet\n\t\t\t\tsorting.push( [ colIdx, asSorting[0], 0 ] );\n\t\t\t\tsorting[sorting.length-1]._idx = 0;\n\t\t\t}\n\t\t}\n\t\telse if ( sorting.length && sorting[0][0] == colIdx ) {\n\t\t\t// Single column - already sorting on this column, modify the sort\n\t\t\tnextSortIdx = next( sorting[0] );\n\n\t\t\tsorting.length = 1;\n\t\t\tsorting[0][1] = asSorting[ nextSortIdx ];\n\t\t\tsorting[0]._idx = nextSortIdx;\n\t\t}\n\t\telse {\n\t\t\t// Single column - sort only on this column\n\t\t\tsorting.length = 0;\n\t\t\tsorting.push( [ colIdx, asSorting[0] ] );\n\t\t\tsorting[0]._idx = 0;\n\t\t}\n\n\t\t// Run the sort by calling a full redraw\n\t\t_fnReDraw( settings );\n\n\t\t// callback used for async user interaction\n\t\tif ( typeof callback == 'function' ) {\n\t\t\tcallback( settings );\n\t\t}\n\t}\n\n\n\t/**\n\t * Attach a sort handler (click) to a node\n\t *  @param {object} settings dataTables settings object\n\t *  @param {node} attachTo node to attach the handler to\n\t *  @param {int} colIdx column sorting index\n\t *  @param {function} [callback] callback function\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSortAttachListener ( settings, attachTo, colIdx, callback )\n\t{\n\t\tvar col = settings.aoColumns[ colIdx ];\n\n\t\t_fnBindAction( attachTo, {}, function (e) {\n\t\t\t/* If the column is not sortable - don't to anything */\n\t\t\tif ( col.bSortable === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_fnProcessingDisplay( settings, true );\n\n\t\t\t// Use a timeout to allow the processing display to be shown.\n\t\t\tsetTimeout( function() {\n\t\t\t\t_fnSortListener( settings, colIdx, e.shiftKey, callback );\n\n\t\t\t\t// In server-side processing, the draw callback will remove the\n\t\t\t\t// processing display\n\t\t\t\tif ( _fnDataSource( settings ) !== 'ssp' ) {\n\t\t\t\t\t_fnProcessingDisplay( settings, false );\n\t\t\t\t}\n\t\t\t}, 0 );\n\t\t} );\n\t}\n\n\n\t/**\n\t * Set the sorting classes on table's body, Note: it is safe to call this function\n\t * when bSort and bSortClasses are false\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSortingClasses( settings )\n\t{\n\t\tvar oldSort = settings.aLastSort;\n\t\tvar sortClass = settings.oClasses.sSortColumn;\n\t\tvar sort = _fnSortFlatten( settings );\n\t\tvar features = settings.oFeatures;\n\t\tvar i, ien, colIdx;\n\n\t\tif ( features.bSort && features.bSortClasses ) {\n\t\t\t// Remove old sorting classes\n\t\t\tfor ( i=0, ien=oldSort.length ; i<ien ; i++ ) {\n\t\t\t\tcolIdx = oldSort[i].src;\n\n\t\t\t\t// Remove column sorting\n\t\t\t\t$( _pluck( settings.aoData, 'anCells', colIdx ) )\n\t\t\t\t\t.removeClass( sortClass + (i<2 ? i+1 : 3) );\n\t\t\t}\n\n\t\t\t// Add new column sorting\n\t\t\tfor ( i=0, ien=sort.length ; i<ien ; i++ ) {\n\t\t\t\tcolIdx = sort[i].src;\n\n\t\t\t\t$( _pluck( settings.aoData, 'anCells', colIdx ) )\n\t\t\t\t\t.addClass( sortClass + (i<2 ? i+1 : 3) );\n\t\t\t}\n\t\t}\n\n\t\tsettings.aLastSort = sort;\n\t}\n\n\n\t// Get the data to sort a column, be it from cache, fresh (populating the\n\t// cache), or from a sort formatter\n\tfunction _fnSortData( settings, idx )\n\t{\n\t\t// Custom sorting function - provided by the sort data type\n\t\tvar column = settings.aoColumns[ idx ];\n\t\tvar customSort = DataTable.ext.order[ column.sSortDataType ];\n\t\tvar customData;\n\n\t\tif ( customSort ) {\n\t\t\tcustomData = customSort.call( settings.oInstance, settings, idx,\n\t\t\t\t_fnColumnIndexToVisible( settings, idx )\n\t\t\t);\n\t\t}\n\n\t\t// Use / populate cache\n\t\tvar row, cellData;\n\t\tvar formatter = DataTable.ext.type.order[ column.sType+\"-pre\" ];\n\n\t\tfor ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\n\t\t\trow = settings.aoData[i];\n\n\t\t\tif ( ! row._aSortData ) {\n\t\t\t\trow._aSortData = [];\n\t\t\t}\n\n\t\t\tif ( ! row._aSortData[idx] || customSort ) {\n\t\t\t\tcellData = customSort ?\n\t\t\t\t\tcustomData[i] : // If there was a custom sort function, use data from there\n\t\t\t\t\t_fnGetCellData( settings, i, idx, 'sort' );\n\n\t\t\t\trow._aSortData[ idx ] = formatter ?\n\t\t\t\t\tformatter( cellData ) :\n\t\t\t\t\tcellData;\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\t/**\n\t * Save the state of a table\n\t *  @param {object} oSettings dataTables settings object\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSaveState ( oSettings )\n\t{\n\t\tif ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t/* Store the interesting variables */\n\t\tvar i, iLen;\n\t\tvar oState = {\n\t\t\t\"iCreate\":      new Date().getTime(),\n\t\t\t\"iStart\":       oSettings._iDisplayStart,\n\t\t\t\"iLength\":      oSettings._iDisplayLength,\n\t\t\t\"aaSorting\":    $.extend( true, [], oSettings.aaSorting ),\n\t\t\t\"oSearch\":      $.extend( true, {}, oSettings.oPreviousSearch ),\n\t\t\t\"aoSearchCols\": $.extend( true, [], oSettings.aoPreSearchCols ),\n\t\t\t\"abVisCols\":    []\n\t\t};\n\n\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t{\n\t\t\toState.abVisCols.push( oSettings.aoColumns[i].bVisible );\n\t\t}\n\n\t\t_fnCallbackFire( oSettings, \"aoStateSaveParams\", 'stateSaveParams', [oSettings, oState] );\n\n\t\toSettings.fnStateSaveCallback.call( oSettings.oInstance, oSettings, oState );\n\t}\n\n\n\t/**\n\t * Attempt to load a saved table state\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {object} oInit DataTables init object so we can override settings\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnLoadState ( oSettings, oInit )\n\t{\n\t\tvar i, ien;\n\t\tvar columns = oSettings.aoColumns;\n\n\t\tif ( !oSettings.oFeatures.bStateSave )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tvar oData = oSettings.fnStateLoadCallback.call( oSettings.oInstance, oSettings );\n\t\tif ( !oData )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t/* Allow custom and plug-in manipulation functions to alter the saved data set and\n\t\t * cancelling of loading by returning false\n\t\t */\n\t\tvar abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );\n\t\tif ( $.inArray( false, abStateLoad ) !== -1 )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t/* Reject old data */\n\t\tif ( oData.iCreate < new Date().getTime() - (oSettings.iStateDuration*1000) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Number of columns have changed - all bets are off, no restore of settings\n\t\tif ( columns.length !== oData.aoSearchCols.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\t/* Store the saved state so it might be accessed at any time */\n\t\toSettings.oLoadedState = $.extend( true, {}, oData );\n\n\t\t/* Restore key features */\n\t\toSettings._iDisplayStart    = oData.iStart;\n\t\toSettings.iInitDisplayStart = oData.iStart;\n\t\toSettings._iDisplayLength   = oData.iLength;\n\t\toSettings.aaSorting         = [];\n\n\t\tvar savedSort = oData.aaSorting;\n\t\tfor ( i=0, ien=savedSort.length ; i<ien ; i++ ) {\n\t\t\toSettings.aaSorting.push( savedSort[i][0] >= columns.length ?\n\t\t\t\t[ 0, savedSort[i][1] ] :\n\t\t\t\tsavedSort[i]\n\t\t\t);\n\t\t}\n\n\t\t/* Search filtering  */\n\t\t$.extend( oSettings.oPreviousSearch, oData.oSearch );\n\t\t$.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );\n\n\t\t/* Column visibility state */\n\t\tfor ( i=0, ien=oData.abVisCols.length ; i<ien ; i++ ) {\n\t\t\tcolumns[i].bVisible = oData.abVisCols[i];\n\t\t}\n\n\t\t_fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );\n\t}\n\n\n\n\t/**\n\t * Return the settings object for a particular table\n\t *  @param {node} table table we are using as a dataTable\n\t *  @returns {object} Settings object - or null if not found\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnSettingsFromNode ( table )\n\t{\n\t\tvar settings = DataTable.settings;\n\t\tvar idx = $.inArray( table, _pluck( settings, 'nTable' ) );\n\n\t\treturn idx !== -1 ?\n\t\t\tsettings[ idx ] :\n\t\t\tnull;\n\t}\n\n\n\t/**\n\t * Log an error message\n\t *  @param {object} settings dataTables settings object\n\t *  @param {int} level log error messages, or display them to the user\n\t *  @param {string} msg error message\n\t *  @param {int} tn Technical note id to get more information about the error.\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnLog( settings, level, msg, tn )\n\t{\n\t\tmsg = 'DataTables warning: '+\n\t\t\t(settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;\n\n\t\tif ( tn ) {\n\t\t\tmsg += '. For more information about this error, please see '+\n\t\t\t'http://datatables.net/tn/'+tn;\n\t\t}\n\n\t\tif ( ! level  ) {\n\t\t\t// Backwards compatibility pre 1.10\n\t\t\tvar ext = DataTable.ext;\n\t\t\tvar type = ext.sErrMode || ext.errMode;\n\n\t\t\tif ( type == 'alert' ) {\n\t\t\t\talert( msg );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new Error(msg);\n\t\t\t}\n\t\t}\n\t\telse if ( window.console && console.log ) {\n\t\t\tconsole.log( msg );\n\t\t}\n\t}\n\n\n\t/**\n\t * See if a property is defined on one object, if so assign it to the other object\n\t *  @param {object} ret target object\n\t *  @param {object} src source object\n\t *  @param {string} name property\n\t *  @param {string} [mappedName] name to map too - optional, name used if not given\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnMap( ret, src, name, mappedName )\n\t{\n\t\tif ( $.isArray( name ) ) {\n\t\t\t$.each( name, function (i, val) {\n\t\t\t\tif ( $.isArray( val ) ) {\n\t\t\t\t\t_fnMap( ret, src, val[0], val[1] );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_fnMap( ret, src, val );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\treturn;\n\t\t}\n\n\t\tif ( mappedName === undefined ) {\n\t\t\tmappedName = name;\n\t\t}\n\n\t\tif ( src[name] !== undefined ) {\n\t\t\tret[mappedName] = src[name];\n\t\t}\n\t}\n\n\n\t/**\n\t * Extend objects - very similar to jQuery.extend, but deep copy objects, and\n\t * shallow copy arrays. The reason we need to do this, is that we don't want to\n\t * deep copy array init values (such as aaSorting) since the dev wouldn't be\n\t * able to override them, but we do want to deep copy arrays.\n\t *  @param {object} out Object to extend\n\t *  @param {object} extender Object from which the properties will be applied to\n\t *      out\n\t *  @param {boolean} breakRefs If true, then arrays will be sliced to take an\n\t *      independent copy with the exception of the `data` or `aaData` parameters\n\t *      if they are present. This is so you can pass in a collection to\n\t *      DataTables and have that used as your data source without breaking the\n\t *      references\n\t *  @returns {object} out Reference, just for convenience - out === the return.\n\t *  @memberof DataTable#oApi\n\t *  @todo This doesn't take account of arrays inside the deep copied objects.\n\t */\n\tfunction _fnExtend( out, extender, breakRefs )\n\t{\n\t\tvar val;\n\n\t\tfor ( var prop in extender ) {\n\t\t\tif ( extender.hasOwnProperty(prop) ) {\n\t\t\t\tval = extender[prop];\n\n\t\t\t\tif ( $.isPlainObject( val ) ) {\n\t\t\t\t\tif ( ! $.isPlainObject( out[prop] ) ) {\n\t\t\t\t\t\tout[prop] = {};\n\t\t\t\t\t}\n\t\t\t\t\t$.extend( true, out[prop], val );\n\t\t\t\t}\n\t\t\t\telse if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {\n\t\t\t\t\tout[prop] = val.slice();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tout[prop] = val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn out;\n\t}\n\n\n\t/**\n\t * Bind an event handers to allow a click or return key to activate the callback.\n\t * This is good for accessibility since a return on the keyboard will have the\n\t * same effect as a click, if the element has focus.\n\t *  @param {element} n Element to bind the action to\n\t *  @param {object} oData Data object to pass to the triggered function\n\t *  @param {function} fn Callback function for when the event is triggered\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnBindAction( n, oData, fn )\n\t{\n\t\t$(n)\n\t\t\t.bind( 'click.DT', oData, function (e) {\n\t\t\t\t\tn.blur(); // Remove focus outline for mouse users\n\t\t\t\t\tfn(e);\n\t\t\t\t} )\n\t\t\t.bind( 'keypress.DT', oData, function (e){\n\t\t\t\tif ( e.which === 13 ) {\n\t\t\t\t\tfn(e);\n\t\t\t\t} } )\n\t\t\t.bind( 'selectstart.DT', function () {\n\t\t\t\t/* Take the brutal approach to cancelling text selection */\n\t\t\t\treturn false;\n\t\t\t\t} );\n\t}\n\n\n\t/**\n\t * Register a callback function. Easily allows a callback function to be added to\n\t * an array store of callback functions that can then all be called together.\n\t *  @param {object} oSettings dataTables settings object\n\t *  @param {string} sStore Name of the array storage for the callbacks in oSettings\n\t *  @param {function} fn Function to be called back\n\t *  @param {string} sName Identifying name for the callback (i.e. a label)\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnCallbackReg( oSettings, sStore, fn, sName )\n\t{\n\t\tif ( fn )\n\t\t{\n\t\t\toSettings[sStore].push( {\n\t\t\t\t\"fn\": fn,\n\t\t\t\t\"sName\": sName\n\t\t\t} );\n\t\t}\n\t}\n\n\n\t/**\n\t * Fire callback functions and trigger events. Note that the loop over the\n\t * callback array store is done backwards! Further note that you do not want to\n\t * fire off triggers in time sensitive applications (for example cell creation)\n\t * as its slow.\n\t *  @param {object} settings dataTables settings object\n\t *  @param {string} callbackArr Name of the array storage for the callbacks in\n\t *      oSettings\n\t *  @param {string} event Name of the jQuery custom event to trigger. If null no\n\t *      trigger is fired\n\t *  @param {array} args Array of arguments to pass to the callback function /\n\t *      trigger\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnCallbackFire( settings, callbackArr, event, args )\n\t{\n\t\tvar ret = [];\n\n\t\tif ( callbackArr ) {\n\t\t\tret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {\n\t\t\t\treturn val.fn.apply( settings.oInstance, args );\n\t\t\t} );\n\t\t}\n\n\t\tif ( event !== null ) {\n\t\t\t$(settings.nTable).trigger( event+'.dt', args );\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\tfunction _fnLengthOverflow ( settings )\n\t{\n\t\tvar\n\t\t\tstart = settings._iDisplayStart,\n\t\t\tend = settings.fnDisplayEnd(),\n\t\t\tlen = settings._iDisplayLength;\n\n\t\t/* If we have space to show extra rows (backing up from the end point - then do so */\n\t\tif ( end === settings.fnRecordsDisplay() )\n\t\t{\n\t\t\tstart = end - len;\n\t\t}\n\n\t\tif ( len === -1 || start < 0 )\n\t\t{\n\t\t\tstart = 0;\n\t\t}\n\n\t\tsettings._iDisplayStart = start;\n\t}\n\n\n\tfunction _fnRenderer( settings, type )\n\t{\n\t\tvar renderer = settings.renderer;\n\t\tvar host = DataTable.ext.renderer[type];\n\n\t\tif ( $.isPlainObject( renderer ) && renderer[type] ) {\n\t\t\t// Specific renderer for this type. If available use it, otherwise use\n\t\t\t// the default.\n\t\t\treturn host[renderer[type]] || host._;\n\t\t}\n\t\telse if ( typeof renderer === 'string' ) {\n\t\t\t// Common renderer - if there is one available for this type use it,\n\t\t\t// otherwise use the default\n\t\t\treturn host[renderer] || host._;\n\t\t}\n\n\t\t// Use the default\n\t\treturn host._;\n\t}\n\n\n\t/**\n\t * Detect the data source being used for the table. Used to simplify the code\n\t * a little (ajax) and to make it compress a little smaller.\n\t *\n\t *  @param {object} settings dataTables settings object\n\t *  @returns {string} Data source\n\t *  @memberof DataTable#oApi\n\t */\n\tfunction _fnDataSource ( settings )\n\t{\n\t\tif ( settings.oFeatures.bServerSide ) {\n\t\t\treturn 'ssp';\n\t\t}\n\t\telse if ( settings.ajax || settings.sAjaxSource ) {\n\t\t\treturn 'ajax';\n\t\t}\n\t\treturn 'dom';\n\t}\n\n\n\tDataTable = function( options )\n\t{\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 *  @deprecated Since v1.10\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', {\"search\": \"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\treturn this.api(true).$( sSelector, oOpts );\n\t\t};\n\n\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 *  @deprecated Since v1.10\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', {\"search\": \"applied\"});\n\t\t *\n\t\t *      // Do something with the data\n\t\t *      alert( data.length+\" rows matched the search\" );\n\t\t *    } );\n\t\t */\n\t\tthis._ = function ( sSelector, oOpts )\n\t\t{\n\t\t\treturn this.api(true).rows( sSelector, oOpts ).data();\n\t\t};\n\n\n\t\t/**\n\t\t * Create a DataTables Api instance, with the currently selected tables for\n\t\t * the Api's context.\n\t\t * @param {boolean} [traditional=false] Set the API instance's context to be\n\t\t *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was\n\t\t *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),\n\t\t *   or if all tables captured in the jQuery object should be used.\n\t\t * @return {DataTables.Api}\n\t\t */\n\t\tthis.api = function ( traditional )\n\t\t{\n\t\t\treturn traditional ?\n\t\t\t\tnew _Api(\n\t\t\t\t\t_fnSettingsFromNode( this[ _ext.iApiIndex ] )\n\t\t\t\t) :\n\t\t\t\tnew _Api( this );\n\t\t};\n\n\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} data 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} [redraw=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 *  @deprecated Since v1.10\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( data, redraw )\n\t\t{\n\t\t\tvar api = this.api( true );\n\n\t\t\t/* Check if we want to add multiple rows or not */\n\t\t\tvar rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?\n\t\t\t\tapi.rows.add( data ) :\n\t\t\t\tapi.row.add( data );\n\n\t\t\tif ( redraw === undefined || redraw ) {\n\t\t\t\tapi.draw();\n\t\t\t}\n\n\t\t\treturn rows.flatten().toArray();\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 api = this.api( true ).columns.adjust();\n\t\t\tvar settings = api.settings()[0];\n\t\t\tvar scroll = settings.oScroll;\n\n\t\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\t\tapi.draw( false );\n\t\t\t}\n\t\t\telse if ( scroll.sX !== \"\" || scroll.sY !== \"\" ) {\n\t\t\t\t/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */\n\t\t\t\t_fnScrollDraw( settings );\n\t\t\t}\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\tvar api = this.api( true ).clear();\n\n\t\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\t\tapi.draw();\n\t\t\t}\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\tthis.api( true ).row( nTr ).child.hide();\n\t\t};\n\n\n\t\t/**\n\t\t * Remove a row for the table\n\t\t *  @param {mixed} target 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} [callBack] Callback function\n\t\t *  @param {bool} [redraw=true] Redraw the table or not\n\t\t *  @returns {array} The row that was deleted\n\t\t *  @dtopt API\n\t\t *  @deprecated Since v1.10\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( target, callback, redraw )\n\t\t{\n\t\t\tvar api = this.api( true );\n\t\t\tvar rows = api.rows( target );\n\t\t\tvar settings = rows.settings()[0];\n\t\t\tvar data = settings.aoData[ rows[0][0] ];\n\n\t\t\trows.remove();\n\n\t\t\tif ( callback ) {\n\t\t\t\tcallback.call( this, settings, data );\n\t\t\t}\n\n\t\t\tif ( redraw === undefined || redraw ) {\n\t\t\t\tapi.draw();\n\t\t\t}\n\n\t\t\treturn data;\n\t\t};\n\n\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} [remove=false] Completely remove the table from the DOM\n\t\t *  @dtopt API\n\t\t *  @deprecated Since v1.10\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 ( remove )\n\t\t{\n\t\t\tthis.api( true ).destroy( remove );\n\t\t};\n\n\n\t\t/**\n\t\t * Redraw the table\n\t\t *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.\n\t\t *  @dtopt API\n\t\t *  @deprecated Since v1.10\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( complete )\n\t\t{\n\t\t\t// Note that this isn't an exact match to the old call to _fnDraw - it takes\n\t\t\t// into account the new data, but can old position.\n\t\t\tthis.api( true ).draw( ! complete );\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 api = this.api( true );\n\n\t\t\tif ( iColumn === null || iColumn === undefined ) {\n\t\t\t\tapi.search( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t\t}\n\n\t\t\tapi.draw();\n\t\t};\n\n\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} [src] 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} [col] 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 *  @deprecated Since v1.10\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( src, col )\n\t\t{\n\t\t\tvar api = this.api( true );\n\n\t\t\tif ( src !== undefined ) {\n\t\t\t\tvar type = src.nodeName ? src.nodeName.toLowerCase() : '';\n\n\t\t\t\treturn col !== undefined || type == 'td' || type == 'th' ?\n\t\t\t\t\tapi.cell( src, col ).data() :\n\t\t\t\t\tapi.row( src ).data();\n\t\t\t}\n\n\t\t\treturn api.data().toArray();\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 api = this.api( true );\n\n\t\t\treturn iRow !== undefined ?\n\t\t\t\tapi.row( iRow ).node() :\n\t\t\t\tapi.rows().nodes().toArray();\n\t\t};\n\n\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} node 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 *  @deprecated Since v1.10\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( node )\n\t\t{\n\t\t\tvar api = this.api( true );\n\t\t\tvar nodeName = node.nodeName.toUpperCase();\n\n\t\t\tif ( nodeName == 'TR' ) {\n\t\t\t\treturn api.row( node ).index();\n\t\t\t}\n\t\t\telse if ( nodeName == 'TD' || nodeName == 'TH' ) {\n\t\t\t\tvar cell = api.cell( node ).index();\n\n\t\t\t\treturn [\n\t\t\t\t\tcell.row,\n\t\t\t\t\tcell.columnVisible,\n\t\t\t\t\tcell.column\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\treturn this.api( true ).row( nTr ).child.isShown();\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\treturn this.api( true ).row( nTr ).child( mHtml, sClass ).show();\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 api = this.api( true ).page( mAction );\n\n\t\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\t\tapi.draw(false);\n\t\t\t}\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 api = this.api( true ).column( iCol ).visible( bShow );\n\n\t\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\t\tapi.columns.adjust().draw();\n\t\t\t}\n\t\t};\n\n\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 *  @deprecated Since v1.10\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[_ext.iApiIndex] );\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\tthis.api( true ).order( aaSort ).draw();\n\t\t};\n\n\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 *  @deprecated Since v1.10\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\tthis.api( true ).order.listener( nNode, iColumn, fnCallback );\n\t\t};\n\n\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, give as null or undefined to\n\t\t *    update a whole row.\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 *  @deprecated Since v1.10\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'], $('tbody tr')[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 api = this.api( true );\n\n\t\t\tif ( iColumn === undefined || iColumn === null ) {\n\t\t\t\tapi.row( mRow ).data( mData );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.cell( mRow, iColumn ).data( mData );\n\t\t\t}\n\n\t\t\tif ( bAction === undefined || bAction ) {\n\t\t\t\tapi.columns.adjust();\n\t\t\t}\n\n\t\t\tif ( bRedraw === undefined || bRedraw ) {\n\t\t\t\tapi.draw();\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\n\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 *  @deprecated Since v1.10\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 = _ext.fnVersionCheck;\n\n\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\n\n\t\t/**\n\t\t * Create a wrapper function for exporting an internal functions to an external API.\n\t\t *  @param {string} fn API function name\n\t\t *  @returns {function} wrapped function\n\t\t *  @memberof DataTable#internal\n\t\t */\n\t\tfunction _fnExternApiFunc (fn)\n\t\t{\n\t\t\treturn function() {\n\t\t\t\tvar args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(\n\t\t\t\t\tArray.prototype.slice.call(arguments)\n\t\t\t\t);\n\t\t\t\treturn DataTable.ext.internal[fn].apply( this, args );\n\t\t\t};\n\t\t}\n\n\n\t\t/**\n\t\t * Reference to internal functions for use by plug-in developers. Note that\n\t\t * these methods are references to internal functions and are considered to be\n\t\t * private. If you use these methods, be aware that they are liable to change\n\t\t * between versions.\n\t\t *  @namespace\n\t\t */\n\t\tthis.oApi = this.internal = {\n\t\t\t_fnExternApiFunc: _fnExternApiFunc,\n\t\t\t_fnBuildAjax: _fnBuildAjax,\n\t\t\t_fnAjaxUpdate: _fnAjaxUpdate,\n\t\t\t_fnAjaxParameters: _fnAjaxParameters,\n\t\t\t_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,\n\t\t\t_fnAjaxDataSrc: _fnAjaxDataSrc,\n\t\t\t_fnAddColumn: _fnAddColumn,\n\t\t\t_fnColumnOptions: _fnColumnOptions,\n\t\t\t_fnAdjustColumnSizing: _fnAdjustColumnSizing,\n\t\t\t_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,\n\t\t\t_fnColumnIndexToVisible: _fnColumnIndexToVisible,\n\t\t\t_fnVisbleColumns: _fnVisbleColumns,\n\t\t\t_fnGetColumns: _fnGetColumns,\n\t\t\t_fnColumnTypes: _fnColumnTypes,\n\t\t\t_fnApplyColumnDefs: _fnApplyColumnDefs,\n\t\t\t_fnHungarianMap: _fnHungarianMap,\n\t\t\t_fnCamelToHungarian: _fnCamelToHungarian,\n\t\t\t_fnLanguageCompat: _fnLanguageCompat,\n\t\t\t_fnBrowserDetect: _fnBrowserDetect,\n\t\t\t_fnAddData: _fnAddData,\n\t\t\t_fnAddTr: _fnAddTr,\n\t\t\t_fnNodeToDataIndex: _fnNodeToDataIndex,\n\t\t\t_fnNodeToColumnIndex: _fnNodeToColumnIndex,\n\t\t\t_fnGetRowData: _fnGetRowData,\n\t\t\t_fnGetCellData: _fnGetCellData,\n\t\t\t_fnSetCellData: _fnSetCellData,\n\t\t\t_fnSplitObjNotation: _fnSplitObjNotation,\n\t\t\t_fnGetObjectDataFn: _fnGetObjectDataFn,\n\t\t\t_fnSetObjectDataFn: _fnSetObjectDataFn,\n\t\t\t_fnGetDataMaster: _fnGetDataMaster,\n\t\t\t_fnClearTable: _fnClearTable,\n\t\t\t_fnDeleteIndex: _fnDeleteIndex,\n\t\t\t_fnInvalidateRow: _fnInvalidateRow,\n\t\t\t_fnGetRowElements: _fnGetRowElements,\n\t\t\t_fnCreateTr: _fnCreateTr,\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_fnAddOptionsHtml: _fnAddOptionsHtml,\n\t\t\t_fnDetectHeader: _fnDetectHeader,\n\t\t\t_fnGetUniqueThs: _fnGetUniqueThs,\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_fnFilterCreateSearch: _fnFilterCreateSearch,\n\t\t\t_fnEscapeRegex: _fnEscapeRegex,\n\t\t\t_fnFilterData: _fnFilterData,\n\t\t\t_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,\n\t\t\t_fnUpdateInfo: _fnUpdateInfo,\n\t\t\t_fnInfoMacros: _fnInfoMacros,\n\t\t\t_fnInitialise: _fnInitialise,\n\t\t\t_fnInitComplete: _fnInitComplete,\n\t\t\t_fnLengthChange: _fnLengthChange,\n\t\t\t_fnFeatureHtmlLength: _fnFeatureHtmlLength,\n\t\t\t_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,\n\t\t\t_fnPageChange: _fnPageChange,\n\t\t\t_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,\n\t\t\t_fnProcessingDisplay: _fnProcessingDisplay,\n\t\t\t_fnFeatureHtmlTable: _fnFeatureHtmlTable,\n\t\t\t_fnScrollDraw: _fnScrollDraw,\n\t\t\t_fnApplyToChildren: _fnApplyToChildren,\n\t\t\t_fnCalculateColumnWidths: _fnCalculateColumnWidths,\n\t\t\t_fnThrottle: _fnThrottle,\n\t\t\t_fnConvertToWidth: _fnConvertToWidth,\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_fnScrollBarWidth: _fnScrollBarWidth,\n\t\t\t_fnSortFlatten: _fnSortFlatten,\n\t\t\t_fnSort: _fnSort,\n\t\t\t_fnSortAria: _fnSortAria,\n\t\t\t_fnSortListener: _fnSortListener,\n\t\t\t_fnSortAttachListener: _fnSortAttachListener,\n\t\t\t_fnSortingClasses: _fnSortingClasses,\n\t\t\t_fnSortData: _fnSortData,\n\t\t\t_fnSaveState: _fnSaveState,\n\t\t\t_fnLoadState: _fnLoadState,\n\t\t\t_fnSettingsFromNode: _fnSettingsFromNode,\n\t\t\t_fnLog: _fnLog,\n\t\t\t_fnMap: _fnMap,\n\t\t\t_fnBindAction: _fnBindAction,\n\t\t\t_fnCallbackReg: _fnCallbackReg,\n\t\t\t_fnCallbackFire: _fnCallbackFire,\n\t\t\t_fnLengthOverflow: _fnLengthOverflow,\n\t\t\t_fnRenderer: _fnRenderer,\n\t\t\t_fnDataSource: _fnDataSource,\n\t\t\t_fnRowAttributes: _fnRowAttributes\n\t\t};\n\n\t\t$.extend( DataTable.ext.internal, this.internal );\n\n\t\tfor ( var fn in DataTable.ext.internal ) {\n\t\t\tif ( fn ) {\n\t\t\t\tthis[fn] = _fnExternApiFunc(fn);\n\t\t\t}\n\t\t}\n\n\n\t\tvar _that = this;\n\t\tvar emptyInit = options === undefined;\n\t\tvar len = this.length;\n\n\t\tif ( emptyInit ) {\n\t\t\toptions = {};\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\t// For each initialisation we want to give it a clean initialisation\n\t\t\t// object that can be bashed around\n\t\t\tvar o = {};\n\t\t\tvar oInit = len > 1 ? // optimisation for single table case\n\t\t\t\t_fnExtend( o, options, true ) :\n\t\t\t\toptions;\n\n\t\t\t/*global oInit,_that,emptyInit*/\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 defaults = DataTable.defaults;\n\n\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, 'Non-table node initialisation ('+this.nodeName+')', 2 );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/* Backwards compatibility for the defaults */\n\t\t\t_fnCompatOpts( defaults );\n\t\t\t_fnCompatCols( defaults.column );\n\n\t\t\t/* Convert the camel-case defaults to Hungarian */\n\t\t\t_fnCamelToHungarian( defaults, defaults, true );\n\t\t\t_fnCamelToHungarian( defaults.column, defaults.column, true );\n\n\t\t\t/* Setting up the initialisation object */\n\t\t\t_fnCamelToHungarian( defaults, oInit );\n\n\t\t\t/* Check to see if we are re-initialising a table */\n\t\t\tvar allSettings = DataTable.settings;\n\t\t\tfor ( i=0, iLen=allSettings.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\t/* Base check on table node */\n\t\t\t\tif ( allSettings[i].nTable == this )\n\t\t\t\t{\n\t\t\t\t\tvar bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;\n\t\t\t\t\tvar bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;\n\n\t\t\t\t\tif ( emptyInit || bRetrieve )\n\t\t\t\t\t{\n\t\t\t\t\t\treturn allSettings[i].oInstance;\n\t\t\t\t\t}\n\t\t\t\t\telse if ( bDestroy )\n\t\t\t\t\t{\n\t\t\t\t\t\tallSettings[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( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\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 ( allSettings[i].sTableId == this.id )\n\t\t\t\t{\n\t\t\t\t\tallSettings.splice( i, 1 );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\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._unique++);\n\t\t\t\tthis.id = sId;\n\t\t\t}\n\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.internal,\n\t\t\t\t\"oInit\":         oInit,\n\t\t\t\t\"sDestroyWidth\": $(this)[0].style.width,\n\t\t\t\t\"sInstance\":     sId,\n\t\t\t\t\"sTableId\":      sId\n\t\t\t} );\n\t\t\tallSettings.push( oSettings );\n\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\n\t\t\t// Backwards compatibility, before we apply all the defaults\n\t\t\t_fnCompatOpts( oInit );\n\n\t\t\tif ( oInit.oLanguage )\n\t\t\t{\n\t\t\t\t_fnLanguageCompat( oInit.oLanguage );\n\t\t\t}\n\n\t\t\t// If the length menu is given, but the init display length is not, use the length menu\n\t\t\tif ( oInit.aLengthMenu && ! oInit.iDisplayLength )\n\t\t\t{\n\t\t\t\toInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?\n\t\t\t\t\toInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];\n\t\t\t}\n\n\t\t\t// Apply the defaults and init options to make a single init object will all\n\t\t\t// options defined from defaults and instance options.\n\t\t\toInit = _fnExtend( $.extend( true, {}, defaults ), oInit );\n\n\n\t\t\t// Map the initialisation options onto the settings object\n\t\t\t_fnMap( oSettings.oFeatures, oInit, [\n\t\t\t\t\"bPaginate\",\n\t\t\t\t\"bLengthChange\",\n\t\t\t\t\"bFilter\",\n\t\t\t\t\"bSort\",\n\t\t\t\t\"bSortMulti\",\n\t\t\t\t\"bInfo\",\n\t\t\t\t\"bProcessing\",\n\t\t\t\t\"bAutoWidth\",\n\t\t\t\t\"bSortClasses\",\n\t\t\t\t\"bServerSide\",\n\t\t\t\t\"bDeferRender\"\n\t\t\t] );\n\t\t\t_fnMap( oSettings, oInit, [\n\t\t\t\t\"asStripeClasses\",\n\t\t\t\t\"ajax\",\n\t\t\t\t\"fnServerData\",\n\t\t\t\t\"fnFormatNumber\",\n\t\t\t\t\"sServerMethod\",\n\t\t\t\t\"aaSorting\",\n\t\t\t\t\"aaSortingFixed\",\n\t\t\t\t\"aLengthMenu\",\n\t\t\t\t\"sPaginationType\",\n\t\t\t\t\"sAjaxSource\",\n\t\t\t\t\"sAjaxDataProp\",\n\t\t\t\t\"iStateDuration\",\n\t\t\t\t\"sDom\",\n\t\t\t\t\"bSortCellsTop\",\n\t\t\t\t\"iTabIndex\",\n\t\t\t\t\"fnStateLoadCallback\",\n\t\t\t\t\"fnStateSaveCallback\",\n\t\t\t\t\"renderer\",\n\t\t\t\t[ \"iCookieDuration\", \"iStateDuration\" ], // backwards compat\n\t\t\t\t[ \"oSearch\", \"oPreviousSearch\" ],\n\t\t\t\t[ \"aoSearchCols\", \"aoPreSearchCols\" ],\n\t\t\t\t[ \"iDisplayLength\", \"_iDisplayLength\" ],\n\t\t\t\t[ \"bJQueryUI\", \"bJUI\" ]\n\t\t\t] );\n\t\t\t_fnMap( oSettings.oScroll, oInit, [\n\t\t\t\t[ \"sScrollX\", \"sX\" ],\n\t\t\t\t[ \"sScrollXInner\", \"sXInner\" ],\n\t\t\t\t[ \"sScrollY\", \"sY\" ],\n\t\t\t\t[ \"bScrollCollapse\", \"bCollapse\" ]\n\t\t\t] );\n\t\t\t_fnMap( oSettings.oLanguage, oInit, \"fnInfoCallback\" );\n\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\n\t\t\t// @todo Remove in 1.11\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, oInit.oClasses );\n\n\t\t\t\tif ( oInit.sDom === defaults.sDom && 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\n\t\t\t\tif ( ! oSettings.renderer ) {\n\t\t\t\t\toSettings.renderer = 'jqueryui';\n\t\t\t\t}\n\t\t\t\telse if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {\n\t\t\t\t\toSettings.renderer.header = 'jqueryui';\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.classes, oInit.oClasses );\n\t\t\t}\n\t\t\t$(this).addClass( oSettings.oClasses.sTable );\n\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\tif ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling\n\t\t\t\toSettings.oScroll.sX = '100%';\n\t\t\t}\n\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\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\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_fnCamelToHungarian( defaults.oLanguage, 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\n\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\n\t\t\t/* Remove row stripe classes if they are already on the table row */\n\t\t\tvar stripeClasses = oSettings.asStripeClasses;\n\t\t\tvar rowOne = $('tbody tr:eq(0)', this);\n\t\t\tif ( $.inArray( true, $.map( stripeClasses, function(el, i) {\n\t\t\t\treturn rowOne.hasClass(el);\n\t\t\t} ) ) !== -1 ) {\n\t\t\t\t$('tbody tr', this).removeClass( stripeClasses.join(' ') );\n\t\t\t\toSettings.asDestroyStripes = stripeClasses.slice();\n\t\t\t}\n\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\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\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_fnAddColumn( oSettings, anThs ? anThs[i] : null );\n\t\t\t}\n\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\n\t\t\t/* HTML5 attribute detection - build an mData object automatically if the\n\t\t\t * attributes are found\n\t\t\t */\n\t\t\tif ( rowOne.length ) {\n\t\t\t\tvar a = function ( cell, name ) {\n\t\t\t\t\treturn cell.getAttribute( 'data-'+name ) ? name : null;\n\t\t\t\t};\n\n\t\t\t\t$.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {\n\t\t\t\t\tvar col = oSettings.aoColumns[i];\n\n\t\t\t\t\tif ( col.mData === i ) {\n\t\t\t\t\t\tvar sort = a( cell, 'sort' ) || a( cell, 'order' );\n\t\t\t\t\t\tvar filter = a( cell, 'filter' ) || a( cell, 'search' );\n\n\t\t\t\t\t\tif ( sort !== null || filter !== null ) {\n\t\t\t\t\t\t\tcol.mData = {\n\t\t\t\t\t\t\t\t_:      i+'.display',\n\t\t\t\t\t\t\t\tsort:   sort !== null   ? i+'.@data-'+sort   : undefined,\n\t\t\t\t\t\t\t\ttype:   sort !== null   ? i+'.@data-'+sort   : undefined,\n\t\t\t\t\t\t\t\tfilter: filter !== null ? i+'.@data-'+filter : undefined\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t_fnColumnOptions( oSettings, i );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\n\t\t\t/* Must be done after everything which can be overridden by the state saving! */\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\n\n\t\t\t/*\n\t\t\t * Sorting\n\t\t\t * @todo For modularisation (1.11) this needs to do into a sort start up handler\n\t\t\t */\n\n\t\t\t// If aaSorting is not defined, then we use the first indicator in asSorting\n\t\t\t// in case that has been altered, so the default sort reflects that option\n\t\t\tif ( oInit.aaSorting === undefined )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\toSettings.aaSorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];\n\t\t\t\t}\n\t\t\t}\n\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\n\t\t\tif ( oSettings.oFeatures.bSort )\n\t\t\t{\n\t\t\t\t_fnCallbackReg( oSettings, 'aoDrawCallback', function () {\n\t\t\t\t\tif ( oSettings.bSorted ) {\n\t\t\t\t\t\tvar aSort = _fnSortFlatten( oSettings );\n\t\t\t\t\t\tvar sortedColumns = {};\n\n\t\t\t\t\t\t$.each( aSort, function (i, val) {\n\t\t\t\t\t\t\tsortedColumns[ val.src ] = val.dir;\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );\n\t\t\t\t\t\t_fnSortingClasses( oSettings );\n\t\t\t\t\t\t_fnSortAria( oSettings );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\n\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\n\t\t\t/* Browser support detection */\n\t\t\t_fnBrowserDetect( oSettings );\n\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\n\t\t\tvar thead = $(this).children('thead');\n\t\t\tif ( thead.length === 0 )\n\t\t\t{\n\t\t\t\tthead = $('<thead/>').appendTo(this);\n\t\t\t}\n\t\t\toSettings.nTHead = thead[0];\n\n\t\t\tvar tbody = $(this).children('tbody');\n\t\t\tif ( tbody.length === 0 )\n\t\t\t{\n\t\t\t\ttbody = $('<tbody/>').appendTo(this);\n\t\t\t}\n\t\t\toSettings.nTBody = tbody[0];\n\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 = $('<tfoot/>').appendTo(this);\n\t\t\t}\n\n\t\t\tif ( tfoot.length === 0 || tfoot.children().length === 0 ) {\n\t\t\t\t$(this).addClass( oSettings.oClasses.sNoFooter );\n\t\t\t}\n\t\t\telse if ( tfoot.length > 0 ) {\n\t\t\t\toSettings.nTFoot = tfoot[0];\n\t\t\t\t_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );\n\t\t\t}\n\n\t\t\t/* Check if there is data passing into the constructor */\n\t\t\tif ( oInit.aaData )\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 if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )\n\t\t\t{\n\t\t\t\t/* Grab the data from the page - only do this when deferred loading or no Ajax\n\t\t\t\t * source since there is no point in reading the DOM data if we are then going\n\t\t\t\t * to replace it with Ajax data\n\t\t\t\t */\n\t\t\t\t_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );\n\t\t\t}\n\n\t\t\t/* Copy the data index array */\n\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\n\t\t\t/* Initialisation complete - table can be drawn */\n\t\t\toSettings.bInitialised = true;\n\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\n\n\t/**\n\t * Computed structure of the DataTables API, defined by the options passed to\n\t * `DataTable.Api.register()` when building the API.\n\t *\n\t * The structure is built in order to speed creation and extension of the Api\n\t * objects since the extensions are effectively pre-parsed.\n\t *\n\t * The array is an array of objects with the following structure, where this\n\t * base array represents the Api prototype base:\n\t *\n\t *     [\n\t *       {\n\t *         name:      'data'                -- string   - Property name\n\t *         val:       function () {},       -- function - Api method (or undefined if just an object\n\t *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result\n\t *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property\n\t *       },\n\t *       {\n\t *         name:     'row'\n\t *         val:       {},\n\t *         methodExt: [ ... ],\n\t *         propExt:   [\n\t *           {\n\t *             name:      'data'\n\t *             val:       function () {},\n\t *             methodExt: [ ... ],\n\t *             propExt:   [ ... ]\n\t *           },\n\t *           ...\n\t *         ]\n\t *       }\n\t *     ]\n\t *\n\t * @type {Array}\n\t * @ignore\n\t */\n\tvar __apiStruct = [];\n\n\n\t/**\n\t * `Array.prototype` reference.\n\t *\n\t * @type object\n\t * @ignore\n\t */\n\tvar __arrayProto = Array.prototype;\n\n\n\n\n\t/**\n\t * Abstraction for `context` parameter of the `Api` constructor to allow it to\n\t * take several different forms for ease of use.\n\t *\n\t * Each of the input parameter types will be converted to a DataTables settings\n\t * object where possible.\n\t *\n\t * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one\n\t *   of:\n\t *\n\t *   * `string` - jQuery selector. Any DataTables' matching the given selector\n\t *     with be found and used.\n\t *   * `node` - `TABLE` node which has already been formed into a DataTable.\n\t *   * `jQuery` - A jQuery object of `TABLE` nodes.\n\t *   * `object` - DataTables settings object\n\t * @return {array|null} Matching DataTables settings objects. `null` or\n\t *   `undefined` is returned if no matching DataTable is found.\n\t * @ignore\n\t */\n\tvar _toSettings = function ( mixed )\n\t{\n\t\tvar idx, jq;\n\t\tvar settings = DataTable.settings;\n\t\tvar tables = $.map( settings, function (el, i) {\n\t\t\treturn el.nTable;\n\t\t} );\n\n\t\tif ( mixed.nTable && mixed.oApi ) {\n\t\t\t// DataTables settings object\n\t\t\treturn [ mixed ];\n\t\t}\n\t\telse if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {\n\t\t\t// Table node\n\t\t\tidx = $.inArray( mixed, tables );\n\t\t\treturn idx !== -1 ? [ settings[idx] ] : null;\n\t\t}\n\t\telse if ( typeof mixed === 'string' ) {\n\t\t\t// jQuery selector\n\t\t\tjq = $(mixed);\n\t\t}\n\t\telse if ( mixed instanceof $ ) {\n\t\t\t// jQuery object (also DataTables instance)\n\t\t\tjq = mixed;\n\t\t}\n\n\t\tif ( jq ) {\n\t\t\treturn jq.map( function(i) {\n\t\t\t\tidx = $.inArray( this, tables );\n\t\t\t\treturn idx !== -1 ? settings[idx] : null;\n\t\t\t} );\n\t\t}\n\t};\n\n\n\t/**\n\t * DataTables API class - used to control and interface with  one or more\n\t * DataTables enhanced tables.\n\t *\n\t * The API class is heavily based on jQuery, presenting a chainable interface\n\t * that you can use to interact with tables. Each instance of the API class has\n\t * a \"context\" - i.e. the tables that it will operate on. This could be a single\n\t * table, all tables on a page or a sub-set thereof.\n\t *\n\t * Additionally the API is designed to allow you to easily work with the data in\n\t * the tables, retrieving and manipulating it as required. This is done by\n\t * presenting the API class as an array like interface. The contents of the\n\t * array depend upon the actions requested by each method (for example\n\t * `rows().nodes()` will return an array of nodes, while `rows().data()` will\n\t * return an array of objects or arrays depending upon your table's\n\t * configuration). The API object has a number of array like methods (`push`,\n\t * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,\n\t * `unique` etc) to assist your working with the data held in a table.\n\t *\n\t * Most methods (those which return an Api instance) are chainable, which means\n\t * the return from a method call also has all of the methods available that the\n\t * top level object had. For example, these two calls are equivalent:\n\t *\n\t *     // Not chained\n\t *     api.row.add( {...} );\n\t *     api.draw();\n\t *\n\t *     // Chained\n\t *     api.row.add( {...} ).draw();\n\t *\n\t * @class DataTable.Api\n\t * @param {array|object|string|jQuery} context DataTable identifier. This is\n\t *   used to define which DataTables enhanced tables this API will operate on.\n\t *   Can be one of:\n\t *\n\t *   * `string` - jQuery selector. Any DataTables' matching the given selector\n\t *     with be found and used.\n\t *   * `node` - `TABLE` node which has already been formed into a DataTable.\n\t *   * `jQuery` - A jQuery object of `TABLE` nodes.\n\t *   * `object` - DataTables settings object\n\t * @param {array} [data] Data to initialise the Api instance with.\n\t *\n\t * @example\n\t *   // Direct initialisation during DataTables construction\n\t *   var api = $('#example').DataTable();\n\t *\n\t * @example\n\t *   // Initialisation using a DataTables jQuery object\n\t *   var api = $('#example').dataTable().api();\n\t *\n\t * @example\n\t *   // Initialisation as a constructor\n\t *   var api = new $.fn.DataTable.Api( 'table.dataTable' );\n\t */\n\tDataTable.Api = _Api = function ( context, data )\n\t{\n\t\tif ( ! this instanceof _Api ) {\n\t\t\tthrow 'DT API must be constructed as a new object';\n\t\t\t// or should it do the 'new' for the caller?\n\t\t\t// return new _Api.apply( this, arguments );\n\t\t}\n\n\t\tvar settings = [];\n\t\tvar ctxSettings = function ( o ) {\n\t\t\tvar a = _toSettings( o );\n\t\t\tif ( a ) {\n\t\t\t\tsettings.push.apply( settings, a );\n\t\t\t}\n\t\t};\n\n\t\tif ( $.isArray( context ) ) {\n\t\t\tfor ( var i=0, ien=context.length ; i<ien ; i++ ) {\n\t\t\t\tctxSettings( context[i] );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tctxSettings( context );\n\t\t}\n\n\t\t// Remove duplicates\n\t\tthis.context = _unique( settings );\n\n\t\t// Initial data\n\t\tif ( data ) {\n\t\t\tthis.push.apply( this, data );\n\t\t}\n\n\t\t// selector\n\t\tthis.selector = {\n\t\t\trows: null,\n\t\t\tcols: null,\n\t\t\topts: null\n\t\t};\n\n\t\t_Api.extend( this, this, __apiStruct );\n\t};\n\n\n\t_Api.prototype = /** @lends DataTables.Api */{\n\t\t/**\n\t\t * Return a new Api instance, comprised of the data held in the current\n\t\t * instance, join with the other array(s) and/or value(s).\n\t\t *\n\t\t * An alias for `Array.prototype.concat`.\n\t\t *\n\t\t * @type method\n\t\t * @param {*} value1 Arrays and/or values to concatenate.\n\t\t * @param {*} [...] Additional arrays and/or values to concatenate.\n\t\t * @returns {DataTables.Api} New API instance, comprising of the combined\n\t\t *   array.\n\t\t */\n\t\tconcat:  __arrayProto.concat,\n\n\n\t\tcontext: [], // array of table settings objects\n\n\n\t\teach: function ( fn )\n\t\t{\n\t\t\tif ( __arrayProto.forEach ) {\n\t\t\t\t// Where possible, use the built-in forEach\n\t\t\t\t__arrayProto.forEach.call( this, fn, this );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Compatibility for browsers without EMCA-252-5 (JS 1.6)\n\t\t\t\tfor ( var i=0, ien=this.length ; i<ien; i++ ) {\n\t\t\t\t\t// In strict mode the execution scope is the passed value\n\t\t\t\t\tfn.call( this, this[i], i, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\n\t\tfilter: function ( fn )\n\t\t{\n\t\t\tvar a = [];\n\n\t\t\tif ( __arrayProto.filter ) {\n\t\t\t\ta = __arrayProto.filter.call( this, fn, this );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Compatibility for browsers without EMCA-252-5 (JS 1.6)\n\t\t\t\tfor ( var i=0, ien=this.length ; i<ien ; i++ ) {\n\t\t\t\t\tif ( fn.call( this, this[i], i, this ) ) {\n\t\t\t\t\t\ta.push( this[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new _Api( this.context, a );\n\t\t},\n\n\n\t\tflatten: function ()\n\t\t{\n\t\t\tvar a = [];\n\t\t\treturn new _Api( this.context, a.concat.apply( a, this ) );\n\t\t},\n\n\n\t\tjoin:    __arrayProto.join,\n\n\n\t\tindexOf: __arrayProto.indexOf || function (obj, start)\n\t\t{\n\t\t\tfor ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {\n\t\t\t\tif ( this[i] === obj ) {\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\n\t\t// Internal only at the moment - relax?\n\t\titerator: function ( flatten, type, fn ) {\n\t\t\tvar\n\t\t\t\ta = [], ret,\n\t\t\t\ti, ien, j, jen,\n\t\t\t\tcontext = this.context,\n\t\t\t\trows, items, item,\n\t\t\t\tselector = this.selector;\n\n\t\t\t// Argument shifting\n\t\t\tif ( typeof flatten === 'string' ) {\n\t\t\t\tfn = type;\n\t\t\t\ttype = flatten;\n\t\t\t\tflatten = false;\n\t\t\t}\n\n\t\t\tfor ( i=0, ien=context.length ; i<ien ; i++ ) {\n\t\t\t\tif ( type === 'table' ) {\n\t\t\t\t\tret = fn( context[i], i );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\ta.push( ret );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( type === 'columns' || type === 'rows' ) {\n\t\t\t\t\t// this has same length as context - one entry for each table\n\t\t\t\t\tret = fn( context[i], this[i], i );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\ta.push( ret );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {\n\t\t\t\t\t// columns and rows share the same structure.\n\t\t\t\t\t// 'this' is an array of column indexes for each context\n\t\t\t\t\titems = this[i];\n\n\t\t\t\t\tif ( type === 'column-rows' ) {\n\t\t\t\t\t\trows = _selector_row_indexes( context[i], selector.opts );\n\t\t\t\t\t}\n\n\t\t\t\t\tfor ( j=0, jen=items.length ; j<jen ; j++ ) {\n\t\t\t\t\t\titem = items[j];\n\n\t\t\t\t\t\tif ( type === 'cell' ) {\n\t\t\t\t\t\t\tret = fn( context[i], item.row, item.column, i, j );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tret = fn( context[i], item, i, j, rows );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\t\ta.push( ret );\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 ( a.length ) {\n\t\t\t\tvar api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );\n\t\t\t\tvar apiSelector = api.selector;\n\t\t\t\tapiSelector.rows = selector.rows;\n\t\t\t\tapiSelector.cols = selector.cols;\n\t\t\t\tapiSelector.opts = selector.opts;\n\t\t\t\treturn api;\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\n\t\tlastIndexOf: __arrayProto.lastIndexOf || function (obj, start)\n\t\t{\n\t\t\t// Bit cheeky...\n\t\t\treturn this.indexOf.apply( this.toArray.reverse(), arguments );\n\t\t},\n\n\n\t\tlength:  0,\n\n\n\t\tmap: function ( fn )\n\t\t{\n\t\t\tvar a = [];\n\n\t\t\tif ( __arrayProto.map ) {\n\t\t\t\ta = __arrayProto.map.call( this, fn, this );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Compatibility for browsers without EMCA-252-5 (JS 1.6)\n\t\t\t\tfor ( var i=0, ien=this.length ; i<ien ; i++ ) {\n\t\t\t\t\ta.push( fn.call( this, this[i], i ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new _Api( this.context, a );\n\t\t},\n\n\n\t\tpluck: function ( prop )\n\t\t{\n\t\t\treturn this.map( function ( el ) {\n\t\t\t\treturn el[ prop ];\n\t\t\t} );\n\t\t},\n\n\t\tpop:     __arrayProto.pop,\n\n\n\t\tpush:    __arrayProto.push,\n\n\n\t\t// Does not return an API instance\n\t\treduce: __arrayProto.reduce || function ( fn, init )\n\t\t{\n\t\t\tvar\n\t\t\t\tvalue,\n\t\t\t\tisSet = false;\n\n\t\t\tif ( arguments.length > 1 ) {\n\t\t\t\tvalue = init;\n\t\t\t\tisSet = true;\n\t\t\t}\n\n\t\t\tfor ( var i=0, ien=this.length ; i<ien ; i++ ) {\n\t\t\t\tif ( ! this.hasOwnProperty(i) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tvalue = isSet ?\n\t\t\t\t\tfn( value, this[i], i, this ) :\n\t\t\t\t\tthis[i];\n\n\t\t\t\tisSet = true;\n\t\t\t}\n\n\t\t\treturn value;\n\t\t},\n\n\n\t\treduceRight: __arrayProto.reduceRight || function ( fn, init )\n\t\t{\n\t\t\tvar\n\t\t\t\tvalue,\n\t\t\t\tisSet = false;\n\n\t\t\tif ( arguments.length > 1 ) {\n\t\t\t\tvalue = init;\n\t\t\t\tisSet = true;\n\t\t\t}\n\n\t\t\tfor ( var i=this.length-1 ; i>=0 ; i-- ) {\n\t\t\t\tif ( ! this.hasOwnProperty(i) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tvalue = isSet ?\n\t\t\t\t\tfn( value, this[i], i, this ) :\n\t\t\t\t\tthis[i];\n\n\t\t\t\tisSet = true;\n\t\t\t}\n\n\t\t\treturn value;\n\t\t},\n\n\t\treverse: __arrayProto.reverse,\n\n\n\t\t// Object with rows, columns and opts\n\t\tselector: null,\n\n\n\t\tshift:   __arrayProto.shift,\n\n\n\t\tsort:    __arrayProto.sort, // ? name - order?\n\n\n\t\tsplice:  __arrayProto.splice,\n\n\n\t\ttoArray: function ()\n\t\t{\n\t\t\treturn __arrayProto.slice.call( this );\n\t\t},\n\n\n\t\tto$: function ()\n\t\t{\n\t\t\treturn $( this );\n\t\t},\n\n\n\t\ttoJQuery: function ()\n\t\t{\n\t\t\treturn $( this );\n\t\t},\n\n\n\t\tunique: function ()\n\t\t{\n\t\t\treturn new _Api( this.context, _unique(this) );\n\t\t},\n\n\n\t\tunshift: __arrayProto.unshift\n\t};\n\n\n\n\n\t_Api.extend = function ( scope, obj, ext )\n\t{\n\t\t// Only extend API instances and static properties of the API\n\t\tif ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar\n\t\t\ti, ien,\n\t\t\tj, jen,\n\t\t\tstruct, inner,\n\t\t\tmethodScoping = function ( fn, struc ) {\n\t\t\t\treturn function () {\n\t\t\t\t\tvar ret = fn.apply( scope, arguments );\n\n\t\t\t\t\t// Method extension\n\t\t\t\t\t_Api.extend( ret, ret, struc.methodExt );\n\t\t\t\t\treturn ret;\n\t\t\t\t};\n\t\t\t};\n\n\t\tfor ( i=0, ien=ext.length ; i<ien ; i++ ) {\n\t\t\tstruct = ext[i];\n\n\t\t\t// Value\n\t\t\tobj[ struct.name ] = typeof struct.val === 'function' ?\n\t\t\t\tmethodScoping( struct.val, struct ) :\n\t\t\t\tstruct.val;\n\n\t\t\tobj[ struct.name ].__dt_wrapper = true;\n\n\t\t\t// Property extension\n\t\t\t_Api.extend( scope, obj[ struct.name ], struct.propExt );\n\t\t}\n\t};\n\n\n\t// @todo - Is there need for an augment function?\n\t// _Api.augment = function ( inst, name )\n\t// {\n\t// \t// Find src object in the structure from the name\n\t// \tvar parts = name.split('.');\n\n\t// \t_Api.extend( inst, obj );\n\t// };\n\n\n\t//     [\n\t//       {\n\t//         name:      'data'                -- string   - Property name\n\t//         val:       function () {},       -- function - Api method (or undefined if just an object\n\t//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result\n\t//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property\n\t//       },\n\t//       {\n\t//         name:     'row'\n\t//         val:       {},\n\t//         methodExt: [ ... ],\n\t//         propExt:   [\n\t//           {\n\t//             name:      'data'\n\t//             val:       function () {},\n\t//             methodExt: [ ... ],\n\t//             propExt:   [ ... ]\n\t//           },\n\t//           ...\n\t//         ]\n\t//       }\n\t//     ]\n\n\t_Api.register = _api_register = function ( name, val )\n\t{\n\t\tif ( $.isArray( name ) ) {\n\t\t\tfor ( var j=0, jen=name.length ; j<jen ; j++ ) {\n\t\t\t\t_Api.register( name[j], val );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tvar\n\t\t\ti, ien,\n\t\t\their = name.split('.'),\n\t\t\tstruct = __apiStruct,\n\t\t\tkey, method;\n\n\t\tvar find = function ( src, name ) {\n\t\t\tfor ( var i=0, ien=src.length ; i<ien ; i++ ) {\n\t\t\t\tif ( src[i].name === name ) {\n\t\t\t\t\treturn src[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\t\tfor ( i=0, ien=heir.length ; i<ien ; i++ ) {\n\t\t\tmethod = heir[i].indexOf('()') !== -1;\n\t\t\tkey = method ?\n\t\t\t\their[i].replace('()', '') :\n\t\t\t\their[i];\n\n\t\t\tvar src = find( struct, key );\n\t\t\tif ( ! src ) {\n\t\t\t\tsrc = {\n\t\t\t\t\tname:      key,\n\t\t\t\t\tval:       {},\n\t\t\t\t\tmethodExt: [],\n\t\t\t\t\tpropExt:   []\n\t\t\t\t};\n\t\t\t\tstruct.push( src );\n\t\t\t}\n\n\t\t\tif ( i === ien-1 ) {\n\t\t\t\tsrc.val = val;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstruct = method ?\n\t\t\t\t\tsrc.methodExt :\n\t\t\t\t\tsrc.propExt;\n\t\t\t}\n\t\t}\n\n\t\t// Rebuild the API with the new construct\n\t\tif ( _Api.ready ) {\n\t\t\tDataTable.api.build();\n\t\t}\n\t};\n\n\n\t_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {\n\t\t_Api.register( pluralName, val );\n\n\t\t_Api.register( singularName, function () {\n\t\t\tvar ret = val.apply( this, arguments );\n\n\t\t\tif ( ret === this ) {\n\t\t\t\t// Returned item is the API instance that was passed in, return it\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\telse if ( ret instanceof _Api ) {\n\t\t\t\t// New API instance returned, want the value from the first item\n\t\t\t\t// in the returned array for the singular result.\n\t\t\t\treturn ret.length ?\n\t\t\t\t\t$.isArray( ret[0] ) ?\n\t\t\t\t\t\tnew _Api( ret.context, ret[0] ) : // Array results are 'enhanced'\n\t\t\t\t\t\tret[0] :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// Non-API return - just fire it back\n\t\t\treturn ret;\n\t\t} );\n\t};\n\n\n\t/**\n\t * Selector for HTML tables. Apply the given selector to the give array of\n\t * DataTables settings objects.\n\t *\n\t * @param {string|integer} [selector] jQuery selector string or integer\n\t * @param  {array} Array of DataTables settings objects to be filtered\n\t * @return {array}\n\t * @ignore\n\t */\n\tvar __table_selector = function ( selector, a )\n\t{\n\t\t// Integer is used to pick out a table by index\n\t\tif ( typeof selector === 'number' ) {\n\t\t\treturn [ a[ selector ] ];\n\t\t}\n\n\t\t// Perform a jQuery selector on the table nodes\n\t\tvar nodes = $.map( a, function (el, i) {\n\t\t\treturn el.nTable;\n\t\t} );\n\n\t\treturn $(nodes)\n\t\t\t.filter( selector )\n\t\t\t.map( function (i) {\n\t\t\t\t// Need to translate back from the table node to the settings\n\t\t\t\tvar idx = $.inArray( this, nodes );\n\t\t\t\treturn a[ idx ];\n\t\t\t} )\n\t\t\t.toArray();\n\t};\n\n\n\n\t/**\n\t * Context selector for the API's context (i.e. the tables the API instance\n\t * refers to.\n\t *\n\t * @name    DataTable.Api#tables\n\t * @param {string|integer} [selector] Selector to pick which tables the iterator\n\t *   should operate on. If not given, all tables in the current context are\n\t *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to\n\t *   select multiple tables or as an integer to select a single table.\n\t * @returns {DataTable.Api} Returns a new API instance if a selector is given.\n\t */\n\t_api_register( 'tables()', function ( selector ) {\n\t\t// A new instance is created if there was a selector specified\n\t\treturn selector ?\n\t\t\tnew _Api( __table_selector( selector, this.context ) ) :\n\t\t\tthis;\n\t} );\n\n\n\t_api_register( 'table()', function ( selector ) {\n\t\tvar tables = this.tables( selector );\n\t\tvar ctx = tables.context;\n\n\t\t// Truncate to the first matched table\n\t\tif ( ctx.length ) {\n\t\t\tctx.length = 1;\n\t\t}\n\n\t\treturn tables;\n\t} );\n\n\n\t_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {\n\t\treturn this.iterator( 'table', function ( ctx ) {\n\t\t\treturn ctx.nTable;\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'tables().body()', 'table().body()' , function () {\n\t\treturn this.iterator( 'table', function ( ctx ) {\n\t\t\treturn ctx.nTBody;\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'tables().header()', 'table().header()' , function () {\n\t\treturn this.iterator( 'table', function ( ctx ) {\n\t\t\treturn ctx.nTHead;\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {\n\t\treturn this.iterator( 'table', function ( ctx ) {\n\t\t\treturn ctx.nTFoot;\n\t\t} );\n\t} );\n\n\n\n\t/**\n\t * Redraw the tables in the current context.\n\t *\n\t * @param {boolean} [reset=true] Reset (default) or hold the current paging\n\t *   position. A full re-sort and re-filter is performed when this method is\n\t *   called, which is why the pagination reset is the default action.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'draw()', function ( resetPaging ) {\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnReDraw( settings, resetPaging===false );\n\t\t} );\n\t} );\n\n\n\n\t/**\n\t * Get the current page index.\n\t *\n\t * @return {integer} Current page index (zero based)\n\t *//**\n\t * Set the current page.\n\t *\n\t * Note that if you attempt to show a page which does not exist, DataTables will\n\t * not throw an error, but rather reset the paging.\n\t *\n\t * @param {integer|string} action The paging action to take. This can be one of:\n\t *  * `integer` - The page index to jump to\n\t *  * `string` - An action to take:\n\t *    * `first` - Jump to first page.\n\t *    * `next` - Jump to the next page\n\t *    * `previous` - Jump to previous page\n\t *    * `last` - Jump to the last page.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'page()', function ( action ) {\n\t\tif ( action === undefined ) {\n\t\t\treturn this.page.info().page; // not an expensive call\n\t\t}\n\n\t\t// else, have an action to take on all tables\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnPageChange( settings, action );\n\t\t} );\n\t} );\n\n\n\t/**\n\t * Paging information for the first table in the current context.\n\t *\n\t * If you require paging information for another table, use the `table()` method\n\t * with a suitable selector.\n\t *\n\t * @return {object} Object with the following properties set:\n\t *  * `page` - Current page index (zero based - i.e. the first page is `0`)\n\t *  * `pages` - Total number of pages\n\t *  * `start` - Display index for the first record shown on the current page\n\t *  * `end` - Display index for the last record shown on the current page\n\t *  * `length` - Display length (number of records). Note that generally `start\n\t *    + length = end`, but this is not always true, for example if there are\n\t *    only 2 records to show on the final page, with a length of 10.\n\t *  * `recordsTotal` - Full data set length\n\t *  * `recordsDisplay` - Data set length once the current filtering criterion\n\t *    are applied.\n\t */\n\t_api_register( 'page.info()', function ( action ) {\n\t\tif ( this.context.length === 0 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar\n\t\t\tsettings   = this.context[0],\n\t\t\tstart      = settings._iDisplayStart,\n\t\t\tlen        = settings._iDisplayLength,\n\t\t\tvisRecords = settings.fnRecordsDisplay(),\n\t\t\tall        = len === -1;\n\n\t\treturn {\n\t\t\t\"page\":           all ? 0 : Math.floor( start / len ),\n\t\t\t\"pages\":          all ? 1 : Math.ceil( visRecords / len ),\n\t\t\t\"start\":          start,\n\t\t\t\"end\":            settings.fnDisplayEnd(),\n\t\t\t\"length\":         len,\n\t\t\t\"recordsTotal\":   settings.fnRecordsTotal(),\n\t\t\t\"recordsDisplay\": visRecords\n\t\t};\n\t} );\n\n\n\t/**\n\t * Get the current page length.\n\t *\n\t * @return {integer} Current page length. Note `-1` indicates that all records\n\t *   are to be shown.\n\t *//**\n\t * Set the current page length.\n\t *\n\t * @param {integer} Page length to set. Use `-1` to show all records.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'page.len()', function ( len ) {\n\t\t// Note that we can't call this function 'length()' because `length`\n\t\t// is a Javascript property of functions which defines how many arguments\n\t\t// the function expects.\n\t\tif ( len === undefined ) {\n\t\t\treturn this.context.length !== 0 ?\n\t\t\t\tthis.context[0]._iDisplayLength :\n\t\t\t\tundefined;\n\t\t}\n\n\t\t// else, set the page length\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnLengthChange( settings, len );\n\t\t} );\n\t} );\n\n\n\n\tvar __reload = function ( settings, holdPosition, callback ) {\n\t\tif ( _fnDataSource( settings ) == 'ssp' ) {\n\t\t\t_fnReDraw( settings, holdPosition );\n\t\t}\n\t\telse {\n\t\t\t// Trigger xhr\n\t\t\t_fnBuildAjax( settings, [], function( json ) {\n\t\t\t\t// xxx can this be reduced?\n\t\t\t\t_fnClearTable( settings );\n\n\t\t\t\tvar data = _fnAjaxDataSrc( settings, json );\n\t\t\t\tfor ( var i=0, ien=data.length ; i<ien ; i++ ) {\n\t\t\t\t\t_fnAddData( settings, data[i] );\n\t\t\t\t}\n\n\t\t\t\t_fnReDraw( settings, holdPosition );\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback( json );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n\n\t/**\n\t * Get the JSON response from the last Ajax request that DataTables made to the\n\t * server. Note that this returns the JSON from the first table in the current\n\t * context.\n\t *\n\t * @return {object} JSON received from the server.\n\t */\n\t_api_register( 'ajax.json()', function () {\n\t\tvar ctx = this.context;\n\n\t\tif ( ctx.length > 0 ) {\n\t\t\treturn ctx[0].json;\n\t\t}\n\n\t\t// else return undefined;\n\t} );\n\n\n\t/**\n\t * Reload tables from the Ajax data source. Note that this function will\n\t * automatically re-draw the table when the remote data has been loaded.\n\t *\n\t * @param {boolean} [reset=true] Reset (default) or hold the current paging\n\t *   position. A full re-sort and re-filter is performed when this method is\n\t *   called, which is why the pagination reset is the default action.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'ajax.reload()', function ( callback, resetPaging ) {\n\t\treturn this.iterator( 'table', function (settings) {\n\t\t\t__reload( settings, resetPaging===false, callback );\n\t\t} );\n\t} );\n\n\n\t/**\n\t * Get the current Ajax URL. Note that this returns the URL from the first\n\t * table in the current context.\n\t *\n\t * @return {string} Current Ajax source URL\n\t *//**\n\t * Set the Ajax URL. Note that this will set the URL for all tables in the\n\t * current context.\n\t *\n\t * @param {string} url URL to set.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'ajax.url()', function ( url ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( url === undefined ) {\n\t\t\t// get\n\t\t\tif ( ctx.length === 0 ) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tctx = ctx[0];\n\n\t\t\treturn ctx.ajax ?\n\t\t\t\t$.isPlainObject( ctx.ajax ) ?\n\t\t\t\t\tctx.ajax.url :\n\t\t\t\t\tctx.ajax :\n\t\t\t\tctx.sAjaxSource;\n\t\t}\n\n\t\t// set\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\tif ( $.isPlainObject( settings.ajax ) ) {\n\t\t\t\tsettings.ajax.url = url;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsettings.ajax = url;\n\t\t\t}\n\t\t\t// No need to consider sAjaxSource here since DataTables gives priority\n\t\t\t// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any\n\t\t\t// value of `sAjaxSource` redundant.\n\t\t} );\n\t} );\n\n\n\t/**\n\t * Load data from the newly set Ajax URL. Note that this method is only\n\t * available when `ajax.url()` is used to set a URL. Additionally, this method\n\t * has the same effect as calling `ajax.reload()` but is provided for\n\t * convenience when setting a new URL. Like `ajax.reload()` it will\n\t * automatically redraw the table once the remote data has been loaded.\n\t *\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {\n\t\t// Same as a reload, but makes sense to present it for easy access after a\n\t\t// url change\n\t\treturn this.iterator( 'table', function ( ctx ) {\n\t\t\t__reload( ctx, resetPaging===false, callback );\n\t\t} );\n\t} );\n\n\n\n\n\tvar _selector_run = function ( selector, select )\n\t{\n\t\tvar\n\t\t\tout = [], res,\n\t\t\ta, i, ien, j, jen;\n\n\t\tif ( ! $.isArray( selector ) ) {\n\t\t\tselector = [ selector ];\n\t\t}\n\n\t\tfor ( i=0, ien=selector.length ; i<ien ; i++ ) {\n\t\t\ta = selector[i] && selector[i].split ?\n\t\t\t\tselector[i].split(',') :\n\t\t\t\t[ selector[i] ];\n\n\t\t\tfor ( j=0, jen=a.length ; j<jen ; j++ ) {\n\t\t\t\tres = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );\n\n\t\t\t\tif ( res && res.length ) {\n\t\t\t\t\tout.push.apply( out, res );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn out;\n\t};\n\n\n\tvar _selector_opts = function ( opts )\n\t{\n\t\tif ( ! opts ) {\n\t\t\topts = {};\n\t\t}\n\n\t\t// Backwards compatibility for 1.9- which used the terminology filter rather\n\t\t// than search\n\t\tif ( opts.filter && ! opts.search ) {\n\t\t\topts.search = opts.filter;\n\t\t}\n\n\t\treturn {\n\t\t\tsearch: opts.search || 'none',\n\t\t\torder:  opts.order  || 'current',\n\t\t\tpage:   opts.page   || 'all'\n\t\t};\n\t};\n\n\n\tvar _selector_first = function ( inst )\n\t{\n\t\t// Reduce the API instance to the first item found\n\t\tfor ( var i=0, ien=inst.length ; i<ien ; i++ ) {\n\t\t\tif ( inst[i].length > 0 ) {\n\t\t\t\t// Assign the first element to the first item in the instance\n\t\t\t\t// and truncate the instance and context\n\t\t\t\tinst[0] = inst[i];\n\t\t\t\tinst.length = 1;\n\t\t\t\tinst.context = [ inst.context[i] ];\n\n\t\t\t\treturn inst;\n\t\t\t}\n\t\t}\n\n\t\t// Not found - return an empty instance\n\t\tinst.length = 0;\n\t\treturn inst;\n\t};\n\n\n\tvar _selector_row_indexes = function ( settings, opts )\n\t{\n\t\tvar\n\t\t\ti, ien, tmp, a=[],\n\t\t\tdisplayFiltered = settings.aiDisplay,\n\t\t\tdisplayMaster = settings.aiDisplayMaster;\n\n\t\tvar\n\t\t\tsearch = opts.search,  // none, applied, removed\n\t\t\torder  = opts.order,   // applied, current, index (original - compatibility with 1.9)\n\t\t\tpage   = opts.page;    // all, current\n\n\t\t// Current page implies that order=current and fitler=applied, since it is\n\t\t// fairly senseless otherwise, regardless of what order and search actually\n\t\t// are\n\t\tif ( page == 'current' )\n\t\t{\n\t\t\tfor ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {\n\t\t\t\ta.push( displayFiltered[i] );\n\t\t\t}\n\t\t}\n\t\telse if ( order == 'current' || order == 'applied' ) {\n\t\t\ta = search == 'none' ?\n\t\t\t\tdisplayMaster.slice() :                      // no search\n\t\t\t\tsearch == 'applied' ?\n\t\t\t\t\tdisplayFiltered.slice() :                // applied search\n\t\t\t\t\t$.map( displayMaster, function (el, i) { // removed search\n\t\t\t\t\t\treturn $.inArray( el, displayFiltered ) === -1 ? el : null;\n\t\t\t\t\t} );\n\t\t}\n\t\telse if ( order == 'index' || order == 'original' ) {\n\t\t\tfor ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\n\t\t\t\tif ( search == 'none' ) {\n\t\t\t\t\ta.push( i );\n\t\t\t\t}\n\t\t\t\telse { // applied | removed\n\t\t\t\t\ttmp = $.inArray( i, displayFiltered );\n\n\t\t\t\t\tif ((tmp === -1 && search == 'removed') ||\n\t\t\t\t\t\t(tmp === 1  && search == 'applied') )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( i );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn a;\n\t};\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Rows\n\t *\n\t * {}          - no selector - use all available rows\n\t * {integer}   - row aoData index\n\t * {node}      - TR node\n\t * {string}    - jQuery selector to apply to the TR elements\n\t * {array}     - jQuery array of nodes, or simply an array of TR nodes\n\t *\n\t */\n\n\n\tvar __row_selector = function ( settings, selector, opts )\n\t{\n\t\treturn _selector_run( selector, function ( sel ) {\n\t\t\tvar selInt = _intVal( sel );\n\n\t\t\t// Short cut - selector is a number and no options provided (default is\n\t\t\t// all records, so no need to check if the index is in there, since it\n\t\t\t// must be - dev error if the index doesn't exist).\n\t\t\tif ( selInt !== null && ! opts ) {\n\t\t\t\treturn [ selInt ];\n\t\t\t}\n\n\t\t\tvar rows = _selector_row_indexes( settings, opts );\n\n\t\t\tif ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {\n\t\t\t\t// Selector - integer\n\t\t\t\treturn [ selInt ];\n\t\t\t}\n\t\t\telse if ( ! sel ) {\n\t\t\t\t// Selector - none\n\t\t\t\treturn rows;\n\t\t\t}\n\n\t\t\t// Get nodes in the order from the `rows` array (can't use `pluck`) @todo - use pluck_order\n\t\t\tvar nodes = [];\n\t\t\tfor ( var i=0, ien=rows.length ; i<ien ; i++ ) {\n\t\t\t\tnodes.push( settings.aoData[ rows[i] ].nTr );\n\t\t\t}\n\n\t\t\tif ( sel.nodeName ) {\n\t\t\t\t// Selector - node\n\t\t\t\tif ( $.inArray( sel, nodes ) !== -1 ) {\n\t\t\t\t\treturn [ sel._DT_RowIndex ];// sel is a TR node that is in the table\n\t\t\t\t\t\t\t\t\t\t\t// and DataTables adds a prop for fast lookup\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Selector - jQuery selector string, array of nodes or jQuery object/\n\t\t\t// As jQuery's .filter() allows jQuery objects to be passed in filter,\n\t\t\t// it also allows arrays, so this will cope with all three options\n\t\t\treturn $(nodes)\n\t\t\t\t.filter( sel )\n\t\t\t\t.map( function () {\n\t\t\t\t\treturn this._DT_RowIndex;\n\t\t\t\t} )\n\t\t\t\t.toArray();\n\t\t} );\n\t};\n\n\n\t/**\n\t *\n\t */\n\t_api_register( 'rows()', function ( selector, opts ) {\n\t\t// argument shifting\n\t\tif ( selector === undefined ) {\n\t\t\tselector = '';\n\t\t}\n\t\telse if ( $.isPlainObject( selector ) ) {\n\t\t\topts = selector;\n\t\t\tselector = '';\n\t\t}\n\n\t\topts = _selector_opts( opts );\n\n\t\tvar inst = this.iterator( 'table', function ( settings ) {\n\t\t\treturn __row_selector( settings, selector, opts );\n\t\t} );\n\n\t\t// Want argument shifting here and in __row_selector?\n\t\tinst.selector.rows = selector;\n\t\tinst.selector.opts = opts;\n\n\t\treturn inst;\n\t} );\n\n\n\t_api_registerPlural( 'rows().nodes()', 'row().node()' , function () {\n\t\treturn this.iterator( 'row', function ( settings, row ) {\n\t\t\t// use pluck order on an array rather - rows gives an array, row gives it individually\n\t\t\treturn settings.aoData[ row ].nTr || undefined;\n\t\t} );\n\t} );\n\n\n\t_api_register( 'rows().data()', function () {\n\t\treturn this.iterator( true, 'rows', function ( settings, rows ) {\n\t\t\treturn _pluck_order( settings.aoData, rows, '_aData' );\n\t\t} );\n\t} );\n\n\t_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {\n\t\treturn this.iterator( 'row', function ( settings, row ) {\n\t\t\tvar r = settings.aoData[ row ];\n\t\t\treturn type === 'search' ? r._aFilterData : r._aSortData;\n\t\t} );\n\t} );\n\n\t_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {\n\t\treturn this.iterator( 'row', function ( settings, row ) {\n\t\t\t_fnInvalidateRow( settings, row, src );\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'rows().indexes()', 'row().index()', function () {\n\t\treturn this.iterator( 'row', function ( settings, row ) {\n\t\t\treturn row;\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'rows().remove()', 'row().remove()', function () {\n\t\tvar that = this;\n\n\t\treturn this.iterator( 'row', function ( settings, row, thatIdx ) {\n\t\t\tvar data = settings.aoData;\n\n\t\t\tdata.splice( row, 1 );\n\n\t\t\t// Update the _DT_RowIndex parameter on all rows in the table\n\t\t\tfor ( var i=0, ien=data.length ; i<ien ; i++ ) {\n\t\t\t\tif ( data[i].nTr !== null ) {\n\t\t\t\t\tdata[i].nTr._DT_RowIndex = i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove the target row from the search array\n\t\t\tvar displayIndex = $.inArray( row, settings.aiDisplay );\n\n\t\t\t// Delete from the display arrays\n\t\t\t_fnDeleteIndex( settings.aiDisplayMaster, row );\n\t\t\t_fnDeleteIndex( settings.aiDisplay, row );\n\t\t\t_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes\n\n\t\t\t// Check for an 'overflow' they case for displaying the table\n\t\t\t_fnLengthOverflow( settings );\n\t\t} );\n\t} );\n\n\n\t_api_register( 'rows.add()', function ( rows ) {\n\t\tvar newRows = this.iterator( 'table', function ( settings ) {\n\t\t\t\tvar row, i, ien;\n\t\t\t\tvar out = [];\n\n\t\t\t\tfor ( i=0, ien=rows.length ; i<ien ; i++ ) {\n\t\t\t\t\trow = rows[i];\n\n\t\t\t\t\tif ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {\n\t\t\t\t\t\tout.push( _fnAddTr( settings, row )[0] );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tout.push( _fnAddData( settings, row ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn out;\n\t\t\t} );\n\n\t\t// Return an Api.rows() extended instance, so rows().nodes() etc can be used\n\t\tvar modRows = this.rows( -1 );\n\t\tmodRows.pop();\n\t\tmodRows.push.apply( modRows, newRows );\n\n\t\treturn modRows;\n\t} );\n\n\n\n\n\n\t/**\n\t *\n\t */\n\t_api_register( 'row()', function ( selector, opts ) {\n\t\treturn _selector_first( this.rows( selector, opts ) );\n\t} );\n\n\n\t_api_register( 'row().data()', function ( data ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( data === undefined ) {\n\t\t\t// Get\n\t\t\treturn ctx.length && this.length ?\n\t\t\t\tctx[0].aoData[ this[0] ]._aData :\n\t\t\t\tundefined;\n\t\t}\n\n\t\t// Set\n\t\tctx[0].aoData[ this[0] ]._aData = data;\n\n\t\t// Automatically invalidate\n\t\t_fnInvalidateRow( ctx[0], this[0], 'data' );\n\n\t\treturn this;\n\t} );\n\n\n\t_api_register( 'row.add()', function ( row ) {\n\t\t// Allow a jQuery object to be passed in - only a single row is added from\n\t\t// it though - the first element in the set\n\t\tif ( row instanceof $ && row.length ) {\n\t\t\trow = row[0];\n\t\t}\n\n\t\tvar rows = this.iterator( 'table', function ( settings ) {\n\t\t\tif ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {\n\t\t\t\treturn _fnAddTr( settings, row )[0];\n\t\t\t}\n\t\t\treturn _fnAddData( settings, row );\n\t\t} );\n\n\t\t// Return an Api.rows() extended instance, with the newly added row selected\n\t\treturn this.row( rows[0] );\n\t} );\n\n\n\n\tvar __details_add = function ( ctx, row, data, klass )\n\t{\n\t\t// Convert to array of TR elements\n\t\tvar rows = [];\n\t\tvar addRow = function ( r, k ) {\n\t\t\tif ( ! r.nodeName || r.nodeName.toUpperCase() !== 'tr' ) {\n\t\t\t\tr = $('<tr><td></td></tr>').find('td').html( r ).parent();\n\t\t\t}\n\n\t\t\t$('td', r).addClass( k )[0].colSpan = _fnVisbleColumns( ctx );\n\t\t\trows.push( r[0] );\n\t\t};\n\n\t\tif ( $.isArray( data ) || data instanceof $ ) {\n\t\t\tfor ( var i=0, ien=data.length ; i<ien ; i++ ) {\n\t\t\t\taddRow( data[i], klass );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\taddRow( data, klass );\n\t\t}\n\n\t\tif ( row._details ) {\n\t\t\trow._details.remove();\n\t\t}\n\n\t\trow._details = $(rows);\n\n\t\t// If the children were already shown, that state should be retained\n\t\tif ( row._detailsShow ) {\n\t\t\trow._details.insertAfter( row.nTr );\n\t\t}\n\t};\n\n\n\tvar __details_display = function ( show ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( ctx.length && this.length ) {\n\t\t\tvar row = ctx[0].aoData[ this[0] ];\n\n\t\t\tif ( row._details ) {\n\t\t\t\trow._detailsShow = show;\n\t\t\t\tif ( show ) {\n\t\t\t\t\trow._details.insertAfter( row.nTr );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\trow._details.remove();\n\t\t\t\t}\n\n\t\t\t\t__details_events( ctx[0] );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n\n\n\tvar __details_events = function ( settings )\n\t{\n\t\tvar table = $(settings.nTable);\n\n\t\ttable.off('draw.DT_details');\n\t\ttable.off('column-visibility.DT_details');\n\n\t\tif ( _pluck( settings.aoData, '_details' ).length > 0 ) {\n\t\t\t// On each draw, insert the required elements into the document\n\t\t\ttable.on('draw.DT_details', function () {\n\t\t\t\ttable.find('tbody tr').each( function () {\n\t\t\t\t\t// Look up the row index for each row and append open row\n\t\t\t\t\tvar rowIdx = _fnNodeToDataIndex( settings, this );\n\t\t\t\t\tvar row = settings.aoData[ rowIdx ];\n\n\t\t\t\t\tif ( row._detailsShow ) {\n\t\t\t\t\t\trow._details.insertAfter( this );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t// Column visibility change - update the colspan\n\t\t\ttable.on( 'column-visibility.DT_details', function ( e, settings, idx, vis ) {\n\t\t\t\t// Update the colspan for the details rows (note, only if it already has\n\t\t\t\t// a colspan)\n\t\t\t\tvar row, visible = _fnVisbleColumns( settings );\n\n\t\t\t\tfor ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\n\t\t\t\t\trow = settings.aoData[i];\n\n\t\t\t\t\tif ( row._details ) {\n\t\t\t\t\t\trow._details.children('td[colspan]').attr('colspan', visible );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n\t// data can be:\n\t//  tr\n\t//  string\n\t//  jQuery or array of any of the above\n\t_api_register( 'row().child()', function ( data, klass ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( data === undefined ) {\n\t\t\t// get\n\t\t\treturn ctx.length && this.length ?\n\t\t\t\tctx[0].aoData[ this[0] ]._details :\n\t\t\t\tundefined;\n\t\t}\n\t\telse if ( ctx.length && this.length ) {\n\t\t\t// set\n\t\t\t__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );\n\t\t}\n\n\t\treturn this;\n\t} );\n\n\t_api_register( [\n\t\t'row().child.show()',\n\t\t'row().child().show()'\n\t], function () {\n\t\t__details_display.call( this, true );\n\t} );\n\n\t_api_register( [\n\t\t'row().child.hide()',\n\t\t'row().child().hide()'\n\t], function () {\n\t\t__details_display.call( this, false );\n\t} );\n\n\t_api_register( 'row().child.isShown()', function () {\n\t\tvar ctx = this.context;\n\n\t\tif ( ctx.length && this.length ) {\n\t\t\t// _detailsShown as false or undefined will fall through to return false\n\t\t\treturn ctx[0].aoData[ this[0] ]._detailsShow || false;\n\t\t}\n\t\treturn false;\n\t} );\n\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Columns\n\t *\n\t * {integer}           - column index (>=0 count from left, <0 count from right)\n\t * \"{integer}:visIdx\"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)\n\t * \"{integer}:visible\" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)\n\t * \"{string}:name\"     - column name\n\t * \"{string}\"          - jQuery selector on column header nodes\n\t *\n\t */\n\n\t// can be an array of these items, comma separated list, or an array of comma\n\t// separated lists\n\n\tvar __re_column_selector = /^(.*):(name|visIdx|visible)$/;\n\n\tvar __column_selector = function ( settings, selector, opts )\n\t{\n\t\tvar\n\t\t\tcolumns = settings.aoColumns,\n\t\t\tnames = _pluck( columns, 'sName' ),\n\t\t\tnodes = _pluck( columns, 'nTh' );\n\n\t\treturn _selector_run( selector, function ( s ) {\n\t\t\tvar selInt = _intVal( s );\n\n\t\t\tif ( s === '' ) {\n\t\t\t\t// All columns\n\t\t\t\treturn _range( settings.aoColumns.length );\n\t\t\t}\n\t\t\telse if ( selInt !== null ) {\n\t\t\t\t// Integer selector\n\t\t\t\treturn [ selInt >= 0 ?\n\t\t\t\t\tselInt : // Count from left\n\t\t\t\t\tcolumns.length + selInt // Count from right (+ because its a negative value)\n\t\t\t\t];\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar match = s.match( __re_column_selector );\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tswitch( match[2] ) {\n\t\t\t\t\t\tcase 'visIdx':\n\t\t\t\t\t\tcase 'visible':\n\t\t\t\t\t\t\tvar idx = parseInt( match[1], 10 );\n\t\t\t\t\t\t\t// Visible index given, convert to column index\n\t\t\t\t\t\t\tif ( idx < 0 ) {\n\t\t\t\t\t\t\t\t// Counting from the right\n\t\t\t\t\t\t\t\tvar visColumns = $.map( columns, function (col,i) {\n\t\t\t\t\t\t\t\t\treturn col.bVisible ? i : null;\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\treturn [ visColumns[ visColumns.length + idx ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Counting from the left\n\t\t\t\t\t\t\treturn [ _fnVisibleToColumnIndex( settings, idx ) ];\n\n\t\t\t\t\t\tcase 'name':\n\t\t\t\t\t\t\t// match by name. `names` is column index complete and in order\n\t\t\t\t\t\t\treturn $.map( names, function (name, i) {\n\t\t\t\t\t\t\t\treturn name === match[1] ? i : null;\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// jQuery selector on the TH elements for the columns\n\t\t\t\t\treturn $( nodes )\n\t\t\t\t\t\t.filter( s )\n\t\t\t\t\t\t.map( function () {\n\t\t\t\t\t\t\treturn $.inArray( this, nodes ); // `nodes` is column index complete and in order\n\t\t\t\t\t\t} )\n\t\t\t\t\t\t.toArray();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t};\n\n\n\n\n\n\tvar __setColumnVis = function ( settings, column, vis ) {\n\t\tvar\n\t\t\tcols = settings.aoColumns,\n\t\t\tcol  = cols[ column ],\n\t\t\tdata = settings.aoData,\n\t\t\trow, cells, i, ien, tr;\n\n\t\t// Get\n\t\tif ( vis === undefined ) {\n\t\t\treturn col.bVisible;\n\t\t}\n\n\t\t// Set\n\t\t// No change\n\t\tif ( col.bVisible === vis ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( vis ) {\n\t\t\t// Insert column\n\t\t\t// Need to decide if we should use appendChild or insertBefore\n\t\t\tvar insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );\n\n\t\t\tfor ( i=0, ien=data.length ; i<ien ; i++ ) {\n\t\t\t\ttr = data[i].nTr;\n\t\t\t\tcells = data[i].anCells;\n\n\t\t\t\tif ( tr ) {\n\t\t\t\t\t// insertBefore can act like appendChild if 2nd arg is null\n\t\t\t\t\ttr.insertBefore( cells[ column ], cells[ insertBefore ] || null );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// Remove column\n\t\t\t$( _pluck( settings.aoData, 'anCells', column ) ).remove();\n\n\t\t\tcol.bVisible = false;\n\t\t\t_fnDrawHead( settings, settings.aoHeader );\n\t\t\t_fnDrawHead( settings, settings.aoFooter );\n\n\t\t\t_fnSaveState( settings );\n\t\t}\n\n\t\t// Common actions\n\t\tcol.bVisible = vis;\n\t\t_fnDrawHead( settings, settings.aoHeader );\n\t\t_fnDrawHead( settings, settings.aoFooter );\n\n\t\t// Automatically adjust column sizing\n\t\t_fnAdjustColumnSizing( settings );\n\n\t\t// Realign columns for scrolling\n\t\tif ( settings.oScroll.sX || settings.oScroll.sY ) {\n\t\t\t_fnScrollDraw( settings );\n\t\t}\n\n\t\t_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );\n\n\t\t_fnSaveState( settings );\n\t};\n\n\n\t/**\n\t *\n\t */\n\t_api_register( 'columns()', function ( selector, opts ) {\n\t\t// argument shifting\n\t\tif ( selector === undefined ) {\n\t\t\tselector = '';\n\t\t}\n\t\telse if ( $.isPlainObject( selector ) ) {\n\t\t\topts = selector;\n\t\t\tselector = '';\n\t\t}\n\n\t\topts = _selector_opts( opts );\n\n\t\tvar inst = this.iterator( 'table', function ( settings ) {\n\t\t\treturn __column_selector( settings, selector, opts );\n\t\t} );\n\n\t\t// Want argument shifting here and in _row_selector?\n\t\tinst.selector.cols = selector;\n\t\tinst.selector.opts = opts;\n\n\t\treturn inst;\n\t} );\n\n\n\t/**\n\t *\n\t */\n\t_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {\n\t\treturn this.iterator( 'column', function ( settings, column ) {\n\t\t\treturn settings.aoColumns[column].nTh;\n\t\t} );\n\t} );\n\n\n\t/**\n\t *\n\t */\n\t_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {\n\t\treturn this.iterator( 'column', function ( settings, column ) {\n\t\t\treturn settings.aoColumns[column].nTf;\n\t\t} );\n\t} );\n\n\n\t/**\n\t *\n\t */\n\t_api_registerPlural( 'columns().data()', 'column().data()', function () {\n\t\treturn this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {\n\t\t\tvar a = [];\n\t\t\tfor ( var row=0, ien=rows.length ; row<ien ; row++ ) {\n\t\t\t\ta.push( _fnGetCellData( settings, rows[row], column, '' ) );\n\t\t\t}\n\t\t\treturn a;\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {\n\t\treturn this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {\n\t\t\treturn _pluck_order( settings.aoData, rows,\n\t\t\t\ttype === 'search' ? '_aFilterData' : '_aSortData', column\n\t\t\t);\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {\n\t\treturn this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {\n\t\t\treturn _pluck_order( settings.aoData, rows, 'anCells', column ) ;\n\t\t} );\n\t} );\n\n\n\n\t_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis ) {\n\t\treturn this.iterator( 'column', function ( settings, column ) {\n\t\t\treturn __setColumnVis( settings, column, vis );\n\t\t} );\n\t} );\n\n\n\n\t_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {\n\t\treturn this.iterator( 'column', function ( settings, column ) {\n\t\t\treturn type === 'visible' ?\n\t\t\t\t_fnColumnIndexToVisible( settings, column ) :\n\t\t\t\tcolumn;\n\t\t} );\n\t} );\n\n\n\t// _api_register( 'columns().show()', function () {\n\t// \tvar selector = this.selector;\n\t// \treturn this.columns( selector.cols, selector.opts ).visible( true );\n\t// } );\n\n\n\t// _api_register( 'columns().hide()', function () {\n\t// \tvar selector = this.selector;\n\t// \treturn this.columns( selector.cols, selector.opts ).visible( false );\n\t// } );\n\n\n\n\t_api_register( 'columns.adjust()', function () {\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnAdjustColumnSizing( settings );\n\t\t} );\n\t} );\n\n\n\t// Convert from one column index type, to another type\n\t_api_register( 'column.index()', function ( type, idx ) {\n\t\tif ( this.context.length !== 0 ) {\n\t\t\tvar ctx = this.context[0];\n\n\t\t\tif ( type === 'fromVisible' || type === 'toData' ) {\n\t\t\t\treturn _fnColumnIndexToVisible( ctx, idx );\n\t\t\t}\n\t\t\telse if ( type === 'fromData' || type === 'toVisible' ) {\n\t\t\t\treturn _fnVisibleToColumnIndex( ctx, idx );\n\t\t\t}\n\t\t}\n\t} );\n\n\n\t_api_register( 'column()', function ( selector, opts ) {\n\t\treturn _selector_first( this.columns( selector, opts ) );\n\t} );\n\n\n\n\n\tvar __cell_selector = function ( settings, selector, opts )\n\t{\n\t\tvar data = settings.aoData;\n\t\tvar rows = _selector_row_indexes( settings, opts );\n\t\tvar cells = _pluck_order( data, rows, 'anCells' );\n\t\tvar allCells = $( [].concat.apply([], cells) );\n\t\tvar row;\n\t\tvar columns = settings.aoColumns.length;\n\t\tvar a, i, ien, j;\n\n\t\treturn _selector_run( selector, function ( s ) {\n\t\t\tif ( ! s ) {\n\t\t\t\t// All cells\n\t\t\t\ta = [];\n\n\t\t\t\tfor ( i=0, ien=rows.length ; i<ien ; i++ ) {\n\t\t\t\t\trow = rows[i];\n\n\t\t\t\t\tfor ( j=0 ; j<columns ; j++ ) {\n\t\t\t\t\t\ta.push( {\n\t\t\t\t\t\t\trow: row,\n\t\t\t\t\t\t\tcolumn: j\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;\n\t\t\t}\n\n\t\t\t// jQuery filtered cells\n\t\t\treturn allCells.filter( s ).map( function (i, el) {\n\t\t\t\trow = el.parentNode._DT_RowIndex;\n\n\t\t\t\treturn {\n\t\t\t\t\trow: row,\n\t\t\t\t\tcolumn: $.inArray( el, data[ row ].anCells )\n\t\t\t\t};\n\t\t\t} );\n\t\t} );\n\t};\n\n\n\n\n\t_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {\n\t\t// Argument shifting\n\t\tif ( $.isPlainObject( rowSelector ) ) {\n\t\t\topts = rowSelector;\n\t\t\trowSelector = null;\n\t\t}\n\t\tif ( $.isPlainObject( columnSelector ) ) {\n\t\t\topts = columnSelector;\n\t\t\tcolumnSelector = null;\n\t\t}\n\n\t\t// Cell selector\n\t\tif ( columnSelector === null || columnSelector === undefined ) {\n\t\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t\treturn __cell_selector( settings, rowSelector, _selector_opts( opts ) );\n\t\t\t} );\n\t\t}\n\n\t\t// Row + column selector\n\t\tvar columns = this.columns( columnSelector, opts );\n\t\tvar rows = this.rows( rowSelector, opts );\n\t\tvar a, i, ien, j, jen;\n\n\t\tvar cells = this.iterator( 'table', function ( settings, idx ) {\n\t\t\ta = [];\n\n\t\t\tfor ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {\n\t\t\t\tfor ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {\n\t\t\t\t\ta.push( {\n\t\t\t\t\t\trow:    rows[idx][i],\n\t\t\t\t\t\tcolumn: columns[idx][j]\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn a;\n\t\t} );\n\n\t\t$.extend( cells.selector, {\n\t\t\tcols: columnSelector,\n\t\t\trows: rowSelector,\n\t\t\topts: opts\n\t\t} );\n\n\t\treturn cells;\n\t} );\n\n\n\t_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {\n\t\treturn this.iterator( 'cell', function ( settings, row, column ) {\n\t\t\treturn settings.aoData[ row ].anCells[ column ];\n\t\t} );\n\t} );\n\n\n\t_api_register( 'cells().data()', function () {\n\t\treturn this.iterator( 'cell', function ( settings, row, column ) {\n\t\t\treturn _fnGetCellData( settings, row, column );\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {\n\t\ttype = type === 'search' ? '_aFilterData' : '_aSortData';\n\n\t\treturn this.iterator( 'cell', function ( settings, row, column ) {\n\t\t\treturn settings.aoData[ row ][ type ][ column ];\n\t\t} );\n\t} );\n\n\n\t_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {\n\t\treturn this.iterator( 'cell', function ( settings, row, column ) {\n\t\t\treturn {\n\t\t\t\trow: row,\n\t\t\t\tcolumn: column,\n\t\t\t\tcolumnVisible: _fnColumnIndexToVisible( settings, column )\n\t\t\t};\n\t\t} );\n\t} );\n\n\n\t_api_register( [\n\t\t'cells().invalidate()',\n\t\t'cell().invalidate()'\n\t], function ( src ) {\n\t\tvar selector = this.selector;\n\n\t\t// Use the rows method of the instance to perform the invalidation, rather\n\t\t// than doing it here. This avoids needing to handle duplicate rows from\n\t\t// the cells.\n\t\tthis.rows( selector.rows, selector.opts ).invalidate( src );\n\n\t\treturn this;\n\t} );\n\n\n\n\n\t_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {\n\t\treturn _selector_first( this.cells( rowSelector, columnSelector, opts ) );\n\t} );\n\n\n\n\t_api_register( 'cell().data()', function ( data ) {\n\t\tvar ctx = this.context;\n\t\tvar cell = this[0];\n\n\t\tif ( data === undefined ) {\n\t\t\t// Get\n\t\t\treturn ctx.length && cell.length ?\n\t\t\t\t_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :\n\t\t\t\tundefined;\n\t\t}\n\n\t\t// Set\n\t\t_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );\n\t\t_fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );\n\n\t\treturn this;\n\t} );\n\n\n\n\t/**\n\t * Get current ordering (sorting) that has been applied to the table.\n\t *\n\t * @returns {array} 2D array containing the sorting information for the first\n\t *   table in the current context. Each element in the parent array represents\n\t *   a column being sorted upon (i.e. multi-sorting with two columns would have\n\t *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is\n\t *   the column index that the sorting condition applies to, the second is the\n\t *   direction of the sort (`desc` or `asc`) and, optionally, the third is the\n\t *   index of the sorting order from the `column.sorting` initialisation array.\n\t *//**\n\t * Set the ordering for the table.\n\t *\n\t * @param {integer} order Column index to sort upon.\n\t * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)\n\t * @returns {DataTables.Api} this\n\t *//**\n\t * Set the ordering for the table.\n\t *\n\t * @param {array} order 1D array of sorting information to be applied.\n\t * @param {array} [...] Optional additional sorting conditions\n\t * @returns {DataTables.Api} this\n\t *//**\n\t * Set the ordering for the table.\n\t *\n\t * @param {array} order 2D array of sorting information to be applied.\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'order()', function ( order, dir ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( order === undefined ) {\n\t\t\t// get\n\t\t\treturn ctx.length !== 0 ?\n\t\t\t\tctx[0].aaSorting :\n\t\t\t\tundefined;\n\t\t}\n\n\t\t// set\n\t\tif ( typeof order === 'number' ) {\n\t\t\t// Simple column / direction passed in\n\t\t\torder = [ [ order, dir ] ];\n\t\t}\n\t\telse if ( ! $.isArray( order[0] ) ) {\n\t\t\t// Arguments passed in (list of 1D arrays)\n\t\t\torder = Array.prototype.slice.call( arguments );\n\t\t}\n\t\t// otherwise a 2D array was passed in\n\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\tsettings.aaSorting = order.slice();\n\t\t} );\n\t} );\n\n\n\t/**\n\t * Attach a sort listener to an element for a given column\n\t *\n\t * @param {node|jQuery|string} node Identifier for the element(s) to attach the\n\t *   listener to. This can take the form of a single DOM node, a jQuery\n\t *   collection of nodes or a jQuery selector which will identify the node(s).\n\t * @param {integer} column the column that a click on this node will sort on\n\t * @param {function} [callback] callback function when sort is run\n\t * @returns {DataTables.Api} this\n\t */\n\t_api_register( 'order.listener()', function ( node, column, callback ) {\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnSortAttachListener( settings, node, column, callback );\n\t\t} );\n\t} );\n\n\n\t// Order by the selected column(s)\n\t_api_register( [\n\t\t'columns().order()',\n\t\t'column().order()'\n\t], function ( dir ) {\n\t\tvar that = this;\n\n\t\treturn this.iterator( 'table', function ( settings, i ) {\n\t\t\tvar sort = [];\n\n\t\t\t$.each( that[i], function (j, col) {\n\t\t\t\tsort.push( [ col, dir ] );\n\t\t\t} );\n\n\t\t\tsettings.aaSorting = sort;\n\t\t} );\n\t} );\n\n\n\n\t_api_register( 'search()', function ( input, regex, smart, caseInsen ) {\n\t\tvar ctx = this.context;\n\n\t\tif ( input === undefined ) {\n\t\t\t// get\n\t\t\treturn ctx.length !== 0 ?\n\t\t\t\tctx[0].oPreviousSearch.sSearch :\n\t\t\t\tundefined;\n\t\t}\n\n\t\t// set\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\tif ( ! settings.oFeatures.bFilter ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {\n\t\t\t\t\"sSearch\": input+\"\",\n\t\t\t\t\"bRegex\":  regex === null ? false : regex,\n\t\t\t\t\"bSmart\":  smart === null ? true  : smart,\n\t\t\t\t\"bCaseInsensitive\": caseInsen === null ? true : caseInsen\n\t\t\t} ), 1 );\n\t\t} );\n\t} );\n\n\n\t_api_register( [\n\t\t'columns().search()',\n\t\t'column().search()'\n\t], function ( input, regex, smart, caseInsen ) {\n\t\treturn this.iterator( 'column', function ( settings, column ) {\n\t\t\tvar preSearch = settings.aoPreSearchCols;\n\n\t\t\tif ( input === undefined ) {\n\t\t\t\t// get\n\t\t\t\treturn preSearch[ column ].sSearch;\n\t\t\t}\n\n\t\t\t// set\n\t\t\tif ( ! settings.oFeatures.bFilter ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$.extend( preSearch[ column ], {\n\t\t\t\t\"sSearch\": input+\"\",\n\t\t\t\t\"bRegex\":  regex === null ? false : regex,\n\t\t\t\t\"bSmart\":  smart === null ? true  : smart,\n\t\t\t\t\"bCaseInsensitive\": caseInsen === null ? true : caseInsen\n\t\t\t} );\n\n\t\t\t_fnFilterComplete( settings, settings.oPreviousSearch, 1 );\n\t\t} );\n\t} );\n\n\n\n\t/**\n\t * Provide a common method for plug-ins to check the version of DataTables being\n\t * used, in order to ensure compatibility.\n\t *\n\t *  @param {string} version Version string to check for, in the format \"X.Y.Z\".\n\t *    Note that the formats \"X\" and \"X.Y\" are also acceptable.\n\t *  @returns {boolean} true if this version of DataTables is greater or equal to\n\t *    the required version, or false if this version of DataTales is not\n\t *    suitable\n\t *  @static\n\t *  @dtopt API-Static\n\t *\n\t *  @example\n\t *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );\n\t */\n\tDataTable.versionCheck = DataTable.fnVersionCheck = function( version )\n\t{\n\t\tvar aThis = DataTable.version.split('.');\n\t\tvar aThat = version.split('.');\n\t\tvar iThis, iThat;\n\n\t\tfor ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {\n\t\t\tiThis = parseInt( aThis[i], 10 ) || 0;\n\t\t\tiThat = parseInt( aThat[i], 10 ) || 0;\n\n\t\t\t// Parts are the same, keep comparing\n\t\t\tif (iThis === iThat) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Parts are different, return immediately\n\t\t\treturn iThis > iThat;\n\t\t}\n\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Check if a `<table>` node is a DataTable table already or not.\n\t *\n\t *  @param {node|jquery|string} table Table node, jQuery object or jQuery\n\t *      selector for the table to test. Note that if more than more than one\n\t *      table is passed on, only the first will be checked\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 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {\n\t *      $('#example').dataTable();\n\t *    }\n\t */\n\tDataTable.isDataTable = DataTable.fnIsDataTable = function ( table )\n\t{\n\t\tvar t = $(table).get(0);\n\t\tvar is = false;\n\n\t\t$.each( DataTable.settings, function (i, o) {\n\t\t\tif ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {\n\t\t\t\tis = true;\n\t\t\t}\n\t\t} );\n\n\t\treturn is;\n\t};\n\n\n\t/**\n\t * Get all DataTable tables that have been initialised - optionally you can\n\t * select to get only currently visible tables.\n\t *\n\t *  @param {boolean} [visible=false] Flag to indicate if you want all (default)\n\t *    or visible tables only.\n\t *  @returns {array} Array of `table` nodes (not DataTable instances) which are\n\t *    DataTables\n\t *  @static\n\t *  @dtopt API-Static\n\t *\n\t *  @example\n\t *    $.each( $.fn.dataTable.tables(true), function () {\n\t *      $(table).DataTable().columns.adjust();\n\t *    } );\n\t */\n\tDataTable.tables = DataTable.fnTables = function ( visible )\n\t{\n\t\treturn jQuery.map( DataTable.settings, function (o) {\n\t\t\tif ( !visible || (visible && $(o.nTable).is(':visible')) ) {\n\t\t\t\treturn o.nTable;\n\t\t\t}\n\t\t} );\n\t};\n\n\n\n\t/**\n\t *\n\t */\n\t_api_register( '$()', function ( selector, opts ) {\n\t\tvar\n\t\t\trows   = this.rows( opts ).nodes(), // Get all rows\n\t\t\tjqRows = $(rows);\n\n\t\treturn $( [].concat(\n\t\t\tjqRows.filter( selector ).toArray(),\n\t\t\tjqRows.find( selector ).toArray()\n\t\t) );\n\t} );\n\n\n\t// jQuery functions to operate on the tables\n\t$.each( [ 'on', 'one', 'off' ], function (i, key) {\n\t\t_api_register( key+'()', function ( /* event, handler */ ) {\n\t\t\tvar args = Array.prototype.slice.call(arguments);\n\n\t\t\t// Add the `dt` namespace automatically if it isn't already present\n\t\t\tif ( args[0].indexOf( '.dt' ) === -1 ) {\n\t\t\t\targs[0] += '.dt';\n\t\t\t}\n\n\t\t\tvar inst = $( this.tables().nodes() );\n\t\t\tinst[key].apply( inst, args );\n\t\t\treturn this;\n\t\t} );\n\t} );\n\n\n\t_api_register( 'clear()', function () {\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\t_fnClearTable( settings );\n\t\t} );\n\t} );\n\n\n\t_api_register( 'settings()', function () {\n\t\treturn new _Api( this.context, this.context );\n\t} );\n\n\n\t_api_register( 'data()', function () {\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\treturn _pluck( settings.aoData, '_aData' );\n\t\t} ).flatten();\n\t} );\n\n\n\t_api_register( 'destroy()', function ( remove ) {\n\t\tremove = remove || false;\n\n\t\treturn this.iterator( 'table', function ( settings ) {\n\t\t\tvar orig      = settings.nTableWrapper.parentNode;\n\t\t\tvar classes   = settings.oClasses;\n\t\t\tvar table     = settings.nTable;\n\t\t\tvar tbody     = settings.nTBody;\n\t\t\tvar thead     = settings.nTHead;\n\t\t\tvar tfoot     = settings.nTFoot;\n\t\t\tvar jqTable   = $(table);\n\t\t\tvar jqTbody   = $(tbody);\n\t\t\tvar jqWrapper = $(settings.nTableWrapper);\n\t\t\tvar rows      = $.map( settings.aoData, function (r) { return r.nTr; } );\n\t\t\tvar i, ien;\n\n\t\t\t// Flag to note that the table is currently being destroyed - no action\n\t\t\t// should be taken\n\t\t\tsettings.bDestroying = true;\n\n\t\t\t// Fire off the destroy callbacks for plug-ins etc\n\t\t\t_fnCallbackFire( settings, \"aoDestroyCallback\", \"destroy\", [settings] );\n\n\t\t\t// If not being removed from the document, make all columns visible\n\t\t\tif ( ! remove ) {\n\t\t\t\tnew _Api( settings ).columns().visible( true );\n\t\t\t}\n\n\t\t\t// Blitz all DT events\n\t\t\tjqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');\n\t\t\t$(window).unbind('.DT-'+settings.sInstance);\n\n\t\t\t// When scrolling we had to break the table up - restore it\n\t\t\tif ( table != thead.parentNode ) {\n\t\t\t\tjqTable.children('thead').remove();\n\t\t\t\tjqTable.append( thead );\n\t\t\t}\n\n\t\t\tif ( tfoot && table != tfoot.parentNode ) {\n\t\t\t\tjqTable.children('tfoot').remove();\n\t\t\t\tjqTable.append( tfoot );\n\t\t\t}\n\n\t\t\t// Remove the DataTables generated nodes, events and classes\n\t\t\tjqTable.remove();\n\t\t\tjqWrapper.remove();\n\n\t\t\tsettings.aaSorting = [];\n\t\t\tsettings.aaSortingFixed = [];\n\t\t\t_fnSortingClasses( settings );\n\n\t\t\t$( rows ).removeClass( settings.asStripeClasses.join(' ') );\n\n\t\t\t$('th, td', thead).removeClass( classes.sSortable+' '+\n\t\t\t\tclasses.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone\n\t\t\t);\n\n\t\t\tif ( settings.bJUI ) {\n\t\t\t\t$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).remove();\n\t\t\t\t$('th, td', thead).each( function () {\n\t\t\t\t\tvar wrapper = $('div.'+classes.sSortJUIWrapper, this);\n\t\t\t\t\t$(this).append( wrapper.contents() );\n\t\t\t\t\twrapper.remove();\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( ! remove ) {\n\t\t\t\t// insertBefore acts like appendChild if !arg[1]\n\t\t\t\torig.insertBefore( table, settings.nTableReinsertBefore );\n\t\t\t}\n\n\t\t\t// Add the TR elements back into the table in their original order\n\t\t\tjqTbody.children().detach();\n\t\t\tjqTbody.append( rows );\n\n\t\t\t// Restore the width of the original table - was read from the style property,\n\t\t\t// so we can restore directly to that\n\t\t\tjqTable\n\t\t\t\t.css( 'width', settings.sDestroyWidth )\n\t\t\t\t.removeClass( classes.sTable );\n\n\t\t\t// If the were originally stripe classes - then we add them back here.\n\t\t\t// Note this is not fool proof (for example if not all rows had stripe\n\t\t\t// classes - but it's a good effort without getting carried away\n\t\t\tien = settings.asDestroyStripes.length;\n\n\t\t\tif ( ien ) {\n\t\t\t\tjqTbody.children().each( function (i) {\n\t\t\t\t\t$(this).addClass( settings.asDestroyStripes[i % ien] );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t/* Remove the settings object from the settings array */\n\t\t\tvar idx = $.inArray( settings, DataTable.settings );\n\t\t\tif ( idx !== -1 ) {\n\t\t\t\tDataTable.settings.splice( idx, 1 );\n\t\t\t}\n\t\t} );\n\t} );\n\n\n\t/**\n\t * Version string for plug-ins to check compatibility. Allowed format is\n\t * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used\n\t * only for non-release builds. See http://semver.org/ for more information.\n\t *  @member\n\t *  @type string\n\t *  @default Version number\n\t */\n\tDataTable.version = \"1.10.0-dev\";\n\n\t/**\n\t * Private data store, containing all of the settings objects that are\n\t * created for the tables on a given page.\n\t *\n\t * Note that the `DataTable.settings` object is aliased to\n\t * `jQuery.fn.dataTableExt` through which it may be accessed and\n\t * manipulated, or `jQuery.fn.dataTable.settings`.\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\n\t * available to it. These models define the objects that are used to hold\n\t * the active state and configuration of the table.\n\t *  @namespace\n\t */\n\tDataTable.models = {};\n\n\n\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\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\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\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\n\n\n\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\n\t\t/**\n\t\t * Array of TD elements for each row. This is null until the row has been\n\t\t * created.\n\t\t *  @type array nodes\n\t\t *  @default []\n\t\t */\n\t\t\"anCells\": null,\n\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\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 null\n\t\t *  @private\n\t\t */\n\t\t\"_aSortData\": null,\n\n\t\t/**\n\t\t * Per cell filtering data cache. As per the sort data cache, used to\n\t\t * increase the performance of the filtering in DataTables\n\t\t *  @type array\n\t\t *  @default null\n\t\t *  @private\n\t\t */\n\t\t\"_aFilterData\": null,\n\n\t\t/**\n\t\t * Filtering data cache. This is the same as the cell filtering cache, but\n\t\t * in this case a string rather than an array. This is easily computed with\n\t\t * a join on `_aFilterData`, but is provided as a cache so the join isn't\n\t\t * needed on every search (memory traded for performance)\n\t\t *  @type array\n\t\t *  @default null\n\t\t *  @private\n\t\t */\n\t\t\"_sFilterRow\": null,\n\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\n\t\t/**\n\t\t * Denote if the original data source was from the DOM, or the data source\n\t\t * object. This is used for invalidating data, so DataTables can\n\t\t * automatically read data from the original source, unless uninstructed\n\t\t * otherwise.\n\t\t *  @type string\n\t\t *  @default null\n\t\t *  @private\n\t\t */\n\t\t\"src\": null\n\t};\n\n\n\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.column}\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\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\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\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\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\n\t\t/**\n\t\t * Store for manual type assignment using the `column.type` option. This\n\t\t * is held in store so we can manipulate the column's `sType` property.\n\t\t *  @type string\n\t\t *  @default null\n\t\t *  @private\n\t\t */\n\t\t\"_sManualType\": null,\n\n\t\t/**\n\t\t * Flag to indicate if HTML5 data attributes should be used as the data\n\t\t * source for filtering or sorting. True is either are.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @private\n\t\t */\n\t\t\"_bAttrSrc\": false,\n\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\n\n\t/*\n\t * Developer note: The properties of the object below are given in Hungarian\n\t * notation, that was used as the interface for DataTables prior to v1.10, however\n\t * from v1.10 onwards the primary interface is camel case. In order to avoid\n\t * breaking backwards compatibility utterly with this change, the Hungarian\n\t * version is still, internally the primary interface, but is is not documented\n\t * - hence the @name tags in each doc comment. This allows a Javascript function\n\t * to create a map from Hungarian notation to camel case (going the other direction\n\t * would require each property to be listed, which would at around 3K to the size\n\t * of DataTables, while this method is about a 0.5K hit.\n\t *\n\t * Ultimately this does pave the way for Hungarian notation to be dropped\n\t * completely, but that is a massive amount of work and will break current\n\t * installs (therefore is on-hold until v2).\n\t */\n\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 *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.data\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 *        \"data\": [\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 *        \"columns\": [\n\t\t *          { \"title\": \"Engine\" },\n\t\t *          { \"title\": \"Browser\" },\n\t\t *          { \"title\": \"Platform\" },\n\t\t *          { \"title\": \"Version\" },\n\t\t *          { \"title\": \"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 (`data`)\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"data\": [\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 *        \"columns\": [\n\t\t *          { \"title\": \"Engine\",   \"data\": \"engine\" },\n\t\t *          { \"title\": \"Browser\",  \"data\": \"browser\" },\n\t\t *          { \"title\": \"Platform\", \"data\": \"platform\" },\n\t\t *          { \"title\": \"Version\",  \"data\": \"version\" },\n\t\t *          { \"title\": \"Grade\",    \"data\": \"grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aaData\": null,\n\n\n\t\t/**\n\t\t * If ordering 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\n\t\t * upon, and the sorting direction, with this variable. The `sorting` array\n\t\t * should contain an array for each column to be sorted initially containing\n\t\t * the column's index and a direction string ('asc' or 'desc').\n\t\t *  @type array\n\t\t *  @default [[0,'asc']]\n\t\t *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.order\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 *        \"order\": [[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 *        \"order\": []\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aaSorting\": [[0,'asc']],\n\n\n\t\t/**\n\t\t * This parameter is basically identical to the `sorting` 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\n\t\t * will always be forced on first - any sorting after that (from the user)\n\t\t * will 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 *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.orderFixed\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"orderFixed\": [[0,'asc']]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"aaSortingFixed\": [],\n\n\n\t\t/**\n\t\t * DataTables can be instructed to load data to display in the table from a\n\t\t * Ajax source. This option defines how that Ajax call is made and where to.\n\t\t *\n\t\t * The `ajax` property has three different modes of operation, depending on\n\t\t * how it is defined. These are:\n\t\t *\n\t\t * * `string` - Set the URL from where the data should be loaded from.\n\t\t * * `object` - Define properties for `jQuery.ajax`.\n\t\t * * `function` - Custom data get function\n\t\t *\n\t\t * `string`\n\t\t * --------\n\t\t *\n\t\t * As a string, the `ajax` property simply defines the URL from which\n\t\t * DataTables will load data.\n\t\t *\n\t\t * `object`\n\t\t * --------\n\t\t *\n\t\t * As an object, the parameters in the object are passed to\n\t\t * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control\n\t\t * of the Ajax request. DataTables has a number of default parameters which\n\t\t * you can override using this option. Please refer to the jQuery\n\t\t * documentation for a full description of the options available, although\n\t\t * the following parameters provide additional options in DataTables or\n\t\t * require special consideration:\n\t\t *\n\t\t * * `data` - As with jQuery, `data` can be provided as an object, but it\n\t\t *   can also be used as a function to manipulate the data DataTables sends\n\t\t *   to the server. The function takes a single parameter, an object of\n\t\t *   parameters with the values that DataTables has readied for sending. An\n\t\t *   object may be returned which will be merged into the DataTables\n\t\t *   defaults, or you can add the items to the object that was passed in and\n\t\t *   not return anything from the function. This supersedes `fnServerParams`\n\t\t *   from DataTables 1.9-.\n\t\t *\n\t\t * * `dataSrc` - By default DataTables will look for the property `data` (or\n\t\t *   `aaData` for compatibility with DataTables 1.9-) when obtaining data\n\t\t *   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\n\t\t *   object notation to get a data source for multiple levels of nesting, or\n\t\t *   it my be used as a function. As a function it takes a single parameter,\n\t\t *   the JSON returned from the server, which can be manipulated as\n\t\t *   required, with the returned value being that used by DataTables as the\n\t\t *   data source for the table. This supersedes `sAjaxDataProp` from\n\t\t *   DataTables 1.9-.\n\t\t *\n\t\t * * `success` - Should not be overridden it is used internally in\n\t\t *   DataTables. To manipulate / transform the data returned by the server\n\t\t *   use `ajax.dataSrc`, or use `ajax` as a function (see below).\n\t\t *\n\t\t * `function`\n\t\t * ----------\n\t\t *\n\t\t * As a function, making the Ajax call is left up to yourself allowing\n\t\t * complete control of the Ajax request. Indeed, if desired, a method other\n\t\t * than Ajax could be used to obtain the required data, such as Web storage\n\t\t * or an AIR database.\n\t\t *\n\t\t * The function is given four parameters and no return is required. The\n\t\t * parameters are:\n\t\t *\n\t\t * 1. _object_ - Data to send to the server\n\t\t * 2. _function_ - Callback function that must be executed when the required\n\t\t *    data has been obtained. That data should be passed into the callback\n\t\t *    as the only parameter\n\t\t * 3. _object_ - DataTables settings object for the table\n\t\t *\n\t\t * Note that this supersedes `fnServerData` from DataTables 1.9-.\n\t\t *\n\t\t *  @type string|object|function\n\t\t *  @default null\n\t\t *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.ajax\n\t\t *  @since 1.10.0\n\t\t *\n\t\t * @example\n\t\t *   // Get JSON data from a file via Ajax.\n\t\t *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": \"data.json\"\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Get JSON data from a file via Ajax, using `dataSrc` to change\n\t\t *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": {\n\t\t *       \"url\": \"data.json\",\n\t\t *       \"dataSrc\": \"tableData\"\n\t\t *     }\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Get JSON data from a file via Ajax, using `dataSrc` to read data\n\t\t *   // from a plain array rather than an array in an object\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": {\n\t\t *       \"url\": \"data.json\",\n\t\t *       \"dataSrc\": \"\"\n\t\t *     }\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Manipulate the data returned from the server - add a link to data\n\t\t *   // (note this can, should, be done using `render` for the column - this\n\t\t *   // is just a simple example of how the data can be manipulated).\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": {\n\t\t *       \"url\": \"data.json\",\n\t\t *       \"dataSrc\": function ( json ) {\n\t\t *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {\n\t\t *           json[i][0] = '<a href=\"/message/'+json[i][0]+'>View message</a>';\n\t\t *         }\n\t\t *         return json;\n\t\t *       }\n\t\t *     }\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Add data to the request\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": {\n\t\t *       \"url\": \"data.json\",\n\t\t *       \"data\": function ( d ) {\n\t\t *         return {\n\t\t *           \"extra_search\": $('#extra').val()\n\t\t *         };\n\t\t *       }\n\t\t *     }\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Send request as POST\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": {\n\t\t *       \"url\": \"data.json\",\n\t\t *       \"type\": \"POST\"\n\t\t *     }\n\t\t *   } );\n\t\t *\n\t\t * @example\n\t\t *   // Get the data from localStorage (could interface with a form for\n\t\t *   // adding, editing and removing rows).\n\t\t *   $('#example').dataTable( {\n\t\t *     \"ajax\": function (data, callback, settings) {\n\t\t *       callback(\n\t\t *         JSON.parse( localStorage.getItem('dataTablesData') )\n\t\t *       );\n\t\t *     }\n\t\t *   } );\n\t\t */\n\t\t\"ajax\": null,\n\n\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 *\n\t\t * Note that the `pageLength` property will be automatically set to the\n\t\t * first value given in this array, unless `pageLength` is also provided.\n\t\t *  @type array\n\t\t *  @default [ 10, 25, 50, 100 ]\n\t\t *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.lengthMenu\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"lengthMenu\": [[10, 25, 50, -1], [10, 25, 50, \"All\"]]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aLengthMenu\": [ 10, 25, 50, 100 ],\n\n\n\t\t/**\n\t\t * The `columns` 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.column}. Note that if you use `columns` 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 *  @name DataTable.defaults.column\n\t\t */\n\t\t\"aoColumns\": null,\n\n\t\t/**\n\t\t * Very similar to `columns`, `columnDefs` allows you to target a specific\n\t\t * column, multiple columns, or all columns, using the `targets` property of\n\t\t * each object in the array. This allows great flexibility when creating\n\t\t * tables, as the `columnDefs` arrays can be of any length, targeting the\n\t\t * columns you specifically want. `columnDefs` may use any of the column\n\t\t * options available: {@link DataTable.defaults.column}, but it _must_\n\t\t * have `targets` defined in each object in the array. Values in the `targets`\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 *  @name DataTable.defaults.columnDefs\n\t\t */\n\t\t\"aoColumnDefs\": null,\n\n\n\t\t/**\n\t\t * Basically the same as `search`, 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 * `search` and `escapeRegex` (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 *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.searchCols\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"searchCols\": [\n\t\t *          null,\n\t\t *          { \"search\": \"My filter\" },\n\t\t *          null,\n\t\t *          { \"search\": \"^[0-9]\", \"escapeRegex\": false }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"aoSearchCols\": [],\n\n\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.stripe*`\n\t\t *    options</i>\n\t\t *\n\t\t *  @dtopt Option\n\t\t *  @name DataTable.defaults.stripeClasses\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"stripeClasses\": [ 'strip1', 'strip2', 'strip3' ]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"asStripeClasses\": null,\n\n\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 `columns`.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.autoWidth\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"autoWidth\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bAutoWidth\": true,\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.deferRender\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"ajax\": \"sources/arrays.txt\",\n\t\t *        \"deferRender\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bDeferRender\": false,\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.destroy\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"srollY\": \"200px\",\n\t\t *        \"paginate\": false\n\t\t *      } );\n\t\t *\n\t\t *      // Some time later....\n\t\t *      $('#example').dataTable( {\n\t\t *        \"filter\": false,\n\t\t *        \"destroy\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bDestroy\": false,\n\n\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.dom}.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.searching\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"searching\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bFilter\": true,\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.info\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"info\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bInfo\": true,\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.jQueryUI\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"jQueryUI\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bJQueryUI\": false,\n\n\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 (`paginate`).\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.lengthChange\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"lengthChange\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bLengthChange\": true,\n\n\n\t\t/**\n\t\t * Enable or disable pagination.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.paging\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"paging\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bPaginate\": true,\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.processing\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"processing\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bProcessing\": false,\n\n\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). `destroy` 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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.retrieve\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 *        \"scrollY\": \"200px\",\n\t\t *        \"paginate\": false,\n\t\t *        \"retrieve\": true\n\t\t *      } );\n\t\t *    }\n\t\t *\n\t\t *    function tableActions ()\n\t\t *    {\n\t\t *      var table = initTable();\n\t\t *      // perform API operations with oTable\n\t\t *    }\n\t\t */\n\t\t\"bRetrieve\": false,\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.scrollCollapse\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"scrollY\": \"200\",\n\t\t *        \"scrollCollapse\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bScrollCollapse\": false,\n\n\n\t\t/**\n\t\t * Configure DataTables to use server-side processing. Note that the\n\t\t * `ajax` 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 *\n\t\t *  @dtopt Features\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.serverSide\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"serverSide\": true,\n\t\t *        \"ajax\": \"xhr.php\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bServerSide\": false,\n\n\n\t\t/**\n\t\t * Enable or disable sorting of columns. Sorting of individual columns can be\n\t\t * disabled by the `sortable` option for each column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.ordering\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"ordering\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSort\": true,\n\n\n\t\t/**\n\t\t * Enable or display DataTables' ability to sort multiple columns at the\n\t\t * same time (activated by shift-click by the user).\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.orderMulti\n\t\t *\n\t\t *  @example\n\t\t *    // Disable multiple column sorting ability\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"orderMulti\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortMulti\": true,\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.orderCellsTop\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"orderCellsTop\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortCellsTop\": false,\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.orderClasses\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"orderClasses\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortClasses\": true,\n\n\n\t\t/**\n\t\t * Enable or disable state saving. When enabled HTML5 `localStorage` will be\n\t\t * used to save table display information such as pagination information,\n\t\t * display length, filtering and sorting. As such when the end user reloads\n\t\t * the page the display display will match what thy had previously set up.\n\t\t *\n\t\t * Due to the use of `localStorage` the default state saving is not supported\n\t\t * in IE6 or 7. If state saving is required in those browsers, use\n\t\t * `stateSaveCallback` to provide a storage solution such as cookies.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.stateSave\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"stateSave\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bStateSave\": false,\n\n\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} row \"TR\" element for the current row\n\t\t *  @param {array} data Raw data array for this row\n\t\t *  @param {int} dataIndex The index of this row in the internal aoData array\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.createdRow\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"createdRow\": function( row, data, dataIndex ) {\n\t\t *          // Bold the grade for all 'A' grade browsers\n\t\t *          if ( data[4] == \"A\" )\n\t\t *          {\n\t\t *            $('td:eq(4)', row).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\n\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} settings DataTables settings object\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.drawCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"drawCallback\": function( settings ) {\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\n\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' event.\n\t\t *  @type function\n\t\t *  @param {node} foot \"TR\" element for the footer\n\t\t *  @param {array} data Full table data (as derived from the original HTML)\n\t\t *  @param {int} start Index for the current display starting point in the\n\t\t *    display array\n\t\t *  @param {int} end Index for the current display ending point in the\n\t\t *    display array\n\t\t *  @param {array int} display Index array to translate the visual position\n\t\t *    to the full data array\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.footerCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"footerCallback\": function( tfoot, data, start, end, display ) {\n\t\t *          tfoot.getElementsByTagName('th')[0].innerHTML = \"Starting index is \"+start;\n\t\t *        }\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"fnFooterCallback\": null,\n\n\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} toFormat number to be formatted\n\t\t *  @returns {string} formatted string for DataTables to show the number\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.formatNumber\n\t\t *\n\t\t *  @example\n\t\t *    // Format a number using a single quote for the separator (note that\n\t\t *    // this can also be done with the language.infoThousands option)\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"formatNumber\": function ( toFormat ) {\n\t\t *          return toFormat.toString().replace(\n\t\t *            /\\B(?=(\\d{3})+(?!\\d))/g, \"'\"\n\t\t *          );\n\t\t *        };\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnFormatNumber\": function ( toFormat ) {\n\t\t\treturn toFormat.toString().replace(\n\t\t\t\t/\\B(?=(\\d{3})+(?!\\d))/g,\n\t\t\t\tthis.oLanguage.sInfoThousands\n\t\t\t);\n\t\t},\n\n\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} head \"TR\" element for the header\n\t\t *  @param {array} data Full table data (as derived from the original HTML)\n\t\t *  @param {int} start Index for the current display starting point in the\n\t\t *    display array\n\t\t *  @param {int} end Index for the current display ending point in the\n\t\t *    display array\n\t\t *  @param {array int} display Index array to translate the visual position\n\t\t *    to the full data array\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.headerCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fheaderCallback\": function( head, data, start, end, display ) {\n\t\t *          head.getElementsByTagName('th')[0].innerHTML = \"Displaying \"+(end-start)+\" records\";\n\t\t *        }\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"fnHeaderCallback\": null,\n\n\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} start Starting position in data for the draw\n\t\t *  @param {int} end End position in data for the draw\n\t\t *  @param {int} max Total number of rows in the table (regardless of\n\t\t *    filtering)\n\t\t *  @param {int} total Total number of rows in the data set, after filtering\n\t\t *  @param {string} pre 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 *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.infoCallback\n\t\t *\n\t\t *  @example\n\t\t *    $('#example').dataTable( {\n\t\t *      \"infoCallback\": function( settings, start, end, max, total, pre ) {\n\t\t *        return start +\" to \"+ end;\n\t\t *      }\n\t\t *    } );\n\t\t */\n\t\t\"fnInfoCallback\": null,\n\n\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} settings 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 *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.initComplete\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"initComplete\": function(settings, 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\n\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} settings 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 *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.preDrawCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"preDrawCallback\": function( settings ) {\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\n\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} row \"TR\" element for the current row\n\t\t *  @param {array} data Raw data array for this row\n\t\t *  @param {int} displayIndex The display index for the current table draw\n\t\t *  @param {int} displayIndexFull The index of the data in the full list of\n\t\t *    rows (after filtering)\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.rowCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"rowCallback\": function( row, data, displayIndex, displayIndexFull ) {\n\t\t *          // Bold the grade for all 'A' grade browsers\n\t\t *          if ( data[4] == \"A\" ) {\n\t\t *            $('td:eq(4)', row).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\n\n\t\t/**\n\t\t * __Deprecated__ The functionality provided by this parameter has now been\n\t\t * superseded by that provided through `ajax`, which should be used instead.\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 so something more suitable for your application.\n\t\t * For example you could use POST data, or pull information from a Gears or\n\t\t * AIR database.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {string} source HTTP source to obtain the data from (`ajax`)\n\t\t *  @param {array} data A key/value pair object containing the data to send\n\t\t *    to the server\n\t\t *  @param {function} callback 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} settings DataTables settings object\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.serverData\n\t\t *\n\t\t *  @deprecated 1.10. Please use `ajax` for this functionality now.\n\t\t */\n\t\t\"fnServerData\": null,\n\n\n\t\t/**\n\t\t * __Deprecated__ The functionality provided by this parameter has now been\n\t\t * superseded by that provided through `ajax`, which should be used instead.\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} data 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 data array passed in,\n\t\t *    as this is passed by reference.\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.serverParams\n\t\t *\n\t\t *  @deprecated 1.10. Please use `ajax` for this functionality now.\n\t\t */\n\t\t\"fnServerParams\": null,\n\n\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 `localStorage`\n\t\t * but you might wish to use a server-side database or cookies.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {object} settings DataTables settings object\n\t\t *  @return {object} The DataTables state object to be loaded\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.stateLoadCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"stateSave\": true,\n\t\t *        \"stateLoadCallback\": function (settings) {\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\"fnStateLoadCallback\": function ( settings ) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(\n\t\t\t\t\tlocalStorage.getItem('DataTables_'+settings.sInstance+'_'+window.location.pathname)\n\t\t\t\t);\n\t\t\t} catch (e) {}\n\t\t},\n\n\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} settings DataTables settings object\n\t\t *  @param {object} data The state object that is to be loaded\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.stateLoadParams\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 *        \"stateSave\": true,\n\t\t *        \"stateLoadParams\": function (settings, data) {\n\t\t *          data.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 *        \"stateSave\": true,\n\t\t *        \"stateLoadParams\": function (settings, data) {\n\t\t *          return false;\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateLoadParams\": null,\n\n\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} settings DataTables settings object\n\t\t *  @param {object} data The state object that was loaded\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.stateLoaded\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 *        \"stateSave\": true,\n\t\t *        \"stateLoaded\": function (settings, data) {\n\t\t *          alert( 'Saved filter was: '+data.oSearch.sSearch );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateLoaded\": null,\n\n\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 DataTables will use `localStorage`\n\t\t * but you might wish to use a server-side database or cookies.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {object} settings DataTables settings object\n\t\t *  @param {object} data The state object to be saved\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.stateSaveCallback\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"stateSave\": true,\n\t\t *        \"stateSaveCallback\": function (settings, data) {\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\": data,\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\"fnStateSaveCallback\": function ( settings, data ) {\n\t\t\ttry {\n\t\t\t\tlocalStorage.setItem(\n\t\t\t\t\t'DataTables_'+settings.sInstance+'_'+window.location.pathname,\n\t\t\t\t\tJSON.stringify(data)\n\t\t\t\t);\n\t\t\t} catch (e) {}\n\t\t},\n\n\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} settings DataTables settings object\n\t\t *  @param {object} data The state object to be saved\n\t\t *\n\t\t *  @dtopt Callbacks\n\t\t *  @name DataTable.defaults.stateSaveParams\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 *        \"stateSave\": true,\n\t\t *        \"stateSaveParams\": function (settings, data) {\n\t\t *          data.oSearch.sSearch = \"\";\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateSaveParams\": null,\n\n\n\t\t/**\n\t\t * Duration for which the saved state information is considered valid. After this period\n\t\t * has elapsed the state will be returned to the default.\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.stateDuration\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"stateDuration\": 60*60*24; // 1 day\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iStateDuration\": 7200,\n\n\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. `deferLoading`\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.deferLoading\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 *        \"serverSide\": true,\n\t\t *        \"ajax\": \"scripts/server_processing.php\",\n\t\t *        \"deferLoading\": 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 *        \"serverSide\": true,\n\t\t *        \"ajax\": \"scripts/server_processing.php\",\n\t\t *        \"deferLoading\": [ 57, 100 ],\n\t\t *        \"search\": {\n\t\t *          \"search\": \"my_filter\"\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iDeferLoading\": null,\n\n\n\t\t/**\n\t\t * Number of rows to display on a single page when using pagination. If\n\t\t * feature enabled (`lengthChange`) 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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.pageLength\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"pageLength\": 50\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iDisplayLength\": 10,\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.displayStart\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"displayStart\": 20\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iDisplayStart\": 0,\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.tabIndex\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"tabIndex\": 1\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iTabIndex\": 0,\n\n\n\t\t/**\n\t\t * Classes that DataTables assigns to the various components and features\n\t\t * that it adds to the HTML table. This allows classes to be configured\n\t\t * during initialisation in addition to through the static\n\t\t * {@link DataTable.ext.oStdClasses} object).\n\t\t *  @namespace\n\t\t *  @name DataTable.defaults.classes\n\t\t */\n\t\t\"oClasses\": {},\n\n\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 *  @name DataTable.defaults.language\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 *  @name DataTable.defaults.language.aria\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.aria.sortAscending\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 *        \"language\": {\n\t\t\t\t *          \"aria\": {\n\t\t\t\t *            \"sortAscending\": \" - 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\": \"：激活排序列升序\",\n\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.aria.sortDescending\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 *        \"language\": {\n\t\t\t\t *          \"aria\": {\n\t\t\t\t *            \"sortDescending\": \" - 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\": \"：激活排序列降序\"\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Pagination string used by DataTables for the built-in pagination\n\t\t\t * control types.\n\t\t\t *  @namespace\n\t\t\t *  @name DataTable.defaults.language.paginate\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.paginate.first\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 *        \"language\": {\n\t\t\t\t *          \"paginate\": {\n\t\t\t\t *            \"first\": \"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\": \"第一页\",\n\n\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.paginate.last\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 *        \"language\": {\n\t\t\t\t *          \"paginate\": {\n\t\t\t\t *            \"last\": \"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\": \"最后一页\",\n\n\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.paginate.next\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 *        \"language\": {\n\t\t\t\t *          \"paginate\": {\n\t\t\t\t *            \"next\": \"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\": \"下一页\",\n\n\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 *\n\t\t\t\t *  @dtopt Language\n\t\t\t\t *  @name DataTable.defaults.language.paginate.previous\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 *        \"language\": {\n\t\t\t\t *          \"paginate\": {\n\t\t\t\t *            \"previous\": \"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\": \"上一页\"\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * This string is shown in preference to `zeroRecords` 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 `zeroRecords` 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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.emptyTable\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 *        \"language\": {\n\t\t\t *          \"emptyTable\": \"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\": \"没有数据\",\n\n\n\t\t\t/**\n\t\t\t * This string gives information to the end user about the information\n\t\t\t * that is current on display on the page. The following tokens can be\n\t\t\t * used in the string and will be dynamically replaced as the table\n\t\t\t * display updates. This tokens can be placed anywhere in the string, or\n\t\t\t * removed as needed by the language requires:\n\t\t\t *\n\t\t\t * * `\\_START\\_` - Display index of the first record on the current page\n\t\t\t * * `\\_END\\_` - Display index of the last record on the current page\n\t\t\t * * `\\_TOTAL\\_` - Number of records in the table after filtering\n\t\t\t * * `\\_MAX\\_` - Number of records in the table without filtering\n\t\t\t * * `\\_PAGE\\_` - Current page number\n\t\t\t * * `\\_PAGES\\_` - Total number of pages of data in the table\n\t\t\t *\n\t\t\t *  @type string\n\t\t\t *  @default Showing _START_ to _END_ of _TOTAL_ entries\n\t\t\t *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.info\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 *        \"language\": {\n\t\t\t *          \"info\": \"Showing page _PAGE_ of _PAGES_\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfo\": \"显示 _START_ 到 _END_ 项，共 _TOTAL_ 项\",\n\n\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 `info`.\n\t\t\t *  @type string\n\t\t\t *  @default Showing 0 to 0 of 0 entries\n\t\t\t *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.infoEmpty\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 *        \"language\": {\n\t\t\t *          \"infoEmpty\": \"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\": \"显示0项\",\n\n\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 (`info`) 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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.infoFiltered\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 *        \"language\": {\n\t\t\t *          \"infoFiltered\": \" - 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\": \"（从 _MAX_ 中筛选）\",\n\n\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 `info` (`infoEmpty` and `infoFiltered` 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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.infoPostFix\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 *        \"language\": {\n\t\t\t *          \"infoPostFix\": \"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\n\n\t\t\t/**\n\t\t\t * DataTables has a build in number formatter (`formatNumber`) 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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.infoThousands\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 *        \"language\": {\n\t\t\t *          \"infoThousands\": \"'\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfoThousands\": \",\",\n\n\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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.lengthMenu\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 *        \"language\": {\n\t\t\t *          \"lengthMenu\": \"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 *        \"language\": {\n\t\t\t *          \"lengthMenu\": '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\": \"显示 _MENU_ entries\",\n\n\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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.loadingRecords\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 *        \"language\": {\n\t\t\t *          \"loadingRecords\": \"Please wait - loading...\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sLoadingRecords\": \"加载中…\",\n\n\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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.processing\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 *        \"language\": {\n\t\t\t *          \"processing\": \"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\": \"处理中…\",\n\n\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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.search\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 *        \"language\": {\n\t\t\t *          \"search\": \"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 *        \"language\": {\n\t\t\t *          \"search\": \"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\": \"查找：\",\n\n\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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.url\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 *        \"language\": {\n\t\t\t *          \"url\": \"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\n\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. `emptyTable` 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 *\n\t\t\t *  @dtopt Language\n\t\t\t *  @name DataTable.defaults.language.zeroRecords\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 *        \"language\": {\n\t\t\t *          \"zeroRecords\": \"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\": \"没有找到符合条件的记录\"\n\t\t},\n\n\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 `search` parameter must be\n\t\t * defined, but all other parameters are optional. When `regex` 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 `smart`\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.search\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"search\": {\"search\": \"Initial search\"}\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"oSearch\": $.extend( {}, DataTable.models.oSearch ),\n\n\n\t\t/**\n\t\t * __Deprecated__ The functionality provided by this parameter has now been\n\t\t * superseded by that provided through `ajax`, which should be used instead.\n\t\t *\n\t\t * By default DataTables will look for the property `data` (or `aaData` for\n\t\t * compatibility with DataTables 1.9-) when obtaining data from an Ajax\n\t\t * source or for server-side processing - this parameter allows that\n\t\t * property to be changed. You can use Javascript dotted object notation to\n\t\t * get a data source for multiple levels of nesting.\n\t\t *  @type string\n\t\t *  @default data\n\t\t *\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.ajaxDataProp\n\t\t *\n\t\t *  @deprecated 1.10. Please use `ajax` for this functionality now.\n\t\t */\n\t\t\"sAjaxDataProp\": \"data\",\n\n\n\t\t/**\n\t\t * __Deprecated__ The functionality provided by this parameter has now been\n\t\t * superseded by that provided through `ajax`, which should be used instead.\n\t\t *\n\t\t * You can instruct DataTables to load data from an external\n\t\t * source using this parameter (use aData if you want to pass data in you\n\t\t * already have). Simply provide a url a JSON object can be obtained from.\n\t\t *  @type string\n\t\t *  @default null\n\t\t *\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.ajaxSource\n\t\t *\n\t\t *  @deprecated 1.10. Please use `ajax` for this functionality now.\n\t\t */\n\t\t\"sAjaxSource\": null,\n\n\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:\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 `jQueryUI` is false)</i> <b>or</b>\n\t\t *    <\"H\"lfr>t<\"F\"ip> <i>(when `jQueryUI` is true)</i>\n\t\t *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.dom\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"dom\": '&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\n\n\t\t/**\n\t\t * DataTables features four different built-in options for the buttons to\n\t\t * display for pagination control:\n\t\t *\n\t\t * * `simple` - 'Previous' and 'Next' buttons only\n\t\t * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers\n\t\t * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons\n\t\t * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus\n\t\t *   page numbers\n\t\t *\n\t\t * Further methods can be added using {@link DataTable.ext.oPagination}.\n\t\t *  @type string\n\t\t *  @default simple_numbers\n\t\t *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.pagingType\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"pagingType\": \"full_numbers\"\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"sPaginationType\": \"simple_numbers\",\n\n\n\t\t/**\n\t\t * Enable horizontal scrolling. When a table is too wide to fit into a\n\t\t * certain layout, or you have a large number of columns in the table, you\n\t\t * can enable x-scrolling to show the table in a viewport, which can be\n\t\t * scrolled. This property can be `true` which will allow the table to\n\t\t * scroll horizontally when needed, or any CSS unit, or a number (in which\n\t\t * case it will be treated as a pixel measurement). Setting as simply `true`\n\t\t * is recommended.\n\t\t *  @type boolean|string\n\t\t *  @default <i>blank string - i.e. disabled</i>\n\t\t *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.scrollX\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"scrollX\": true,\n\t\t *        \"scrollCollapse\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollX\": \"\",\n\n\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 *\n\t\t *  @dtopt Options\n\t\t *  @name DataTable.defaults.scrollXInner\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"scrollX\": \"100%\",\n\t\t *        \"scrollXInner\": \"110%\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollXInner\": \"\",\n\n\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 *\n\t\t *  @dtopt Features\n\t\t *  @name DataTable.defaults.scrollY\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"scrollY\": \"200px\",\n\t\t *        \"paginate\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollY\": \"\",\n\n\n\t\t/**\n\t\t * __Deprecated__ The functionality provided by this parameter has now been\n\t\t * superseded by that provided through `ajax`, which should be used instead.\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 *\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t *  @name DataTable.defaults.serverMethod\n\t\t *\n\t\t *  @deprecated 1.10. Please use `ajax` for this functionality now.\n\t\t */\n\t\t\"sServerMethod\": \"GET\",\n\n\n\t\t/**\n\t\t * DataTables makes use of renderers when displaying HTML elements for\n\t\t * a table. These renderers can be added or modified by plug-ins to\n\t\t * generate suitable mark-up for a site. For example the Bootstrap\n\t\t * integration plug-in for DataTables uses a paging button renderer to\n\t\t * display pagination buttons in the mark-up required by Bootstrap.\n\t\t *\n\t\t * For further information about the renderers available see\n\t\t * DataTable.ext.renderer\n\t\t *  @type string|object\n\t\t *  @default null\n\t\t *\n\t\t *  @name DataTable.defaults.renderer\n\t\t *\n\t\t */\n\t\t\"renderer\": null\n\t};\n\n\t_fnHungarianMap( DataTable.defaults );\n\n\n\n\t/*\n\t * Developer note - See note in model.defaults.js about the use of Hungarian\n\t * notation and camel case.\n\t */\n\n\t/**\n\t * Column options that can be given to DataTables at initialisation time.\n\t *  @namespace\n\t */\n\tDataTable.defaults.column = {\n\t\t/**\n\t\t * Define which column(s) an order will occur on for this column. This\n\t\t * allows a column's ordering to take multiple columns into account when\n\t\t * doing a sort or use the data from a different column. For example first\n\t\t * name / last name columns make sense to do a multi-column sort over the\n\t\t * two columns.\n\t\t *  @type array|int\n\t\t *  @default null <i>Takes the value of the column index automatically</i>\n\t\t *\n\t\t *  @name DataTable.defaults.column.orderData\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"orderData\": [ 0, 1 ], \"targets\": [ 0 ] },\n\t\t *          { \"orderData\": [ 1, 0 ], \"targets\": [ 1 ] },\n\t\t *          { \"orderData\": 2, \"targets\": [ 2 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"orderData\": [ 0, 1 ] },\n\t\t *          { \"orderData\": [ 1, 0 ] },\n\t\t *          { \"orderData\": 2 },\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\t\"iDataSort\": -1,\n\n\n\t\t/**\n\t\t * You can control the default ordering direction, and even alter the\n\t\t * behaviour of the sort handler (i.e. only allow ascending ordering etc)\n\t\t * using this parameter.\n\t\t *  @type array\n\t\t *  @default [ 'asc', 'desc' ]\n\t\t *\n\t\t *  @name DataTable.defaults.column.orderSequence\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"orderSequence\": [ \"asc\" ], \"targets\": [ 1 ] },\n\t\t *          { \"orderSequence\": [ \"desc\", \"asc\", \"asc\" ], \"targets\": [ 2 ] },\n\t\t *          { \"orderSequence\": [ \"desc\" ], \"targets\": [ 3 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          null,\n\t\t *          { \"orderSequence\": [ \"asc\" ] },\n\t\t *          { \"orderSequence\": [ \"desc\", \"asc\", \"asc\" ] },\n\t\t *          { \"orderSequence\": [ \"desc\" ] },\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"asSorting\": [ 'asc', 'desc' ],\n\n\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 *\n\t\t *  @name DataTable.defaults.column.searchable\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"searchable\": false, \"targets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"searchable\": 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\n\n\t\t/**\n\t\t * Enable or disable ordering on this column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *\n\t\t *  @name DataTable.defaults.column.orderable\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"orderable\": false, \"targets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"orderable\": 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\n\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 *\n\t\t *  @name DataTable.defaults.column.visible\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"visible\": false, \"targets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"visible\": 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\n\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} td The TD node that has been created\n\t\t *  @param {*} cellData The Data for the cell\n\t\t *  @param {array|object} rowData The data for the whole row\n\t\t *  @param {int} row The row index for the aoData data store\n\t\t *  @param {int} col The column index for aoColumns\n\t\t *\n\t\t *  @name DataTable.defaults.column.createdCell\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 *        \"columnDefs\": [ {\n\t\t *          \"targets\": [3],\n\t\t *          \"createdCell\": function (td, cellData, rowData, row, col) {\n\t\t *            if ( cellData == \"1.7\" ) {\n\t\t *              $(td).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\n\n\t\t/**\n\t\t * This parameter has been replaced by `data` in DataTables to ensure naming\n\t\t * consistency. `dataProp` can still be used, as there is backwards\n\t\t * compatibility in DataTables for this option, but it is strongly\n\t\t * recommended that you use `data` in preference to `dataProp`.\n\t\t *  @name DataTable.defaults.column.dataProp\n\t\t */\n\n\n\t\t/**\n\t\t * This property can be used to read data from any data source property,\n\t\t * including deeply nested objects / properties. `data` can be given in a\n\t\t * number of different ways which effect its behaviour:\n\t\t *\n\t\t * * `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).\n\t\t * * `string` - read an object property from the data source. There are\n\t\t *   three 'special' options that can be used in the string to alter how\n\t\t *   DataTables reads the data from the source object:\n\t\t *    * `.` - Dotted Javascript notation. Just as you use a `.` in\n\t\t *      Javascript to read from nested objects, so to can the options\n\t\t *      specified in `data`. For example: `browser.version` or\n\t\t *      `browser.name`. If your object parameter name contains a period, use\n\t\t *      `\\\\` to escape it - i.e. `first\\\\.name`.\n\t\t *    * `[]` - Array notation. DataTables can automatically combine data\n\t\t *      from and array source, joining the data with the characters provided\n\t\t *      between the two brackets. For example: `name[, ]` would provide a\n\t\t *      comma-space separated list from the source array. If no characters\n\t\t *      are provided between the brackets, the original array source is\n\t\t *      returned.\n\t\t *    * `()` - Function notation. Adding `()` to the end of a parameter will\n\t\t *      execute a function of the name given. For example: `browser()` for a\n\t\t *      simple function on the data source, `browser.version()` for a\n\t\t *      function in a nested property or even `browser().version` to get an\n\t\t *      object property if the function called returns an object. Note that\n\t\t *      function notation is recommended for use in `render` rather than\n\t\t *      `data` as it is much simpler to use as a renderer.\n\t\t * * `null` - use the original data source for the row rather than plucking\n\t\t *   data directly from it. This action has effects on two other\n\t\t *   initialisation options:\n\t\t *    * `defaultContent` - When null is given as the `data` option and\n\t\t *      `defaultContent` is specified for the column, the value defined by\n\t\t *      `defaultContent` will be used for the cell.\n\t\t *    * `render` - When null is used for the `data` option and the `render`\n\t\t *      option is specified for the column, the whole data source for the\n\t\t *      row is used for the renderer.\n\t\t * * `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 *    * Parameters:\n\t\t *      * `{array|object}` The data source for the row\n\t\t *      * `{string}` The type call data requested - this will be 'set' when\n\t\t *        setting data or 'filter', 'display', 'type', 'sort' or undefined\n\t\t *        when gathering data. Note that when `undefined` is given for the\n\t\t *        type DataTables expects to get the raw data for the object back<\n\t\t *      * `{*}` Data to set when the second parameter is 'set'.\n\t\t *    * Return:\n\t\t *      * The return value from the function is not required when 'set' is\n\t\t *        the type of call, but otherwise the return is what will be used\n\t\t *        for the data requested.\n\t\t *\n\t\t * Note that `data` is a getter and setter option. If you just require\n\t\t * formatting of data for output, you will likely want to use `render` which\n\t\t * is simply a getter and thus simpler to use.\n\t\t *\n\t\t * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The\n\t\t * name change reflects the flexibility of this property and is consistent\n\t\t * with the naming of mRender. If 'mDataProp' is given, then it will still\n\t\t * be used by DataTables, as it automatically maps the old name to the new\n\t\t * if required.\n\t\t *\n\t\t *  @type string|int|function|null\n\t\t *  @default null <i>Use automatically calculated column index</i>\n\t\t *\n\t\t *  @name DataTable.defaults.column.data\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Read table data from objects\n\t\t *    // JSON structure for each row:\n\t\t *    //   {\n\t\t *    //      \"engine\": {value},\n\t\t *    //      \"browser\": {value},\n\t\t *    //      \"platform\": {value},\n\t\t *    //      \"version\": {value},\n\t\t *    //      \"grade\": {value}\n\t\t *    //   }\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"ajaxSource\": \"sources/objects.txt\",\n\t\t *        \"columns\": [\n\t\t *          { \"data\": \"engine\" },\n\t\t *          { \"data\": \"browser\" },\n\t\t *          { \"data\": \"platform\" },\n\t\t *          { \"data\": \"version\" },\n\t\t *          { \"data\": \"grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Read information from deeply nested objects\n\t\t *    // JSON structure for each row:\n\t\t *    //   {\n\t\t *    //      \"engine\": {value},\n\t\t *    //      \"browser\": {value},\n\t\t *    //      \"platform\": {\n\t\t *    //         \"inner\": {value}\n\t\t *    //      },\n\t\t *    //      \"details\": [\n\t\t *    //         {value}, {value}\n\t\t *    //      ]\n\t\t *    //   }\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"ajaxSource\": \"sources/deep.txt\",\n\t\t *        \"columns\": [\n\t\t *          { \"data\": \"engine\" },\n\t\t *          { \"data\": \"browser\" },\n\t\t *          { \"data\": \"platform.inner\" },\n\t\t *          { \"data\": \"platform.details.0\" },\n\t\t *          { \"data\": \"platform.details.1\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `data` 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 *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": 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 *  @example\n\t\t *    // Using default content\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": null,\n\t\t *          \"defaultContent\": \"Click to edit\"\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using array notation - outputting a list from an array\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": \"name[, ]\"\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t */\n\t\t\"mData\": null,\n\n\n\t\t/**\n\t\t * This property is the rendering partner to `data` and it is suggested that\n\t\t * when you want to manipulate data for display (including filtering,\n\t\t * sorting etc) without altering the underlying data for the table, use this\n\t\t * property. `render` can be considered to be the the read only companion to\n\t\t * `data` which is read / write (then as such more complex). Like `data`\n\t\t * this option can be given in a number of different ways to effect its\n\t\t * behaviour:\n\t\t *\n\t\t * * `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).\n\t\t * * `string` - read an object property from the data source. There are\n\t\t *   three 'special' options that can be used in the string to alter how\n\t\t *   DataTables reads the data from the source object:\n\t\t *    * `.` - Dotted Javascript notation. Just as you use a `.` in\n\t\t *      Javascript to read from nested objects, so to can the options\n\t\t *      specified in `data`. For example: `browser.version` or\n\t\t *      `browser.name`. If your object parameter name contains a period, use\n\t\t *      `\\\\` to escape it - i.e. `first\\\\.name`.\n\t\t *    * `[]` - Array notation. DataTables can automatically combine data\n\t\t *      from and array source, joining the data with the characters provided\n\t\t *      between the two brackets. For example: `name[, ]` would provide a\n\t\t *      comma-space separated list from the source array. If no characters\n\t\t *      are provided between the brackets, the original array source is\n\t\t *      returned.\n\t\t *    * `()` - Function notation. Adding `()` to the end of a parameter will\n\t\t *      execute a function of the name given. For example: `browser()` for a\n\t\t *      simple function on the data source, `browser.version()` for a\n\t\t *      function in a nested property or even `browser().version` to get an\n\t\t *      object property if the function called returns an object.\n\t\t * * `object` - use different data for the different data types requested by\n\t\t *   DataTables ('filter', 'display', 'type' or 'sort'). The property names\n\t\t *   of the object is the data type the property refers to and the value can\n\t\t *   defined using an integer, string or function using the same rules as\n\t\t *   `render` normally does. Note that an `_` option _must_ be specified.\n\t\t *   This is the default value to use if you haven't specified a value for\n\t\t *   the data type requested by DataTables.\n\t\t * * `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 *    * Parameters:\n\t\t *      * {array|object} The data source for the row (based on `data`)\n\t\t *      * {string} The type call data requested - this will be 'filter',\n\t\t *        'display', 'type' or 'sort'.\n\t\t *      * {array|object} The full data source for the row (not based on\n\t\t *        `data`)\n\t\t *    * Return:\n\t\t *      * The return value from the function is what will be used for the\n\t\t *        data requested.\n\t\t *\n\t\t *  @type string|int|function|object|null\n\t\t *  @default null Use the data source value.\n\t\t *\n\t\t *  @name DataTable.defaults.column.render\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 *      $('#example').dataTable( {\n\t\t *        \"ajaxSource\": \"sources/deep.txt\",\n\t\t *        \"columns\": [\n\t\t *          { \"data\": \"engine\" },\n\t\t *          { \"data\": \"browser\" },\n\t\t *          {\n\t\t *            \"data\": \"platform\",\n\t\t *            \"render\": \"[, ].name\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Execute a function to obtain data\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": null, // Use the full data source object for the renderer's source\n\t\t *          \"render\": \"browserName()\"\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // As an object, extracting different data for the different types\n\t\t *    // This would be used with a data source such as:\n\t\t *    //   { \"phone\": 5552368, \"phone_filter\": \"5552368 555-2368\", \"phone_display\": \"555-2368\" }\n\t\t *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`\n\t\t *    // (which has both forms) is used for filtering for if a user inputs either format, while\n\t\t *    // the formatted phone number is the one that is shown in the table.\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": null, // Use the full data source object for the renderer's source\n\t\t *          \"render\": {\n\t\t *            \"_\": \"phone\",\n\t\t *            \"filter\": \"phone_filter\",\n\t\t *            \"display\": \"phone_display\"\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 *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"data\": \"download_link\",\n\t\t *          \"render\": 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\n\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 *\n\t\t *  @name DataTable.defaults.column.cellType\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 *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [ {\n\t\t *          \"targets\": [ 0 ],\n\t\t *          \"cellType\": \"th\"\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sCellType\": \"td\",\n\n\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 *\n\t\t *  @name DataTable.defaults.column.class\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"class\": \"my_class\", \"targets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"class\": \"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\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!\n\t\t *  @type string\n\t\t *  @default <i>Empty string<i>\n\t\t *\n\t\t *  @name DataTable.defaults.column.contentPadding\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          {\n\t\t *            \"contentPadding\": \"mmm\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sContentPadding\": \"\",\n\n\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 `data`\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 *  @name DataTable.defaults.column.defaultContent\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          {\n\t\t *            \"data\": null,\n\t\t *            \"defaultContent\": \"Edit\",\n\t\t *            \"targets\": [ -1 ]\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          {\n\t\t *            \"data\": null,\n\t\t *            \"defaultContent\": \"Edit\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sDefaultContent\": null,\n\n\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 *\n\t\t *  @name DataTable.defaults.column.name\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"name\": \"engine\", \"targets\": [ 0 ] },\n\t\t *          { \"name\": \"browser\", \"targets\": [ 1 ] },\n\t\t *          { \"name\": \"platform\", \"targets\": [ 2 ] },\n\t\t *          { \"name\": \"version\", \"targets\": [ 3 ] },\n\t\t *          { \"name\": \"grade\", \"targets\": [ 4 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"name\": \"engine\" },\n\t\t *          { \"name\": \"browser\" },\n\t\t *          { \"name\": \"platform\" },\n\t\t *          { \"name\": \"version\" },\n\t\t *          { \"name\": \"grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sName\": \"\",\n\n\n\t\t/**\n\t\t * Defines a data source type for the ordering 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 ordering. This allows ordering to occur on user\n\t\t * editable elements such as form inputs.\n\t\t *  @type string\n\t\t *  @default std\n\t\t *\n\t\t *  @name DataTable.defaults.column.orderDataType\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"orderDataType\": \"dom-text\", \"targets\": [ 2, 3 ] },\n\t\t *          { \"type\": \"numeric\", \"targets\": [ 3 ] },\n\t\t *          { \"orderDataType\": \"dom-select\", \"targets\": [ 4 ] },\n\t\t *          { \"orderDataType\": \"dom-checkbox\", \"targets\": [ 5 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          null,\n\t\t *          null,\n\t\t *          { \"orderDataType\": \"dom-text\" },\n\t\t *          { \"orderDataType\": \"dom-text\", \"type\": \"numeric\" },\n\t\t *          { \"orderDataType\": \"dom-select\" },\n\t\t *          { \"orderDataType\": \"dom-checkbox\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sSortDataType\": \"std\",\n\n\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 *\n\t\t *  @name DataTable.defaults.column.title\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"title\": \"My column title\", \"targets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"title\": \"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\n\n\t\t/**\n\t\t * The type allows you to specify how the data for this column will be\n\t\t * ordered. Four types (string, numeric, date and html (which will strip\n\t\t * HTML tags before ordering)) are currently available. Note that only date\n\t\t * formats understood by Javascript's Date() object will be accepted as type\n\t\t * date. For example: \"Mar 26, 2008 5:03 PM\". May take the values: 'string',\n\t\t * 'numeric', 'date' or 'html' (by default). Further types can be adding\n\t\t * through plug-ins.\n\t\t *  @type string\n\t\t *  @default null <i>Auto-detected from raw data</i>\n\t\t *\n\t\t *  @name DataTable.defaults.column.type\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"type\": \"html\", \"targets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"type\": \"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\n\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 applies '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 *\n\t\t *  @name DataTable.defaults.column.width\n\t\t *  @dtopt Columns\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columnDefs`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columnDefs\": [\n\t\t *          { \"width\": \"20%\", \"targets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Using `columns`\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"columns\": [\n\t\t *          { \"width\": \"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\n\t_fnHungarianMap( DataTable.defaults.column );\n\n\n\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\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\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\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\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\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\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\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\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\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\n\t\t\t/**\n\t\t\t * Multi-column sorting\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\"bSortMulti\": null,\n\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\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\n\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 * 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\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\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\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\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\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\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\n\t\t\t/**\n\t\t\t * Determine if the vertical scrollbar is on the right or left of the\n\t\t\t * scrolling container - needed for rtl language layout, although not\n\t\t\t * all browsers move the scrollbar (Safari).\n\t\t\t *  @type boolean\n\t\t\t *  @default false\n\t\t\t */\n\t\t\t\"bScrollbarLeft\": false\n\t\t},\n\n\n\t\t\"ajax\": null,\n\n\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\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\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\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\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\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\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\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\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\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 * </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\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\n\t\t *  @default []\n\t\t */\n\t\t\"aaSortingFixed\": [],\n\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\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\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\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\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\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\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\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\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\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\n\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\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\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\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\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\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\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\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\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\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\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\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\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\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\n\t\t/**\n\t\t * The state duration (for `stateSave`) 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\"iStateDuration\": 0,\n\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\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\n\t\t/**\n\t\t * State that was loaded. Useful for back reference\n\t\t *  @type object\n\t\t *  @default null\n\t\t */\n\t\t\"oLoadedState\": null,\n\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\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\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\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\n\t\t/**\n\t\t * JSON returned from the server in the last Ajax request\n\t\t *  @type object\n\t\t *  @default undefined\n\t\t */\n\t\t\"json\": undefined,\n\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\n\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\treturn _fnDataSource( this ) == 'ssp' ?\n\t\t\t\tthis._iRecordsTotal * 1 :\n\t\t\t\tthis.aiDisplayMaster.length;\n\t\t},\n\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\treturn _fnDataSource( this ) == 'ssp' ?\n\t\t\t\tthis._iRecordsDisplay * 1 :\n\t\t\t\tthis.aiDisplay.length;\n\t\t},\n\n\t\t/**\n\t\t * Get the display end point - aiDisplay index\n\t\t *  @type function\n\t\t */\n\t\t\"fnDisplayEnd\": function ()\n\t\t{\n\t\t\tvar\n\t\t\t\tlen      = this._iDisplayLength,\n\t\t\t\tstart    = this._iDisplayStart,\n\t\t\t\tcalc     = start + len,\n\t\t\t\trecords  = this.aiDisplay.length,\n\t\t\t\tfeatures = this.oFeatures,\n\t\t\t\tpaginate = features.bPaginate;\n\n\t\t\tif ( features.bServerSide ) {\n\t\t\t\treturn paginate === false || len === -1 ?\n\t\t\t\t\tstart + records :\n\t\t\t\t\tMath.min( start+len, this._iRecordsDisplay );\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn ! paginate || calc>records || len===-1 ?\n\t\t\t\t\trecords :\n\t\t\t\t\tcalc;\n\t\t\t}\n\t\t},\n\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\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\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\n\t\t/**\n\t\t * DIV container for the footer scrolling table if scrolling\n\t\t */\n\t\t\"nScrollHead\": null,\n\n\t\t/**\n\t\t * DIV container for the footer scrolling table if scrolling\n\t\t */\n\t\t\"nScrollFoot\": null,\n\n\t\t/**\n\t\t * Last applied sort\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aLastSort\": [],\n\n\t\t/**\n\t\t * Stored plug-in instances\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\t\"oPlugins\": {}\n\t};\n\n\t/**\n\t * Extension object for DataTables that is used to provide all extension\n\t * options.\n\t *\n\t * Note that the `DataTable.ext` object is available through\n\t * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is\n\t * also aliased to `jQuery.fn.dataTableExt` for historic reasons.\n\t *  @namespace\n\t *  @extends DataTable.models.ext\n\t */\n\n\n\t/**\n\t * DataTables extensions\n\t *\n\t * This namespace acts as a collection area for plug-ins that can be used to\n\t * extend DataTables capabilities. Indeed many of the build in methods\n\t * use this method to provide their own capabilities (sorting methods for\n\t * example).\n\t *\n\t * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy\n\t * reasons\n\t *\n\t *  @namespace\n\t */\n\tDataTable.ext = _ext = {\n\t\t/**\n\t\t * Element class names\n\t\t *\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\tclasses: {},\n\n\n\t\t/**\n\t\t * Error reporting.\n\t\t *\n\t\t * How should DataTables report an error. Can take the value 'alert' or\n\t\t * 'throw'\n\t\t *\n\t\t *  @type string\n\t\t *  @default alert\n\t\t */\n\t\terrMode: \"alert\",\n\n\n\t\t/**\n\t\t * Feature plug-ins.\n\t\t *\n\t\t * 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 then available for\n\t\t * use through the `dom` initialisation option.\n\t\t *\n\t\t * Each feature plug-in is described by an object which must have the\n\t\t * following properties:\n\t\t *\n\t\t * * `fnInit` - function that is used to initialise the plug-in,\n\t\t * * `cFeature` - a character so the feature can be enabled by the `dom`\n\t\t *   instillation option. This is case sensitive.\n\t\t *\n\t\t * The `fnInit` function has the following input parameters:\n\t\t *\n\t\t * 1. `{object}` DataTables settings object: see\n\t\t *    {@link DataTable.models.oSettings}\n\t\t *\n\t\t * And the following return is expected:\n\t\t *\n\t\t * * {node|null} The element which contains your feature. Note that the\n\t\t *   return may also be void if your plug-in does not require to inject any\n\t\t *   DOM elements into DataTables control (`dom`) - for example this might\n\t\t *   be useful when developing a plug-in which allows table control via\n\t\t *   keyboard entry\n\t\t *\n\t\t *  @type array\n\t\t *\n\t\t *  @example\n\t\t *    $.fn.dataTable.ext.features.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 *    } );\n\t\t */\n\t\tfeature: [],\n\n\n\t\t/**\n\t\t * Row searching.\n\t\t *\n\t\t * This method of searching is complimentary to the default type based\n\t\t * searching, and a lot more comprehensive as it allows you complete control\n\t\t * over the searching logic. Each element in this array is a function\n\t\t * (parameters described below) that is called for every row in the table,\n\t\t * and your logic decides if it should be included in the searching data set\n\t\t * or not.\n\t\t *\n\t\t * Searching functions have the following input parameters:\n\t\t *\n\t\t * 1. `{object}` DataTables settings object: see\n\t\t *    {@link DataTable.models.oSettings}\n\t\t * 2. `{array|object}` Data for the row to be processed (same as the\n\t\t *    original format that was passed in as the data source, or an array\n\t\t *    from a DOM data source\n\t\t * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which\n\t\t *    can be useful to retrieve the `TR` element if you need DOM interaction.\n\t\t *\n\t\t * And the following return is expected:\n\t\t *\n\t\t * * {boolean} Include the row in the searched result set (true) or not\n\t\t *   (false)\n\t\t *\n\t\t * Note that as with the main search ability in DataTables, technically this\n\t\t * is \"filtering\", since it is subtractive. However, for consistency in\n\t\t * naming we call it searching here.\n\t\t *\n\t\t *  @type array\n\t\t *  @default []\n\t\t *\n\t\t *  @example\n\t\t *    // The following example shows custom search being applied to the\n\t\t *    // fourth column (i.e. the data[3] index) based on two input values\n\t\t *    // from the end-user, matching the data in a certain range.\n\t\t *    $.fn.dataTable.ext.search.push(\n\t\t *      function( settings, data, dataIndex ) {\n\t\t *        var min = document.getElementById('min').value * 1;\n\t\t *        var max = document.getElementById('max').value * 1;\n\t\t *        var version = data[3] == \"-\" ? 0 : data[3]*1;\n\t\t *\n\t\t *        if ( min == \"\" && max == \"\" ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( min == \"\" && version < max ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( min < version && \"\" == max ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( min < version && version < max ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        return false;\n\t\t *      }\n\t\t *    );\n\t\t */\n\t\tsearch: [],\n\n\n\t\t/**\n\t\t * Internal functions, exposed for used in plug-ins.\n\t\t *\n\t\t * Please note that you should not need to use the internal methods for\n\t\t * anything other than a plug-in (and even then, try to avoid if possible).\n\t\t * The internal function may change between releases.\n\t\t *\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\tinternal: {},\n\n\n\t\t/**\n\t\t * Legacy configuration options. Enable and disable legacy options that\n\t\t * are available in DataTables.\n\t\t *\n\t\t *  @type object\n\t\t */\n\t\tlegacy: {\n\t\t\t/**\n\t\t\t * Enable / disable DataTables 1.9 compatible server-side processing\n\t\t\t * requests\n\t\t\t *\n\t\t\t *  @type boolean\n\t\t\t *  @default false\n\t\t\t */\n\t\t\tajax: false\n\t\t},\n\n\n\t\t/**\n\t\t * Pagination plug-in methods.\n\t\t *\n\t\t * Each entry in this object is a function and defines which buttons should\n\t\t * be shown by the pagination rendering method that is used for the table:\n\t\t * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the\n\t\t * buttons are displayed in the document, while the functions here tell it\n\t\t * what buttons to display. This is done by returning an array of button\n\t\t * descriptions (what each button will do).\n\t\t *\n\t\t * Pagination types (the four built in options and any additional plug-in\n\t\t * options defined here) can be used through the `paginationType`\n\t\t * initialisation parameter.\n\t\t *\n\t\t * The functions defined take two parameters:\n\t\t *\n\t\t * 1. `{int} page` The current page index\n\t\t * 2. `{int} pages` The number of pages in the table\n\t\t *\n\t\t * Each function is expected to return an array where each element of the\n\t\t * array can be one of:\n\t\t *\n\t\t * * `first` - Jump to first page when activated\n\t\t * * `last` - Jump to last page when activated\n\t\t * * `previous` - Show previous page when activated\n\t\t * * `next` - Show next page when activated\n\t\t * * `{int}` - Show page of the index given\n\t\t * * `{array}` - A nested array containing the above elements to add a\n\t\t *   containing 'DIV' element (might be useful for styling).\n\t\t *\n\t\t * Note that DataTables v1.9- used this object slightly differently whereby\n\t\t * an object with two functions would be defined for each plug-in. That\n\t\t * ability is still supported by DataTables 1.10+ to provide backwards\n\t\t * compatibility, but this option of use is now decremented and no longer\n\t\t * documented in DataTables 1.10+.\n\t\t *\n\t\t *  @type object\n\t\t *  @default {}\n\t\t *\n\t\t *  @example\n\t\t *    // Show previous, next and current page buttons only\n\t\t *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {\n\t\t *      return [ 'previous', page, 'next' ];\n\t\t *    };\n\t\t */\n\t\tpager: {},\n\n\n\t\trenderer: {\n\t\t\tpageButton: {},\n\t\t\theader: {}\n\t\t},\n\n\n\t\t/**\n\t\t * Ordering plug-ins - custom data source\n\t\t *\n\t\t * The extension options for ordering of data available here is complimentary\n\t\t * to the default type based ordering that DataTables typically uses. It\n\t\t * allows much greater control over the the data that is being used to\n\t\t * order a column, but is necessarily therefore more complex.\n\t\t *\n\t\t * This type of ordering is useful if you want to do ordering based on data\n\t\t * live from the DOM (for example the contents of an 'input' element) rather\n\t\t * than just the static string that DataTables knows of.\n\t\t *\n\t\t * The way these plug-ins work is that you create an array of the values you\n\t\t * wish to be ordering for the column in question and then return that\n\t\t * array. The data in the array much be in the index order of the rows in\n\t\t * the table (not the currently ordering order!). Which order data gathering\n\t\t * function is run here depends on the `dt-init columns.orderDataType`\n\t\t * parameter that is used for the column (if any).\n\t\t *\n\t\t * The functions defined take two parameters:\n\t\t *\n\t\t * 1. `{object}` DataTables settings object: see\n\t\t *    {@link DataTable.models.oSettings}\n\t\t * 2. `{int}` Target column index\n\t\t *\n\t\t * Each function is expected to return an array:\n\t\t *\n\t\t * * `{array}` Data for the column to be ordering upon\n\t\t *\n\t\t *  @type array\n\t\t *\n\t\t *  @example\n\t\t *    // Ordering using `input` node values\n\t\t *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )\n\t\t *    {\n\t\t *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {\n\t\t *        return $('input', td).val();\n\t\t *      } );\n\t\t *    }\n\t\t */\n\t\torder: {},\n\n\n\t\t/**\n\t\t * Type based plug-ins.\n\t\t *\n\t\t * Each column in DataTables has a type assigned to it, either by automatic\n\t\t * detection or by direct assignment using the `type` option for the column.\n\t\t * The type of a column will effect how it is ordering and search (plug-ins\n\t\t * can also make use of the column type if required).\n\t\t *\n\t\t * @namespace\n\t\t */\n\t\ttype: {\n\t\t\t/**\n\t\t\t * Type detection functions.\n\t\t\t *\n\t\t\t * The functions defined in this object are used to automatically detect\n\t\t\t * a column's type, making initialisation of DataTables super easy, even\n\t\t\t * when complex data is in the table.\n\t\t\t *\n\t\t\t * The functions defined take a single parameter:\n\t\t\t *\n\t\t     *  1. `{*}` Data from the column cell to be analysed\n\t\t\t *\n\t\t\t * Each function is expected to return:\n\t\t\t *\n\t\t\t * * `{string|null}` Data type detected, or null if unknown (and thus\n\t\t\t *   pass it on to the other type detection functions.\n\t\t\t *\n\t\t\t *  @type array\n\t\t\t *\n\t\t\t *  @example\n\t\t\t *    // Currency type detection plug-in:\n\t\t\t *    $.fn.dataTable.ext.type.detect.push(\n\t\t\t *      function ( data ) {\n\t\t\t *        // Check the numeric part\n\t\t\t *        if ( ! $.isNumeric( data.substring(1) ) ) {\n\t\t\t *          return null;\n\t\t\t *        }\n\t\t\t *\n\t\t\t *        // Check prefixed by currency\n\t\t\t *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {\n\t\t\t *          return 'currency';\n\t\t\t *        }\n\t\t\t *        return null;\n\t\t\t *      }\n\t\t\t *    );\n\t\t\t */\n\t\t\tdetect: [],\n\n\n\t\t\t/**\n\t\t\t * Type based search formatting.\n\t\t\t *\n\t\t\t * The type based searching functions can be used to pre-format the\n\t\t\t * data to be search on. For example, it can be used to strip HTML\n\t\t\t * tags or to de-format telephone numbers for numeric only searching.\n\t\t\t *\n\t\t\t * Note that is a search is not defined for a column of a given type,\n\t\t\t * no search formatting will be performed.\n\t\t\t *\n\t\t\t * Pre-processing of searching data plug-ins - When you assign the sType\n\t\t\t * for a column (or have it automatically detected for you by DataTables\n\t\t\t * or a type detection plug-in), you will typically be using this for\n\t\t\t * custom sorting, but it can also be used to provide custom searching\n\t\t\t * by allowing you to pre-processing the data and returning the data in\n\t\t\t * the format that should be searched upon. This is done by adding\n\t\t\t * functions this object with a parameter name which matches the sType\n\t\t\t * for that target column. This is the corollary of <i>afnSortData</i>\n\t\t\t * for searching data.\n\t\t\t *\n\t\t\t * The functions defined take a single parameter:\n\t\t\t *\n\t\t     *  1. `{*}` Data from the column cell to be prepared for searching\n\t\t\t *\n\t\t\t * Each function is expected to return:\n\t\t\t *\n\t\t\t * * `{string|null}` Formatted string that will be used for the searching.\n\t\t\t *\n\t\t\t *  @type object\n\t\t\t *  @default {}\n\t\t\t *\n\t\t\t *  @example\n\t\t\t *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {\n\t\t\t *      return d.replace(/\\n/g,\" \").replace( /<.*?>/g, \"\" );\n\t\t\t *    }\n\t\t\t */\n\t\t\tsearch: {},\n\n\n\t\t\t/**\n\t\t\t * Type based ordering.\n\t\t\t *\n\t\t\t * The column type tells DataTables what ordering to apply to the table\n\t\t\t * when a column is sorted upon. The order for each type that is defined,\n\t\t\t * is defined by the functions available in this object.\n\t\t\t *\n\t\t\t * Each ordering option can be described by three properties added to\n\t\t\t * this object:\n\t\t\t *\n\t\t\t * * `{type}-pre` - Pre-formatting function\n\t\t\t * * `{type}-asc` - Ascending order function\n\t\t\t * * `{type}-desc` - Descending order function\n\t\t\t *\n\t\t\t * All three can be used together, only `{type}-pre` or only\n\t\t\t * `{type}-asc` and `{type}-desc` together. It is generally recommended\n\t\t\t * that only `{type}-pre` is used, as this provides the optimal\n\t\t\t * implementation in terms of speed, although the others are provided\n\t\t\t * for compatibility with existing Javascript sort functions.\n\t\t\t *\n\t\t\t * `{type}-pre`: Functions defined take a single parameter:\n\t\t\t *\n\t\t     *  1. `{*}` Data from the column cell to be prepared for ordering\n\t\t\t *\n\t\t\t * And return:\n\t\t\t *\n\t\t\t * * `{*}` Data to be sorted upon\n\t\t\t *\n\t\t\t * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort\n\t\t\t * functions, taking two parameters:\n\t\t\t *\n\t\t     *  1. `{*}` Data to compare to the second parameter\n\t\t     *  2. `{*}` Data to compare to the first parameter\n\t\t\t *\n\t\t\t * And returning:\n\t\t\t *\n\t\t\t * * `{*}` Ordering match: <0 if first parameter should be sorted lower\n\t\t\t *   than the second parameter, ===0 if the two parameters are equal and\n\t\t\t *   >0 if the first parameter should be sorted height than the second\n\t\t\t *   parameter.\n\t\t\t *\n\t\t\t *  @type object\n\t\t\t *  @default {}\n\t\t\t *\n\t\t\t *  @example\n\t\t\t *    // Numeric ordering of formatted numbers with a pre-formatter\n\t\t\t *    $.extend( $.fn.dataTable.ext.type.order, {\n\t\t\t *      \"string-pre\": function(x) {\n\t\t\t *        a = (a === \"-\" || a === \"\") ? 0 : a.replace( /[^\\d\\-\\.]/g, \"\" );\n\t\t\t *        return parseFloat( a );\n\t\t\t *      }\n\t\t\t *    } );\n\t\t\t *\n\t\t\t *  @example\n\t\t\t *    // Case-sensitive string ordering, with no pre-formatting method\n\t\t\t *    $.extend( $.fn.dataTable.ext.order, {\n\t\t\t *      \"string-case-asc\": function(x,y) {\n\t\t\t *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));\n\t\t\t *      },\n\t\t\t *      \"string-case-desc\": function(x,y) {\n\t\t\t *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));\n\t\t\t *      }\n\t\t\t *    } );\n\t\t\t */\n\t\t\torder: {}\n\t\t},\n\n\t\t/**\n\t\t * Unique DataTables instance counter\n\t\t *\n\t\t * @type int\n\t\t * @private\n\t\t */\n\t\t_unique: 0,\n\n\n\t\t//\n\t\t// Depreciated\n\t\t// The following properties are retained for backwards compatiblity only.\n\t\t// The should not be used in new projects and will be removed in a future\n\t\t// version\n\t\t//\n\n\t\t/**\n\t\t * Version check function.\n\t\t *  @type function\n\t\t *  @depreciated Since 1.10\n\t\t */\n\t\tfnVersionCheck: DataTable.fnVersionCheck,\n\n\n\t\t/**\n\t\t * Index for what 'this' index API functions should use\n\t\t *  @type int\n\t\t *  @deprecated Since v1.10\n\t\t */\n\t\tiApiIndex: 0,\n\n\n\t\t/**\n\t\t * jQuery UI class container\n\t\t *  @type object\n\t\t *  @deprecated Since v1.10\n\t\t */\n\t\toJUIClasses: {},\n\n\n\t\t/**\n\t\t * Software version\n\t\t *  @type string\n\t\t *  @deprecated Since v1.10\n\t\t */\n\t\tsVersion: DataTable.version\n\t};\n\n\n\t//\n\t// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts\n\t//\n\t$.extend( _ext, {\n\t\tafnFiltering: _ext.filter,\n\t\taTypes:       _ext.type.detect,\n\t\tofnSearch:    _ext.type.search,\n\t\toSort:        _ext.type.order,\n\t\tafnSortData:  _ext.order,\n\t\taoFeatures:   _ext.feature,\n\t\toApi:         _ext.internal,\n\t\toStdClasses:  _ext.classes,\n\t\toPagination:  _ext.pager\n\t} );\n\n\n\t$.extend( DataTable.ext.classes, {\n\t\t\"sTable\": \"dataTable\",\n\t\t\"sNoFooter\": \"no-footer\",\n\n\t\t/* Paging buttons */\n\t\t\"sPageButton\": \"paginate_button\",\n\t\t\"sPageButtonActive\": \"current\",\n\t\t\"sPageButtonDisabled\": \"disabled\",\n\n\t\t/* Striping classes */\n\t\t\"sStripeOdd\": \"odd\",\n\t\t\"sStripeEven\": \"even\",\n\n\t\t/* Empty row */\n\t\t\"sRowEmpty\": \"dataTables_empty\",\n\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\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\n\t\t/* Filtering */\n\t\t\"sFilterInput\": \"\",\n\n\t\t/* Page length */\n\t\t\"sLengthSelect\": \"\",\n\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\n\t\t/* Misc */\n\t\t\"sHeaderTH\": \"\",\n\t\t\"sFooterTH\": \"\",\n\n\t\t// Deprecated\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\"sJUIHeader\": \"\",\n\t\t\"sJUIFooter\": \"\"\n\t} );\n\n\n\t(function() {\n\n\t// Reused strings for better compression. Closure compiler appears to have a\n\t// weird edge case where it is trying to expand strings rather than use the\n\t// variable version. This results in about 200 bytes being added, for very\n\t// little preference benefit since it this run on script load only.\n\tvar _empty = '';\n\t_empty = '';\n\n\tvar _stateDefault = _empty + 'ui-state-default';\n\tvar _sortIcon     = _empty + 'css_right ui-icon ui-icon-';\n\tvar _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';\n\n\t$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {\n\t\t/* Full numbers paging buttons */\n\t\t\"sPageButton\":         \"fg-button ui-button \"+_stateDefault,\n\t\t\"sPageButtonActive\":   \"ui-state-disabled\",\n\t\t\"sPageButtonDisabled\": \"ui-state-disabled\",\n\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\n\t\t/* Sorting */\n\t\t\"sSortAsc\":            _stateDefault+\" sorting_asc\",\n\t\t\"sSortDesc\":           _stateDefault+\" sorting_desc\",\n\t\t\"sSortable\":           _stateDefault+\" sorting\",\n\t\t\"sSortableAsc\":        _stateDefault+\" sorting_asc_disabled\",\n\t\t\"sSortableDesc\":       _stateDefault+\" sorting_desc_disabled\",\n\t\t\"sSortableNone\":       _stateDefault+\" sorting_disabled\",\n\t\t\"sSortJUIAsc\":         _sortIcon+\"triangle-1-n\",\n\t\t\"sSortJUIDesc\":        _sortIcon+\"triangle-1-s\",\n\t\t\"sSortJUI\":            _sortIcon+\"carat-2-n-s\",\n\t\t\"sSortJUIAscAllowed\":  _sortIcon+\"carat-1-n\",\n\t\t\"sSortJUIDescAllowed\": _sortIcon+\"carat-1-s\",\n\t\t\"sSortJUIWrapper\":     \"DataTables_sort_wrapper\",\n\t\t\"sSortIcon\":           \"DataTables_sort_icon\",\n\n\t\t/* Scrolling */\n\t\t\"sScrollHead\": \"dataTables_scrollHead \"+_stateDefault,\n\t\t\"sScrollFoot\": \"dataTables_scrollFoot \"+_stateDefault,\n\n\t\t/* Misc */\n\t\t\"sHeaderTH\":  _stateDefault,\n\t\t\"sFooterTH\":  _stateDefault,\n\t\t\"sJUIHeader\": _headerFooter+\" ui-corner-tl ui-corner-tr\",\n\t\t\"sJUIFooter\": _headerFooter+\" ui-corner-bl ui-corner-br\"\n\t} );\n\n\t}());\n\n\n\n\tvar extPagination = DataTable.ext.pager;\n\n\tfunction _numbers ( page, pages ) {\n\t\tvar\n\t\t\tnumbers = [],\n\t\t\tbuttons = extPagination.numbers_length,\n\t\t\thalf = Math.floor( buttons / 2 ),\n\t\t\ti = 1;\n\n\t\tif ( pages <= buttons ) {\n\t\t\tnumbers = _range( 0, pages );\n\t\t}\n\t\telse if ( page <= half ) {\n\t\t\tnumbers = _range( 0, buttons-2 );\n\t\t\tnumbers.push( 'ellipsis' );\n\t\t\tnumbers.push( pages-1 );\n\t\t}\n\t\telse if ( page >= pages - 1 - half ) {\n\t\t\tnumbers = _range( pages-(buttons-2), pages );\n\t\t\tnumbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6\n\t\t\tnumbers.splice( 0, 0, 0 );\n\t\t}\n\t\telse {\n\t\t\tnumbers = _range( page-1, page+2 );\n\t\t\tnumbers.push( 'ellipsis' );\n\t\t\tnumbers.push( pages-1 );\n\t\t\tnumbers.splice( 0, 0, 'ellipsis' );\n\t\t\tnumbers.splice( 0, 0, 0 );\n\t\t}\n\n\t\tnumbers.DT_el = 'span';\n\t\treturn numbers;\n\t}\n\n\n\t$.extend( extPagination, {\n\t\tsimple: function ( page, pages ) {\n\t\t\treturn [ 'previous', 'next' ];\n\t\t},\n\n\t\tfull: function ( page, pages ) {\n\t\t\treturn [  'first', 'previous', 'next', 'last' ];\n\t\t},\n\n\t\tsimple_numbers: function ( page, pages ) {\n\t\t\treturn [ 'previous', _numbers(page, pages), 'next' ];\n\t\t},\n\n\t\tfull_numbers: function ( page, pages ) {\n\t\t\treturn [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];\n\t\t},\n\n\t\t// For testing and plug-ins to use\n\t\t_numbers: _numbers,\n\t\tnumbers_length: 7\n\t} );\n\n\n\t$.extend( true, DataTable.ext.renderer, {\n\t\tpageButton: {\n\t\t\t_: function ( settings, host, idx, buttons, page, pages ) {\n\t\t\t\tvar classes = settings.oClasses;\n\t\t\t\tvar lang = settings.oLanguage.oPaginate;\n\t\t\t\tvar btnDisplay, btnClass;\n\n\t\t\t\tvar attach = function( container, buttons ) {\n\t\t\t\t\tvar i, ien, node, button;\n\t\t\t\t\tvar clickHandler = function ( e ) {\n\t\t\t\t\t\t_fnPageChange( settings, e.data.action, true );\n\t\t\t\t\t};\n\n\t\t\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\t\t\tbutton = buttons[i];\n\n\t\t\t\t\t\tif ( $.isArray( button ) ) {\n\t\t\t\t\t\t\tvar inner = $( '<'+(button.DT_el || 'div')+'/>' )\n\t\t\t\t\t\t\t\t.appendTo( container );\n\t\t\t\t\t\t\tattach( inner, button );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbtnDisplay = '';\n\t\t\t\t\t\t\tbtnClass = '';\n\n\t\t\t\t\t\t\tswitch ( button ) {\n\t\t\t\t\t\t\t\tcase 'ellipsis':\n\t\t\t\t\t\t\t\t\tcontainer.append('<span>&hellip;</span>');\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'first':\n\t\t\t\t\t\t\t\t\tbtnDisplay = lang.sFirst;\n\t\t\t\t\t\t\t\t\tbtnClass = button + (page > 0 ?\n\t\t\t\t\t\t\t\t\t\t'' : ' '+classes.sPageButtonDisabled);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'previous':\n\t\t\t\t\t\t\t\t\tbtnDisplay = lang.sPrevious;\n\t\t\t\t\t\t\t\t\tbtnClass = button + (page > 0 ?\n\t\t\t\t\t\t\t\t\t\t'' : ' '+classes.sPageButtonDisabled);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'next':\n\t\t\t\t\t\t\t\t\tbtnDisplay = lang.sNext;\n\t\t\t\t\t\t\t\t\tbtnClass = button + (page < pages-1 ?\n\t\t\t\t\t\t\t\t\t\t'' : ' '+classes.sPageButtonDisabled);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'last':\n\t\t\t\t\t\t\t\t\tbtnDisplay = lang.sLast;\n\t\t\t\t\t\t\t\t\tbtnClass = button + (page < pages-1 ?\n\t\t\t\t\t\t\t\t\t\t'' : ' '+classes.sPageButtonDisabled);\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tbtnDisplay = button + 1;\n\t\t\t\t\t\t\t\t\tbtnClass = page === button ?\n\t\t\t\t\t\t\t\t\t\tclasses.sPageButtonActive : '';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( btnDisplay ) {\n\t\t\t\t\t\t\t\tnode = $('<a>', {\n\t\t\t\t\t\t\t\t\t\t'class': classes.sPageButton+' '+btnClass,\n\t\t\t\t\t\t\t\t\t\t'aria-controls': settings.sTableId,\n\t\t\t\t\t\t\t\t\t\t'tabindex': settings.iTabIndex,\n\t\t\t\t\t\t\t\t\t\t'id': idx === 0 && typeof button === 'string' ?\n\t\t\t\t\t\t\t\t\t\t\tsettings.sTableId +'_'+ button :\n\t\t\t\t\t\t\t\t\t\t\tnull\n\t\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t\t\t.html( btnDisplay )\n\t\t\t\t\t\t\t\t\t.appendTo( container );\n\n\t\t\t\t\t\t\t\t_fnBindAction(\n\t\t\t\t\t\t\t\t\tnode, {action: button}, clickHandler\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\tattach( $(host).empty(), buttons );\n\t\t\t}\n\t\t}\n\t} );\n\n\n\n\tvar __numericReplace = function ( d, re1, re2 ) {\n\t\tif ( !d || d === '-' ) {\n\t\t\treturn -Infinity;\n\t\t}\n\n\t\tif ( d.replace ) {\n\t\t\tif ( re1 ) {\n\t\t\t\td = d.replace( re1, '' );\n\t\t\t}\n\n\t\t\tif ( re2 ) {\n\t\t\t\td = d.replace( re2, '' );\n\t\t\t}\n\t\t}\n\n\t\treturn d * 1;\n\t};\n\n\n\t$.extend( DataTable.ext.type.order, {\n\t\t// Dates\n\t\t\"date-pre\": function ( d )\n\t\t{\n\t\t\treturn Date.parse( d ) || 0;\n\t\t},\n\n\t\t// Plain numbers\n\t\t\"numeric-pre\": function ( d )\n\t\t{\n\t\t\treturn __numericReplace( d );\n\t\t},\n\n\t\t// Formatted numbers\n\t\t\"numeric-fmt-pre\": function ( d )\n\t\t{\n\t\t\treturn __numericReplace( d, _re_formatted_numeric );\n\t\t},\n\n\t\t// HTML numeric\n\t\t\"html-numeric-pre\": function ( d )\n\t\t{\n\t\t\treturn __numericReplace( d, _re_html );\n\t\t},\n\n\t\t// HTML numeric, formatted\n\t\t\"html-numeric-fmt-pre\": function ( d )\n\t\t{\n\t\t\treturn __numericReplace( d, _re_html, _re_formatted_numeric );\n\t\t},\n\n\t\t// html\n\t\t\"html-pre\": function ( a )\n\t\t{\n\t\t\treturn a.replace ?\n\t\t\t\ta.replace( /<.*?>/g, \"\" ).toLowerCase() :\n\t\t\t\ta+'';\n\t\t},\n\n\t\t// string\n\t\t\"string-pre\": function ( a )\n\t\t{\n\t\t\treturn typeof a === 'string' ?\n\t\t\t\ta.toLowerCase() :\n\t\t\t\t! a || ! a.toString ?\n\t\t\t\t\t'' :\n\t\t\t\t\ta.toString();\n\t\t},\n\n\t\t// string-asc and -desc are retained only for compatibility with the old\n\t\t// sort methods\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\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} );\n\n\n\t// Built in type detection. See model.ext.aTypes for information about\n\t// what is required from this methods.\n\t$.extend( DataTable.ext.type.detect, [\n\t\t// Plain numbers - first since V8 detects some plain numbers as dates\n\t\t// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).\n\t\tfunction ( d )\n\t\t{\n\t\t\treturn _isNumber( d ) ? 'numeric' : null;\n\t\t},\n\n\t\t// Dates (only those recognised by the browser's Date.parse)\n\t\tfunction ( d )\n\t\t{\n\t\t\t// V8 will remove any unknown characters at the start of the expression,\n\t\t\t// leading to false matches such as `$245.12` being a valid date. See\n\t\t\t// forum thread 18941 for detail.\n\t\t\tif ( d && ! _re_date_start.test(d) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tvar parsed = Date.parse(d);\n\t\t\treturn (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;\n\t\t},\n\n\t\t// Formatted numbers\n\t\tfunction ( d )\n\t\t{\n\t\t\treturn _isNumber( d, true ) ? 'numeric-fmt' : null;\n\t\t},\n\n\t\t// HTML numeric\n\t\tfunction ( d )\n\t\t{\n\t\t\treturn _htmlNumeric( d ) ? 'html-numeric' : null;\n\t\t},\n\n\t\t// HTML numeric, formatted\n\t\tfunction ( d )\n\t\t{\n\t\t\treturn _htmlNumeric( d, true ) ? 'html-numeric-fmt' : null;\n\t\t},\n\n\t\t// HTML (this is strict checking - there much be html)\n\t\tfunction ( d )\n\t\t{\n\t\t\treturn _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?\n\t\t\t\t'html' : null;\n\t\t}\n\t] );\n\n\n\n\t// Filter formatting functions. See model.ext.ofnSearch for information about\n\t// what is required from these methods.\n\n\n\t$.extend( DataTable.ext.type.search, {\n\t\thtml: function ( data ) {\n\t\t\treturn _empty(data) ?\n\t\t\t\t'' :\n\t\t\t\ttypeof data === 'string' ?\n\t\t\t\t\tdata\n\t\t\t\t\t\t.replace( _re_new_lines, \" \" )\n\t\t\t\t\t\t.replace( _re_html, \"\" ) :\n\t\t\t\t\t'';\n\t\t},\n\n\t\tstring: function ( data ) {\n\t\t\treturn _empty(data) ?\n\t\t\t\t'' :\n\t\t\t\ttypeof data === 'string' ?\n\t\t\t\t\tdata.replace( _re_new_lines, \" \" ) :\n\t\t\t\t\tdata;\n\t\t}\n\t} );\n\n\n\n\t$.extend( true, DataTable.ext.renderer, {\n\t\theader: {\n\t\t\t_: function ( settings, cell, column, idx, classes ) {\n\t\t\t\t// No additional mark-up required\n\n\t\t\t\t// Attach a sort listener to update on sort\n\t\t\t\t$(settings.nTable).on( 'order.dt', function ( e, settings, sorting, columns ) {\n\t\t\t\t\tcell\n\t\t\t\t\t\t.removeClass(\n\t\t\t\t\t\t\tcolumn.sSortingClass +' '+\n\t\t\t\t\t\t\tclasses.sSortAsc +' '+\n\t\t\t\t\t\t\tclasses.sSortDesc\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.addClass( columns[ idx ] == 'asc' ?\n\t\t\t\t\t\t\tclasses.sSortAsc : columns[ idx ] == 'desc' ?\n\t\t\t\t\t\t\t\tclasses.sSortDesc :\n\t\t\t\t\t\t\t\tcolumn.sSortingClass\n\t\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t},\n\n\t\t\tjqueryui: function ( settings, cell, column, idx, classes ) {\n\t\t\t\t$('<div/>')\n\t\t\t\t\t.addClass( classes.sSortJUIWrapper )\n\t\t\t\t\t.append( cell.contents() )\n\t\t\t\t\t.append( $('<span/>')\n\t\t\t\t\t\t.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )\n\t\t\t\t\t)\n\t\t\t\t\t.appendTo( cell );\n\n\t\t\t\t// Attach a sort listener to update on sort\n\t\t\t\t$(settings.nTable).on( 'order.dt', function ( e, settings, sorting, columns ) {\n\t\t\t\t\tcell\n\t\t\t\t\t\t.removeClass( classes.sSortAsc +\" \"+classes.sSortDesc )\n\t\t\t\t\t\t.addClass( columns[ idx ] == 'asc' ?\n\t\t\t\t\t\t\tclasses.sSortAsc : columns[ idx ] == 'desc' ?\n\t\t\t\t\t\t\t\tclasses.sSortDesc :\n\t\t\t\t\t\t\t\tcolumn.sSortingClass\n\t\t\t\t\t\t);\n\n\t\t\t\t\tcell\n\t\t\t\t\t\t.find( 'span' )\n\t\t\t\t\t\t.removeClass(\n\t\t\t\t\t\t\tclasses.sSortJUIAsc +\" \"+\n\t\t\t\t\t\t\tclasses.sSortJUIDesc +\" \"+\n\t\t\t\t\t\t\tclasses.sSortJUI +\" \"+\n\t\t\t\t\t\t\tclasses.sSortJUIAscAllowed +\" \"+\n\t\t\t\t\t\t\tclasses.sSortJUIDescAllowed\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.addClass( columns[ idx ] == 'asc' ?\n\t\t\t\t\t\t\tclasses.sSortJUIAsc : columns[ idx ] == 'desc' ?\n\t\t\t\t\t\t\t\tclasses.sSortJUIDesc :\n\t\t\t\t\t\t\t\tcolumn.sSortingClassJUI\n\t\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t} );\n\n\n\t// jQuery access\n\t$.fn.dataTable = DataTable;\n\n\t// Legacy aliases\n\t$.fn.dataTableSettings = DataTable.settings;\n\t$.fn.dataTableExt = DataTable.ext;\n\n\t// With a capital `D` we return a DataTables API instance rather than a\n\t// jQuery object\n\t$.fn.DataTable = function ( opts ) {\n\t\treturn $(this).dataTable( opts ).api();\n\t};\n\n\t// All properties that are available to $.fn.dataTable should also be\n\t// available on $.fn.DataTable\n\t$.each( DataTable, function ( prop, val ) {\n\t\t$.fn.DataTable[ prop ] = val;\n\t} );\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\n\t * point as fnDrawCallback. This may be useful for binding events or\n\t * performing calculations when the table is altered at all.\n\t *  @name DataTable#draw.dt\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 * Search event, fired when the searching applied to the table (using the\n\t * built-in global search, or column filters) is altered.\n\t *  @name DataTable#search.dt\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.dt\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 * Order event, fired when the ordering applied to the table is altered.\n\t *  @name DataTable#order.dt\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\n\t * drawn, including Ajax data loaded, if Ajax data is required.\n\t *  @name DataTable#init.dt\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\n\t * is required. This event allows modification of the state saving object\n\t * prior to actually doing the save, including addition or other state\n\t * properties (for plug-ins) or modification of a DataTables core property.\n\t *  @name DataTable#stateSaveParams.dt\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\n\t * data, but prior to the settings object being modified by the saved state\n\t * - allowing modification of the saved state is required or loading of\n\t * state for a plug-in.\n\t *  @name DataTable#stateLoadParams.dt\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\n\t * the settings object has been modified by the loaded data.\n\t *  @name DataTable#stateLoaded.dt\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\n\t * (be it, order, searcg or anything else). It can be used to indicate to\n\t * the end user that there is something happening, or that something has\n\t * finished.\n\t *  @name DataTable#processing.dt\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\n\t * request to made to the server for new data. This event is called before\n\t * DataTables processed the returned data, so it can also be used to pre-\n\t * process the data returned from the server, if needed.\n\t *\n\t * Note that this trigger is called in `fnServerData`, if you override\n\t * `fnServerData` and which to use this event, you need to trigger it in you\n\t * success function.\n\t *  @name DataTable#xhr.dt\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\t *  @example\n\t *     // Use a custom property returned from the server in another DOM element\n\t *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\n\t *       $('#status').html( json.status );\n\t *     } );\n\t *\n\t *  @example\n\t *     // Pre-process the data returned from the server\n\t *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\n\t *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {\n\t *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;\n\t *       }\n\t *       // Note no return - manipulate the data directly in the JSON object.\n\t *     } );\n\t */\n\n\t/**\n\t * Destroy event, fired when the DataTable is destroyed by calling fnDestroy\n\t * or passing the bDestroy:true parameter in the initialisation object. This\n\t * can be used to remove bound events, added DOM nodes, etc.\n\t *  @name DataTable#destroy.dt\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 length change event, fired when number of records to show on each\n\t * page (the length) is changed.\n\t *  @name DataTable#length.dt\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 {integer} len New length\n\t */\n\n\t/**\n\t * Column sizing has changed.\n\t *  @name DataTable#column-sizing.dt\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 * Column visibility has changed.\n\t *  @name DataTable#column-visibility.dt\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 {int} column Column index\n\t *  @param {bool} vis `false` if column now hidden, or `true` if visible\n\t */\n}));\n\n}(window, document, jQuery));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/datapicker/bootstrap-datepicker.js",
    "content": "/* =========================================================\n * bootstrap-datepicker.js\n * Repo: https://github.com/eternicode/bootstrap-datepicker/\n * Demo: http://eternicode.github.io/bootstrap-datepicker/\n * Docs: http://bootstrap-datepicker.readthedocs.org/\n * Forked from http://www.eyecon.ro/bootstrap-datepicker\n * =========================================================\n * Started by Stefan Petre; improvements by Andrew Rowls + contributors\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($, undefined){\n\n\tvar $window = $(window);\n\n\tfunction UTCDate(){\n\t\treturn new Date(Date.UTC.apply(Date, arguments));\n\t}\n\tfunction UTCToday(){\n\t\tvar today = new Date();\n\t\treturn UTCDate(today.getFullYear(), today.getMonth(), today.getDate());\n\t}\n\tfunction alias(method){\n\t\treturn function(){\n\t\t\treturn this[method].apply(this, arguments);\n\t\t};\n\t}\n\n\tvar DateArray = (function(){\n\t\tvar extras = {\n\t\t\tget: function(i){\n\t\t\t\treturn this.slice(i)[0];\n\t\t\t},\n\t\t\tcontains: function(d){\n\t\t\t\t// Array.indexOf is not cross-browser;\n\t\t\t\t// $.inArray doesn't work with Dates\n\t\t\t\tvar val = d && d.valueOf();\n\t\t\t\tfor (var i=0, l=this.length; i < l; i++)\n\t\t\t\t\tif (this[i].valueOf() === val)\n\t\t\t\t\t\treturn i;\n\t\t\t\treturn -1;\n\t\t\t},\n\t\t\tremove: function(i){\n\t\t\t\tthis.splice(i,1);\n\t\t\t},\n\t\t\treplace: function(new_array){\n\t\t\t\tif (!new_array)\n\t\t\t\t\treturn;\n\t\t\t\tif (!$.isArray(new_array))\n\t\t\t\t\tnew_array = [new_array];\n\t\t\t\tthis.clear();\n\t\t\t\tthis.push.apply(this, new_array);\n\t\t\t},\n\t\t\tclear: function(){\n\t\t\t\tthis.splice(0);\n\t\t\t},\n\t\t\tcopy: function(){\n\t\t\t\tvar a = new DateArray();\n\t\t\t\ta.replace(this);\n\t\t\t\treturn a;\n\t\t\t}\n\t\t};\n\n\t\treturn function(){\n\t\t\tvar a = [];\n\t\t\ta.push.apply(a, arguments);\n\t\t\t$.extend(a, extras);\n\t\t\treturn a;\n\t\t};\n\t})();\n\n\n\t// Picker object\n\n\tvar Datepicker = function(element, options){\n\t\tthis.dates = new DateArray();\n\t\tthis.viewDate = UTCToday();\n\t\tthis.focusDate = null;\n\n\t\tthis._process_options(options);\n\n\t\tthis.element = $(element);\n\t\tthis.isInline = false;\n\t\tthis.isInput = this.element.is('input');\n\t\tthis.component = this.element.is('.date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;\n\t\tthis.hasInput = this.component && this.element.find('input').length;\n\t\tif (this.component && this.component.length === 0)\n\t\t\tthis.component = false;\n\n\t\tthis.picker = $(DPGlobal.template);\n\t\tthis._buildEvents();\n\t\tthis._attachEvents();\n\n\t\tif (this.isInline){\n\t\t\tthis.picker.addClass('datepicker-inline').appendTo(this.element);\n\t\t}\n\t\telse {\n\t\t\tthis.picker.addClass('datepicker-dropdown dropdown-menu');\n\t\t}\n\n\t\tif (this.o.rtl){\n\t\t\tthis.picker.addClass('datepicker-rtl');\n\t\t}\n\n\t\tthis.viewMode = this.o.startView;\n\n\t\tif (this.o.calendarWeeks)\n\t\t\tthis.picker.find('tfoot th.today')\n\t\t\t\t\t\t.attr('colspan', function(i, val){\n\t\t\t\t\t\t\treturn parseInt(val) + 1;\n\t\t\t\t\t\t});\n\n\t\tthis._allow_update = false;\n\n\t\tthis.setStartDate(this._o.startDate);\n\t\tthis.setEndDate(this._o.endDate);\n\t\tthis.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);\n\n\t\tthis.fillDow();\n\t\tthis.fillMonths();\n\n\t\tthis._allow_update = true;\n\n\t\tthis.update();\n\t\tthis.showMode();\n\n\t\tif (this.isInline){\n\t\t\tthis.show();\n\t\t}\n\t};\n\n\tDatepicker.prototype = {\n\t\tconstructor: Datepicker,\n\n\t\t_process_options: function(opts){\n\t\t\t// Store raw options for reference\n\t\t\tthis._o = $.extend({}, this._o, opts);\n\t\t\t// Processed options\n\t\t\tvar o = this.o = $.extend({}, this._o);\n\n\t\t\t// Check if \"de-DE\" style date is available, if not language should\n\t\t\t// fallback to 2 letter code eg \"de\"\n\t\t\tvar lang = o.language;\n\t\t\tif (!dates[lang]){\n\t\t\t\tlang = lang.split('-')[0];\n\t\t\t\tif (!dates[lang])\n\t\t\t\t\tlang = defaults.language;\n\t\t\t}\n\t\t\to.language = lang;\n\n\t\t\tswitch (o.startView){\n\t\t\t\tcase 2:\n\t\t\t\tcase 'decade':\n\t\t\t\t\to.startView = 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 'year':\n\t\t\t\t\to.startView = 1;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\to.startView = 0;\n\t\t\t}\n\n\t\t\tswitch (o.minViewMode){\n\t\t\t\tcase 1:\n\t\t\t\tcase 'months':\n\t\t\t\t\to.minViewMode = 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\tcase 'years':\n\t\t\t\t\to.minViewMode = 2;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\to.minViewMode = 0;\n\t\t\t}\n\n\t\t\to.startView = Math.max(o.startView, o.minViewMode);\n\n\t\t\t// true, false, or Number > 0\n\t\t\tif (o.multidate !== true){\n\t\t\t\to.multidate = Number(o.multidate) || false;\n\t\t\t\tif (o.multidate !== false)\n\t\t\t\t\to.multidate = Math.max(0, o.multidate);\n\t\t\t\telse\n\t\t\t\t\to.multidate = 1;\n\t\t\t}\n\t\t\to.multidateSeparator = String(o.multidateSeparator);\n\n\t\t\to.weekStart %= 7;\n\t\t\to.weekEnd = ((o.weekStart + 6) % 7);\n\n\t\t\tvar format = DPGlobal.parseFormat(o.format);\n\t\t\tif (o.startDate !== -Infinity){\n\t\t\t\tif (!!o.startDate){\n\t\t\t\t\tif (o.startDate instanceof Date)\n\t\t\t\t\t\to.startDate = this._local_to_utc(this._zero_time(o.startDate));\n\t\t\t\t\telse\n\t\t\t\t\t\to.startDate = DPGlobal.parseDate(o.startDate, format, o.language);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\to.startDate = -Infinity;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (o.endDate !== Infinity){\n\t\t\t\tif (!!o.endDate){\n\t\t\t\t\tif (o.endDate instanceof Date)\n\t\t\t\t\t\to.endDate = this._local_to_utc(this._zero_time(o.endDate));\n\t\t\t\t\telse\n\t\t\t\t\t\to.endDate = DPGlobal.parseDate(o.endDate, format, o.language);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\to.endDate = Infinity;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\to.daysOfWeekDisabled = o.daysOfWeekDisabled||[];\n\t\t\tif (!$.isArray(o.daysOfWeekDisabled))\n\t\t\t\to.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\\s]*/);\n\t\t\to.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){\n\t\t\t\treturn parseInt(d, 10);\n\t\t\t});\n\n\t\t\tvar plc = String(o.orientation).toLowerCase().split(/\\s+/g),\n\t\t\t\t_plc = o.orientation.toLowerCase();\n\t\t\tplc = $.grep(plc, function(word){\n\t\t\t\treturn (/^auto|left|right|top|bottom$/).test(word);\n\t\t\t});\n\t\t\to.orientation = {x: 'auto', y: 'auto'};\n\t\t\tif (!_plc || _plc === 'auto')\n\t\t\t\t; // no action\n\t\t\telse if (plc.length === 1){\n\t\t\t\tswitch (plc[0]){\n\t\t\t\t\tcase 'top':\n\t\t\t\t\tcase 'bottom':\n\t\t\t\t\t\to.orientation.y = plc[0];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'left':\n\t\t\t\t\tcase 'right':\n\t\t\t\t\t\to.orientation.x = plc[0];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t_plc = $.grep(plc, function(word){\n\t\t\t\t\treturn (/^left|right$/).test(word);\n\t\t\t\t});\n\t\t\t\to.orientation.x = _plc[0] || 'auto';\n\n\t\t\t\t_plc = $.grep(plc, function(word){\n\t\t\t\t\treturn (/^top|bottom$/).test(word);\n\t\t\t\t});\n\t\t\t\to.orientation.y = _plc[0] || 'auto';\n\t\t\t}\n\t\t},\n\t\t_events: [],\n\t\t_secondaryEvents: [],\n\t\t_applyEvents: function(evs){\n\t\t\tfor (var i=0, el, ch, ev; i < evs.length; i++){\n\t\t\t\tel = evs[i][0];\n\t\t\t\tif (evs[i].length === 2){\n\t\t\t\t\tch = undefined;\n\t\t\t\t\tev = evs[i][1];\n\t\t\t\t}\n\t\t\t\telse if (evs[i].length === 3){\n\t\t\t\t\tch = evs[i][1];\n\t\t\t\t\tev = evs[i][2];\n\t\t\t\t}\n\t\t\t\tel.on(ev, ch);\n\t\t\t}\n\t\t},\n\t\t_unapplyEvents: function(evs){\n\t\t\tfor (var i=0, el, ev, ch; i < evs.length; i++){\n\t\t\t\tel = evs[i][0];\n\t\t\t\tif (evs[i].length === 2){\n\t\t\t\t\tch = undefined;\n\t\t\t\t\tev = evs[i][1];\n\t\t\t\t}\n\t\t\t\telse if (evs[i].length === 3){\n\t\t\t\t\tch = evs[i][1];\n\t\t\t\t\tev = evs[i][2];\n\t\t\t\t}\n\t\t\t\tel.off(ev, ch);\n\t\t\t}\n\t\t},\n\t\t_buildEvents: function(){\n\t\t\tif (this.isInput){ // single input\n\t\t\t\tthis._events = [\n\t\t\t\t\t[this.element, {\n\t\t\t\t\t\tfocus: $.proxy(this.show, this),\n\t\t\t\t\t\tkeyup: $.proxy(function(e){\n\t\t\t\t\t\t\tif ($.inArray(e.keyCode, [27,37,39,38,40,32,13,9]) === -1)\n\t\t\t\t\t\t\t\tthis.update();\n\t\t\t\t\t\t}, this),\n\t\t\t\t\t\tkeydown: $.proxy(this.keydown, this)\n\t\t\t\t\t}]\n\t\t\t\t];\n\t\t\t}\n\t\t\telse if (this.component && this.hasInput){ // component: input + button\n\t\t\t\tthis._events = [\n\t\t\t\t\t// For components that are not readonly, allow keyboard nav\n\t\t\t\t\t[this.element.find('input'), {\n\t\t\t\t\t\tfocus: $.proxy(this.show, this),\n\t\t\t\t\t\tkeyup: $.proxy(function(e){\n\t\t\t\t\t\t\tif ($.inArray(e.keyCode, [27,37,39,38,40,32,13,9]) === -1)\n\t\t\t\t\t\t\t\tthis.update();\n\t\t\t\t\t\t}, this),\n\t\t\t\t\t\tkeydown: $.proxy(this.keydown, this)\n\t\t\t\t\t}],\n\t\t\t\t\t[this.component, {\n\t\t\t\t\t\tclick: $.proxy(this.show, this)\n\t\t\t\t\t}]\n\t\t\t\t];\n\t\t\t}\n\t\t\telse if (this.element.is('div')){  // inline datepicker\n\t\t\t\tthis.isInline = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._events = [\n\t\t\t\t\t[this.element, {\n\t\t\t\t\t\tclick: $.proxy(this.show, this)\n\t\t\t\t\t}]\n\t\t\t\t];\n\t\t\t}\n\t\t\tthis._events.push(\n\t\t\t\t// Component: listen for blur on element descendants\n\t\t\t\t[this.element, '*', {\n\t\t\t\t\tblur: $.proxy(function(e){\n\t\t\t\t\t\tthis._focused_from = e.target;\n\t\t\t\t\t}, this)\n\t\t\t\t}],\n\t\t\t\t// Input: listen for blur on element\n\t\t\t\t[this.element, {\n\t\t\t\t\tblur: $.proxy(function(e){\n\t\t\t\t\t\tthis._focused_from = e.target;\n\t\t\t\t\t}, this)\n\t\t\t\t}]\n\t\t\t);\n\n\t\t\tthis._secondaryEvents = [\n\t\t\t\t[this.picker, {\n\t\t\t\t\tclick: $.proxy(this.click, this)\n\t\t\t\t}],\n\t\t\t\t[$(window), {\n\t\t\t\t\tresize: $.proxy(this.place, this)\n\t\t\t\t}],\n\t\t\t\t[$(document), {\n\t\t\t\t\t'mousedown touchstart': $.proxy(function(e){\n\t\t\t\t\t\t// Clicked outside the datepicker, hide it\n\t\t\t\t\t\tif (!(\n\t\t\t\t\t\t\tthis.element.is(e.target) ||\n\t\t\t\t\t\t\tthis.element.find(e.target).length ||\n\t\t\t\t\t\t\tthis.picker.is(e.target) ||\n\t\t\t\t\t\t\tthis.picker.find(e.target).length\n\t\t\t\t\t\t)){\n\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this)\n\t\t\t\t}]\n\t\t\t];\n\t\t},\n\t\t_attachEvents: function(){\n\t\t\tthis._detachEvents();\n\t\t\tthis._applyEvents(this._events);\n\t\t},\n\t\t_detachEvents: function(){\n\t\t\tthis._unapplyEvents(this._events);\n\t\t},\n\t\t_attachSecondaryEvents: function(){\n\t\t\tthis._detachSecondaryEvents();\n\t\t\tthis._applyEvents(this._secondaryEvents);\n\t\t},\n\t\t_detachSecondaryEvents: function(){\n\t\t\tthis._unapplyEvents(this._secondaryEvents);\n\t\t},\n\t\t_trigger: function(event, altdate){\n\t\t\tvar date = altdate || this.dates.get(-1),\n\t\t\t\tlocal_date = this._utc_to_local(date);\n\n\t\t\tthis.element.trigger({\n\t\t\t\ttype: event,\n\t\t\t\tdate: local_date,\n\t\t\t\tdates: $.map(this.dates, this._utc_to_local),\n\t\t\t\tformat: $.proxy(function(ix, format){\n\t\t\t\t\tif (arguments.length === 0){\n\t\t\t\t\t\tix = this.dates.length - 1;\n\t\t\t\t\t\tformat = this.o.format;\n\t\t\t\t\t}\n\t\t\t\t\telse if (typeof ix === 'string'){\n\t\t\t\t\t\tformat = ix;\n\t\t\t\t\t\tix = this.dates.length - 1;\n\t\t\t\t\t}\n\t\t\t\t\tformat = format || this.o.format;\n\t\t\t\t\tvar date = this.dates.get(ix);\n\t\t\t\t\treturn DPGlobal.formatDate(date, format, this.o.language);\n\t\t\t\t}, this)\n\t\t\t});\n\t\t},\n\n\t\tshow: function(){\n\t\t\tif (!this.isInline)\n\t\t\t\tthis.picker.appendTo('body');\n\t\t\tthis.picker.show();\n\t\t\tthis.place();\n\t\t\tthis._attachSecondaryEvents();\n\t\t\tthis._trigger('show');\n\t\t},\n\n\t\thide: function(){\n\t\t\tif (this.isInline)\n\t\t\t\treturn;\n\t\t\tif (!this.picker.is(':visible'))\n\t\t\t\treturn;\n\t\t\tthis.focusDate = null;\n\t\t\tthis.picker.hide().detach();\n\t\t\tthis._detachSecondaryEvents();\n\t\t\tthis.viewMode = this.o.startView;\n\t\t\tthis.showMode();\n\n\t\t\tif (\n\t\t\t\tthis.o.forceParse &&\n\t\t\t\t(\n\t\t\t\t\tthis.isInput && this.element.val() ||\n\t\t\t\t\tthis.hasInput && this.element.find('input').val()\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tthis.setValue();\n\t\t\tthis._trigger('hide');\n\t\t},\n\n\t\tremove: function(){\n\t\t\tthis.hide();\n\t\t\tthis._detachEvents();\n\t\t\tthis._detachSecondaryEvents();\n\t\t\tthis.picker.remove();\n\t\t\tdelete this.element.data().datepicker;\n\t\t\tif (!this.isInput){\n\t\t\t\tdelete this.element.data().date;\n\t\t\t}\n\t\t},\n\n\t\t_utc_to_local: function(utc){\n\t\t\treturn utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));\n\t\t},\n\t\t_local_to_utc: function(local){\n\t\t\treturn local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));\n\t\t},\n\t\t_zero_time: function(local){\n\t\t\treturn local && new Date(local.getFullYear(), local.getMonth(), local.getDate());\n\t\t},\n\t\t_zero_utc_time: function(utc){\n\t\t\treturn utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));\n\t\t},\n\n\t\tgetDates: function(){\n\t\t\treturn $.map(this.dates, this._utc_to_local);\n\t\t},\n\n\t\tgetUTCDates: function(){\n\t\t\treturn $.map(this.dates, function(d){\n\t\t\t\treturn new Date(d);\n\t\t\t});\n\t\t},\n\n\t\tgetDate: function(){\n\t\t\treturn this._utc_to_local(this.getUTCDate());\n\t\t},\n\n\t\tgetUTCDate: function(){\n\t\t\treturn new Date(this.dates.get(-1));\n\t\t},\n\n\t\tsetDates: function(){\n\t\t\tvar args = $.isArray(arguments[0]) ? arguments[0] : arguments;\n\t\t\tthis.update.apply(this, args);\n\t\t\tthis._trigger('changeDate');\n\t\t\tthis.setValue();\n\t\t},\n\n\t\tsetUTCDates: function(){\n\t\t\tvar args = $.isArray(arguments[0]) ? arguments[0] : arguments;\n\t\t\tthis.update.apply(this, $.map(args, this._utc_to_local));\n\t\t\tthis._trigger('changeDate');\n\t\t\tthis.setValue();\n\t\t},\n\n\t\tsetDate: alias('setDates'),\n\t\tsetUTCDate: alias('setUTCDates'),\n\n\t\tsetValue: function(){\n\t\t\tvar formatted = this.getFormattedDate();\n\t\t\tif (!this.isInput){\n\t\t\t\tif (this.component){\n\t\t\t\t\tthis.element.find('input').val(formatted).change();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.element.val(formatted).change();\n\t\t\t}\n\t\t},\n\n\t\tgetFormattedDate: function(format){\n\t\t\tif (format === undefined)\n\t\t\t\tformat = this.o.format;\n\n\t\t\tvar lang = this.o.language;\n\t\t\treturn $.map(this.dates, function(d){\n\t\t\t\treturn DPGlobal.formatDate(d, format, lang);\n\t\t\t}).join(this.o.multidateSeparator);\n\t\t},\n\n\t\tsetStartDate: function(startDate){\n\t\t\tthis._process_options({startDate: startDate});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetEndDate: function(endDate){\n\t\t\tthis._process_options({endDate: endDate});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetDaysOfWeekDisabled: function(daysOfWeekDisabled){\n\t\t\tthis._process_options({daysOfWeekDisabled: daysOfWeekDisabled});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tplace: function(){\n\t\t\tif (this.isInline)\n\t\t\t\treturn;\n\t\t\tvar calendarWidth = this.picker.outerWidth(),\n\t\t\t\tcalendarHeight = this.picker.outerHeight(),\n\t\t\t\tvisualPadding = 10,\n\t\t\t\twindowWidth = $window.width(),\n\t\t\t\twindowHeight = $window.height(),\n\t\t\t\tscrollTop = $window.scrollTop();\n\n\t\t\tvar zIndex = parseInt(this.element.parents().filter(function(){\n\t\t\t\t\treturn $(this).css('z-index') !== 'auto';\n\t\t\t\t}).first().css('z-index'))+10;\n\t\t\tvar offset = this.component ? this.component.parent().offset() : this.element.offset();\n\t\t\tvar height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);\n\t\t\tvar width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);\n\t\t\tvar left = offset.left,\n\t\t\t\ttop = offset.top;\n\n\t\t\tthis.picker.removeClass(\n\t\t\t\t'datepicker-orient-top datepicker-orient-bottom '+\n\t\t\t\t'datepicker-orient-right datepicker-orient-left'\n\t\t\t);\n\n\t\t\tif (this.o.orientation.x !== 'auto'){\n\t\t\t\tthis.picker.addClass('datepicker-orient-' + this.o.orientation.x);\n\t\t\t\tif (this.o.orientation.x === 'right')\n\t\t\t\t\tleft -= calendarWidth - width;\n\t\t\t}\n\t\t\t// auto x orientation is best-placement: if it crosses a window\n\t\t\t// edge, fudge it sideways\n\t\t\telse {\n\t\t\t\t// Default to left\n\t\t\t\tthis.picker.addClass('datepicker-orient-left');\n\t\t\t\tif (offset.left < 0)\n\t\t\t\t\tleft -= offset.left - visualPadding;\n\t\t\t\telse if (offset.left + calendarWidth > windowWidth)\n\t\t\t\t\tleft = windowWidth - calendarWidth - visualPadding;\n\t\t\t}\n\n\t\t\t// auto y orientation is best-situation: top or bottom, no fudging,\n\t\t\t// decision based on which shows more of the calendar\n\t\t\tvar yorient = this.o.orientation.y,\n\t\t\t\ttop_overflow, bottom_overflow;\n\t\t\tif (yorient === 'auto'){\n\t\t\t\ttop_overflow = -scrollTop + offset.top - calendarHeight;\n\t\t\t\tbottom_overflow = scrollTop + windowHeight - (offset.top + height + calendarHeight);\n\t\t\t\tif (Math.max(top_overflow, bottom_overflow) === bottom_overflow)\n\t\t\t\t\tyorient = 'top';\n\t\t\t\telse\n\t\t\t\t\tyorient = 'bottom';\n\t\t\t}\n\t\t\tthis.picker.addClass('datepicker-orient-' + yorient);\n\t\t\tif (yorient === 'top')\n\t\t\t\ttop += height;\n\t\t\telse\n\t\t\t\ttop -= calendarHeight + parseInt(this.picker.css('padding-top'));\n\n\t\t\tthis.picker.css({\n\t\t\t\ttop: top,\n\t\t\t\tleft: left,\n\t\t\t\tzIndex: zIndex\n\t\t\t});\n\t\t},\n\n\t\t_allow_update: true,\n\t\tupdate: function(){\n\t\t\tif (!this._allow_update)\n\t\t\t\treturn;\n\n\t\t\tvar oldDates = this.dates.copy(),\n\t\t\t\tdates = [],\n\t\t\t\tfromArgs = false;\n\t\t\tif (arguments.length){\n\t\t\t\t$.each(arguments, $.proxy(function(i, date){\n\t\t\t\t\tif (date instanceof Date)\n\t\t\t\t\t\tdate = this._local_to_utc(date);\n\t\t\t\t\tdates.push(date);\n\t\t\t\t}, this));\n\t\t\t\tfromArgs = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdates = this.isInput\n\t\t\t\t\t\t? this.element.val()\n\t\t\t\t\t\t: this.element.data('date') || this.element.find('input').val();\n\t\t\t\tif (dates && this.o.multidate)\n\t\t\t\t\tdates = dates.split(this.o.multidateSeparator);\n\t\t\t\telse\n\t\t\t\t\tdates = [dates];\n\t\t\t\tdelete this.element.data().date;\n\t\t\t}\n\n\t\t\tdates = $.map(dates, $.proxy(function(date){\n\t\t\t\treturn DPGlobal.parseDate(date, this.o.format, this.o.language);\n\t\t\t}, this));\n\t\t\tdates = $.grep(dates, $.proxy(function(date){\n\t\t\t\treturn (\n\t\t\t\t\tdate < this.o.startDate ||\n\t\t\t\t\tdate > this.o.endDate ||\n\t\t\t\t\t!date\n\t\t\t\t);\n\t\t\t}, this), true);\n\t\t\tthis.dates.replace(dates);\n\n\t\t\tif (this.dates.length)\n\t\t\t\tthis.viewDate = new Date(this.dates.get(-1));\n\t\t\telse if (this.viewDate < this.o.startDate)\n\t\t\t\tthis.viewDate = new Date(this.o.startDate);\n\t\t\telse if (this.viewDate > this.o.endDate)\n\t\t\t\tthis.viewDate = new Date(this.o.endDate);\n\n\t\t\tif (fromArgs){\n\t\t\t\t// setting date by clicking\n\t\t\t\tthis.setValue();\n\t\t\t}\n\t\t\telse if (dates.length){\n\t\t\t\t// setting date by typing\n\t\t\t\tif (String(oldDates) !== String(this.dates))\n\t\t\t\t\tthis._trigger('changeDate');\n\t\t\t}\n\t\t\tif (!this.dates.length && oldDates.length)\n\t\t\t\tthis._trigger('clearDate');\n\n\t\t\tthis.fill();\n\t\t},\n\n\t\tfillDow: function(){\n\t\t\tvar dowCnt = this.o.weekStart,\n\t\t\t\thtml = '<tr>';\n\t\t\tif (this.o.calendarWeeks){\n\t\t\t\tvar cell = '<th class=\"cw\">&nbsp;</th>';\n\t\t\t\thtml += cell;\n\t\t\t\tthis.picker.find('.datepicker-days thead tr:first-child').prepend(cell);\n\t\t\t}\n\t\t\twhile (dowCnt < this.o.weekStart + 7){\n\t\t\t\thtml += '<th class=\"dow\">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';\n\t\t\t}\n\t\t\thtml += '</tr>';\n\t\t\tthis.picker.find('.datepicker-days thead').append(html);\n\t\t},\n\n\t\tfillMonths: function(){\n\t\t\tvar html = '',\n\t\t\ti = 0;\n\t\t\twhile (i < 12){\n\t\t\t\thtml += '<span class=\"month\">'+dates[this.o.language].monthsShort[i++]+'</span>';\n\t\t\t}\n\t\t\tthis.picker.find('.datepicker-months td').html(html);\n\t\t},\n\n\t\tsetRange: function(range){\n\t\t\tif (!range || !range.length)\n\t\t\t\tdelete this.range;\n\t\t\telse\n\t\t\t\tthis.range = $.map(range, function(d){\n\t\t\t\t\treturn d.valueOf();\n\t\t\t\t});\n\t\t\tthis.fill();\n\t\t},\n\n\t\tgetClassNames: function(date){\n\t\t\tvar cls = [],\n\t\t\t\tyear = this.viewDate.getUTCFullYear(),\n\t\t\t\tmonth = this.viewDate.getUTCMonth(),\n\t\t\t\ttoday = new Date();\n\t\t\tif (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){\n\t\t\t\tcls.push('old');\n\t\t\t}\n\t\t\telse if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){\n\t\t\t\tcls.push('new');\n\t\t\t}\n\t\t\tif (this.focusDate && date.valueOf() === this.focusDate.valueOf())\n\t\t\t\tcls.push('focused');\n\t\t\t// Compare internal UTC date with local today, not UTC today\n\t\t\tif (this.o.todayHighlight &&\n\t\t\t\tdate.getUTCFullYear() === today.getFullYear() &&\n\t\t\t\tdate.getUTCMonth() === today.getMonth() &&\n\t\t\t\tdate.getUTCDate() === today.getDate()){\n\t\t\t\tcls.push('today');\n\t\t\t}\n\t\t\tif (this.dates.contains(date) !== -1)\n\t\t\t\tcls.push('active');\n\t\t\tif (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate ||\n\t\t\t\t$.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){\n\t\t\t\tcls.push('disabled');\n\t\t\t}\n\t\t\tif (this.range){\n\t\t\t\tif (date > this.range[0] && date < this.range[this.range.length-1]){\n\t\t\t\t\tcls.push('range');\n\t\t\t\t}\n\t\t\t\tif ($.inArray(date.valueOf(), this.range) !== -1){\n\t\t\t\t\tcls.push('selected');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn cls;\n\t\t},\n\n\t\tfill: function(){\n\t\t\tvar d = new Date(this.viewDate),\n\t\t\t\tyear = d.getUTCFullYear(),\n\t\t\t\tmonth = d.getUTCMonth(),\n\t\t\t\tstartYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,\n\t\t\t\tstartMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,\n\t\t\t\tendYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,\n\t\t\t\tendMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,\n\t\t\t\ttodaytxt = dates[this.o.language].today || dates['en'].today || '',\n\t\t\t\tcleartxt = dates[this.o.language].clear || dates['en'].clear || '',\n\t\t\t\ttooltip;\n\t\t\tthis.picker.find('.datepicker-days thead th.datepicker-switch')\n\t\t\t\t\t\t.text(dates[this.o.language].months[month]+' '+year);\n\t\t\tthis.picker.find('tfoot th.today')\n\t\t\t\t\t\t.text(todaytxt)\n\t\t\t\t\t\t.toggle(this.o.todayBtn !== false);\n\t\t\tthis.picker.find('tfoot th.clear')\n\t\t\t\t\t\t.text(cleartxt)\n\t\t\t\t\t\t.toggle(this.o.clearBtn !== false);\n\t\t\tthis.updateNavArrows();\n\t\t\tthis.fillMonths();\n\t\t\tvar prevMonth = UTCDate(year, month-1, 28),\n\t\t\t\tday = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());\n\t\t\tprevMonth.setUTCDate(day);\n\t\t\tprevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);\n\t\t\tvar nextMonth = new Date(prevMonth);\n\t\t\tnextMonth.setUTCDate(nextMonth.getUTCDate() + 42);\n\t\t\tnextMonth = nextMonth.valueOf();\n\t\t\tvar html = [];\n\t\t\tvar clsName;\n\t\t\twhile (prevMonth.valueOf() < nextMonth){\n\t\t\t\tif (prevMonth.getUTCDay() === this.o.weekStart){\n\t\t\t\t\thtml.push('<tr>');\n\t\t\t\t\tif (this.o.calendarWeeks){\n\t\t\t\t\t\t// ISO 8601: First week contains first thursday.\n\t\t\t\t\t\t// ISO also states week starts on Monday, but we can be more abstract here.\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t// Start of current week: based on weekstart/current date\n\t\t\t\t\t\t\tws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),\n\t\t\t\t\t\t\t// Thursday of this week\n\t\t\t\t\t\t\tth = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),\n\t\t\t\t\t\t\t// First Thursday of year, year from thursday\n\t\t\t\t\t\t\tyth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),\n\t\t\t\t\t\t\t// Calendar week: ms between thursdays, div ms per day, div 7 days\n\t\t\t\t\t\t\tcalWeek =  (th - yth) / 864e5 / 7 + 1;\n\t\t\t\t\t\thtml.push('<td class=\"cw\">'+ calWeek +'</td>');\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclsName = this.getClassNames(prevMonth);\n\t\t\t\tclsName.push('day');\n\n\t\t\t\tif (this.o.beforeShowDay !== $.noop){\n\t\t\t\t\tvar before = this.o.beforeShowDay(this._utc_to_local(prevMonth));\n\t\t\t\t\tif (before === undefined)\n\t\t\t\t\t\tbefore = {};\n\t\t\t\t\telse if (typeof(before) === 'boolean')\n\t\t\t\t\t\tbefore = {enabled: before};\n\t\t\t\t\telse if (typeof(before) === 'string')\n\t\t\t\t\t\tbefore = {classes: before};\n\t\t\t\t\tif (before.enabled === false)\n\t\t\t\t\t\tclsName.push('disabled');\n\t\t\t\t\tif (before.classes)\n\t\t\t\t\t\tclsName = clsName.concat(before.classes.split(/\\s+/));\n\t\t\t\t\tif (before.tooltip)\n\t\t\t\t\t\ttooltip = before.tooltip;\n\t\t\t\t}\n\n\t\t\t\tclsName = $.unique(clsName);\n\t\t\t\thtml.push('<td class=\"'+clsName.join(' ')+'\"' + (tooltip ? ' title=\"'+tooltip+'\"' : '') + '>'+prevMonth.getUTCDate() + '</td>');\n\t\t\t\tif (prevMonth.getUTCDay() === this.o.weekEnd){\n\t\t\t\t\thtml.push('</tr>');\n\t\t\t\t}\n\t\t\t\tprevMonth.setUTCDate(prevMonth.getUTCDate()+1);\n\t\t\t}\n\t\t\tthis.picker.find('.datepicker-days tbody').empty().append(html.join(''));\n\n\t\t\tvar months = this.picker.find('.datepicker-months')\n\t\t\t\t\t\t.find('th:eq(1)')\n\t\t\t\t\t\t\t.text(year)\n\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t.find('span').removeClass('active');\n\n\t\t\t$.each(this.dates, function(i, d){\n\t\t\t\tif (d.getUTCFullYear() === year)\n\t\t\t\t\tmonths.eq(d.getUTCMonth()).addClass('active');\n\t\t\t});\n\n\t\t\tif (year < startYear || year > endYear){\n\t\t\t\tmonths.addClass('disabled');\n\t\t\t}\n\t\t\tif (year === startYear){\n\t\t\t\tmonths.slice(0, startMonth).addClass('disabled');\n\t\t\t}\n\t\t\tif (year === endYear){\n\t\t\t\tmonths.slice(endMonth+1).addClass('disabled');\n\t\t\t}\n\n\t\t\thtml = '';\n\t\t\tyear = parseInt(year/10, 10) * 10;\n\t\t\tvar yearCont = this.picker.find('.datepicker-years')\n\t\t\t\t\t\t\t\t.find('th:eq(1)')\n\t\t\t\t\t\t\t\t\t.text(year + '-' + (year + 9))\n\t\t\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t\t\t.find('td');\n\t\t\tyear -= 1;\n\t\t\tvar years = $.map(this.dates, function(d){\n\t\t\t\t\treturn d.getUTCFullYear();\n\t\t\t\t}),\n\t\t\t\tclasses;\n\t\t\tfor (var i = -1; i < 11; i++){\n\t\t\t\tclasses = ['year'];\n\t\t\t\tif (i === -1)\n\t\t\t\t\tclasses.push('old');\n\t\t\t\telse if (i === 10)\n\t\t\t\t\tclasses.push('new');\n\t\t\t\tif ($.inArray(year, years) !== -1)\n\t\t\t\t\tclasses.push('active');\n\t\t\t\tif (year < startYear || year > endYear)\n\t\t\t\t\tclasses.push('disabled');\n\t\t\t\thtml += '<span class=\"' + classes.join(' ') + '\">'+year+'</span>';\n\t\t\t\tyear += 1;\n\t\t\t}\n\t\t\tyearCont.html(html);\n\t\t},\n\n\t\tupdateNavArrows: function(){\n\t\t\tif (!this._allow_update)\n\t\t\t\treturn;\n\n\t\t\tvar d = new Date(this.viewDate),\n\t\t\t\tyear = d.getUTCFullYear(),\n\t\t\t\tmonth = d.getUTCMonth();\n\t\t\tswitch (this.viewMode){\n\t\t\t\tcase 0:\n\t\t\t\t\tif (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){\n\t\t\t\t\t\tthis.picker.find('.prev').css({visibility: 'hidden'});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.picker.find('.prev').css({visibility: 'visible'});\n\t\t\t\t\t}\n\t\t\t\t\tif (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){\n\t\t\t\t\t\tthis.picker.find('.next').css({visibility: 'hidden'});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.picker.find('.next').css({visibility: 'visible'});\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\t\tif (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()){\n\t\t\t\t\t\tthis.picker.find('.prev').css({visibility: 'hidden'});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.picker.find('.prev').css({visibility: 'visible'});\n\t\t\t\t\t}\n\t\t\t\t\tif (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()){\n\t\t\t\t\t\tthis.picker.find('.next').css({visibility: 'hidden'});\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.picker.find('.next').css({visibility: 'visible'});\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\tclick: function(e){\n\t\t\te.preventDefault();\n\t\t\tvar target = $(e.target).closest('span, td, th'),\n\t\t\t\tyear, month, day;\n\t\t\tif (target.length === 1){\n\t\t\t\tswitch (target[0].nodeName.toLowerCase()){\n\t\t\t\t\tcase 'th':\n\t\t\t\t\t\tswitch (target[0].className){\n\t\t\t\t\t\t\tcase 'datepicker-switch':\n\t\t\t\t\t\t\t\tthis.showMode(1);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'prev':\n\t\t\t\t\t\t\tcase 'next':\n\t\t\t\t\t\t\t\tvar dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);\n\t\t\t\t\t\t\t\tswitch (this.viewMode){\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tthis.viewDate = this.moveMonth(this.viewDate, dir);\n\t\t\t\t\t\t\t\t\t\tthis._trigger('changeMonth', this.viewDate);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t\tthis.viewDate = this.moveYear(this.viewDate, dir);\n\t\t\t\t\t\t\t\t\t\tif (this.viewMode === 1)\n\t\t\t\t\t\t\t\t\t\t\tthis._trigger('changeYear', this.viewDate);\n\t\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\tthis.fill();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'today':\n\t\t\t\t\t\t\t\tvar date = new Date();\n\t\t\t\t\t\t\t\tdate = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);\n\n\t\t\t\t\t\t\t\tthis.showMode(-2);\n\t\t\t\t\t\t\t\tvar which = this.o.todayBtn === 'linked' ? null : 'view';\n\t\t\t\t\t\t\t\tthis._setDate(date, which);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'clear':\n\t\t\t\t\t\t\t\tvar element;\n\t\t\t\t\t\t\t\tif (this.isInput)\n\t\t\t\t\t\t\t\t\telement = this.element;\n\t\t\t\t\t\t\t\telse if (this.component)\n\t\t\t\t\t\t\t\t\telement = this.element.find('input');\n\t\t\t\t\t\t\t\tif (element)\n\t\t\t\t\t\t\t\t\telement.val(\"\").change();\n\t\t\t\t\t\t\t\tthis.update();\n\t\t\t\t\t\t\t\tthis._trigger('changeDate');\n\t\t\t\t\t\t\t\tif (this.o.autoclose)\n\t\t\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'span':\n\t\t\t\t\t\tif (!target.is('.disabled')){\n\t\t\t\t\t\t\tthis.viewDate.setUTCDate(1);\n\t\t\t\t\t\t\tif (target.is('.month')){\n\t\t\t\t\t\t\t\tday = 1;\n\t\t\t\t\t\t\t\tmonth = target.parent().find('span').index(target);\n\t\t\t\t\t\t\t\tyear = this.viewDate.getUTCFullYear();\n\t\t\t\t\t\t\t\tthis.viewDate.setUTCMonth(month);\n\t\t\t\t\t\t\t\tthis._trigger('changeMonth', this.viewDate);\n\t\t\t\t\t\t\t\tif (this.o.minViewMode === 1){\n\t\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tday = 1;\n\t\t\t\t\t\t\t\tmonth = 0;\n\t\t\t\t\t\t\t\tyear = parseInt(target.text(), 10)||0;\n\t\t\t\t\t\t\t\tthis.viewDate.setUTCFullYear(year);\n\t\t\t\t\t\t\t\tthis._trigger('changeYear', this.viewDate);\n\t\t\t\t\t\t\t\tif (this.o.minViewMode === 2){\n\t\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.showMode(-1);\n\t\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'td':\n\t\t\t\t\t\tif (target.is('.day') && !target.is('.disabled')){\n\t\t\t\t\t\t\tday = parseInt(target.text(), 10)||1;\n\t\t\t\t\t\t\tyear = this.viewDate.getUTCFullYear();\n\t\t\t\t\t\t\tmonth = this.viewDate.getUTCMonth();\n\t\t\t\t\t\t\tif (target.is('.old')){\n\t\t\t\t\t\t\t\tif (month === 0){\n\t\t\t\t\t\t\t\t\tmonth = 11;\n\t\t\t\t\t\t\t\t\tyear -= 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\tmonth -= 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (target.is('.new')){\n\t\t\t\t\t\t\t\tif (month === 11){\n\t\t\t\t\t\t\t\t\tmonth = 0;\n\t\t\t\t\t\t\t\t\tyear += 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\tmonth += 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.picker.is(':visible') && this._focused_from){\n\t\t\t\t$(this._focused_from).focus();\n\t\t\t}\n\t\t\tdelete this._focused_from;\n\t\t},\n\n\t\t_toggle_multidate: function(date){\n\t\t\tvar ix = this.dates.contains(date);\n\t\t\tif (!date){\n\t\t\t\tthis.dates.clear();\n\t\t\t}\n\t\t\telse if (ix !== -1){\n\t\t\t\tthis.dates.remove(ix);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.dates.push(date);\n\t\t\t}\n\t\t\tif (typeof this.o.multidate === 'number')\n\t\t\t\twhile (this.dates.length > this.o.multidate)\n\t\t\t\t\tthis.dates.remove(0);\n\t\t},\n\n\t\t_setDate: function(date, which){\n\t\t\tif (!which || which === 'date')\n\t\t\t\tthis._toggle_multidate(date && new Date(date));\n\t\t\tif (!which || which  === 'view')\n\t\t\t\tthis.viewDate = date && new Date(date);\n\n\t\t\tthis.fill();\n\t\t\tthis.setValue();\n\t\t\tthis._trigger('changeDate');\n\t\t\tvar element;\n\t\t\tif (this.isInput){\n\t\t\t\telement = this.element;\n\t\t\t}\n\t\t\telse if (this.component){\n\t\t\t\telement = this.element.find('input');\n\t\t\t}\n\t\t\tif (element){\n\t\t\t\telement.change();\n\t\t\t}\n\t\t\tif (this.o.autoclose && (!which || which === 'date')){\n\t\t\t\tthis.hide();\n\t\t\t}\n\t\t},\n\n\t\tmoveMonth: function(date, dir){\n\t\t\tif (!date)\n\t\t\t\treturn undefined;\n\t\t\tif (!dir)\n\t\t\t\treturn date;\n\t\t\tvar new_date = new Date(date.valueOf()),\n\t\t\t\tday = new_date.getUTCDate(),\n\t\t\t\tmonth = new_date.getUTCMonth(),\n\t\t\t\tmag = Math.abs(dir),\n\t\t\t\tnew_month, test;\n\t\t\tdir = dir > 0 ? 1 : -1;\n\t\t\tif (mag === 1){\n\t\t\t\ttest = dir === -1\n\t\t\t\t\t// If going back one month, make sure month is not current month\n\t\t\t\t\t// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)\n\t\t\t\t\t? function(){\n\t\t\t\t\t\treturn new_date.getUTCMonth() === month;\n\t\t\t\t\t}\n\t\t\t\t\t// If going forward one month, make sure month is as expected\n\t\t\t\t\t// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)\n\t\t\t\t\t: function(){\n\t\t\t\t\t\treturn new_date.getUTCMonth() !== new_month;\n\t\t\t\t\t};\n\t\t\t\tnew_month = month + dir;\n\t\t\t\tnew_date.setUTCMonth(new_month);\n\t\t\t\t// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11\n\t\t\t\tif (new_month < 0 || new_month > 11)\n\t\t\t\t\tnew_month = (new_month + 12) % 12;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// For magnitudes >1, move one month at a time...\n\t\t\t\tfor (var i=0; i < mag; i++)\n\t\t\t\t\t// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...\n\t\t\t\t\tnew_date = this.moveMonth(new_date, dir);\n\t\t\t\t// ...then reset the day, keeping it in the new month\n\t\t\t\tnew_month = new_date.getUTCMonth();\n\t\t\t\tnew_date.setUTCDate(day);\n\t\t\t\ttest = function(){\n\t\t\t\t\treturn new_month !== new_date.getUTCMonth();\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Common date-resetting loop -- if date is beyond end of month, make it\n\t\t\t// end of month\n\t\t\twhile (test()){\n\t\t\t\tnew_date.setUTCDate(--day);\n\t\t\t\tnew_date.setUTCMonth(new_month);\n\t\t\t}\n\t\t\treturn new_date;\n\t\t},\n\n\t\tmoveYear: function(date, dir){\n\t\t\treturn this.moveMonth(date, dir*12);\n\t\t},\n\n\t\tdateWithinRange: function(date){\n\t\t\treturn date >= this.o.startDate && date <= this.o.endDate;\n\t\t},\n\n\t\tkeydown: function(e){\n\t\t\tif (this.picker.is(':not(:visible)')){\n\t\t\t\tif (e.keyCode === 27) // allow escape to hide and re-show picker\n\t\t\t\t\tthis.show();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar dateChanged = false,\n\t\t\t\tdir, newDate, newViewDate,\n\t\t\t\tfocusDate = this.focusDate || this.viewDate;\n\t\t\tswitch (e.keyCode){\n\t\t\t\tcase 27: // escape\n\t\t\t\t\tif (this.focusDate){\n\t\t\t\t\t\tthis.focusDate = null;\n\t\t\t\t\t\tthis.viewDate = this.dates.get(-1) || this.viewDate;\n\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 37: // left\n\t\t\t\tcase 39: // right\n\t\t\t\t\tif (!this.o.keyboardNavigation)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdir = e.keyCode === 37 ? -1 : 1;\n\t\t\t\t\tif (e.ctrlKey){\n\t\t\t\t\t\tnewDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);\n\t\t\t\t\t\tnewViewDate = this.moveYear(focusDate, dir);\n\t\t\t\t\t\tthis._trigger('changeYear', this.viewDate);\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.shiftKey){\n\t\t\t\t\t\tnewDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);\n\t\t\t\t\t\tnewViewDate = this.moveMonth(focusDate, dir);\n\t\t\t\t\t\tthis._trigger('changeMonth', this.viewDate);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnewDate = new Date(this.dates.get(-1) || UTCToday());\n\t\t\t\t\t\tnewDate.setUTCDate(newDate.getUTCDate() + dir);\n\t\t\t\t\t\tnewViewDate = new Date(focusDate);\n\t\t\t\t\t\tnewViewDate.setUTCDate(focusDate.getUTCDate() + dir);\n\t\t\t\t\t}\n\t\t\t\t\tif (this.dateWithinRange(newDate)){\n\t\t\t\t\t\tthis.focusDate = this.viewDate = newViewDate;\n\t\t\t\t\t\tthis.setValue();\n\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 38: // up\n\t\t\t\tcase 40: // down\n\t\t\t\t\tif (!this.o.keyboardNavigation)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdir = e.keyCode === 38 ? -1 : 1;\n\t\t\t\t\tif (e.ctrlKey){\n\t\t\t\t\t\tnewDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);\n\t\t\t\t\t\tnewViewDate = this.moveYear(focusDate, dir);\n\t\t\t\t\t\tthis._trigger('changeYear', this.viewDate);\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.shiftKey){\n\t\t\t\t\t\tnewDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);\n\t\t\t\t\t\tnewViewDate = this.moveMonth(focusDate, dir);\n\t\t\t\t\t\tthis._trigger('changeMonth', this.viewDate);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnewDate = new Date(this.dates.get(-1) || UTCToday());\n\t\t\t\t\t\tnewDate.setUTCDate(newDate.getUTCDate() + dir * 7);\n\t\t\t\t\t\tnewViewDate = new Date(focusDate);\n\t\t\t\t\t\tnewViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);\n\t\t\t\t\t}\n\t\t\t\t\tif (this.dateWithinRange(newDate)){\n\t\t\t\t\t\tthis.focusDate = this.viewDate = newViewDate;\n\t\t\t\t\t\tthis.setValue();\n\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 32: // spacebar\n\t\t\t\t\t// Spacebar is used in manually typing dates in some formats.\n\t\t\t\t\t// As such, its behavior should not be hijacked.\n\t\t\t\t\tbreak;\n\t\t\t\tcase 13: // enter\n\t\t\t\t\tfocusDate = this.focusDate || this.dates.get(-1) || this.viewDate;\n\t\t\t\t\tthis._toggle_multidate(focusDate);\n\t\t\t\t\tdateChanged = true;\n\t\t\t\t\tthis.focusDate = null;\n\t\t\t\t\tthis.viewDate = this.dates.get(-1) || this.viewDate;\n\t\t\t\t\tthis.setValue();\n\t\t\t\t\tthis.fill();\n\t\t\t\t\tif (this.picker.is(':visible')){\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tif (this.o.autoclose)\n\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 9: // tab\n\t\t\t\t\tthis.focusDate = null;\n\t\t\t\t\tthis.viewDate = this.dates.get(-1) || this.viewDate;\n\t\t\t\t\tthis.fill();\n\t\t\t\t\tthis.hide();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (dateChanged){\n\t\t\t\tif (this.dates.length)\n\t\t\t\t\tthis._trigger('changeDate');\n\t\t\t\telse\n\t\t\t\t\tthis._trigger('clearDate');\n\t\t\t\tvar element;\n\t\t\t\tif (this.isInput){\n\t\t\t\t\telement = this.element;\n\t\t\t\t}\n\t\t\t\telse if (this.component){\n\t\t\t\t\telement = this.element.find('input');\n\t\t\t\t}\n\t\t\t\tif (element){\n\t\t\t\t\telement.change();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tshowMode: function(dir){\n\t\t\tif (dir){\n\t\t\t\tthis.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));\n\t\t\t}\n\t\t\tthis.picker\n\t\t\t\t.find('>div')\n\t\t\t\t.hide()\n\t\t\t\t.filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName)\n\t\t\t\t\t.css('display', 'block');\n\t\t\tthis.updateNavArrows();\n\t\t}\n\t};\n\n\tvar DateRangePicker = function(element, options){\n\t\tthis.element = $(element);\n\t\tthis.inputs = $.map(options.inputs, function(i){\n\t\t\treturn i.jquery ? i[0] : i;\n\t\t});\n\t\tdelete options.inputs;\n\n\t\t$(this.inputs)\n\t\t\t.datepicker(options)\n\t\t\t.bind('changeDate', $.proxy(this.dateUpdated, this));\n\n\t\tthis.pickers = $.map(this.inputs, function(i){\n\t\t\treturn $(i).data('datepicker');\n\t\t});\n\t\tthis.updateDates();\n\t};\n\tDateRangePicker.prototype = {\n\t\tupdateDates: function(){\n\t\t\tthis.dates = $.map(this.pickers, function(i){\n\t\t\t\treturn i.getUTCDate();\n\t\t\t});\n\t\t\tthis.updateRanges();\n\t\t},\n\t\tupdateRanges: function(){\n\t\t\tvar range = $.map(this.dates, function(d){\n\t\t\t\treturn d.valueOf();\n\t\t\t});\n\t\t\t$.each(this.pickers, function(i, p){\n\t\t\t\tp.setRange(range);\n\t\t\t});\n\t\t},\n\t\tdateUpdated: function(e){\n\t\t\t// `this.updating` is a workaround for preventing infinite recursion\n\t\t\t// between `changeDate` triggering and `setUTCDate` calling.  Until\n\t\t\t// there is a better mechanism.\n\t\t\tif (this.updating)\n\t\t\t\treturn;\n\t\t\tthis.updating = true;\n\n\t\t\tvar dp = $(e.target).data('datepicker'),\n\t\t\t\tnew_date = dp.getUTCDate(),\n\t\t\t\ti = $.inArray(e.target, this.inputs),\n\t\t\t\tl = this.inputs.length;\n\t\t\tif (i === -1)\n\t\t\t\treturn;\n\n\t\t\t$.each(this.pickers, function(i, p){\n\t\t\t\tif (!p.getUTCDate())\n\t\t\t\t\tp.setUTCDate(new_date);\n\t\t\t});\n\n\t\t\tif (new_date < this.dates[i]){\n\t\t\t\t// Date being moved earlier/left\n\t\t\t\twhile (i >= 0 && new_date < this.dates[i]){\n\t\t\t\t\tthis.pickers[i--].setUTCDate(new_date);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (new_date > this.dates[i]){\n\t\t\t\t// Date being moved later/right\n\t\t\t\twhile (i < l && new_date > this.dates[i]){\n\t\t\t\t\tthis.pickers[i++].setUTCDate(new_date);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.updateDates();\n\n\t\t\tdelete this.updating;\n\t\t},\n\t\tremove: function(){\n\t\t\t$.map(this.pickers, function(p){ p.remove(); });\n\t\t\tdelete this.element.data().datepicker;\n\t\t}\n\t};\n\n\tfunction opts_from_el(el, prefix){\n\t\t// Derive options from element data-attrs\n\t\tvar data = $(el).data(),\n\t\t\tout = {}, inkey,\n\t\t\treplace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');\n\t\tprefix = new RegExp('^' + prefix.toLowerCase());\n\t\tfunction re_lower(_,a){\n\t\t\treturn a.toLowerCase();\n\t\t}\n\t\tfor (var key in data)\n\t\t\tif (prefix.test(key)){\n\t\t\t\tinkey = key.replace(replace, re_lower);\n\t\t\t\tout[inkey] = data[key];\n\t\t\t}\n\t\treturn out;\n\t}\n\n\tfunction opts_from_locale(lang){\n\t\t// Derive options from locale plugins\n\t\tvar out = {};\n\t\t// Check if \"de-DE\" style date is available, if not language should\n\t\t// fallback to 2 letter code eg \"de\"\n\t\tif (!dates[lang]){\n\t\t\tlang = lang.split('-')[0];\n\t\t\tif (!dates[lang])\n\t\t\t\treturn;\n\t\t}\n\t\tvar d = dates[lang];\n\t\t$.each(locale_opts, function(i,k){\n\t\t\tif (k in d)\n\t\t\t\tout[k] = d[k];\n\t\t});\n\t\treturn out;\n\t}\n\n\tvar old = $.fn.datepicker;\n\t$.fn.datepicker = function(option){\n\t\tvar args = Array.apply(null, arguments);\n\t\targs.shift();\n\t\tvar internal_return;\n\t\tthis.each(function(){\n\t\t\tvar $this = $(this),\n\t\t\t\tdata = $this.data('datepicker'),\n\t\t\t\toptions = typeof option === 'object' && option;\n\t\t\tif (!data){\n\t\t\t\tvar elopts = opts_from_el(this, 'date'),\n\t\t\t\t\t// Preliminary otions\n\t\t\t\t\txopts = $.extend({}, defaults, elopts, options),\n\t\t\t\t\tlocopts = opts_from_locale(xopts.language),\n\t\t\t\t\t// Options priority: js args, data-attrs, locales, defaults\n\t\t\t\t\topts = $.extend({}, defaults, locopts, elopts, options);\n\t\t\t\tif ($this.is('.input-daterange') || opts.inputs){\n\t\t\t\t\tvar ropts = {\n\t\t\t\t\t\tinputs: opts.inputs || $this.find('input').toArray()\n\t\t\t\t\t};\n\t\t\t\t\t$this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts))));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$this.data('datepicker', (data = new Datepicker(this, opts)));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof option === 'string' && typeof data[option] === 'function'){\n\t\t\t\tinternal_return = data[option].apply(data, args);\n\t\t\t\tif (internal_return !== undefined)\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (internal_return !== undefined)\n\t\t\treturn internal_return;\n\t\telse\n\t\t\treturn this;\n\t};\n\n\tvar defaults = $.fn.datepicker.defaults = {\n\t\tautoclose: false,\n\t\tbeforeShowDay: $.noop,\n\t\tcalendarWeeks: false,\n\t\tclearBtn: false,\n\t\tdaysOfWeekDisabled: [],\n\t\tendDate: Infinity,\n\t\tforceParse: true,\n\t\tformat: 'yyyy-mm-dd',\n\t\tkeyboardNavigation: true,\n\t\tlanguage: 'en',\n\t\tminViewMode: 0,\n\t\tmultidate: false,\n\t\tmultidateSeparator: ',',\n\t\torientation: \"auto\",\n\t\trtl: false,\n\t\tstartDate: -Infinity,\n\t\tstartView: 0,\n\t\ttodayBtn: false,\n\t\ttodayHighlight: false,\n\t\tweekStart: 0\n\t};\n\tvar locale_opts = $.fn.datepicker.locale_opts = [\n\t\t'format',\n\t\t'rtl',\n\t\t'weekStart'\n\t];\n\t$.fn.datepicker.Constructor = Datepicker;\n\tvar dates = $.fn.datepicker.dates = {\n\t\ten: {\n\t\t\tdays: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\", \"星期日\"],\n\t\t\tdaysShort: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"日\"],\n\t\t\tdaysMin: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"日\"],\n\t\t\tmonths: [\"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"],\n\t\t\tmonthsShort: [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\"],\n\t\t\ttoday: \"今天\",\n\t\t\tclear: \"清空\"\n\t\t}\n\t};\n\n\tvar DPGlobal = {\n\t\tmodes: [\n\t\t\t{\n\t\t\t\tclsName: 'days',\n\t\t\t\tnavFnc: 'Month',\n\t\t\t\tnavStep: 1\n\t\t\t},\n\t\t\t{\n\t\t\t\tclsName: 'months',\n\t\t\t\tnavFnc: 'FullYear',\n\t\t\t\tnavStep: 1\n\t\t\t},\n\t\t\t{\n\t\t\t\tclsName: 'years',\n\t\t\t\tnavFnc: 'FullYear',\n\t\t\t\tnavStep: 10\n\t\t}],\n\t\tisLeapYear: function(year){\n\t\t\treturn (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));\n\t\t},\n\t\tgetDaysInMonth: function(year, month){\n\t\t\treturn [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];\n\t\t},\n\t\tvalidParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,\n\t\tnonpunctuation: /[^ -\\/:-@\\[\\u3400-\\u9fff-`{-~\\t\\n\\r]+/g,\n\t\tparseFormat: function(format){\n\t\t\t// IE treats \\0 as a string end in inputs (truncating the value),\n\t\t\t// so it's a bad format delimiter, anyway\n\t\t\tvar separators = format.replace(this.validParts, '\\0').split('\\0'),\n\t\t\t\tparts = format.match(this.validParts);\n\t\t\tif (!separators || !separators.length || !parts || parts.length === 0){\n\t\t\t\tthrow new Error(\"Invalid date format.\");\n\t\t\t}\n\t\t\treturn {separators: separators, parts: parts};\n\t\t},\n\t\tparseDate: function(date, format, language){\n\t\t\tif (!date)\n\t\t\t\treturn undefined;\n\t\t\tif (date instanceof Date)\n\t\t\t\treturn date;\n\t\t\tif (typeof format === 'string')\n\t\t\t\tformat = DPGlobal.parseFormat(format);\n\t\t\tvar part_re = /([\\-+]\\d+)([dmwy])/,\n\t\t\t\tparts = date.match(/([\\-+]\\d+)([dmwy])/g),\n\t\t\t\tpart, dir, i;\n\t\t\tif (/^[\\-+]\\d+[dmwy]([\\s,]+[\\-+]\\d+[dmwy])*$/.test(date)){\n\t\t\t\tdate = new Date();\n\t\t\t\tfor (i=0; i < parts.length; i++){\n\t\t\t\t\tpart = part_re.exec(parts[i]);\n\t\t\t\t\tdir = parseInt(part[1]);\n\t\t\t\t\tswitch (part[2]){\n\t\t\t\t\t\tcase 'd':\n\t\t\t\t\t\t\tdate.setUTCDate(date.getUTCDate() + dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'm':\n\t\t\t\t\t\t\tdate = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'w':\n\t\t\t\t\t\t\tdate.setUTCDate(date.getUTCDate() + dir * 7);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'y':\n\t\t\t\t\t\t\tdate = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);\n\t\t\t}\n\t\t\tparts = date && date.match(this.nonpunctuation) || [];\n\t\t\tdate = new Date();\n\t\t\tvar parsed = {},\n\t\t\t\tsetters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],\n\t\t\t\tsetters_map = {\n\t\t\t\t\tyyyy: function(d,v){\n\t\t\t\t\t\treturn d.setUTCFullYear(v);\n\t\t\t\t\t},\n\t\t\t\t\tyy: function(d,v){\n\t\t\t\t\t\treturn d.setUTCFullYear(2000+v);\n\t\t\t\t\t},\n\t\t\t\t\tm: function(d,v){\n\t\t\t\t\t\tif (isNaN(d))\n\t\t\t\t\t\t\treturn d;\n\t\t\t\t\t\tv -= 1;\n\t\t\t\t\t\twhile (v < 0) v += 12;\n\t\t\t\t\t\tv %= 12;\n\t\t\t\t\t\td.setUTCMonth(v);\n\t\t\t\t\t\twhile (d.getUTCMonth() !== v)\n\t\t\t\t\t\t\td.setUTCDate(d.getUTCDate()-1);\n\t\t\t\t\t\treturn d;\n\t\t\t\t\t},\n\t\t\t\t\td: function(d,v){\n\t\t\t\t\t\treturn d.setUTCDate(v);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tval, filtered;\n\t\t\tsetters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];\n\t\t\tsetters_map['dd'] = setters_map['d'];\n\t\t\tdate = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);\n\t\t\tvar fparts = format.parts.slice();\n\t\t\t// Remove noop parts\n\t\t\tif (parts.length !== fparts.length){\n\t\t\t\tfparts = $(fparts).filter(function(i,p){\n\t\t\t\t\treturn $.inArray(p, setters_order) !== -1;\n\t\t\t\t}).toArray();\n\t\t\t}\n\t\t\t// Process remainder\n\t\t\tfunction match_part(){\n\t\t\t\tvar m = this.slice(0, parts[i].length),\n\t\t\t\t\tp = parts[i].slice(0, m.length);\n\t\t\t\treturn m === p;\n\t\t\t}\n\t\t\tif (parts.length === fparts.length){\n\t\t\t\tvar cnt;\n\t\t\t\tfor (i=0, cnt = fparts.length; i < cnt; i++){\n\t\t\t\t\tval = parseInt(parts[i], 10);\n\t\t\t\t\tpart = fparts[i];\n\t\t\t\t\tif (isNaN(val)){\n\t\t\t\t\t\tswitch (part){\n\t\t\t\t\t\t\tcase 'MM':\n\t\t\t\t\t\t\t\tfiltered = $(dates[language].months).filter(match_part);\n\t\t\t\t\t\t\t\tval = $.inArray(filtered[0], dates[language].months) + 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'M':\n\t\t\t\t\t\t\t\tfiltered = $(dates[language].monthsShort).filter(match_part);\n\t\t\t\t\t\t\t\tval = $.inArray(filtered[0], dates[language].monthsShort) + 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparsed[part] = val;\n\t\t\t\t}\n\t\t\t\tvar _date, s;\n\t\t\t\tfor (i=0; i < setters_order.length; i++){\n\t\t\t\t\ts = setters_order[i];\n\t\t\t\t\tif (s in parsed && !isNaN(parsed[s])){\n\t\t\t\t\t\t_date = new Date(date);\n\t\t\t\t\t\tsetters_map[s](_date, parsed[s]);\n\t\t\t\t\t\tif (!isNaN(_date))\n\t\t\t\t\t\t\tdate = _date;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn date;\n\t\t},\n\t\tformatDate: function(date, format, language){\n\t\t\tif (!date)\n\t\t\t\treturn '';\n\t\t\tif (typeof format === 'string')\n\t\t\t\tformat = DPGlobal.parseFormat(format);\n\t\t\tvar val = {\n\t\t\t\td: date.getUTCDate(),\n\t\t\t\tD: dates[language].daysShort[date.getUTCDay()],\n\t\t\t\tDD: dates[language].days[date.getUTCDay()],\n\t\t\t\tm: date.getUTCMonth() + 1,\n\t\t\t\tM: dates[language].monthsShort[date.getUTCMonth()],\n\t\t\t\tMM: dates[language].months[date.getUTCMonth()],\n\t\t\t\tyy: date.getUTCFullYear().toString().substring(2),\n\t\t\t\tyyyy: date.getUTCFullYear()\n\t\t\t};\n\t\t\tval.dd = (val.d < 10 ? '0' : '') + val.d;\n\t\t\tval.mm = (val.m < 10 ? '0' : '') + val.m;\n\t\t\tdate = [];\n\t\t\tvar seps = $.extend([], format.separators);\n\t\t\tfor (var i=0, cnt = format.parts.length; i <= cnt; i++){\n\t\t\t\tif (seps.length)\n\t\t\t\t\tdate.push(seps.shift());\n\t\t\t\tdate.push(val[format.parts[i]]);\n\t\t\t}\n\t\t\treturn date.join('');\n\t\t},\n\t\theadTemplate: '<thead>'+\n\t\t\t\t\t\t\t'<tr>'+\n\t\t\t\t\t\t\t\t'<th class=\"prev\">&laquo;</th>'+\n\t\t\t\t\t\t\t\t'<th colspan=\"5\" class=\"datepicker-switch\"></th>'+\n\t\t\t\t\t\t\t\t'<th class=\"next\">&raquo;</th>'+\n\t\t\t\t\t\t\t'</tr>'+\n\t\t\t\t\t\t'</thead>',\n\t\tcontTemplate: '<tbody><tr><td colspan=\"7\"></td></tr></tbody>',\n\t\tfootTemplate: '<tfoot>'+\n\t\t\t\t\t\t\t'<tr>'+\n\t\t\t\t\t\t\t\t'<th colspan=\"7\" class=\"today\"></th>'+\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 colspan=\"7\" class=\"clear\"></th>'+\n\t\t\t\t\t\t\t'</tr>'+\n\t\t\t\t\t\t'</tfoot>'\n\t};\n\tDPGlobal.template = '<div class=\"datepicker\">'+\n\t\t\t\t\t\t\t'<div class=\"datepicker-days\">'+\n\t\t\t\t\t\t\t\t'<table class=\" table-condensed\">'+\n\t\t\t\t\t\t\t\t\tDPGlobal.headTemplate+\n\t\t\t\t\t\t\t\t\t'<tbody></tbody>'+\n\t\t\t\t\t\t\t\t\tDPGlobal.footTemplate+\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\t'<div class=\"datepicker-months\">'+\n\t\t\t\t\t\t\t\t'<table class=\"table-condensed\">'+\n\t\t\t\t\t\t\t\t\tDPGlobal.headTemplate+\n\t\t\t\t\t\t\t\t\tDPGlobal.contTemplate+\n\t\t\t\t\t\t\t\t\tDPGlobal.footTemplate+\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\t'<div class=\"datepicker-years\">'+\n\t\t\t\t\t\t\t\t'<table class=\"table-condensed\">'+\n\t\t\t\t\t\t\t\t\tDPGlobal.headTemplate+\n\t\t\t\t\t\t\t\t\tDPGlobal.contTemplate+\n\t\t\t\t\t\t\t\t\tDPGlobal.footTemplate+\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\n\t$.fn.datepicker.DPGlobal = DPGlobal;\n\n\n\t/* DATEPICKER NO CONFLICT\n\t* =================== */\n\n\t$.fn.datepicker.noConflict = function(){\n\t\t$.fn.datepicker = old;\n\t\treturn this;\n\t};\n\n\n\t/* DATEPICKER DATA-API\n\t* ================== */\n\n\t$(document).on(\n\t\t'focus.datepicker.data-api click.datepicker.data-api',\n\t\t'[data-provide=\"datepicker\"]',\n\t\tfunction(e){\n\t\t\tvar $this = $(this);\n\t\t\tif ($this.data('datepicker'))\n\t\t\t\treturn;\n\t\t\te.preventDefault();\n\t\t\t// component click requires us to explicitly show it\n\t\t\t$this.datepicker('show');\n\t\t}\n\t);\n\t$(function(){\n\t\t$('[data-provide=\"datepicker-inline\"]').datepicker();\n\t});\n\n}(window.jQuery));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/diff_match_patch/diff_match_patch.js",
    "content": "(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}\ndiff_match_patch.prototype.diff_main=function(a,b,c,d){\"undefined\"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error(\"Null input. (diff_main)\");if(a==b)return a?[[0,a]]:[];\"undefined\"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,\nb,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};\ndiff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,\nd):this.diff_bisect_(a,b,d)};\ndiff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,\"\"]);for(var e=d=b=0,f=\"\",g=\"\";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=\"\"}b++}a.pop();return a};\ndiff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=\nu)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};\ndiff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};\ndiff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b=\"\",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf(\"\\n\",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]=\"\";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\ndiff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join(\"\")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\ndiff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g=\"\",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;\nvar d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};\ndiff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];\nd=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};\ndiff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);\nreturn i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=\nh,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\ndiff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,\"\"]);for(var b=0,c=0,d=0,e=\"\",f=\"\",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-\ng),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=\"\"}\"\"===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,\na[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};\ndiff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,\"&amp;\").replace(d,\"&lt;\").replace(e,\"&gt;\").replace(f,\"&para;<br>\");switch(h){case 1:b[g]='<ins style=\"background:#e6ffe6;\">'+j+\"</ins>\";break;case -1:b[g]='<del style=\"background:#ffe6e6;\">'+j+\"</del>\";break;case 0:b[g]=\"<span>\"+j+\"</span>\"}}return b.join(\"\")};\ndiff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\ndiff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]=\"+\"+encodeURI(a[c][1]);break;case -1:b[c]=\"-\"+a[c][1].length;break;case 0:b[c]=\"=\"+a[c][1].length}return b.join(\"\\t\").replace(/%20/g,\" \")};\ndiff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case \"+\":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error(\"Illegal escape in diff_fromDelta: \"+h);}break;case \"-\":case \"=\":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error(\"Invalid number in diff_fromDelta: \"+h);h=a.substring(e,e+=i);\"=\"==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error(\"Invalid diff operation in diff_fromDelta: \"+\nf[g]);}}if(e!=a.length)throw Error(\"Delta length (\"+e+\") does not equal source text length (\"+a.length+\").\");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error(\"Null input. (match_main)\");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\ndiff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error(\"Pattern too long for this browser.\");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+\nk)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};\ndiff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\ndiff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=\nc.length+d.length;a.length2+=c.length+d.length}};\ndiff_match_patch.prototype.patch_make=function(a,b,c){var d;if(\"string\"==typeof a&&\"string\"==typeof b&&\"undefined\"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&\"object\"==typeof a&&\"undefined\"==typeof b&&\"undefined\"==typeof c)b=a,d=this.diff_text1(b);else if(\"string\"==typeof a&&b&&\"object\"==typeof b&&\"undefined\"==typeof c)d=a;else if(\"string\"==typeof a&&\"string\"==typeof b&&c&&\"object\"==typeof c)d=a,b=c;else throw Error(\"Unknown call format to patch_make.\");\nif(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&\ne&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\ndiff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);\nif(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,\nj+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\ndiff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c=\"\",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,\nc]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\ndiff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g=\"\";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;\"\"!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),\nj=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);\"\"!==i&&\n(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join(\"\")};\ndiff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split(\"\\n\");for(var c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error(\"Invalid patch string: \"+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);\"\"===e[2]?(f.start1--,f.length1=1):\"0\"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);\"\"===e[4]?(f.start2--,f.length2=1):\"0\"==e[4]?f.length2=0:(f.start2--,f.length2=\nparseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error(\"Illegal escape in patch_fromText: \"+g);}if(\"-\"==e)f.diffs.push([-1,g]);else if(\"+\"==e)f.diffs.push([1,g]);else if(\" \"==e)f.diffs.push([0,g]);else if(\"@\"==e)break;else if(\"\"!==e)throw Error('Invalid patch mode \"'+e+'\" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\ndiff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+\",0\":1==this.length1?this.start1+1:this.start1+1+\",\"+this.length1;b=0===this.length2?this.start2+\",0\":1==this.length2?this.start2+1:this.start2+1+\",\"+this.length2;a=[\"@@ -\"+a+\" +\"+b+\" @@\\n\"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c=\"+\";break;case -1:c=\"-\";break;case 0:c=\" \"}a[b+1]=c+encodeURI(this.diffs[b][1])+\"\\n\"}return a.join(\"\").replace(/%20/g,\" \")};\nthis.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/distpicker/distpicker.js",
    "content": "/*!\n * Distpicker v1.0.4\n * https://github.com/fengyuanchen/distpicker\n *\n * Copyright (c) 2014-2016 Fengyuan Chen\n * Released under the MIT license\n *\n * Date: 2016-06-01T15:05:52.606Z\n */\n\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as anonymous module.\n    define(['jquery', 'ChineseDistricts'], factory);\n  } else if (typeof exports === 'object') {\n    // Node / CommonJS\n    factory(require('jquery'), require('ChineseDistricts'));\n  } else {\n    // Browser globals.\n    factory(jQuery, ChineseDistricts);\n  }\n})(function ($, ChineseDistricts) {\n\n  'use strict';\n\n  if (typeof ChineseDistricts === 'undefined') {\n    throw new Error('The file \"distpicker.data.js\" must be included first!');\n  }\n\n  var NAMESPACE = 'distpicker';\n  var EVENT_CHANGE = 'change.' + NAMESPACE;\n  var PROVINCE = 'province';\n  var CIRY = 'city';\n  var DISTRICT = 'district';\n\n  function Distpicker(element, options) {\n    this.$element = $(element);\n    this.options = $.extend({}, Distpicker.DEFAULTS, $.isPlainObject(options) && options);\n    this.placeholders = $.extend({}, Distpicker.DEFAULTS);\n    this.active = false;\n    this.init();\n  }\n\n  Distpicker.prototype = {\n    constructor: Distpicker,\n\n    init: function () {\n      var options = this.options;\n      var $select = this.$element.find('select');\n      var length = $select.length;\n      var data = {};\n\n      $select.each(function () {\n        $.extend(data, $(this).data());\n      });\n\n      $.each([PROVINCE, CIRY, DISTRICT], $.proxy(function (i, type) {\n        if (data[type]) {\n          options[type] = data[type];\n          this['$' + type] = $select.filter('[data-' + type + ']');\n        } else {\n          this['$' + type] = length > i ? $select.eq(i) : null;\n        }\n      }, this));\n\n      this.bind();\n\n      // Reset all the selects (after event binding)\n      this.reset();\n\n      this.active = true;\n    },\n\n    bind: function () {\n      if (this.$province) {\n        this.$province.on(EVENT_CHANGE, (this._changeProvince = $.proxy(function () {\n          this.output(CIRY);\n          this.output(DISTRICT);\n        }, this)));\n      }\n\n      if (this.$city) {\n        this.$city.on(EVENT_CHANGE, (this._changeCity = $.proxy(function () {\n          this.output(DISTRICT);\n        }, this)));\n      }\n    },\n\n    unbind: function () {\n      if (this.$province) {\n        this.$province.off(EVENT_CHANGE, this._changeProvince);\n      }\n\n      if (this.$city) {\n        this.$city.off(EVENT_CHANGE, this._changeCity);\n      }\n    },\n\n    output: function (type) {\n      var options = this.options;\n      var placeholders = this.placeholders;\n      var $select = this['$' + type];\n      var districts = {};\n      var data = [];\n      var code;\n      var matched;\n      var value;\n\n      if (!$select || !$select.length) {\n        return;\n      }\n\n      value = options[type];\n\n      code = (\n        type === PROVINCE ? 86 :\n        type === CIRY ? this.$province && this.$province.find(':selected').data('code') :\n        type === DISTRICT ? this.$city && this.$city.find(':selected').data('code') : code\n      );\n\n      districts = $.isNumeric(code) ? ChineseDistricts[code] : null;\n\n      if ($.isPlainObject(districts)) {\n        $.each(districts, function (code, address) {\n          var selected = address === value;\n\n          if (selected) {\n            matched = true;\n          }\n\n          data.push({\n            code: code,\n            address: address,\n            selected: selected\n          });\n        });\n      }\n\n      if (!matched) {\n        if (data.length && (options.autoSelect || options.autoselect)) {\n          data[0].selected = true;\n        }\n\n        // Save the unmatched value as a placeholder at the first output\n        if (!this.active && value) {\n          placeholders[type] = value;\n        }\n      }\n\n      // Add placeholder option\n      if (options.placeholder) {\n        data.unshift({\n          code: '',\n          address: placeholders[type],\n          selected: false\n        });\n      }\n\n      $select.html(this.getList(data));\n    },\n\n    getList: function (data) {\n      var list = [];\n\n      $.each(data, function (i, n) {\n        list.push(\n          '<option' +\n          ' value=\"' + (n.address && n.code ? n.address : '') + '\"' +\n          ' data-code=\"' + (n.code || '') + '\"' +\n          (n.selected ? ' selected' : '') +\n          '>' +\n            (n.address || '') +\n          '</option>'\n        );\n      });\n\n      return list.join('');\n    },\n\n    reset: function (deep) {\n      if (!deep) {\n        this.output(PROVINCE);\n        this.output(CIRY);\n        this.output(DISTRICT);\n      } else if (this.$province) {\n        this.$province.find(':first').prop('selected', true).trigger(EVENT_CHANGE);\n      }\n    },\n\n    destroy: function () {\n      this.unbind();\n      this.$element.removeData(NAMESPACE);\n    }\n  };\n\n  Distpicker.DEFAULTS = {\n    autoSelect: true,\n    placeholder: true,\n    province: '—— 省 ——',\n    city: '—— 市 ——',\n    district: '—— 区 ——'\n  };\n\n  Distpicker.setDefaults = function (options) {\n    $.extend(Distpicker.DEFAULTS, options);\n  };\n\n  // Save the other distpicker\n  Distpicker.other = $.fn.distpicker;\n\n  // Register as jQuery plugin\n  $.fn.distpicker = function (option) {\n    var args = [].slice.call(arguments, 1);\n\n    return this.each(function () {\n      var $this = $(this);\n      var data = $this.data(NAMESPACE);\n      var options;\n      var fn;\n\n      if (!data) {\n        if (/destroy/.test(option)) {\n          return;\n        }\n\n        options = $.extend({}, $this.data(), $.isPlainObject(option) && option);\n        $this.data(NAMESPACE, (data = new Distpicker(this, options)));\n      }\n\n      if (typeof option === 'string' && $.isFunction(fn = data[option])) {\n        fn.apply(data, args);\n      }\n    });\n  };\n\n  $.fn.distpicker.Constructor = Distpicker;\n  $.fn.distpicker.setDefaults = Distpicker.setDefaults;\n\n  // No conflict\n  $.fn.distpicker.noConflict = function () {\n    $.fn.distpicker = Distpicker.other;\n    return this;\n  };\n\n  $(function () {\n    $('[data-toggle=\"distpicker\"]').distpicker();\n  });\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/dropzone/dropzone.js",
    "content": "\n;(function(){\n\n    /**\n     * Require the module at `name`.\n     *\n     * @param {String} name\n     * @return {Object} exports\n     * @api public\n     */\n\n    function require(name) {\n        var module = require.modules[name];\n        if (!module) throw new Error('failed to require \"' + name + '\"');\n\n        if (!('exports' in module) && typeof module.definition === 'function') {\n            module.client = module.component = true;\n            module.definition.call(this, module.exports = {}, module);\n            delete module.definition;\n        }\n\n        return module.exports;\n    }\n\n    /**\n     * Registered modules.\n     */\n\n    require.modules = {};\n\n    /**\n     * Register module at `name` with callback `definition`.\n     *\n     * @param {String} name\n     * @param {Function} definition\n     * @api private\n     */\n\n    require.register = function (name, definition) {\n        require.modules[name] = {\n            definition: definition\n        };\n    };\n\n    /**\n     * Define a module's exports immediately with `exports`.\n     *\n     * @param {String} name\n     * @param {Generic} exports\n     * @api private\n     */\n\n    require.define = function (name, exports) {\n        require.modules[name] = {\n            exports: exports\n        };\n    };\n    require.register(\"component~emitter@1.1.2\", function (exports, module) {\n\n        /**\n         * Expose `Emitter`.\n         */\n\n        module.exports = Emitter;\n\n        /**\n         * Initialize a new `Emitter`.\n         *\n         * @api public\n         */\n\n        function Emitter(obj) {\n            if (obj) return mixin(obj);\n        };\n\n        /**\n         * Mixin the emitter properties.\n         *\n         * @param {Object} obj\n         * @return {Object}\n         * @api private\n         */\n\n        function mixin(obj) {\n            for (var key in Emitter.prototype) {\n                obj[key] = Emitter.prototype[key];\n            }\n            return obj;\n        }\n\n        /**\n         * Listen on the given `event` with `fn`.\n         *\n         * @param {String} event\n         * @param {Function} fn\n         * @return {Emitter}\n         * @api public\n         */\n\n        Emitter.prototype.on =\n            Emitter.prototype.addEventListener = function(event, fn){\n                this._callbacks = this._callbacks || {};\n                (this._callbacks[event] = this._callbacks[event] || [])\n                    .push(fn);\n                return this;\n            };\n\n        /**\n         * Adds an `event` listener that will be invoked a single\n         * time then automatically removed.\n         *\n         * @param {String} event\n         * @param {Function} fn\n         * @return {Emitter}\n         * @api public\n         */\n\n        Emitter.prototype.once = function(event, fn){\n            var self = this;\n            this._callbacks = this._callbacks || {};\n\n            function on() {\n                self.off(event, on);\n                fn.apply(this, arguments);\n            }\n\n            on.fn = fn;\n            this.on(event, on);\n            return this;\n        };\n\n        /**\n         * Remove the given callback for `event` or all\n         * registered callbacks.\n         *\n         * @param {String} event\n         * @param {Function} fn\n         * @return {Emitter}\n         * @api public\n         */\n\n        Emitter.prototype.off =\n            Emitter.prototype.removeListener =\n                Emitter.prototype.removeAllListeners =\n                    Emitter.prototype.removeEventListener = function(event, fn){\n                        this._callbacks = this._callbacks || {};\n\n                        // all\n                        if (0 == arguments.length) {\n                            this._callbacks = {};\n                            return this;\n                        }\n\n                        // specific event\n                        var callbacks = this._callbacks[event];\n                        if (!callbacks) return this;\n\n                        // remove all handlers\n                        if (1 == arguments.length) {\n                            delete this._callbacks[event];\n                            return this;\n                        }\n\n                        // remove specific handler\n                        var cb;\n                        for (var i = 0; i < callbacks.length; i++) {\n                            cb = callbacks[i];\n                            if (cb === fn || cb.fn === fn) {\n                                callbacks.splice(i, 1);\n                                break;\n                            }\n                        }\n                        return this;\n                    };\n\n        /**\n         * Emit `event` with the given args.\n         *\n         * @param {String} event\n         * @param {Mixed} ...\n         * @return {Emitter}\n         */\n\n        Emitter.prototype.emit = function(event){\n            this._callbacks = this._callbacks || {};\n            var args = [].slice.call(arguments, 1)\n                , callbacks = this._callbacks[event];\n\n            if (callbacks) {\n                callbacks = callbacks.slice(0);\n                for (var i = 0, len = callbacks.length; i < len; ++i) {\n                    callbacks[i].apply(this, args);\n                }\n            }\n\n            return this;\n        };\n\n        /**\n         * Return array of callbacks for `event`.\n         *\n         * @param {String} event\n         * @return {Array}\n         * @api public\n         */\n\n        Emitter.prototype.listeners = function(event){\n            this._callbacks = this._callbacks || {};\n            return this._callbacks[event] || [];\n        };\n\n        /**\n         * Check if this emitter has `event` handlers.\n         *\n         * @param {String} event\n         * @return {Boolean}\n         * @api public\n         */\n\n        Emitter.prototype.hasListeners = function(event){\n            return !! this.listeners(event).length;\n        };\n\n    });\n\n    require.register(\"dropzone\", function (exports, module) {\n\n\n        /**\n         * Exposing dropzone\n         */\n        module.exports = require(\"dropzone/lib/dropzone.js\");\n\n    });\n\n    require.register(\"dropzone/lib/dropzone.js\", function (exports, module) {\n\n        /*\n         *\n         * More info at [www.dropzonejs.com](http://www.dropzonejs.com)\n         *\n         * Copyright (c) 2012, Matias Meno\n         *\n         * Permission is hereby granted, free of charge, to any person obtaining a copy\n         * of this software and associated documentation files (the \"Software\"), to deal\n         * in the Software without restriction, including without limitation the rights\n         * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n         * copies of the Software, and to permit persons to whom the Software is\n         * furnished to do so, subject to the following conditions:\n         *\n         * The above copyright notice and this permission notice shall be included in\n         * all copies or substantial portions of the Software.\n         *\n         * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n         * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n         * THE SOFTWARE.\n         *\n         */\n\n        (function() {\n            var Dropzone, Em, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without,\n                __hasProp = {}.hasOwnProperty,\n                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n                __slice = [].slice;\n\n            Em = typeof Emitter !== \"undefined\" && Emitter !== null ? Emitter : require(\"component~emitter@1.1.2\");\n\n            noop = function() {};\n\n            Dropzone = (function(_super) {\n                var extend;\n\n                __extends(Dropzone, _super);\n\n\n                /*\n                 This is a list of all available events you can register on a dropzone object.\n\n                 You can register an event handler like this:\n\n                 dropzone.on(\"dragEnter\", function() { });\n                 */\n\n                Dropzone.prototype.events = [\"drop\", \"dragstart\", \"dragend\", \"dragenter\", \"dragover\", \"dragleave\", \"addedfile\", \"removedfile\", \"thumbnail\", \"error\", \"errormultiple\", \"processing\", \"processingmultiple\", \"uploadprogress\", \"totaluploadprogress\", \"sending\", \"sendingmultiple\", \"success\", \"successmultiple\", \"canceled\", \"canceledmultiple\", \"complete\", \"completemultiple\", \"reset\", \"maxfilesexceeded\", \"maxfilesreached\"];\n\n                Dropzone.prototype.defaultOptions = {\n                    url: null,\n                    method: \"post\",\n                    withCredentials: false,\n                    parallelUploads: 2,\n                    uploadMultiple: false,\n                    maxFilesize: 256,\n                    paramName: \"file\",\n                    createImageThumbnails: true,\n                    maxThumbnailFilesize: 10,\n                    thumbnailWidth: 100,\n                    thumbnailHeight: 100,\n                    maxFiles: null,\n                    params: {},\n                    clickable: true,\n                    ignoreHiddenFiles: true,\n                    acceptedFiles: null,\n                    acceptedMimeTypes: null,\n                    autoProcessQueue: true,\n                    autoQueue: true,\n                    addRemoveLinks: false,\n                    previewsContainer: null,\n                    dictDefaultMessage: \"Drop files here to upload\",\n                    dictFallbackMessage: \"Your browser does not support drag'n'drop file uploads.\",\n                    dictFallbackText: \"Please use the fallback form below to upload your files like in the olden days.\",\n                    dictFileTooBig: \"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.\",\n                    dictInvalidFileType: \"You can't upload files of this type.\",\n                    dictResponseError: \"Server responded with {{statusCode}} code.\",\n                    dictCancelUpload: \"Cancel upload\",\n                    dictCancelUploadConfirmation: \"Are you sure you want to cancel this upload?\",\n                    dictRemoveFile: \"Remove file\",\n                    dictRemoveFileConfirmation: null,\n                    dictMaxFilesExceeded: \"You can not upload any more files.\",\n                    accept: function(file, done) {\n                        return done();\n                    },\n                    init: function() {\n                        return noop;\n                    },\n                    forceFallback: false,\n                    fallback: function() {\n                        var child, messageElement, span, _i, _len, _ref;\n                        this.element.className = \"\" + this.element.className + \" dz-browser-not-supported\";\n                        _ref = this.element.getElementsByTagName(\"div\");\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            child = _ref[_i];\n                            if (/(^| )dz-message($| )/.test(child.className)) {\n                                messageElement = child;\n                                child.className = \"dz-message\";\n                                continue;\n                            }\n                        }\n                        if (!messageElement) {\n                            messageElement = Dropzone.createElement(\"<div class=\\\"dz-message\\\"><span></span></div>\");\n                            this.element.appendChild(messageElement);\n                        }\n                        span = messageElement.getElementsByTagName(\"span\")[0];\n                        if (span) {\n                            span.textContent = this.options.dictFallbackMessage;\n                        }\n                        return this.element.appendChild(this.getFallbackForm());\n                    },\n                    resize: function(file) {\n                        var info, srcRatio, trgRatio;\n                        info = {\n                            srcX: 0,\n                            srcY: 0,\n                            srcWidth: file.width,\n                            srcHeight: file.height\n                        };\n                        srcRatio = file.width / file.height;\n                        trgRatio = this.options.thumbnailWidth / this.options.thumbnailHeight;\n                        if (file.height < this.options.thumbnailHeight || file.width < this.options.thumbnailWidth) {\n                            info.trgHeight = info.srcHeight;\n                            info.trgWidth = info.srcWidth;\n                        } else {\n                            if (srcRatio > trgRatio) {\n                                info.srcHeight = file.height;\n                                info.srcWidth = info.srcHeight * trgRatio;\n                            } else {\n                                info.srcWidth = file.width;\n                                info.srcHeight = info.srcWidth / trgRatio;\n                            }\n                        }\n                        info.srcX = (file.width - info.srcWidth) / 2;\n                        info.srcY = (file.height - info.srcHeight) / 2;\n                        return info;\n                    },\n\n                    /*\n                     Those functions register themselves to the events on init and handle all\n                     the user interface specific stuff. Overwriting them won't break the upload\n                     but can break the way it's displayed.\n                     You can overwrite them if you don't like the default behavior. If you just\n                     want to add an additional event handler, register it on the dropzone object\n                     and don't overwrite those options.\n                     */\n                    drop: function(e) {\n                        return this.element.classList.remove(\"dz-drag-hover\");\n                    },\n                    dragstart: noop,\n                    dragend: function(e) {\n                        return this.element.classList.remove(\"dz-drag-hover\");\n                    },\n                    dragenter: function(e) {\n                        return this.element.classList.add(\"dz-drag-hover\");\n                    },\n                    dragover: function(e) {\n                        return this.element.classList.add(\"dz-drag-hover\");\n                    },\n                    dragleave: function(e) {\n                        return this.element.classList.remove(\"dz-drag-hover\");\n                    },\n                    paste: noop,\n                    reset: function() {\n                        return this.element.classList.remove(\"dz-started\");\n                    },\n                    addedfile: function(file) {\n                        var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;\n                        if (this.element === this.previewsContainer) {\n                            this.element.classList.add(\"dz-started\");\n                        }\n                        file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());\n                        file.previewTemplate = file.previewElement;\n                        this.previewsContainer.appendChild(file.previewElement);\n                        _ref = file.previewElement.querySelectorAll(\"[data-dz-name]\");\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            node = _ref[_i];\n                            node.textContent = file.name;\n                        }\n                        _ref1 = file.previewElement.querySelectorAll(\"[data-dz-size]\");\n                        for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n                            node = _ref1[_j];\n                            node.innerHTML = this.filesize(file.size);\n                        }\n                        if (this.options.addRemoveLinks) {\n                            file._removeLink = Dropzone.createElement(\"<a class=\\\"dz-remove\\\" href=\\\"javascript:undefined;\\\" data-dz-remove>\" + this.options.dictRemoveFile + \"</a>\");\n                            file.previewElement.appendChild(file._removeLink);\n                        }\n                        removeFileEvent = (function(_this) {\n                            return function(e) {\n                                e.preventDefault();\n                                e.stopPropagation();\n                                if (file.status === Dropzone.UPLOADING) {\n                                    return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {\n                                        return _this.removeFile(file);\n                                    });\n                                } else {\n                                    if (_this.options.dictRemoveFileConfirmation) {\n                                        return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {\n                                            return _this.removeFile(file);\n                                        });\n                                    } else {\n                                        return _this.removeFile(file);\n                                    }\n                                }\n                            };\n                        })(this);\n                        _ref2 = file.previewElement.querySelectorAll(\"[data-dz-remove]\");\n                        _results = [];\n                        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {\n                            removeLink = _ref2[_k];\n                            _results.push(removeLink.addEventListener(\"click\", removeFileEvent));\n                        }\n                        return _results;\n                    },\n                    removedfile: function(file) {\n                        var _ref;\n                        if ((_ref = file.previewElement) != null) {\n                            _ref.parentNode.removeChild(file.previewElement);\n                        }\n                        return this._updateMaxFilesReachedClass();\n                    },\n                    thumbnail: function(file, dataUrl) {\n                        var thumbnailElement, _i, _len, _ref, _results;\n                        file.previewElement.classList.remove(\"dz-file-preview\");\n                        file.previewElement.classList.add(\"dz-image-preview\");\n                        _ref = file.previewElement.querySelectorAll(\"[data-dz-thumbnail]\");\n                        _results = [];\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            thumbnailElement = _ref[_i];\n                            thumbnailElement.alt = file.name;\n                            _results.push(thumbnailElement.src = dataUrl);\n                        }\n                        return _results;\n                    },\n                    error: function(file, message) {\n                        var node, _i, _len, _ref, _results;\n                        file.previewElement.classList.add(\"dz-error\");\n                        if (typeof message !== \"String\" && message.error) {\n                            message = message.error;\n                        }\n                        _ref = file.previewElement.querySelectorAll(\"[data-dz-errormessage]\");\n                        _results = [];\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            node = _ref[_i];\n                            _results.push(node.textContent = message);\n                        }\n                        return _results;\n                    },\n                    errormultiple: noop,\n                    processing: function(file) {\n                        file.previewElement.classList.add(\"dz-processing\");\n                        if (file._removeLink) {\n                            return file._removeLink.textContent = this.options.dictCancelUpload;\n                        }\n                    },\n                    processingmultiple: noop,\n                    uploadprogress: function(file, progress, bytesSent) {\n                        var node, _i, _len, _ref, _results;\n                        _ref = file.previewElement.querySelectorAll(\"[data-dz-uploadprogress]\");\n                        _results = [];\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            node = _ref[_i];\n                            _results.push(node.style.width = \"\" + progress + \"%\");\n                        }\n                        return _results;\n                    },\n                    totaluploadprogress: noop,\n                    sending: noop,\n                    sendingmultiple: noop,\n                    success: function(file) {\n                        return file.previewElement.classList.add(\"dz-success\");\n                    },\n                    successmultiple: noop,\n                    canceled: function(file) {\n                        return this.emit(\"error\", file, \"Upload canceled.\");\n                    },\n                    canceledmultiple: noop,\n                    complete: function(file) {\n                        if (file._removeLink) {\n                            return file._removeLink.textContent = this.options.dictRemoveFile;\n                        }\n                    },\n                    completemultiple: noop,\n                    maxfilesexceeded: noop,\n                    maxfilesreached: noop,\n                    previewTemplate: \"<div class=\\\"dz-preview dz-file-preview\\\">\\n  <div class=\\\"dz-details\\\">\\n    <div class=\\\"dz-filename\\\"><span data-dz-name></span></div>\\n    <div class=\\\"dz-size\\\" data-dz-size></div>\\n    <img data-dz-thumbnail />\\n  </div>\\n  <div class=\\\"dz-progress\\\"><span class=\\\"dz-upload\\\" data-dz-uploadprogress></span></div>\\n  <div class=\\\"dz-success-mark\\\"><span>✔</span></div>\\n  <div class=\\\"dz-error-mark\\\"><span>✘</span></div>\\n  <div class=\\\"dz-error-message\\\"><span data-dz-errormessage></span></div>\\n</div>\"\n                };\n\n                extend = function() {\n                    var key, object, objects, target, val, _i, _len;\n                    target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n                    for (_i = 0, _len = objects.length; _i < _len; _i++) {\n                        object = objects[_i];\n                        for (key in object) {\n                            val = object[key];\n                            target[key] = val;\n                        }\n                    }\n                    return target;\n                };\n\n                function Dropzone(element, options) {\n                    var elementOptions, fallback, _ref;\n                    this.element = element;\n                    this.version = Dropzone.version;\n                    this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\\n*/g, \"\");\n                    this.clickableElements = [];\n                    this.listeners = [];\n                    this.files = [];\n                    if (typeof this.element === \"string\") {\n                        this.element = document.querySelector(this.element);\n                    }\n                    if (!(this.element && (this.element.nodeType != null))) {\n                        throw new Error(\"Invalid dropzone element.\");\n                    }\n                    if (this.element.dropzone) {\n                        throw new Error(\"Dropzone already attached.\");\n                    }\n                    Dropzone.instances.push(this);\n                    this.element.dropzone = this;\n                    elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};\n                    this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});\n                    if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {\n                        return this.options.fallback.call(this);\n                    }\n                    if (this.options.url == null) {\n                        this.options.url = this.element.getAttribute(\"action\");\n                    }\n                    if (!this.options.url) {\n                        throw new Error(\"No URL provided.\");\n                    }\n                    if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {\n                        throw new Error(\"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.\");\n                    }\n                    if (this.options.acceptedMimeTypes) {\n                        this.options.acceptedFiles = this.options.acceptedMimeTypes;\n                        delete this.options.acceptedMimeTypes;\n                    }\n                    this.options.method = this.options.method.toUpperCase();\n                    if ((fallback = this.getExistingFallback()) && fallback.parentNode) {\n                        fallback.parentNode.removeChild(fallback);\n                    }\n                    if (this.options.previewsContainer) {\n                        this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, \"previewsContainer\");\n                    } else {\n                        this.previewsContainer = this.element;\n                    }\n                    if (this.options.clickable) {\n                        if (this.options.clickable === true) {\n                            this.clickableElements = [this.element];\n                        } else {\n                            this.clickableElements = Dropzone.getElements(this.options.clickable, \"clickable\");\n                        }\n                    }\n                    this.init();\n                }\n\n                Dropzone.prototype.getAcceptedFiles = function() {\n                    var file, _i, _len, _ref, _results;\n                    _ref = this.files;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        if (file.accepted) {\n                            _results.push(file);\n                        }\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.getRejectedFiles = function() {\n                    var file, _i, _len, _ref, _results;\n                    _ref = this.files;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        if (!file.accepted) {\n                            _results.push(file);\n                        }\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.getFilesWithStatus = function(status) {\n                    var file, _i, _len, _ref, _results;\n                    _ref = this.files;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        if (file.status === status) {\n                            _results.push(file);\n                        }\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.getQueuedFiles = function() {\n                    return this.getFilesWithStatus(Dropzone.QUEUED);\n                };\n\n                Dropzone.prototype.getUploadingFiles = function() {\n                    return this.getFilesWithStatus(Dropzone.UPLOADING);\n                };\n\n                Dropzone.prototype.getActiveFiles = function() {\n                    var file, _i, _len, _ref, _results;\n                    _ref = this.files;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {\n                            _results.push(file);\n                        }\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.init = function() {\n                    var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1;\n                    if (this.element.tagName === \"form\") {\n                        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n                    }\n                    if (this.element.classList.contains(\"dropzone\") && !this.element.querySelector(\".dz-message\")) {\n                        this.element.appendChild(Dropzone.createElement(\"<div class=\\\"dz-default dz-message\\\"><span>\" + this.options.dictDefaultMessage + \"</span></div>\"));\n                    }\n                    if (this.clickableElements.length) {\n                        setupHiddenFileInput = (function(_this) {\n                            return function() {\n                                if (_this.hiddenFileInput) {\n                                    document.body.removeChild(_this.hiddenFileInput);\n                                }\n                                _this.hiddenFileInput = document.createElement(\"input\");\n                                _this.hiddenFileInput.setAttribute(\"type\", \"file\");\n                                if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {\n                                    _this.hiddenFileInput.setAttribute(\"multiple\", \"multiple\");\n                                }\n                                _this.hiddenFileInput.className = \"dz-hidden-input\";\n                                if (_this.options.acceptedFiles != null) {\n                                    _this.hiddenFileInput.setAttribute(\"accept\", _this.options.acceptedFiles);\n                                }\n                                _this.hiddenFileInput.style.visibility = \"hidden\";\n                                _this.hiddenFileInput.style.position = \"absolute\";\n                                _this.hiddenFileInput.style.top = \"0\";\n                                _this.hiddenFileInput.style.left = \"0\";\n                                _this.hiddenFileInput.style.height = \"0\";\n                                _this.hiddenFileInput.style.width = \"0\";\n                                document.body.appendChild(_this.hiddenFileInput);\n                                return _this.hiddenFileInput.addEventListener(\"change\", function() {\n                                    var file, files, _i, _len;\n                                    files = _this.hiddenFileInput.files;\n                                    if (files.length) {\n                                        for (_i = 0, _len = files.length; _i < _len; _i++) {\n                                            file = files[_i];\n                                            _this.addFile(file);\n                                        }\n                                    }\n                                    return setupHiddenFileInput();\n                                });\n                            };\n                        })(this);\n                        setupHiddenFileInput();\n                    }\n                    this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL;\n                    _ref1 = this.events;\n                    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n                        eventName = _ref1[_i];\n                        this.on(eventName, this.options[eventName]);\n                    }\n                    this.on(\"uploadprogress\", (function(_this) {\n                        return function() {\n                            return _this.updateTotalUploadProgress();\n                        };\n                    })(this));\n                    this.on(\"removedfile\", (function(_this) {\n                        return function() {\n                            return _this.updateTotalUploadProgress();\n                        };\n                    })(this));\n                    this.on(\"canceled\", (function(_this) {\n                        return function(file) {\n                            return _this.emit(\"complete\", file);\n                        };\n                    })(this));\n                    this.on(\"complete\", (function(_this) {\n                        return function(file) {\n                            if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {\n                                return setTimeout((function() {\n                                    return _this.emit(\"queuecomplete\");\n                                }), 0);\n                            }\n                        };\n                    })(this));\n                    noPropagation = function(e) {\n                        e.stopPropagation();\n                        if (e.preventDefault) {\n                            return e.preventDefault();\n                        } else {\n                            return e.returnValue = false;\n                        }\n                    };\n                    this.listeners = [\n                        {\n                            element: this.element,\n                            events: {\n                                \"dragstart\": (function(_this) {\n                                    return function(e) {\n                                        return _this.emit(\"dragstart\", e);\n                                    };\n                                })(this),\n                                \"dragenter\": (function(_this) {\n                                    return function(e) {\n                                        noPropagation(e);\n                                        return _this.emit(\"dragenter\", e);\n                                    };\n                                })(this),\n                                \"dragover\": (function(_this) {\n                                    return function(e) {\n                                        var efct;\n                                        try {\n                                            efct = e.dataTransfer.effectAllowed;\n                                        } catch (_error) {}\n                                        e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';\n                                        noPropagation(e);\n                                        return _this.emit(\"dragover\", e);\n                                    };\n                                })(this),\n                                \"dragleave\": (function(_this) {\n                                    return function(e) {\n                                        return _this.emit(\"dragleave\", e);\n                                    };\n                                })(this),\n                                \"drop\": (function(_this) {\n                                    return function(e) {\n                                        noPropagation(e);\n                                        return _this.drop(e);\n                                    };\n                                })(this),\n                                \"dragend\": (function(_this) {\n                                    return function(e) {\n                                        return _this.emit(\"dragend\", e);\n                                    };\n                                })(this)\n                            }\n                        }\n                    ];\n                    this.clickableElements.forEach((function(_this) {\n                        return function(clickableElement) {\n                            return _this.listeners.push({\n                                element: clickableElement,\n                                events: {\n                                    \"click\": function(evt) {\n                                        if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(\".dz-message\")))) {\n                                            return _this.hiddenFileInput.click();\n                                        }\n                                    }\n                                }\n                            });\n                        };\n                    })(this));\n                    this.enable();\n                    return this.options.init.call(this);\n                };\n\n                Dropzone.prototype.destroy = function() {\n                    var _ref;\n                    this.disable();\n                    this.removeAllFiles(true);\n                    if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) {\n                        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);\n                        this.hiddenFileInput = null;\n                    }\n                    delete this.element.dropzone;\n                    return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);\n                };\n\n                Dropzone.prototype.updateTotalUploadProgress = function() {\n                    var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref;\n                    totalBytesSent = 0;\n                    totalBytes = 0;\n                    activeFiles = this.getActiveFiles();\n                    if (activeFiles.length) {\n                        _ref = this.getActiveFiles();\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            file = _ref[_i];\n                            totalBytesSent += file.upload.bytesSent;\n                            totalBytes += file.upload.total;\n                        }\n                        totalUploadProgress = 100 * totalBytesSent / totalBytes;\n                    } else {\n                        totalUploadProgress = 100;\n                    }\n                    return this.emit(\"totaluploadprogress\", totalUploadProgress, totalBytes, totalBytesSent);\n                };\n\n                Dropzone.prototype.getFallbackForm = function() {\n                    var existingFallback, fields, fieldsString, form;\n                    if (existingFallback = this.getExistingFallback()) {\n                        return existingFallback;\n                    }\n                    fieldsString = \"<div class=\\\"dz-fallback\\\">\";\n                    if (this.options.dictFallbackText) {\n                        fieldsString += \"<p>\" + this.options.dictFallbackText + \"</p>\";\n                    }\n                    fieldsString += \"<input type=\\\"file\\\" name=\\\"\" + this.options.paramName + (this.options.uploadMultiple ? \"[]\" : \"\") + \"\\\" \" + (this.options.uploadMultiple ? 'multiple=\"multiple\"' : void 0) + \" /><input type=\\\"submit\\\" value=\\\"Upload!\\\"></div>\";\n                    fields = Dropzone.createElement(fieldsString);\n                    if (this.element.tagName !== \"FORM\") {\n                        form = Dropzone.createElement(\"<form action=\\\"\" + this.options.url + \"\\\" enctype=\\\"multipart/form-data\\\" method=\\\"\" + this.options.method + \"\\\"></form>\");\n                        form.appendChild(fields);\n                    } else {\n                        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n                        this.element.setAttribute(\"method\", this.options.method);\n                    }\n                    return form != null ? form : fields;\n                };\n\n                Dropzone.prototype.getExistingFallback = function() {\n                    var fallback, getFallback, tagName, _i, _len, _ref;\n                    getFallback = function(elements) {\n                        var el, _i, _len;\n                        for (_i = 0, _len = elements.length; _i < _len; _i++) {\n                            el = elements[_i];\n                            if (/(^| )fallback($| )/.test(el.className)) {\n                                return el;\n                            }\n                        }\n                    };\n                    _ref = [\"div\", \"form\"];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        tagName = _ref[_i];\n                        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {\n                            return fallback;\n                        }\n                    }\n                };\n\n                Dropzone.prototype.setupEventListeners = function() {\n                    var elementListeners, event, listener, _i, _len, _ref, _results;\n                    _ref = this.listeners;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        elementListeners = _ref[_i];\n                        _results.push((function() {\n                            var _ref1, _results1;\n                            _ref1 = elementListeners.events;\n                            _results1 = [];\n                            for (event in _ref1) {\n                                listener = _ref1[event];\n                                _results1.push(elementListeners.element.addEventListener(event, listener, false));\n                            }\n                            return _results1;\n                        })());\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.removeEventListeners = function() {\n                    var elementListeners, event, listener, _i, _len, _ref, _results;\n                    _ref = this.listeners;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        elementListeners = _ref[_i];\n                        _results.push((function() {\n                            var _ref1, _results1;\n                            _ref1 = elementListeners.events;\n                            _results1 = [];\n                            for (event in _ref1) {\n                                listener = _ref1[event];\n                                _results1.push(elementListeners.element.removeEventListener(event, listener, false));\n                            }\n                            return _results1;\n                        })());\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.disable = function() {\n                    var file, _i, _len, _ref, _results;\n                    this.clickableElements.forEach(function(element) {\n                        return element.classList.remove(\"dz-clickable\");\n                    });\n                    this.removeEventListeners();\n                    _ref = this.files;\n                    _results = [];\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        _results.push(this.cancelUpload(file));\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype.enable = function() {\n                    this.clickableElements.forEach(function(element) {\n                        return element.classList.add(\"dz-clickable\");\n                    });\n                    return this.setupEventListeners();\n                };\n\n                Dropzone.prototype.filesize = function(size) {\n                    var string;\n                    if (size >= 1024 * 1024 * 1024 * 1024 / 10) {\n                        size = size / (1024 * 1024 * 1024 * 1024 / 10);\n                        string = \"TiB\";\n                    } else if (size >= 1024 * 1024 * 1024 / 10) {\n                        size = size / (1024 * 1024 * 1024 / 10);\n                        string = \"GiB\";\n                    } else if (size >= 1024 * 1024 / 10) {\n                        size = size / (1024 * 1024 / 10);\n                        string = \"MiB\";\n                    } else if (size >= 1024 / 10) {\n                        size = size / (1024 / 10);\n                        string = \"KiB\";\n                    } else {\n                        size = size * 10;\n                        string = \"b\";\n                    }\n                    return \"<strong>\" + (Math.round(size) / 10) + \"</strong> \" + string;\n                };\n\n                Dropzone.prototype._updateMaxFilesReachedClass = function() {\n                    if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {\n                        if (this.getAcceptedFiles().length === this.options.maxFiles) {\n                            this.emit('maxfilesreached', this.files);\n                        }\n                        return this.element.classList.add(\"dz-max-files-reached\");\n                    } else {\n                        return this.element.classList.remove(\"dz-max-files-reached\");\n                    }\n                };\n\n                Dropzone.prototype.drop = function(e) {\n                    var files, items;\n                    if (!e.dataTransfer) {\n                        return;\n                    }\n                    this.emit(\"drop\", e);\n                    files = e.dataTransfer.files;\n                    if (files.length) {\n                        items = e.dataTransfer.items;\n                        if (items && items.length && (items[0].webkitGetAsEntry != null)) {\n                            this._addFilesFromItems(items);\n                        } else {\n                            this.handleFiles(files);\n                        }\n                    }\n                };\n\n                Dropzone.prototype.paste = function(e) {\n                    var items, _ref;\n                    if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {\n                        return;\n                    }\n                    this.emit(\"paste\", e);\n                    items = e.clipboardData.items;\n                    if (items.length) {\n                        return this._addFilesFromItems(items);\n                    }\n                };\n\n                Dropzone.prototype.handleFiles = function(files) {\n                    var file, _i, _len, _results;\n                    _results = [];\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        _results.push(this.addFile(file));\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype._addFilesFromItems = function(items) {\n                    var entry, item, _i, _len, _results;\n                    _results = [];\n                    for (_i = 0, _len = items.length; _i < _len; _i++) {\n                        item = items[_i];\n                        if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {\n                            if (entry.isFile) {\n                                _results.push(this.addFile(item.getAsFile()));\n                            } else if (entry.isDirectory) {\n                                _results.push(this._addFilesFromDirectory(entry, entry.name));\n                            } else {\n                                _results.push(void 0);\n                            }\n                        } else if (item.getAsFile != null) {\n                            if ((item.kind == null) || item.kind === \"file\") {\n                                _results.push(this.addFile(item.getAsFile()));\n                            } else {\n                                _results.push(void 0);\n                            }\n                        } else {\n                            _results.push(void 0);\n                        }\n                    }\n                    return _results;\n                };\n\n                Dropzone.prototype._addFilesFromDirectory = function(directory, path) {\n                    var dirReader, entriesReader;\n                    dirReader = directory.createReader();\n                    entriesReader = (function(_this) {\n                        return function(entries) {\n                            var entry, _i, _len;\n                            for (_i = 0, _len = entries.length; _i < _len; _i++) {\n                                entry = entries[_i];\n                                if (entry.isFile) {\n                                    entry.file(function(file) {\n                                        if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {\n                                            return;\n                                        }\n                                        file.fullPath = \"\" + path + \"/\" + file.name;\n                                        return _this.addFile(file);\n                                    });\n                                } else if (entry.isDirectory) {\n                                    _this._addFilesFromDirectory(entry, \"\" + path + \"/\" + entry.name);\n                                }\n                            }\n                        };\n                    })(this);\n                    return dirReader.readEntries(entriesReader, function(error) {\n                        return typeof console !== \"undefined\" && console !== null ? typeof console.log === \"function\" ? console.log(error) : void 0 : void 0;\n                    });\n                };\n\n                Dropzone.prototype.accept = function(file, done) {\n                    if (file.size > this.options.maxFilesize * 1024 * 1024) {\n                        return done(this.options.dictFileTooBig.replace(\"{{filesize}}\", Math.round(file.size / 1024 / 10.24) / 100).replace(\"{{maxFilesize}}\", this.options.maxFilesize));\n                    } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {\n                        return done(this.options.dictInvalidFileType);\n                    } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {\n                        done(this.options.dictMaxFilesExceeded.replace(\"{{maxFiles}}\", this.options.maxFiles));\n                        return this.emit(\"maxfilesexceeded\", file);\n                    } else {\n                        return this.options.accept.call(this, file, done);\n                    }\n                };\n\n                Dropzone.prototype.addFile = function(file) {\n                    file.upload = {\n                        progress: 0,\n                        total: file.size,\n                        bytesSent: 0\n                    };\n                    this.files.push(file);\n                    file.status = Dropzone.ADDED;\n                    this.emit(\"addedfile\", file);\n                    this._enqueueThumbnail(file);\n                    return this.accept(file, (function(_this) {\n                        return function(error) {\n                            if (error) {\n                                file.accepted = false;\n                                _this._errorProcessing([file], error);\n                            } else {\n                                file.accepted = true;\n                                if (_this.options.autoQueue) {\n                                    _this.enqueueFile(file);\n                                }\n                            }\n                            return _this._updateMaxFilesReachedClass();\n                        };\n                    })(this));\n                };\n\n                Dropzone.prototype.enqueueFiles = function(files) {\n                    var file, _i, _len;\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        this.enqueueFile(file);\n                    }\n                    return null;\n                };\n\n                Dropzone.prototype.enqueueFile = function(file) {\n                    if (file.status === Dropzone.ADDED && file.accepted === true) {\n                        file.status = Dropzone.QUEUED;\n                        if (this.options.autoProcessQueue) {\n                            return setTimeout(((function(_this) {\n                                return function() {\n                                    return _this.processQueue();\n                                };\n                            })(this)), 0);\n                        }\n                    } else {\n                        throw new Error(\"This file can't be queued because it has already been processed or was rejected.\");\n                    }\n                };\n\n                Dropzone.prototype._thumbnailQueue = [];\n\n                Dropzone.prototype._processingThumbnail = false;\n\n                Dropzone.prototype._enqueueThumbnail = function(file) {\n                    if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {\n                        this._thumbnailQueue.push(file);\n                        return setTimeout(((function(_this) {\n                            return function() {\n                                return _this._processThumbnailQueue();\n                            };\n                        })(this)), 0);\n                    }\n                };\n\n                Dropzone.prototype._processThumbnailQueue = function() {\n                    if (this._processingThumbnail || this._thumbnailQueue.length === 0) {\n                        return;\n                    }\n                    this._processingThumbnail = true;\n                    return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {\n                        return function() {\n                            _this._processingThumbnail = false;\n                            return _this._processThumbnailQueue();\n                        };\n                    })(this));\n                };\n\n                Dropzone.prototype.removeFile = function(file) {\n                    if (file.status === Dropzone.UPLOADING) {\n                        this.cancelUpload(file);\n                    }\n                    this.files = without(this.files, file);\n                    this.emit(\"removedfile\", file);\n                    if (this.files.length === 0) {\n                        return this.emit(\"reset\");\n                    }\n                };\n\n                Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {\n                    var file, _i, _len, _ref;\n                    if (cancelIfNecessary == null) {\n                        cancelIfNecessary = false;\n                    }\n                    _ref = this.files.slice();\n                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                        file = _ref[_i];\n                        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {\n                            this.removeFile(file);\n                        }\n                    }\n                    return null;\n                };\n\n                Dropzone.prototype.createThumbnail = function(file, callback) {\n                    var fileReader;\n                    fileReader = new FileReader;\n                    fileReader.onload = (function(_this) {\n                        return function() {\n                            var img;\n                            img = document.createElement(\"img\");\n                            img.onload = function() {\n                                var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;\n                                file.width = img.width;\n                                file.height = img.height;\n                                resizeInfo = _this.options.resize.call(_this, file);\n                                if (resizeInfo.trgWidth == null) {\n                                    resizeInfo.trgWidth = _this.options.thumbnailWidth;\n                                }\n                                if (resizeInfo.trgHeight == null) {\n                                    resizeInfo.trgHeight = _this.options.thumbnailHeight;\n                                }\n                                canvas = document.createElement(\"canvas\");\n                                ctx = canvas.getContext(\"2d\");\n                                canvas.width = resizeInfo.trgWidth;\n                                canvas.height = resizeInfo.trgHeight;\n                                drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);\n                                thumbnail = canvas.toDataURL(\"image/png\");\n                                _this.emit(\"thumbnail\", file, thumbnail);\n                                if (callback != null) {\n                                    return callback();\n                                }\n                            };\n                            return img.src = fileReader.result;\n                        };\n                    })(this);\n                    return fileReader.readAsDataURL(file);\n                };\n\n                Dropzone.prototype.processQueue = function() {\n                    var i, parallelUploads, processingLength, queuedFiles;\n                    parallelUploads = this.options.parallelUploads;\n                    processingLength = this.getUploadingFiles().length;\n                    i = processingLength;\n                    if (processingLength >= parallelUploads) {\n                        return;\n                    }\n                    queuedFiles = this.getQueuedFiles();\n                    if (!(queuedFiles.length > 0)) {\n                        return;\n                    }\n                    if (this.options.uploadMultiple) {\n                        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));\n                    } else {\n                        while (i < parallelUploads) {\n                            if (!queuedFiles.length) {\n                                return;\n                            }\n                            this.processFile(queuedFiles.shift());\n                            i++;\n                        }\n                    }\n                };\n\n                Dropzone.prototype.processFile = function(file) {\n                    return this.processFiles([file]);\n                };\n\n                Dropzone.prototype.processFiles = function(files) {\n                    var file, _i, _len;\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        file.processing = true;\n                        file.status = Dropzone.UPLOADING;\n                        this.emit(\"processing\", file);\n                    }\n                    if (this.options.uploadMultiple) {\n                        this.emit(\"processingmultiple\", files);\n                    }\n                    return this.uploadFiles(files);\n                };\n\n                Dropzone.prototype._getFilesWithXhr = function(xhr) {\n                    var file, files;\n                    return files = (function() {\n                        var _i, _len, _ref, _results;\n                        _ref = this.files;\n                        _results = [];\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            file = _ref[_i];\n                            if (file.xhr === xhr) {\n                                _results.push(file);\n                            }\n                        }\n                        return _results;\n                    }).call(this);\n                };\n\n                Dropzone.prototype.cancelUpload = function(file) {\n                    var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref;\n                    if (file.status === Dropzone.UPLOADING) {\n                        groupedFiles = this._getFilesWithXhr(file.xhr);\n                        for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) {\n                            groupedFile = groupedFiles[_i];\n                            groupedFile.status = Dropzone.CANCELED;\n                        }\n                        file.xhr.abort();\n                        for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) {\n                            groupedFile = groupedFiles[_j];\n                            this.emit(\"canceled\", groupedFile);\n                        }\n                        if (this.options.uploadMultiple) {\n                            this.emit(\"canceledmultiple\", groupedFiles);\n                        }\n                    } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) {\n                        file.status = Dropzone.CANCELED;\n                        this.emit(\"canceled\", file);\n                        if (this.options.uploadMultiple) {\n                            this.emit(\"canceledmultiple\", [file]);\n                        }\n                    }\n                    if (this.options.autoProcessQueue) {\n                        return this.processQueue();\n                    }\n                };\n\n                Dropzone.prototype.uploadFile = function(file) {\n                    return this.uploadFiles([file]);\n                };\n\n                Dropzone.prototype.uploadFiles = function(files) {\n                    var file, formData, handleError, headerName, headerValue, headers, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4;\n                    xhr = new XMLHttpRequest();\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        file.xhr = xhr;\n                    }\n                    xhr.open(this.options.method, this.options.url, true);\n                    xhr.withCredentials = !!this.options.withCredentials;\n                    response = null;\n                    handleError = (function(_this) {\n                        return function() {\n                            var _j, _len1, _results;\n                            _results = [];\n                            for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n                                file = files[_j];\n                                _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace(\"{{statusCode}}\", xhr.status), xhr));\n                            }\n                            return _results;\n                        };\n                    })(this);\n                    updateProgress = (function(_this) {\n                        return function(e) {\n                            var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results;\n                            if (e != null) {\n                                progress = 100 * e.loaded / e.total;\n                                for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n                                    file = files[_j];\n                                    file.upload = {\n                                        progress: progress,\n                                        total: e.total,\n                                        bytesSent: e.loaded\n                                    };\n                                }\n                            } else {\n                                allFilesFinished = true;\n                                progress = 100;\n                                for (_k = 0, _len2 = files.length; _k < _len2; _k++) {\n                                    file = files[_k];\n                                    if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) {\n                                        allFilesFinished = false;\n                                    }\n                                    file.upload.progress = progress;\n                                    file.upload.bytesSent = file.upload.total;\n                                }\n                                if (allFilesFinished) {\n                                    return;\n                                }\n                            }\n                            _results = [];\n                            for (_l = 0, _len3 = files.length; _l < _len3; _l++) {\n                                file = files[_l];\n                                _results.push(_this.emit(\"uploadprogress\", file, progress, file.upload.bytesSent));\n                            }\n                            return _results;\n                        };\n                    })(this);\n                    xhr.onload = (function(_this) {\n                        return function(e) {\n                            var _ref;\n                            if (files[0].status === Dropzone.CANCELED) {\n                                return;\n                            }\n                            if (xhr.readyState !== 4) {\n                                return;\n                            }\n                            response = xhr.responseText;\n                            if (xhr.getResponseHeader(\"content-type\") && ~xhr.getResponseHeader(\"content-type\").indexOf(\"application/json\")) {\n                                try {\n                                    response = JSON.parse(response);\n                                } catch (_error) {\n                                    e = _error;\n                                    response = \"Invalid JSON response from server.\";\n                                }\n                            }\n                            updateProgress();\n                            if (!((200 <= (_ref = xhr.status) && _ref < 300))) {\n                                return handleError();\n                            } else {\n                                return _this._finished(files, response, e);\n                            }\n                        };\n                    })(this);\n                    xhr.onerror = (function(_this) {\n                        return function() {\n                            if (files[0].status === Dropzone.CANCELED) {\n                                return;\n                            }\n                            return handleError();\n                        };\n                    })(this);\n                    progressObj = (_ref = xhr.upload) != null ? _ref : xhr;\n                    progressObj.onprogress = updateProgress;\n                    headers = {\n                        \"Accept\": \"application/json\",\n                        \"Cache-Control\": \"no-cache\",\n                        \"X-Requested-With\": \"XMLHttpRequest\"\n                    };\n                    if (this.options.headers) {\n                        extend(headers, this.options.headers);\n                    }\n                    for (headerName in headers) {\n                        headerValue = headers[headerName];\n                        xhr.setRequestHeader(headerName, headerValue);\n                    }\n                    formData = new FormData();\n                    if (this.options.params) {\n                        _ref1 = this.options.params;\n                        for (key in _ref1) {\n                            value = _ref1[key];\n                            formData.append(key, value);\n                        }\n                    }\n                    for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n                        file = files[_j];\n                        this.emit(\"sending\", file, xhr, formData);\n                    }\n                    if (this.options.uploadMultiple) {\n                        this.emit(\"sendingmultiple\", files, xhr, formData);\n                    }\n                    if (this.element.tagName === \"FORM\") {\n                        _ref2 = this.element.querySelectorAll(\"input, textarea, select, button\");\n                        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {\n                            input = _ref2[_k];\n                            inputName = input.getAttribute(\"name\");\n                            inputType = input.getAttribute(\"type\");\n                            if (input.tagName === \"SELECT\" && input.hasAttribute(\"multiple\")) {\n                                _ref3 = input.options;\n                                for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {\n                                    option = _ref3[_l];\n                                    if (option.selected) {\n                                        formData.append(inputName, option.value);\n                                    }\n                                }\n                            } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== \"checkbox\" && _ref4 !== \"radio\") || input.checked) {\n                                formData.append(inputName, input.value);\n                            }\n                        }\n                    }\n                    for (_m = 0, _len4 = files.length; _m < _len4; _m++) {\n                        file = files[_m];\n                        formData.append(\"\" + this.options.paramName + (this.options.uploadMultiple ? \"[]\" : \"\"), file, file.name);\n                    }\n                    return xhr.send(formData);\n                };\n\n                Dropzone.prototype._finished = function(files, responseText, e) {\n                    var file, _i, _len;\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        file.status = Dropzone.SUCCESS;\n                        this.emit(\"success\", file, responseText, e);\n                        this.emit(\"complete\", file);\n                    }\n                    if (this.options.uploadMultiple) {\n                        this.emit(\"successmultiple\", files, responseText, e);\n                        this.emit(\"completemultiple\", files);\n                    }\n                    if (this.options.autoProcessQueue) {\n                        return this.processQueue();\n                    }\n                };\n\n                Dropzone.prototype._errorProcessing = function(files, message, xhr) {\n                    var file, _i, _len;\n                    for (_i = 0, _len = files.length; _i < _len; _i++) {\n                        file = files[_i];\n                        file.status = Dropzone.ERROR;\n                        this.emit(\"error\", file, message, xhr);\n                        this.emit(\"complete\", file);\n                    }\n                    if (this.options.uploadMultiple) {\n                        this.emit(\"errormultiple\", files, message, xhr);\n                        this.emit(\"completemultiple\", files);\n                    }\n                    if (this.options.autoProcessQueue) {\n                        return this.processQueue();\n                    }\n                };\n\n                return Dropzone;\n\n            })(Em);\n\n            Dropzone.version = \"3.8.7\";\n\n            Dropzone.options = {};\n\n            Dropzone.optionsForElement = function(element) {\n                if (element.getAttribute(\"id\")) {\n                    return Dropzone.options[camelize(element.getAttribute(\"id\"))];\n                } else {\n                    return void 0;\n                }\n            };\n\n            Dropzone.instances = [];\n\n            Dropzone.forElement = function(element) {\n                if (typeof element === \"string\") {\n                    element = document.querySelector(element);\n                }\n                if ((element != null ? element.dropzone : void 0) == null) {\n                    throw new Error(\"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.\");\n                }\n                return element.dropzone;\n            };\n\n            Dropzone.autoDiscover = true;\n\n            Dropzone.discover = function() {\n                var checkElements, dropzone, dropzones, _i, _len, _results;\n                if (document.querySelectorAll) {\n                    dropzones = document.querySelectorAll(\".dropzone\");\n                } else {\n                    dropzones = [];\n                    checkElements = function(elements) {\n                        var el, _i, _len, _results;\n                        _results = [];\n                        for (_i = 0, _len = elements.length; _i < _len; _i++) {\n                            el = elements[_i];\n                            if (/(^| )dropzone($| )/.test(el.className)) {\n                                _results.push(dropzones.push(el));\n                            } else {\n                                _results.push(void 0);\n                            }\n                        }\n                        return _results;\n                    };\n                    checkElements(document.getElementsByTagName(\"div\"));\n                    checkElements(document.getElementsByTagName(\"form\"));\n                }\n                _results = [];\n                for (_i = 0, _len = dropzones.length; _i < _len; _i++) {\n                    dropzone = dropzones[_i];\n                    if (Dropzone.optionsForElement(dropzone) !== false) {\n                        _results.push(new Dropzone(dropzone));\n                    } else {\n                        _results.push(void 0);\n                    }\n                }\n                return _results;\n            };\n\n            Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\\/12/i];\n\n            Dropzone.isBrowserSupported = function() {\n                var capableBrowser, regex, _i, _len, _ref;\n                capableBrowser = true;\n                if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {\n                    if (!(\"classList\" in document.createElement(\"a\"))) {\n                        capableBrowser = false;\n                    } else {\n                        _ref = Dropzone.blacklistedBrowsers;\n                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                            regex = _ref[_i];\n                            if (regex.test(navigator.userAgent)) {\n                                capableBrowser = false;\n                                continue;\n                            }\n                        }\n                    }\n                } else {\n                    capableBrowser = false;\n                }\n                return capableBrowser;\n            };\n\n            without = function(list, rejectedItem) {\n                var item, _i, _len, _results;\n                _results = [];\n                for (_i = 0, _len = list.length; _i < _len; _i++) {\n                    item = list[_i];\n                    if (item !== rejectedItem) {\n                        _results.push(item);\n                    }\n                }\n                return _results;\n            };\n\n            camelize = function(str) {\n                return str.replace(/[\\-_](\\w)/g, function(match) {\n                    return match.charAt(1).toUpperCase();\n                });\n            };\n\n            Dropzone.createElement = function(string) {\n                var div;\n                div = document.createElement(\"div\");\n                div.innerHTML = string;\n                return div.childNodes[0];\n            };\n\n            Dropzone.elementInside = function(element, container) {\n                if (element === container) {\n                    return true;\n                }\n                while (element = element.parentNode) {\n                    if (element === container) {\n                        return true;\n                    }\n                }\n                return false;\n            };\n\n            Dropzone.getElement = function(el, name) {\n                var element;\n                if (typeof el === \"string\") {\n                    element = document.querySelector(el);\n                } else if (el.nodeType != null) {\n                    element = el;\n                }\n                if (element == null) {\n                    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector or a plain HTML element.\");\n                }\n                return element;\n            };\n\n            Dropzone.getElements = function(els, name) {\n                var e, el, elements, _i, _j, _len, _len1, _ref;\n                if (els instanceof Array) {\n                    elements = [];\n                    try {\n                        for (_i = 0, _len = els.length; _i < _len; _i++) {\n                            el = els[_i];\n                            elements.push(this.getElement(el, name));\n                        }\n                    } catch (_error) {\n                        e = _error;\n                        elements = null;\n                    }\n                } else if (typeof els === \"string\") {\n                    elements = [];\n                    _ref = document.querySelectorAll(els);\n                    for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {\n                        el = _ref[_j];\n                        elements.push(el);\n                    }\n                } else if (els.nodeType != null) {\n                    elements = [els];\n                }\n                if (!((elements != null) && elements.length)) {\n                    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.\");\n                }\n                return elements;\n            };\n\n            Dropzone.confirm = function(question, accepted, rejected) {\n                if (window.confirm(question)) {\n                    return accepted();\n                } else if (rejected != null) {\n                    return rejected();\n                }\n            };\n\n            Dropzone.isValidFile = function(file, acceptedFiles) {\n                var baseMimeType, mimeType, validType, _i, _len;\n                if (!acceptedFiles) {\n                    return true;\n                }\n                acceptedFiles = acceptedFiles.split(\",\");\n                mimeType = file.type;\n                baseMimeType = mimeType.replace(/\\/.*$/, \"\");\n                for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) {\n                    validType = acceptedFiles[_i];\n                    validType = validType.trim();\n                    if (validType.charAt(0) === \".\") {\n                        if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {\n                            return true;\n                        }\n                    } else if (/\\/\\*$/.test(validType)) {\n                        if (baseMimeType === validType.replace(/\\/.*$/, \"\")) {\n                            return true;\n                        }\n                    } else {\n                        if (mimeType === validType) {\n                            return true;\n                        }\n                    }\n                }\n                return false;\n            };\n\n            if (typeof jQuery !== \"undefined\" && jQuery !== null) {\n                jQuery.fn.dropzone = function(options) {\n                    return this.each(function() {\n                        return new Dropzone(this, options);\n                    });\n                };\n            }\n\n            if (typeof module !== \"undefined\" && module !== null) {\n                module.exports = Dropzone;\n            } else {\n                window.Dropzone = Dropzone;\n            }\n\n            Dropzone.ADDED = \"added\";\n\n            Dropzone.QUEUED = \"queued\";\n\n            Dropzone.ACCEPTED = Dropzone.QUEUED;\n\n            Dropzone.UPLOADING = \"uploading\";\n\n            Dropzone.PROCESSING = Dropzone.UPLOADING;\n\n            Dropzone.CANCELED = \"canceled\";\n\n            Dropzone.ERROR = \"error\";\n\n            Dropzone.SUCCESS = \"success\";\n\n\n            /*\n\n             Bugfix for iOS 6 and 7\n             Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios\n             based on the work of https://github.com/stomita/ios-imagefile-megapixel\n             */\n\n            detectVerticalSquash = function(img) {\n                var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;\n                iw = img.naturalWidth;\n                ih = img.naturalHeight;\n                canvas = document.createElement(\"canvas\");\n                canvas.width = 1;\n                canvas.height = ih;\n                ctx = canvas.getContext(\"2d\");\n                ctx.drawImage(img, 0, 0);\n                data = ctx.getImageData(0, 0, 1, ih).data;\n                sy = 0;\n                ey = ih;\n                py = ih;\n                while (py > sy) {\n                    alpha = data[(py - 1) * 4 + 3];\n                    if (alpha === 0) {\n                        ey = py;\n                    } else {\n                        sy = py;\n                    }\n                    py = (ey + sy) >> 1;\n                }\n                ratio = py / ih;\n                if (ratio === 0) {\n                    return 1;\n                } else {\n                    return ratio;\n                }\n            };\n\n            drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {\n                var vertSquashRatio;\n                vertSquashRatio = detectVerticalSquash(img);\n                return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);\n            };\n\n\n            /*\n             * contentloaded.js\n             *\n             * Author: Diego Perini (diego.perini at gmail.com)\n             * Summary: cross-browser wrapper for DOMContentLoaded\n             * Updated: 20101020\n             * License: MIT\n             * Version: 1.2\n             *\n             * URL:\n             * http://javascript.nwbox.com/ContentLoaded/\n             * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE\n             */\n\n            contentLoaded = function(win, fn) {\n                var add, doc, done, init, poll, pre, rem, root, top;\n                done = false;\n                top = true;\n                doc = win.document;\n                root = doc.documentElement;\n                add = (doc.addEventListener ? \"addEventListener\" : \"attachEvent\");\n                rem = (doc.addEventListener ? \"removeEventListener\" : \"detachEvent\");\n                pre = (doc.addEventListener ? \"\" : \"on\");\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)) {\n                        return fn.call(win, e.type || e);\n                    }\n                };\n                poll = function() {\n                    var e;\n                    try {\n                        root.doScroll(\"left\");\n                    } catch (_error) {\n                        e = _error;\n                        setTimeout(poll, 50);\n                        return;\n                    }\n                    return init(\"poll\");\n                };\n                if (doc.readyState !== \"complete\") {\n                    if (doc.createEventObject && root.doScroll) {\n                        try {\n                            top = !win.frameElement;\n                        } catch (_error) {}\n                        if (top) {\n                            poll();\n                        }\n                    }\n                    doc[add](pre + \"DOMContentLoaded\", init, false);\n                    doc[add](pre + \"readystatechange\", init, false);\n                    return win[add](pre + \"load\", init, false);\n                }\n            };\n\n            Dropzone._autoDiscoverFunction = function() {\n                if (Dropzone.autoDiscover) {\n                    return Dropzone.discover();\n                }\n            };\n\n            contentLoaded(window, Dropzone._autoDiscoverFunction);\n\n        }).call(this);\n\n    });\n\n    if (typeof exports == \"object\") {\n        module.exports = require(\"dropzone\");\n    } else if (typeof define == \"function\" && define.amd) {\n        define([], function(){ return require(\"dropzone\"); });\n    } else {\n        this[\"Dropzone\"] = require(\"dropzone\");\n    }\n})()\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/duallistbox/jquery.bootstrap-duallistbox.js",
    "content": ";(function ($, window, document, undefined) {\n  // Create the defaults once\n  var pluginName = 'bootstrapDualListbox',\n    defaults = {\n      bootstrap2Compatible: false,\n      filterTextClear: '显示全部',\n      filterPlaceHolder: '查找',\n      moveSelectedLabel: '移动选择',\n      moveAllLabel: '移动全部',\n      removeSelectedLabel: '移除选择',\n      removeAllLabel: '移除全部',\n      moveOnSelect: true,                                                                 // true/false (forced true on androids, see the comment later)\n      preserveSelectionOnMove: false,                                                     // 'all' / 'moved' / false\n      selectedListLabel: false,                                                           // 'string', false\n      nonSelectedListLabel: false,                                                        // 'string', false\n      helperSelectNamePostfix: '_helper',                                                 // 'string_of_postfix' / false\n      selectorMinimalHeight: 100,\n      showFilterInputs: true,                                                             // whether to show filter inputs\n      nonSelectedFilter: '',                                                              // string, filter the non selected options\n      selectedFilter: '',                                                                 // string, filter the selected options\n      infoText: '全部：{0}',                                                        // text when all options are visible / false for no info text\n      infoTextFiltered: '<span class=\"label label-warning\">查找</span> &nbsp; {0}/{1}', // when not all of the options are visible due to the filter\n      infoTextEmpty: '空',                                                        // when there are no options present in the list\n      filterOnValues: false                                                               // filter by selector's values, boolean\n    },\n    // Selections are invisible on android if the containing select is styled with CSS\n    // http://code.google.com/p/android/issues/detail?id=16922\n    isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());\n\n  // The actual plugin constructor\n  function BootstrapDualListbox(element, options) {\n    this.element = $(element);\n    // jQuery has an extend method which merges the contents of two or\n    // more objects, storing the result in the first object. The first object\n    // is generally empty as we don't want to alter the default options for\n    // future instances of the plugin\n    this.settings = $.extend({}, defaults, options);\n    this._defaults = defaults;\n    this._name = pluginName;\n    this.init();\n  }\n\n  function triggerChangeEvent(dualListbox) {\n    dualListbox.element.trigger('change');\n  }\n\n  function updateSelectionStates(dualListbox) {\n    dualListbox.element.find('option').each(function(index, item) {\n      var $item = $(item);\n      if (typeof($item.data('original-index')) === 'undefined') {\n        $item.data('original-index', dualListbox.elementCount++);\n      }\n      if (typeof($item.data('_selected')) === 'undefined') {\n        $item.data('_selected', false);\n      }\n    });\n  }\n\n  function changeSelectionState(dualListbox, original_index, selected) {\n    dualListbox.element.find('option').each(function(index, item) {\n      var $item = $(item);\n      if ($item.data('original-index') === original_index) {\n        $item.prop('selected', selected);\n      }\n    });\n  }\n\n  function formatString(s, args) {\n    return s.replace(/\\{(\\d+)\\}/g, function(match, number) {\n      return typeof args[number] !== 'undefined' ? args[number] : match;\n    });\n  }\n\n  function refreshInfo(dualListbox) {\n    if (!dualListbox.settings.infoText) {\n      return;\n    }\n\n    var visible1 = dualListbox.elements.select1.find('option').length,\n      visible2 = dualListbox.elements.select2.find('option').length,\n      all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,\n      all2 = dualListbox.selectedElements,\n      content = '';\n\n    if (all1 === 0) {\n      content = dualListbox.settings.infoTextEmpty;\n    } else if (visible1 === all1) {\n      content = formatString(dualListbox.settings.infoText, [visible1, all1]);\n    } else {\n      content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);\n    }\n\n    dualListbox.elements.info1.html(content);\n    dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));\n\n    if (all2 === 0) {\n      content = dualListbox.settings.infoTextEmpty;\n    } else if (visible2 === all2) {\n      content = formatString(dualListbox.settings.infoText, [visible2, all2]);\n    } else {\n      content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);\n    }\n\n    dualListbox.elements.info2.html(content);\n    dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));\n  }\n\n  function refreshSelects(dualListbox) {\n    dualListbox.selectedElements = 0;\n\n    dualListbox.elements.select1.empty();\n    dualListbox.elements.select2.empty();\n\n    dualListbox.element.find('option').each(function(index, item) {\n      var $item = $(item);\n      if ($item.prop('selected')) {\n        dualListbox.selectedElements++;\n        dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));\n      } else {\n        dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));\n      }\n    });\n\n    if (dualListbox.settings.showFilterInputs) {\n      filter(dualListbox, 1);\n      filter(dualListbox, 2);\n    }\n    refreshInfo(dualListbox);\n  }\n\n  function filter(dualListbox, selectIndex) {\n    if (!dualListbox.settings.showFilterInputs) {\n      return;\n    }\n\n    saveSelections(dualListbox, selectIndex);\n\n    dualListbox.elements['select'+selectIndex].empty().scrollTop(0);\n    var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),\n      options = dualListbox.element;\n\n    if (selectIndex === 1) {\n      options = options.find('option').not(':selected');\n    } else  {\n      options = options.find('option:selected');\n    }\n\n    options.each(function(index, item) {\n      var $item = $(item),\n        isFiltered = true;\n      if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {\n        isFiltered = false;\n        dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));\n      }\n      dualListbox.element.find('option').eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);\n    });\n\n    refreshInfo(dualListbox);\n  }\n\n  function saveSelections(dualListbox, selectIndex) {\n    dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {\n      var $item = $(item);\n      dualListbox.element.find('option').eq($item.data('original-index')).data('_selected', $item.prop('selected'));\n    });\n  }\n\n  function sortOptions(select) {\n    select.find('option').sort(function(a, b) {\n      return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;\n    }).appendTo(select);\n  }\n\n  function clearSelections(dualListbox) {\n    dualListbox.elements.select1.find('option').each(function() {\n      dualListbox.element.find('option').data('_selected', false);\n    });\n  }\n\n  function move(dualListbox) {\n    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n      saveSelections(dualListbox, 2);\n    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n    }\n\n    dualListbox.elements.select1.find('option:selected').each(function(index, item) {\n      var $item = $(item);\n      if (!$item.data('filtered1')) {\n        changeSelectionState(dualListbox, $item.data('original-index'), true);\n      }\n    });\n\n    refreshSelects(dualListbox);\n    triggerChangeEvent(dualListbox);\n    sortOptions(dualListbox.elements.select2);\n  }\n\n  function remove(dualListbox) {\n    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n      saveSelections(dualListbox, 2);\n    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 2);\n    }\n\n    dualListbox.elements.select2.find('option:selected').each(function(index, item) {\n      var $item = $(item);\n      if (!$item.data('filtered2')) {\n        changeSelectionState(dualListbox, $item.data('original-index'), false);\n      }\n    });\n\n    refreshSelects(dualListbox);\n    triggerChangeEvent(dualListbox);\n    sortOptions(dualListbox.elements.select1);\n  }\n\n  function moveAll(dualListbox) {\n    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n      saveSelections(dualListbox, 2);\n    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n    }\n\n    dualListbox.element.find('option').each(function(index, item) {\n      var $item = $(item);\n      if (!$item.data('filtered1')) {\n        $item.prop('selected', true);\n      }\n    });\n\n    refreshSelects(dualListbox);\n    triggerChangeEvent(dualListbox);\n  }\n\n  function removeAll(dualListbox) {\n    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 1);\n      saveSelections(dualListbox, 2);\n    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n      saveSelections(dualListbox, 2);\n    }\n\n    dualListbox.element.find('option').each(function(index, item) {\n      var $item = $(item);\n      if (!$item.data('filtered2')) {\n        $item.prop('selected', false);\n      }\n    });\n\n    refreshSelects(dualListbox);\n    triggerChangeEvent(dualListbox);\n  }\n\n  function bindEvents(dualListbox) {\n    dualListbox.elements.form.submit(function(e) {\n      if (dualListbox.elements.filterInput1.is(':focus')) {\n        e.preventDefault();\n        dualListbox.elements.filterInput1.focusout();\n      } else if (dualListbox.elements.filterInput2.is(':focus')) {\n        e.preventDefault();\n        dualListbox.elements.filterInput2.focusout();\n      }\n    });\n\n    dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){\n      dualListbox.refresh(mustClearSelections);\n    });\n\n    dualListbox.elements.filterClear1.on('click', function() {\n      dualListbox.setNonSelectedFilter('', true);\n    });\n\n    dualListbox.elements.filterClear2.on('click', function() {\n      dualListbox.setSelectedFilter('', true);\n    });\n\n    dualListbox.elements.moveButton.on('click', function() {\n      move(dualListbox);\n    });\n\n    dualListbox.elements.moveAllButton.on('click', function() {\n      moveAll(dualListbox);\n    });\n\n    dualListbox.elements.removeButton.on('click', function() {\n      remove(dualListbox);\n    });\n\n    dualListbox.elements.removeAllButton.on('click', function() {\n      removeAll(dualListbox);\n    });\n\n    dualListbox.elements.filterInput1.on('change keyup', function() {\n      filter(dualListbox, 1);\n    });\n\n    dualListbox.elements.filterInput2.on('change keyup', function() {\n      filter(dualListbox, 2);\n    });\n  }\n\n  BootstrapDualListbox.prototype = {\n    init: function () {\n      // Add the custom HTML template\n      this.container = $('' +\n        '<div class=\"bootstrap-duallistbox-container\">' +\n        ' <div class=\"box1\">' +\n        '   <label></label>' +\n        '   <span class=\"info-container\">' +\n        '     <span class=\"info\"></span>' +\n        '     <button type=\"button\" class=\"btn clear1 pull-right\"></button>' +\n        '   </span>' +\n        '   <div class=\"btn-group buttons\">' +\n        '     <button type=\"button\" class=\"btn moveall\">' +\n        '       <i></i>' +\n        '       <i></i>' +\n        '     </button>' +\n        '     <button type=\"button\" class=\"btn move\">' +\n        '       <i></i>' +\n        '     </button>' +\n        '   </div>' +\n        '   <input class=\"filter\" type=\"text\">' +\n        '   <select multiple=\"multiple\"></select>' +\n        ' </div>' +\n        ' <div class=\"box2\">' +\n        '   <label></label>' +\n        '   <span class=\"info-container\">' +\n        '     <span class=\"info\"></span>' +\n        '     <button type=\"button\" class=\"btn clear2 pull-right\"></button>' +\n        '   </span>' +\n        '   <div class=\"btn-group buttons\">' +\n        '     <button type=\"button\" class=\"btn remove\">' +\n        '       <i></i>' +\n        '     </button>' +\n        '     <button type=\"button\" class=\"btn removeall\">' +\n        '       <i></i>' +\n        '       <i></i>' +\n        '     </button>' +\n        '   </div>' +\n        '   <input class=\"filter\" type=\"text\">' +\n        '   <select multiple=\"multiple\"></select>' +\n        ' </div>' +\n        '</div>')\n        .insertBefore(this.element);\n\n      // Cache the inner elements\n      this.elements = {\n        originalSelect: this.element,\n        box1: $('.box1', this.container),\n        box2: $('.box2', this.container),\n        filterInput1: $('.box1 .filter', this.container),\n        filterInput2: $('.box2 .filter', this.container),\n        filterClear1: $('.box1 .clear1', this.container),\n        filterClear2: $('.box2 .clear2', this.container),\n        label1: $('.box1 > label', this.container),\n        label2: $('.box2 > label', this.container),\n        info1: $('.box1 .info', this.container),\n        info2: $('.box2 .info', this.container),\n        select1: $('.box1 select', this.container),\n        select2: $('.box2 select', this.container),\n        moveButton: $('.box1 .move', this.container),\n        removeButton: $('.box2 .remove', this.container),\n        moveAllButton: $('.box1 .moveall', this.container),\n        removeAllButton: $('.box2 .removeall', this.container),\n        form: $($('.box1 .filter', this.container)[0].form)\n      };\n\n      // Set select IDs\n      this.originalSelectName = this.element.attr('name') || '';\n      var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,\n        select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;\n      this.elements.select1.attr('id', select1Id);\n      this.elements.select2.attr('id', select2Id);\n      this.elements.label1.attr('for', select1Id);\n      this.elements.label2.attr('for', select2Id);\n\n      // Apply all settings\n      this.selectedElements = 0;\n      this.elementCount = 0;\n      this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);\n      this.setFilterTextClear(this.settings.filterTextClear);\n      this.setFilterPlaceHolder(this.settings.filterPlaceHolder);\n      this.setMoveSelectedLabel(this.settings.moveSelectedLabel);\n      this.setMoveAllLabel(this.settings.moveAllLabel);\n      this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);\n      this.setRemoveAllLabel(this.settings.removeAllLabel);\n      this.setMoveOnSelect(this.settings.moveOnSelect);\n      this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);\n      this.setSelectedListLabel(this.settings.selectedListLabel);\n      this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);\n      this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);\n      this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);\n\n      updateSelectionStates(this);\n\n      this.setShowFilterInputs(this.settings.showFilterInputs);\n      this.setNonSelectedFilter(this.settings.nonSelectedFilter);\n      this.setSelectedFilter(this.settings.selectedFilter);\n      this.setInfoText(this.settings.infoText);\n      this.setInfoTextFiltered(this.settings.infoTextFiltered);\n      this.setInfoTextEmpty(this.settings.infoTextEmpty);\n      this.setFilterOnValues(this.settings.filterOnValues);\n\n      // Hide the original select\n      this.element.hide();\n\n      bindEvents(this);\n      refreshSelects(this);\n\n      return this.element;\n    },\n    setBootstrap2Compatible: function(value, refresh) {\n      this.settings.bootstrap2Compatible = value;\n      if (value) {\n        this.container.removeClass('row').addClass('row-fluid bs2compatible');\n        this.container.find('.box1, .box2').removeClass('col-xs-6').addClass('span6');\n        this.container.find('.clear1, .clear2').removeClass('btn-white btn-xs').addClass('btn-mini');\n        this.container.find('input, select').removeClass('form-control');\n        this.container.find('.btn').removeClass('btn-white');\n        this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');\n        this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');\n      } else {\n        this.container.removeClass('row-fluid bs2compatible').addClass('row');\n        this.container.find('.box1, .box2').removeClass('span6').addClass('col-xs-6');\n        this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-white btn-xs');\n        this.container.find('input, select').addClass('form-control');\n        this.container.find('.btn').addClass('btn-white');\n        this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');\n        this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');\n      }\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setFilterTextClear: function(value, refresh) {\n      this.settings.filterTextClear = value;\n      this.elements.filterClear1.html(value);\n      this.elements.filterClear2.html(value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setFilterPlaceHolder: function(value, refresh) {\n      this.settings.filterPlaceHolder = value;\n      this.elements.filterInput1.attr('placeholder', value);\n      this.elements.filterInput2.attr('placeholder', value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setMoveSelectedLabel: function(value, refresh) {\n      this.settings.moveSelectedLabel = value;\n      this.elements.moveButton.attr('title', value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setMoveAllLabel: function(value, refresh) {\n      this.settings.moveAllLabel = value;\n      this.elements.moveAllButton.attr('title', value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setRemoveSelectedLabel: function(value, refresh) {\n      this.settings.removeSelectedLabel = value;\n      this.elements.removeButton.attr('title', value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setRemoveAllLabel: function(value, refresh) {\n      this.settings.removeAllLabel = value;\n      this.elements.removeAllButton.attr('title', value);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setMoveOnSelect: function(value, refresh) {\n      if (isBuggyAndroid) {\n        value = true;\n      }\n      this.settings.moveOnSelect = value;\n      if (this.settings.moveOnSelect) {\n        this.container.addClass('moveonselect');\n        var self = this;\n        this.elements.select1.on('change', function() {\n          move(self);\n        });\n        this.elements.select2.on('change', function() {\n          remove(self);\n        });\n      } else {\n        this.container.removeClass('moveonselect');\n        this.elements.select1.off('change');\n        this.elements.select2.off('change');\n      }\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setPreserveSelectionOnMove: function(value, refresh) {\n      // We are forcing to move on select and disabling preserveSelectionOnMove on Android\n      if (isBuggyAndroid) {\n        value = false;\n      }\n      this.settings.preserveSelectionOnMove = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setSelectedListLabel: function(value, refresh) {\n      this.settings.selectedListLabel = value;\n      if (value) {\n        this.elements.label2.show().html(value);\n      } else {\n        this.elements.label2.hide().html(value);\n      }\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setNonSelectedListLabel: function(value, refresh) {\n      this.settings.nonSelectedListLabel = value;\n      if (value) {\n        this.elements.label1.show().html(value);\n      } else {\n        this.elements.label1.hide().html(value);\n      }\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setHelperSelectNamePostfix: function(value, refresh) {\n      this.settings.helperSelectNamePostfix = value;\n      if (value) {\n        this.elements.select1.attr('name', this.originalSelectName + value + '1');\n        this.elements.select2.attr('name', this.originalSelectName + value + '2');\n      } else {\n        this.elements.select1.removeAttr('name');\n        this.elements.select2.removeAttr('name');\n      }\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setSelectOrMinimalHeight: function(value, refresh) {\n      this.settings.selectorMinimalHeight = value;\n      var height = this.element.height();\n      if (this.element.height() < value) {\n        height = value;\n      }\n      this.elements.select1.height(height);\n      this.elements.select2.height(height);\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setShowFilterInputs: function(value, refresh) {\n      if (!value) {\n        this.setNonSelectedFilter('');\n        this.setSelectedFilter('');\n        refreshSelects(this);\n        this.elements.filterInput1.hide();\n        this.elements.filterInput2.hide();\n      } else {\n        this.elements.filterInput1.show();\n        this.elements.filterInput2.show();\n      }\n      this.settings.showFilterInputs = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setNonSelectedFilter: function(value, refresh) {\n      if (this.settings.showFilterInputs) {\n        this.settings.nonSelectedFilter = value;\n        this.elements.filterInput1.val(value);\n        if (refresh) {\n          refreshSelects(this);\n        }\n        return this.element;\n      }\n    },\n    setSelectedFilter: function(value, refresh) {\n      if (this.settings.showFilterInputs) {\n        this.settings.selectedFilter = value;\n        this.elements.filterInput2.val(value);\n        if (refresh) {\n          refreshSelects(this);\n        }\n        return this.element;\n      }\n    },\n    setInfoText: function(value, refresh) {\n      this.settings.infoText = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setInfoTextFiltered: function(value, refresh) {\n      this.settings.infoTextFiltered = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setInfoTextEmpty: function(value, refresh) {\n      this.settings.infoTextEmpty = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    setFilterOnValues: function(value, refresh) {\n      this.settings.filterOnValues = value;\n      if (refresh) {\n        refreshSelects(this);\n      }\n      return this.element;\n    },\n    getContainer: function() {\n      return this.container;\n    },\n    refresh: function(mustClearSelections) {\n      updateSelectionStates(this);\n\n      if (!mustClearSelections) {\n        saveSelections(this, 1);\n        saveSelections(this, 2);\n      } else {\n        clearSelections(this);\n      }\n\n      refreshSelects(this);\n    },\n    destroy: function() {\n      this.container.remove();\n      this.element.show();\n      $.data(this, 'plugin_' + pluginName, null);\n      return this.element;\n    }\n  };\n\n  // A really lightweight plugin wrapper around the constructor,\n  // preventing against multiple instantiations\n  $.fn[ pluginName ] = function (options) {\n    var args = arguments;\n\n    // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.\n    if (options === undefined || typeof options === 'object') {\n      return this.each(function () {\n        // If this is not a select\n        if (!$(this).is('select')) {\n          $(this).find('select').each(function(index, item) {\n            // For each nested select, instantiate the Dual List Box\n            $(item).bootstrapDualListbox(options);\n          });\n        } else if (!$.data(this, 'plugin_' + pluginName)) {\n          // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet\n\n          // if it has no instance, create a new one, pass options to our plugin constructor,\n          // and store the plugin instance in the elements jQuery data object.\n          $.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));\n        }\n      });\n      // If the first parameter is a string and it doesn't start with an underscore or \"contains\" the `init`-function,\n      // treat this as a call to a public method.\n    } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {\n\n      // Cache the method call to make it possible to return a value\n      var returns;\n\n      this.each(function () {\n        var instance = $.data(this, 'plugin_' + pluginName);\n        // Tests that there's already a plugin-instance and checks that the requested public method exists\n        if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {\n          // Call the method of our plugin instance, and pass it the supplied arguments.\n          returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));\n        }\n      });\n\n      // If the earlier cached method gives a value back return the value,\n      // otherwise return this to preserve chainability.\n      return returns !== undefined ? returns : this;\n    }\n\n  };\n\n})(jQuery, window, document);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/easypiechart/jquery.easypiechart.js",
    "content": "/**!\n * easyPieChart\n * Lightweight plugin to render simple, animated and retina optimized pie charts\n *\n * @license\n * @author 郑保乐\n * @version 2.1.5\n **/\n\n(function(root, factory) {\n    if(typeof exports === 'object') {\n        module.exports = factory(require('jquery'));\n    }\n    else if(typeof define === 'function' && define.amd) {\n        define(['jquery'], factory);\n    }\n    else {\n        factory(root.jQuery);\n    }\n}(this, function($) {\n\n    /**\n     * Renderer to render the chart on a canvas object\n     * @param {DOMElement} el      DOM element to host the canvas (root of the plugin)\n     * @param {object}     options options object of the plugin\n     */\n    var CanvasRenderer = function(el, options) {\n        var cachedBackground;\n        var canvas = document.createElement('canvas');\n\n        el.appendChild(canvas);\n\n        if (typeof(G_vmlCanvasManager) !== 'undefined') {\n            G_vmlCanvasManager.initElement(canvas);\n        }\n\n        var ctx = canvas.getContext('2d');\n\n        canvas.width = canvas.height = options.size;\n\n        // canvas on retina devices\n        var scaleBy = 1;\n        if (window.devicePixelRatio > 1) {\n            scaleBy = window.devicePixelRatio;\n            canvas.style.width = canvas.style.height = [options.size, 'px'].join('');\n            canvas.width = canvas.height = options.size * scaleBy;\n            ctx.scale(scaleBy, scaleBy);\n        }\n\n        // move 0,0 coordinates to the center\n        ctx.translate(options.size / 2, options.size / 2);\n\n        // rotate canvas -90deg\n        ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);\n\n        var radius = (options.size - options.lineWidth) / 2;\n        if (options.scaleColor && options.scaleLength) {\n            radius -= options.scaleLength + 2; // 2 is the distance between scale and bar\n        }\n\n        // IE polyfill for Date\n        Date.now = Date.now || function() {\n            return +(new Date());\n        };\n\n        /**\n         * Draw a circle around the center of the canvas\n         * @param {strong} color     Valid CSS color string\n         * @param {number} lineWidth Width of the line in px\n         * @param {number} percent   Percentage to draw (float between -1 and 1)\n         */\n        var drawCircle = function(color, lineWidth, percent) {\n            percent = Math.min(Math.max(-1, percent || 0), 1);\n            var isNegative = percent <= 0 ? true : false;\n\n            ctx.beginPath();\n            ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);\n\n            ctx.strokeStyle = color;\n            ctx.lineWidth = lineWidth;\n\n            ctx.stroke();\n        };\n\n        /**\n         * Draw the scale of the chart\n         */\n        var drawScale = function() {\n            var offset;\n            var length;\n\n            ctx.lineWidth = 1;\n            ctx.fillStyle = options.scaleColor;\n\n            ctx.save();\n            for (var i = 24; i > 0; --i) {\n                if (i % 6 === 0) {\n                    length = options.scaleLength;\n                    offset = 0;\n                } else {\n                    length = options.scaleLength * 0.6;\n                    offset = options.scaleLength - length;\n                }\n                ctx.fillRect(-options.size/2 + offset, 0, length, 1);\n                ctx.rotate(Math.PI / 12);\n            }\n            ctx.restore();\n        };\n\n        /**\n         * Request animation frame wrapper with polyfill\n         * @return {function} Request animation frame method or timeout fallback\n         */\n        var reqAnimationFrame = (function() {\n            return  window.requestAnimationFrame ||\n                window.webkitRequestAnimationFrame ||\n                window.mozRequestAnimationFrame ||\n                function(callback) {\n                    window.setTimeout(callback, 1000 / 60);\n                };\n        }());\n\n        /**\n         * Draw the background of the plugin including the scale and the track\n         */\n        var drawBackground = function() {\n            if(options.scaleColor) drawScale();\n            if(options.trackColor) drawCircle(options.trackColor, options.lineWidth, 1);\n        };\n\n        /**\n         * Canvas accessor\n         */\n        this.getCanvas = function() {\n            return canvas;\n        };\n\n        /**\n         * Canvas 2D context 'ctx' accessor\n         */\n        this.getCtx = function() {\n            return ctx;\n        };\n\n        /**\n         * Clear the complete canvas\n         */\n        this.clear = function() {\n            ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);\n        };\n\n        /**\n         * Draw the complete chart\n         * @param {number} percent Percent shown by the chart between -100 and 100\n         */\n        this.draw = function(percent) {\n            // do we need to render a background\n            if (!!options.scaleColor || !!options.trackColor) {\n                // getImageData and putImageData are supported\n                if (ctx.getImageData && ctx.putImageData) {\n                    if (!cachedBackground) {\n                        drawBackground();\n                        cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);\n                    } else {\n                        ctx.putImageData(cachedBackground, 0, 0);\n                    }\n                } else {\n                    this.clear();\n                    drawBackground();\n                }\n            } else {\n                this.clear();\n            }\n\n            ctx.lineCap = options.lineCap;\n\n            // if barcolor is a function execute it and pass the percent as a value\n            var color;\n            if (typeof(options.barColor) === 'function') {\n                color = options.barColor(percent);\n            } else {\n                color = options.barColor;\n            }\n\n            // draw bar\n            drawCircle(color, options.lineWidth, percent / 100);\n        }.bind(this);\n\n        /**\n         * Animate from some percent to some other percentage\n         * @param {number} from Starting percentage\n         * @param {number} to   Final percentage\n         */\n        this.animate = function(from, to) {\n            var startTime = Date.now();\n            options.onStart(from, to);\n            var animation = function() {\n                var process = Math.min(Date.now() - startTime, options.animate.duration);\n                var currentValue = options.easing(this, process, from, to - from, options.animate.duration);\n                this.draw(currentValue);\n                options.onStep(from, to, currentValue);\n                if (process >= options.animate.duration) {\n                    options.onStop(from, to);\n                } else {\n                    reqAnimationFrame(animation);\n                }\n            }.bind(this);\n\n            reqAnimationFrame(animation);\n        }.bind(this);\n    };\n\n    var EasyPieChart = function(el, opts) {\n        var defaultOptions = {\n            barColor: '#ef1e25',\n            trackColor: '#f9f9f9',\n            scaleColor: '#dfe0e0',\n            scaleLength: 5,\n            lineCap: 'round',\n            lineWidth: 3,\n            size: 110,\n            rotate: 0,\n            animate: {\n                duration: 1000,\n                enabled: true\n            },\n            easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/\n                t = t / (d/2);\n                if (t < 1) {\n                    return c / 2 * t * t + b;\n                }\n                return -c/2 * ((--t)*(t-2) - 1) + b;\n            },\n            onStart: function(from, to) {\n                return;\n            },\n            onStep: function(from, to, currentValue) {\n                return;\n            },\n            onStop: function(from, to) {\n                return;\n            }\n        };\n\n        // detect present renderer\n        if (typeof(CanvasRenderer) !== 'undefined') {\n            defaultOptions.renderer = CanvasRenderer;\n        } else if (typeof(SVGRenderer) !== 'undefined') {\n            defaultOptions.renderer = SVGRenderer;\n        } else {\n            throw new Error('Please load either the SVG- or the CanvasRenderer');\n        }\n\n        var options = {};\n        var currentValue = 0;\n\n        /**\n         * Initialize the plugin by creating the options object and initialize rendering\n         */\n        var init = function() {\n            this.el = el;\n            this.options = options;\n\n            // merge user options into default options\n            for (var i in defaultOptions) {\n                if (defaultOptions.hasOwnProperty(i)) {\n                    options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];\n                    if (typeof(options[i]) === 'function') {\n                        options[i] = options[i].bind(this);\n                    }\n                }\n            }\n\n            // check for jQuery easing\n            if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {\n                options.easing = jQuery.easing[options.easing];\n            } else {\n                options.easing = defaultOptions.easing;\n            }\n\n            // process earlier animate option to avoid bc breaks\n            if (typeof(options.animate) === 'number') {\n                options.animate = {\n                    duration: options.animate,\n                    enabled: true\n                };\n            }\n\n            if (typeof(options.animate) === 'boolean' && !options.animate) {\n                options.animate = {\n                    duration: 1000,\n                    enabled: options.animate\n                };\n            }\n\n            // create renderer\n            this.renderer = new options.renderer(el, options);\n\n            // initial draw\n            this.renderer.draw(currentValue);\n\n            // initial update\n            if (el.dataset && el.dataset.percent) {\n                this.update(parseFloat(el.dataset.percent));\n            } else if (el.getAttribute && el.getAttribute('data-percent')) {\n                this.update(parseFloat(el.getAttribute('data-percent')));\n            }\n        }.bind(this);\n\n        /**\n         * Update the value of the chart\n         * @param  {number} newValue Number between 0 and 100\n         * @return {object}          Instance of the plugin for method chaining\n         */\n        this.update = function(newValue) {\n            newValue = parseFloat(newValue);\n            if (options.animate.enabled) {\n                this.renderer.animate(currentValue, newValue);\n            } else {\n                this.renderer.draw(newValue);\n            }\n            currentValue = newValue;\n            return this;\n        }.bind(this);\n\n        /**\n         * Disable animation\n         * @return {object} Instance of the plugin for method chaining\n         */\n        this.disableAnimation = function() {\n            options.animate.enabled = false;\n            return this;\n        };\n\n        /**\n         * Enable animation\n         * @return {object} Instance of the plugin for method chaining\n         */\n        this.enableAnimation = function() {\n            options.animate.enabled = true;\n            return this;\n        };\n\n        init();\n    };\n\n    $.fn.easyPieChart = function(options) {\n        return this.each(function() {\n            var instanceOptions;\n\n            if (!$.data(this, 'easyPieChart')) {\n                instanceOptions = $.extend({}, options, $(this).data());\n                $.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions));\n            }\n        });\n    };\n\n\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/echarts/echarts-all.js",
    "content": "!function(e){var t,i;!function(){function e(e,t){if(!t)return e;if(0===e.indexOf(\".\")){var i=t.split(\"/\"),n=e.split(\"/\"),a=i.length-1,o=n.length,r=0,s=0;e:for(var l=0;o>l;l++)switch(n[l]){case\"..\":if(!(a>r))break e;r++,s++;break;case\".\":s++;break;default:break e}return i.length=a-r,n=n.slice(s),i.concat(n).join(\"/\")}return e}function n(t){function i(i,r){if(\"string\"==typeof i){var s=n[i];return s||(s=o(e(i,t)),n[i]=s),s}i instanceof Array&&(r=r||function(){},r.apply(this,a(i,r,t)))}var n={};return i}function a(i,n,a){for(var s=[],l=r[a],h=0,m=Math.min(i.length,n.length);m>h;h++){var V,U=e(i[h],a);switch(U){case\"require\":V=l&&l.require||t;break;case\"exports\":V=l.exports;break;case\"module\":V=l;break;default:V=o(U)}s.push(V)}return s}function o(e){var t=r[e];if(!t)throw new Error(\"No \"+e);if(!t.defined){var i=t.factory,n=i.apply(this,a(t.deps||[],i,e));\"undefined\"!=typeof n&&(t.exports=n),t.defined=1}return t.exports}var r={};i=function(e,t,i){r[e]={id:e,deps:t,factory:i,defined:0,exports:{},require:n(e)}},t=n(\"\")}(),i(\"echarts\",[\"echarts/echarts\"],function(e){return e}),i(\"echarts/echarts\",[\"require\",\"./config\",\"zrender/tool/util\",\"zrender/tool/event\",\"zrender/tool/env\",\"zrender\",\"zrender/config\",\"./chart/island\",\"./component/toolbox\",\"./component\",\"./component/title\",\"./component/tooltip\",\"./component/legend\",\"./util/ecData\",\"./chart\",\"zrender/tool/color\",\"./component/timeline\",\"zrender/shape/Image\",\"zrender/loadingEffect/Bar\",\"zrender/loadingEffect/Bubble\",\"zrender/loadingEffect/DynamicLine\",\"zrender/loadingEffect/Ring\",\"zrender/loadingEffect/Spin\",\"zrender/loadingEffect/Whirling\",\"./theme/macarons\",\"./theme/infographic\"],function(e){function t(){r.Dispatcher.call(this)}function i(e){e.innerHTML=\"\",this._themeConfig={},this.dom=e,this._connected=!1,this._status={dragIn:!1,dragOut:!1,needRefresh:!1},this._curEventType=!1,this._chartList=[],this._messageCenter=new t,this._messageCenterOutSide=new t,this.resize=this.resize(),this._init()}function n(e,t,i,n,a){for(var o=e._chartList,r=o.length;r--;){var s=o[r];\"function\"==typeof s[t]&&s[t](i,n,a)}}var a=e(\"./config\"),o=e(\"zrender/tool/util\"),r=e(\"zrender/tool/event\"),s={},l=e(\"zrender/tool/env\").canvasSupported,h=new Date-0,m={},V=\"_echarts_instance_\";s.version=\"2.2.7\",s.dependencies={zrender:\"2.1.1\"},s.init=function(t,n){var a=e(\"zrender\");a.version.replace(\".\",\"\")-0<s.dependencies.zrender.replace(\".\",\"\")-0&&console.error(\"ZRender \"+a.version+\" is too old for ECharts \"+s.version+\". Current version need ZRender \"+s.dependencies.zrender+\"+\"),t=t instanceof Array?t[0]:t;var o=t.getAttribute(V);return o||(o=h++,t.setAttribute(V,o)),m[o]&&m[o].dispose(),m[o]=new i(t),m[o].id=o,m[o].canvasSupported=l,m[o].setTheme(n),m[o]},s.getInstanceById=function(e){return m[e]},o.merge(t.prototype,r.Dispatcher.prototype,!0);var U=e(\"zrender/config\").EVENT,d=[\"CLICK\",\"DBLCLICK\",\"MOUSEOVER\",\"MOUSEOUT\",\"DRAGSTART\",\"DRAGEND\",\"DRAGENTER\",\"DRAGOVER\",\"DRAGLEAVE\",\"DROP\"];return i.prototype={_init:function(){var t=this,i=e(\"zrender\").init(this.dom);this._zr=i,this._messageCenter.dispatch=function(e,i,n,a){n=n||{},n.type=e,n.event=i,t._messageCenter.dispatchWithContext(e,n,a),t._messageCenterOutSide.dispatchWithContext(e,n,a)},this._onevent=function(e){return t.__onevent(e)};for(var n in a.EVENT)\"CLICK\"!=n&&\"DBLCLICK\"!=n&&\"HOVER\"!=n&&\"MOUSEOUT\"!=n&&\"MAP_ROAM\"!=n&&this._messageCenter.bind(a.EVENT[n],this._onevent,this);var o={};this._onzrevent=function(e){return t[o[e.type]](e)};for(var r=0,s=d.length;s>r;r++){var l=d[r],h=U[l];o[h]=\"_on\"+l.toLowerCase(),i.on(h,this._onzrevent)}this.chart={},this.component={};var m=e(\"./chart/island\");this._island=new m(this._themeConfig,this._messageCenter,i,{},this),this.chart.island=this._island;var V=e(\"./component/toolbox\");this._toolbox=new V(this._themeConfig,this._messageCenter,i,{},this),this.component.toolbox=this._toolbox;var p=e(\"./component\");p.define(\"title\",e(\"./component/title\")),p.define(\"tooltip\",e(\"./component/tooltip\")),p.define(\"legend\",e(\"./component/legend\")),(0===i.getWidth()||0===i.getHeight())&&console.error(\"Dom’s width & height should be ready before init.\")},__onevent:function(e){e.__echartsId=e.__echartsId||this.id;var t=e.__echartsId===this.id;switch(this._curEventType||(this._curEventType=e.type),e.type){case a.EVENT.LEGEND_SELECTED:this._onlegendSelected(e);break;case a.EVENT.DATA_ZOOM:if(!t){var i=this.component.dataZoom;i&&(i.silence(!0),i.absoluteZoom(e.zoom),i.silence(!1))}this._ondataZoom(e);break;case a.EVENT.DATA_RANGE:t&&this._ondataRange(e);break;case a.EVENT.MAGIC_TYPE_CHANGED:if(!t){var n=this.component.toolbox;n&&(n.silence(!0),n.setMagicType(e.magicType),n.silence(!1))}this._onmagicTypeChanged(e);break;case a.EVENT.DATA_VIEW_CHANGED:t&&this._ondataViewChanged(e);break;case a.EVENT.TOOLTIP_HOVER:t&&this._tooltipHover(e);break;case a.EVENT.RESTORE:this._onrestore();break;case a.EVENT.REFRESH:t&&this._onrefresh(e);break;case a.EVENT.TOOLTIP_IN_GRID:case a.EVENT.TOOLTIP_OUT_GRID:if(t){if(this._connected){var o=this.component.grid;o&&(e.x=(e.event.zrenderX-o.getX())/o.getWidth(),e.y=(e.event.zrenderY-o.getY())/o.getHeight())}}else{var o=this.component.grid;o&&this._zr.trigger(\"mousemove\",{connectTrigger:!0,zrenderX:o.getX()+e.x*o.getWidth(),zrenderY:o.getY()+e.y*o.getHeight()})}}if(this._connected&&t&&this._curEventType===e.type){for(var r in this._connected)this._connected[r].connectedEventHandler(e);this._curEventType=null}(!t||!this._connected&&t)&&(this._curEventType=null)},_onclick:function(e){if(n(this,\"onclick\",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.CLICK,e.event,t,this)}},_ondblclick:function(e){if(n(this,\"ondblclick\",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.DBLCLICK,e.event,t,this)}},_onmouseover:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.HOVER,e.event,t,this)}},_onmouseout:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.MOUSEOUT,e.event,t,this)}},_ondragstart:function(e){this._status={dragIn:!1,dragOut:!1,needRefresh:!1},n(this,\"ondragstart\",e)},_ondragenter:function(e){n(this,\"ondragenter\",e)},_ondragover:function(e){n(this,\"ondragover\",e)},_ondragleave:function(e){n(this,\"ondragleave\",e)},_ondrop:function(e){n(this,\"ondrop\",e,this._status),this._island.ondrop(e,this._status)},_ondragend:function(e){if(n(this,\"ondragend\",e,this._status),this._timeline&&this._timeline.ondragend(e,this._status),this._island.ondragend(e,this._status),this._status.needRefresh){this._syncBackupData(this._option);var t=this._messageCenter;t.dispatch(a.EVENT.DATA_CHANGED,e.event,this._eventPackage(e.target),this),t.dispatch(a.EVENT.REFRESH,null,null,this)}},_onlegendSelected:function(e){this._status.needRefresh=!1,n(this,\"onlegendSelected\",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataZoom:function(e){this._status.needRefresh=!1,n(this,\"ondataZoom\",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataRange:function(e){this._clearEffect(),this._status.needRefresh=!1,n(this,\"ondataRange\",e,this._status),this._status.needRefresh&&this._zr.refreshNextFrame()},_onmagicTypeChanged:function(){this._clearEffect(),this._render(this._toolbox.getMagicOption())},_ondataViewChanged:function(e){this._syncBackupData(e.option),this._messageCenter.dispatch(a.EVENT.DATA_CHANGED,null,e,this),this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_tooltipHover:function(e){var t=[];n(this,\"ontooltipHover\",e,t)},_onrestore:function(){this.restore()},_onrefresh:function(e){this._refreshInside=!0,this.refresh(e),this._refreshInside=!1},_syncBackupData:function(e){this.component.dataZoom&&this.component.dataZoom.syncBackupData(e)},_eventPackage:function(t){if(t){var i=e(\"./util/ecData\"),n=i.get(t,\"seriesIndex\"),a=i.get(t,\"dataIndex\");return a=-1!=n&&this.component.dataZoom?this.component.dataZoom.getRealDataIndex(n,a):a,{seriesIndex:n,seriesName:(i.get(t,\"series\")||{}).name,dataIndex:a,data:i.get(t,\"data\"),name:i.get(t,\"name\"),value:i.get(t,\"value\"),special:i.get(t,\"special\")}}},_noDataCheck:function(e){for(var t=e.series,i=0,n=t.length;n>i;i++)if(t[i].type==a.CHART_TYPE_MAP||t[i].data&&t[i].data.length>0||t[i].markPoint&&t[i].markPoint.data&&t[i].markPoint.data.length>0||t[i].markLine&&t[i].markLine.data&&t[i].markLine.data.length>0||t[i].nodes&&t[i].nodes.length>0||t[i].links&&t[i].links.length>0||t[i].matrix&&t[i].matrix.length>0||t[i].eventList&&t[i].eventList.length>0)return!1;var o=this._option&&this._option.noDataLoadingOption||this._themeConfig.noDataLoadingOption||a.noDataLoadingOption||{text:this._option&&this._option.noDataText||this._themeConfig.noDataText||a.noDataText,effect:this._option&&this._option.noDataEffect||this._themeConfig.noDataEffect||a.noDataEffect};return this.clear(),this.showLoading(o),!0},_render:function(t){if(this._mergeGlobalConifg(t),!this._noDataCheck(t)){var i=t.backgroundColor;if(i)if(l||-1==i.indexOf(\"rgba\"))this.dom.style.backgroundColor=i;else{var n=i.split(\",\");this.dom.style.filter=\"alpha(opacity=\"+100*n[3].substring(0,n[3].lastIndexOf(\")\"))+\")\",n.length=3,n[0]=n[0].replace(\"a\",\"\"),this.dom.style.backgroundColor=n.join(\",\")+\")\"}this._zr.clearAnimation(),this._chartList=[];var o=e(\"./chart\"),r=e(\"./component\");(t.xAxis||t.yAxis)&&(t.grid=t.grid||{},t.dataZoom=t.dataZoom||{});for(var s,h,m,V=[\"title\",\"legend\",\"tooltip\",\"dataRange\",\"roamController\",\"grid\",\"dataZoom\",\"xAxis\",\"yAxis\",\"polar\"],U=0,d=V.length;d>U;U++)h=V[U],m=this.component[h],t[h]?(m?m.refresh&&m.refresh(t):(s=r.get(/^[xy]Axis$/.test(h)?\"axis\":h),m=new s(this._themeConfig,this._messageCenter,this._zr,t,this,h),this.component[h]=m),this._chartList.push(m)):m&&(m.dispose(),this.component[h]=null,delete this.component[h]);for(var p,c,u,y={},U=0,d=t.series.length;d>U;U++)c=t.series[U].type,c?y[c]||(y[c]=!0,p=o.get(c),p?(this.chart[c]?(u=this.chart[c],u.refresh(t)):u=new p(this._themeConfig,this._messageCenter,this._zr,t,this),this._chartList.push(u),this.chart[c]=u):console.error(c+\" has not been required.\")):console.error(\"series[\"+U+\"] chart type has not been defined.\");for(c in this.chart)c==a.CHART_TYPE_ISLAND||y[c]||(this.chart[c].dispose(),this.chart[c]=null,delete this.chart[c]);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._island.refresh(t),this._toolbox.refresh(t),t.animation&&!t.renderAsImage?this._zr.refresh():this._zr.render();var g=\"IMG\"+this.id,b=document.getElementById(g);t.renderAsImage&&l?(b?b.src=this.getDataURL(t.renderAsImage):(b=this.getImage(t.renderAsImage),b.id=g,b.style.position=\"absolute\",b.style.left=0,b.style.top=0,this.dom.firstChild.appendChild(b)),this.un(),this._zr.un(),this._disposeChartList(),this._zr.clear()):b&&b.parentNode.removeChild(b),b=null,this._option=t}},restore:function(){this._clearEffect(),this._option=o.clone(this._optionRestore),this._disposeChartList(),this._island.clear(),this._toolbox.reset(this._option,!0),this._render(this._option)},refresh:function(e){this._clearEffect(),e=e||{};var t=e.option;!this._refreshInside&&t&&(t=this.getOption(),o.merge(t,e.option,!0),o.merge(this._optionRestore,e.option,!0),this._toolbox.reset(t)),this._island.refresh(t),this._toolbox.refresh(t),this._zr.clearAnimation();for(var i=0,n=this._chartList.length;n>i;i++)this._chartList[i].refresh&&this._chartList[i].refresh(t);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._zr.refresh()},_disposeChartList:function(){this._clearEffect(),this._zr.clearAnimation();for(var e=this._chartList.length;e--;){var t=this._chartList[e];if(t){var i=t.type;this.chart[i]&&delete this.chart[i],this.component[i]&&delete this.component[i],t.dispose&&t.dispose()}}this._chartList=[]},_mergeGlobalConifg:function(t){for(var i=[\"backgroundColor\",\"calculable\",\"calculableColor\",\"calculableHolderColor\",\"nameConnector\",\"valueConnector\",\"animation\",\"animationThreshold\",\"animationDuration\",\"animationDurationUpdate\",\"animationEasing\",\"addDataAnimation\",\"symbolList\",\"DRAG_ENABLE_TIME\"],n=i.length;n--;){var o=i[n];null==t[o]&&(t[o]=null!=this._themeConfig[o]?this._themeConfig[o]:a[o])}var r=t.color;r&&r.length||(r=this._themeConfig.color||a.color),this._zr.getColor=function(t){var i=e(\"zrender/tool/color\");return i.getColor(t,r)},l||(t.animation=!1,t.addDataAnimation=!1)},setOption:function(e,t){return e.timeline?this._setTimelineOption(e):this._setOption(e,t)},_setOption:function(e,t,i){return!t&&this._option?this._option=o.merge(this.getOption(),o.clone(e),!0):(this._option=o.clone(e),!i&&this._timeline&&this._timeline.dispose()),this._optionRestore=o.clone(this._option),this._option.series&&0!==this._option.series.length?(this.component.dataZoom&&(this._option.dataZoom||this._option.toolbox&&this._option.toolbox.feature&&this._option.toolbox.feature.dataZoom&&this._option.toolbox.feature.dataZoom.show)&&this.component.dataZoom.syncOption(this._option),this._toolbox.reset(this._option),this._render(this._option),this):void this._zr.clear()},getOption:function(){function e(e){var n=i._optionRestore[e];if(n)if(n instanceof Array)for(var a=n.length;a--;)t[e][a].data=o.clone(n[a].data);else t[e].data=o.clone(n.data)}var t=o.clone(this._option),i=this;return e(\"xAxis\"),e(\"yAxis\"),e(\"series\"),t},setSeries:function(e,t){return t?(this._option.series=e,this.setOption(this._option,t)):this.setOption({series:e}),this},getSeries:function(){return this.getOption().series},_setTimelineOption:function(t){this._timeline&&this._timeline.dispose();var i=e(\"./component/timeline\"),n=new i(this._themeConfig,this._messageCenter,this._zr,t,this);return this._timeline=n,this.component.timeline=this._timeline,this},addData:function(e,t,i,n,r){function s(){if(V._zr){V._zr.clearAnimation();for(var e=0,t=X.length;t>e;e++)X[e].motionlessOnce=h.addDataAnimation&&X[e].addDataAnimation;V._messageCenter.dispatch(a.EVENT.REFRESH,null,{option:h},V)}}for(var l=e instanceof Array?e:[[e,t,i,n,r]],h=this.getOption(),m=this._optionRestore,V=this,U=0,d=l.length;d>U;U++){e=l[U][0],t=l[U][1],i=l[U][2],n=l[U][3],r=l[U][4];var p=m.series[e],c=i?\"unshift\":\"push\",u=i?\"pop\":\"shift\";if(p){var y=p.data,g=h.series[e].data;if(y[c](t),g[c](t),n||(y[u](),t=g[u]()),null!=r){var b,f;if(p.type===a.CHART_TYPE_PIE&&(b=m.legend)&&(f=b.data)){var k=h.legend.data;if(f[c](r),k[c](r),!n){var x=o.indexOf(f,t.name);-1!=x&&f.splice(x,1),x=o.indexOf(k,t.name),-1!=x&&k.splice(x,1)}}else if(null!=m.xAxis&&null!=m.yAxis){var _,L,W=p.xAxisIndex||0;(null==m.xAxis[W].type||\"category\"===m.xAxis[W].type)&&(_=m.xAxis[W].data,L=h.xAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]())),W=p.yAxisIndex||0,\"category\"===m.yAxis[W].type&&(_=m.yAxis[W].data,L=h.yAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]()))}}this._option.series[e].data=h.series[e].data}}this._zr.clearAnimation();for(var X=this._chartList,v=0,w=function(){v--,0===v&&s()},U=0,d=X.length;d>U;U++)h.addDataAnimation&&X[U].addDataAnimation&&(v++,X[U].addDataAnimation(l,w));return this.component.dataZoom&&this.component.dataZoom.syncOption(h),this._option=h,h.addDataAnimation||setTimeout(s,0),this},addMarkPoint:function(e,t){return this._addMark(e,t,\"markPoint\")},addMarkLine:function(e,t){return this._addMark(e,t,\"markLine\")},_addMark:function(e,t,i){var n,a=this._option.series;if(a&&(n=a[e])){var r=this._optionRestore.series,s=r[e],l=n[i],h=s[i];l=n[i]=l||{data:[]},h=s[i]=h||{data:[]};for(var m in t)\"data\"===m?(l.data=l.data.concat(t.data),h.data=h.data.concat(t.data)):\"object\"!=typeof t[m]||null==l[m]?l[m]=h[m]=t[m]:(o.merge(l[m],t[m],!0),o.merge(h[m],t[m],!0));var V=this.chart[n.type];V&&V.addMark(e,t,i)}return this},delMarkPoint:function(e,t){return this._delMark(e,t,\"markPoint\")},delMarkLine:function(e,t){return this._delMark(e,t,\"markLine\")},_delMark:function(e,t,i){var n,a,o,r=this._option.series;if(!(r&&(n=r[e])&&(a=n[i])&&(o=a.data)))return this;t=t.split(\" > \");for(var s=-1,l=0,h=o.length;h>l;l++){var m=o[l];if(m instanceof Array){if(m[0].name===t[0]&&m[1].name===t[1]){s=l;break}}else if(m.name===t[0]){s=l;break}}if(s>-1){o.splice(s,1),this._optionRestore.series[e][i].data.splice(s,1);var V=this.chart[n.type];V&&V.delMark(e,t.join(\" > \"),i)}return this},getDom:function(){return this.dom},getZrender:function(){return this._zr},getDataURL:function(e){if(!l)return\"\";if(0===this._chartList.length){var t=\"IMG\"+this.id,i=document.getElementById(t);if(i)return i.src}var n=this.component.tooltip;switch(n&&n.hideTip(),e){case\"jpeg\":break;default:e=\"png\"}var a=this._option.backgroundColor;return a&&\"rgba(0,0,0,0)\"===a.replace(\" \",\"\")&&(a=\"#fff\"),this._zr.toDataURL(\"image/\"+e,a)},getImage:function(e){var t=this._optionRestore.title,i=document.createElement(\"img\");return i.src=this.getDataURL(e),i.title=t&&t.text||\"ECharts\",i},getConnectedDataURL:function(t){if(!this.isConnected())return this.getDataURL(t);var i=this.dom,n={self:{img:this.getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight}},a=n.self.left,o=n.self.top,r=n.self.right,s=n.self.bottom;for(var l in this._connected)i=this._connected[l].getDom(),n[l]={img:this._connected[l].getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight},a=Math.min(a,n[l].left),o=Math.min(o,n[l].top),r=Math.max(r,n[l].right),s=Math.max(s,n[l].bottom);var h=document.createElement(\"div\");h.style.position=\"absolute\",h.style.left=\"-4000px\",h.style.width=r-a+\"px\",h.style.height=s-o+\"px\",document.body.appendChild(h);var m=e(\"zrender\").init(h),V=e(\"zrender/shape/Image\");for(var l in n)m.addShape(new V({style:{x:n[l].left-a,y:n[l].top-o,image:n[l].img}}));m.render();var U=this._option.backgroundColor;U&&\"rgba(0,0,0,0)\"===U.replace(/ /g,\"\")&&(U=\"#fff\");var d=m.toDataURL(\"image/png\",U);return setTimeout(function(){m.dispose(),h.parentNode.removeChild(h),h=null},100),d},getConnectedImage:function(e){var t=this._optionRestore.title,i=document.createElement(\"img\");return i.src=this.getConnectedDataURL(e),i.title=t&&t.text||\"ECharts\",i},on:function(e,t){return this._messageCenterOutSide.bind(e,t,this),this},un:function(e,t){return this._messageCenterOutSide.unbind(e,t),this},connect:function(e){if(!e)return this;if(this._connected||(this._connected={}),e instanceof Array)for(var t=0,i=e.length;i>t;t++)this._connected[e[t].id]=e[t];else this._connected[e.id]=e;return this},disConnect:function(e){if(!e||!this._connected)return this;if(e instanceof Array)for(var t=0,i=e.length;i>t;t++)delete this._connected[e[t].id];else delete this._connected[e.id];for(var n in this._connected)return this;return this._connected=!1,this},connectedEventHandler:function(e){e.__echartsId!=this.id&&this._onevent(e)},isConnected:function(){return!!this._connected},showLoading:function(t){var i={bar:e(\"zrender/loadingEffect/Bar\"),bubble:e(\"zrender/loadingEffect/Bubble\"),dynamicLine:e(\"zrender/loadingEffect/DynamicLine\"),ring:e(\"zrender/loadingEffect/Ring\"),spin:e(\"zrender/loadingEffect/Spin\"),whirling:e(\"zrender/loadingEffect/Whirling\")};this._toolbox.hideDataView(),t=t||{};var n=t.textStyle||{};t.textStyle=n;var r=o.merge(o.merge(o.clone(n),this._themeConfig.textStyle),a.textStyle);n.textFont=r.fontStyle+\" \"+r.fontWeight+\" \"+r.fontSize+\"px \"+r.fontFamily,n.text=t.text||this._option&&this._option.loadingText||this._themeConfig.loadingText||a.loadingText,null!=t.x&&(n.x=t.x),null!=t.y&&(n.y=t.y),t.effectOption=t.effectOption||{},t.effectOption.textStyle=n;var s=t.effect;return(\"string\"==typeof s||null==s)&&(s=i[t.effect||this._option&&this._option.loadingEffect||this._themeConfig.loadingEffect||a.loadingEffect]||i.spin),this._zr.showLoading(new s(t.effectOption)),this},hideLoading:function(){return this._zr.hideLoading(),this},setTheme:function(t){if(t){if(\"string\"==typeof t)switch(t){case\"macarons\":t=e(\"./theme/macarons\");break;case\"infographic\":t=e(\"./theme/infographic\");break;default:t={}}else t=t||{};this._themeConfig=t}if(!l){var i=this._themeConfig.textStyle;i&&i.fontFamily&&i.fontFamily2&&(i.fontFamily=i.fontFamily2),i=a.textStyle,i.fontFamily=i.fontFamily2}this._timeline&&this._timeline.setTheme(!0),this._optionRestore&&this.restore()},resize:function(){var e=this;return function(){if(e._clearEffect(),e._zr.resize(),e._option&&e._option.renderAsImage&&l)return e._render(e._option),e;e._zr.clearAnimation(),e._island.resize(),e._toolbox.resize(),e._timeline&&e._timeline.resize();for(var t=0,i=e._chartList.length;i>t;t++)e._chartList[t].resize&&e._chartList[t].resize();return e.component.grid&&e.component.grid.refixAxisShape(e.component),e._zr.refresh(),e._messageCenter.dispatch(a.EVENT.RESIZE,null,null,e),e}},_clearEffect:function(){this._zr.modLayer(a.EFFECT_ZLEVEL,{motionBlur:!1}),this._zr.painter.clearLayer(a.EFFECT_ZLEVEL)},clear:function(){return this._disposeChartList(),this._zr.clear(),this._option={},this._optionRestore={},this.dom.style.backgroundColor=null,this},dispose:function(){var e=this.dom.getAttribute(V);e&&delete m[e],this._island.dispose(),this._toolbox.dispose(),this._timeline&&this._timeline.dispose(),this._messageCenter.unbind(),this.clear(),this._zr.dispose(),this._zr=null}},s}),i(\"echarts/config\",[],function(){var e={CHART_TYPE_LINE:\"line\",CHART_TYPE_BAR:\"bar\",CHART_TYPE_SCATTER:\"scatter\",CHART_TYPE_PIE:\"pie\",CHART_TYPE_RADAR:\"radar\",CHART_TYPE_VENN:\"venn\",CHART_TYPE_TREEMAP:\"treemap\",CHART_TYPE_TREE:\"tree\",CHART_TYPE_MAP:\"map\",CHART_TYPE_K:\"k\",CHART_TYPE_ISLAND:\"island\",CHART_TYPE_FORCE:\"force\",CHART_TYPE_CHORD:\"chord\",CHART_TYPE_GAUGE:\"gauge\",CHART_TYPE_FUNNEL:\"funnel\",CHART_TYPE_EVENTRIVER:\"eventRiver\",CHART_TYPE_WORDCLOUD:\"wordCloud\",CHART_TYPE_HEATMAP:\"heatmap\",COMPONENT_TYPE_TITLE:\"title\",COMPONENT_TYPE_LEGEND:\"legend\",COMPONENT_TYPE_DATARANGE:\"dataRange\",COMPONENT_TYPE_DATAVIEW:\"dataView\",COMPONENT_TYPE_DATAZOOM:\"dataZoom\",COMPONENT_TYPE_TOOLBOX:\"toolbox\",COMPONENT_TYPE_TOOLTIP:\"tooltip\",COMPONENT_TYPE_GRID:\"grid\",COMPONENT_TYPE_AXIS:\"axis\",COMPONENT_TYPE_POLAR:\"polar\",COMPONENT_TYPE_X_AXIS:\"xAxis\",COMPONENT_TYPE_Y_AXIS:\"yAxis\",COMPONENT_TYPE_AXIS_CATEGORY:\"categoryAxis\",COMPONENT_TYPE_AXIS_VALUE:\"valueAxis\",COMPONENT_TYPE_TIMELINE:\"timeline\",COMPONENT_TYPE_ROAMCONTROLLER:\"roamController\",backgroundColor:\"rgba(0,0,0,0)\",color:[\"#ff7f50\",\"#87cefa\",\"#da70d6\",\"#32cd32\",\"#6495ed\",\"#ff69b4\",\"#ba55d3\",\"#cd5c5c\",\"#ffa500\",\"#40e0d0\",\"#1e90ff\",\"#ff6347\",\"#7b68ee\",\"#00fa9a\",\"#ffd700\",\"#6699FF\",\"#ff6666\",\"#3cb371\",\"#b8860b\",\"#30e0e0\"],markPoint:{clickable:!0,symbol:\"pin\",symbolSize:10,large:!1,effect:{show:!1,loop:!0,period:15,type:\"scale\",scaleSize:2,bounceDistance:10},itemStyle:{normal:{borderWidth:2,label:{show:!0,position:\"inside\"}},emphasis:{label:{show:!0}}}},markLine:{clickable:!0,symbol:[\"circle\",\"arrow\"],symbolSize:[2,4],smoothness:.2,precision:2,effect:{show:!1,loop:!0,period:15,scaleSize:2},bundling:{enable:!1,maxTurningAngle:45},itemStyle:{normal:{borderWidth:1.5,label:{show:!0,position:\"end\"},lineStyle:{type:\"dashed\"}},emphasis:{label:{show:!1},lineStyle:{}}}},textStyle:{decoration:\"none\",fontFamily:\"Arial, Verdana, sans-serif\",fontFamily2:\"微软雅黑\",fontSize:12,fontStyle:\"normal\",fontWeight:\"normal\"},EVENT:{REFRESH:\"refresh\",RESTORE:\"restore\",RESIZE:\"resize\",CLICK:\"click\",DBLCLICK:\"dblclick\",HOVER:\"hover\",MOUSEOUT:\"mouseout\",DATA_CHANGED:\"dataChanged\",DATA_ZOOM:\"dataZoom\",DATA_RANGE:\"dataRange\",DATA_RANGE_SELECTED:\"dataRangeSelected\",DATA_RANGE_HOVERLINK:\"dataRangeHoverLink\",LEGEND_SELECTED:\"legendSelected\",LEGEND_HOVERLINK:\"legendHoverLink\",MAP_SELECTED:\"mapSelected\",PIE_SELECTED:\"pieSelected\",MAGIC_TYPE_CHANGED:\"magicTypeChanged\",DATA_VIEW_CHANGED:\"dataViewChanged\",TIMELINE_CHANGED:\"timelineChanged\",MAP_ROAM:\"mapRoam\",FORCE_LAYOUT_END:\"forceLayoutEnd\",TOOLTIP_HOVER:\"tooltipHover\",TOOLTIP_IN_GRID:\"tooltipInGrid\",TOOLTIP_OUT_GRID:\"tooltipOutGrid\",ROAMCONTROLLER:\"roamController\"},DRAG_ENABLE_TIME:120,EFFECT_ZLEVEL:10,effectBlendAlpha:.95,symbolList:[\"circle\",\"rectangle\",\"triangle\",\"diamond\",\"emptyCircle\",\"emptyRectangle\",\"emptyTriangle\",\"emptyDiamond\"],loadingEffect:\"spin\",loadingText:\"数据读取中...\",noDataEffect:\"bubble\",noDataText:\"暂无数据\",calculable:!1,calculableColor:\"rgba(255,165,0,0.6)\",calculableHolderColor:\"#ccc\",nameConnector:\" & \",valueConnector:\": \",animation:!0,addDataAnimation:!0,animationThreshold:2e3,animationDuration:2e3,animationDurationUpdate:500,animationEasing:\"ExponentialOut\"};return e}),i(\"zrender/tool/util\",[\"require\",\"../dep/excanvas\"],function(e){function t(e){return e&&1===e.nodeType&&\"string\"==typeof e.nodeName}function i(e){if(\"object\"==typeof e&&null!==e){var n=e;if(e instanceof Array){n=[];for(var a=0,o=e.length;o>a;a++)n[a]=i(e[a])}else if(!y[g.call(e)]&&!t(e)){n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=i(e[r]))}return n}return e}function n(e,i,n,o){if(i.hasOwnProperty(n)){var r=e[n];\"object\"!=typeof r||y[g.call(r)]||t(r)?!o&&n in e||(e[n]=i[n]):a(e[n],i[n],o)}}function a(e,t,i){for(var a in t)n(e,t,a,i);return e}function o(){if(!U)if(e(\"../dep/excanvas\"),window.G_vmlCanvasManager){var t=document.createElement(\"div\");t.style.position=\"absolute\",t.style.top=\"-1000px\",document.body.appendChild(t),U=G_vmlCanvasManager.initElement(t).getContext(\"2d\")}else U=document.createElement(\"canvas\").getContext(\"2d\");return U}function r(e,t){if(e.indexOf)return e.indexOf(t);for(var i=0,n=e.length;n>i;i++)if(e[i]===t)return i;return-1}function s(e,t){function i(){}var n=e.prototype;i.prototype=t.prototype,e.prototype=new i;for(var a in n)e.prototype[a]=n[a];e.constructor=e}function l(e,t,i){if(e&&t)if(e.forEach&&e.forEach===p)e.forEach(t,i);else if(e.length===+e.length)for(var n=0,a=e.length;a>n;n++)t.call(i,e[n],n,e);else for(var o in e)e.hasOwnProperty(o)&&t.call(i,e[o],o,e)}function h(e,t,i){if(e&&t){if(e.map&&e.map===c)return e.map(t,i);for(var n=[],a=0,o=e.length;o>a;a++)n.push(t.call(i,e[a],a,e));return n}}function m(e,t,i){if(e&&t){if(e.filter&&e.filter===u)return e.filter(t,i);for(var n=[],a=0,o=e.length;o>a;a++)t.call(i,e[a],a,e)&&n.push(e[a]);return n}}function V(e,t){return function(){e.apply(t,arguments)}}var U,d=Array.prototype,p=d.forEach,c=d.map,u=d.filter,y={\"[object Function]\":1,\"[object RegExp]\":1,\"[object Date]\":1,\"[object Error]\":1,\"[object CanvasGradient]\":1},g=Object.prototype.toString;return{inherits:s,clone:i,merge:a,getContext:o,indexOf:r,each:l,map:h,filter:m,bind:V}}),i(\"zrender/tool/event\",[\"require\",\"../mixin/Eventful\"],function(e){\"use strict\";function t(e){return\"undefined\"!=typeof e.zrenderX&&e.zrenderX||\"undefined\"!=typeof e.offsetX&&e.offsetX||\"undefined\"!=typeof e.layerX&&e.layerX||\"undefined\"!=typeof e.clientX&&e.clientX}function i(e){return\"undefined\"!=typeof e.zrenderY&&e.zrenderY||\"undefined\"!=typeof e.offsetY&&e.offsetY||\"undefined\"!=typeof e.layerY&&e.layerY||\"undefined\"!=typeof e.clientY&&e.clientY}function n(e){return\"undefined\"!=typeof e.zrenderDelta&&e.zrenderDelta||\"undefined\"!=typeof e.wheelDelta&&e.wheelDelta||\"undefined\"!=typeof e.detail&&-e.detail}var a=e(\"../mixin/Eventful\"),o=\"function\"==typeof window.addEventListener?function(e){e.preventDefault(),e.stopPropagation(),e.cancelBubble=!0}:function(e){e.returnValue=!1,e.cancelBubble=!0};return{getX:t,getY:i,getDelta:n,stop:o,Dispatcher:a}}),i(\"zrender/tool/env\",[],function(){function e(e){var t=this.os={},i=this.browser={},n=e.match(/Web[kK]it[\\/]{0,1}([\\d.]+)/),a=e.match(/(Android);?[\\s\\/]+([\\d.]+)?/),o=e.match(/(iPad).*OS\\s([\\d_]+)/),r=e.match(/(iPod)(.*OS\\s([\\d_]+))?/),s=!o&&e.match(/(iPhone\\sOS)\\s([\\d_]+)/),l=e.match(/(webOS|hpwOS)[\\s\\/]([\\d.]+)/),h=l&&e.match(/TouchPad/),m=e.match(/Kindle\\/([\\d.]+)/),V=e.match(/Silk\\/([\\d._]+)/),U=e.match(/(BlackBerry).*Version\\/([\\d.]+)/),d=e.match(/(BB10).*Version\\/([\\d.]+)/),p=e.match(/(RIM\\sTablet\\sOS)\\s([\\d.]+)/),c=e.match(/PlayBook/),u=e.match(/Chrome\\/([\\d.]+)/)||e.match(/CriOS\\/([\\d.]+)/),y=e.match(/Firefox\\/([\\d.]+)/),g=e.match(/MSIE ([\\d.]+)/),b=n&&e.match(/Mobile\\//)&&!u,f=e.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/)&&!u,g=e.match(/MSIE\\s([\\d.]+)/);return(i.webkit=!!n)&&(i.version=n[1]),a&&(t.android=!0,t.version=a[2]),s&&!r&&(t.ios=t.iphone=!0,t.version=s[2].replace(/_/g,\".\")),o&&(t.ios=t.ipad=!0,t.version=o[2].replace(/_/g,\".\")),r&&(t.ios=t.ipod=!0,t.version=r[3]?r[3].replace(/_/g,\".\"):null),l&&(t.webos=!0,t.version=l[2]),h&&(t.touchpad=!0),U&&(t.blackberry=!0,t.version=U[2]),d&&(t.bb10=!0,t.version=d[2]),p&&(t.rimtabletos=!0,t.version=p[2]),c&&(i.playbook=!0),m&&(t.kindle=!0,t.version=m[1]),V&&(i.silk=!0,i.version=V[1]),!V&&t.android&&e.match(/Kindle Fire/)&&(i.silk=!0),u&&(i.chrome=!0,i.version=u[1]),y&&(i.firefox=!0,i.version=y[1]),g&&(i.ie=!0,i.version=g[1]),b&&(e.match(/Safari/)||t.ios)&&(i.safari=!0),f&&(i.webview=!0),g&&(i.ie=!0,i.version=g[1]),t.tablet=!!(o||c||a&&!e.match(/Mobile/)||y&&e.match(/Tablet/)||g&&!e.match(/Phone/)&&e.match(/Touch/)),t.phone=!(t.tablet||t.ipod||!(a||s||l||U||d||u&&e.match(/Android/)||u&&e.match(/CriOS\\/([\\d.]+)/)||y&&e.match(/Mobile/)||g&&e.match(/Touch/))),{browser:i,os:t,canvasSupported:document.createElement(\"canvas\").getContext?!0:!1}}return e(navigator.userAgent)}),i(\"zrender\",[\"zrender/zrender\"],function(e){return e}),i(\"zrender/zrender\",[\"require\",\"./dep/excanvas\",\"./tool/util\",\"./tool/log\",\"./tool/guid\",\"./Handler\",\"./Painter\",\"./Storage\",\"./animation/Animation\",\"./tool/env\"],function(e){function t(e){return function(){e._needsRefreshNextFrame&&e.refresh()}}e(\"./dep/excanvas\");var i=e(\"./tool/util\"),n=e(\"./tool/log\"),a=e(\"./tool/guid\"),o=e(\"./Handler\"),r=e(\"./Painter\"),s=e(\"./Storage\"),l=e(\"./animation/Animation\"),h={},m={};m.version=\"2.1.1\",m.init=function(e){var t=new V(a(),e);return h[t.id]=t,t},m.dispose=function(e){if(e)e.dispose();else{for(var t in h)h[t].dispose();h={}}return m},m.getInstance=function(e){return h[e]},m.delInstance=function(e){return delete h[e],m};var V=function(i,n){this.id=i,this.env=e(\"./tool/env\"),this.storage=new s,this.painter=new r(n,this.storage),this.handler=new o(n,this.storage,this.painter),this.animation=new l({stage:{update:t(this)}}),this.animation.start();var a=this;this.painter.refreshNextFrame=function(){a.refreshNextFrame()},this._needsRefreshNextFrame=!1;var a=this,h=this.storage,m=h.delFromMap;h.delFromMap=function(e){var t=h.get(e);a.stopAnimation(t),m.call(h,e)}};return V.prototype.getId=function(){return this.id},V.prototype.addShape=function(e){return this.addElement(e),this},V.prototype.addGroup=function(e){return this.addElement(e),this},V.prototype.delShape=function(e){return this.delElement(e),this},V.prototype.delGroup=function(e){return this.delElement(e),this},V.prototype.modShape=function(e,t){return this.modElement(e,t),this},V.prototype.modGroup=function(e,t){return this.modElement(e,t),this},V.prototype.addElement=function(e){return this.storage.addRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.delElement=function(e){return this.storage.delRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.modElement=function(e,t){return this.storage.mod(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.modLayer=function(e,t){return this.painter.modLayer(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.addHoverShape=function(e){return this.storage.addHover(e),this},V.prototype.render=function(e){return this.painter.render(e),this._needsRefreshNextFrame=!1,this},V.prototype.refresh=function(e){return this.painter.refresh(e),this._needsRefreshNextFrame=!1,this},V.prototype.refreshNextFrame=function(){return this._needsRefreshNextFrame=!0,this},V.prototype.refreshHover=function(e){return this.painter.refreshHover(e),this},V.prototype.refreshShapes=function(e,t){return this.painter.refreshShapes(e,t),this},V.prototype.resize=function(){return this.painter.resize(),this},V.prototype.animate=function(e,t,a){var o=this;if(\"string\"==typeof e&&(e=this.storage.get(e)),e){var r;if(t){for(var s=t.split(\".\"),l=e,h=0,m=s.length;m>h;h++)l&&(l=l[s[h]]);l&&(r=l)}else r=e;if(!r)return void n('Property \"'+t+'\" is not existed in element '+e.id);\n\nnull==e.__animators&&(e.__animators=[]);var V=e.__animators,U=this.animation.animate(r,{loop:a}).during(function(){o.modShape(e)}).done(function(){var t=i.indexOf(e.__animators,U);t>=0&&V.splice(t,1)});return V.push(U),U}n(\"Element not existed\")},V.prototype.stopAnimation=function(e){if(e.__animators){for(var t=e.__animators,i=t.length,n=0;i>n;n++)t[n].stop();t.length=0}return this},V.prototype.clearAnimation=function(){return this.animation.clear(),this},V.prototype.showLoading=function(e){return this.painter.showLoading(e),this},V.prototype.hideLoading=function(){return this.painter.hideLoading(),this},V.prototype.getWidth=function(){return this.painter.getWidth()},V.prototype.getHeight=function(){return this.painter.getHeight()},V.prototype.toDataURL=function(e,t,i){return this.painter.toDataURL(e,t,i)},V.prototype.shapeToImage=function(e,t,i){var n=a();return this.painter.shapeToImage(n,e,t,i)},V.prototype.on=function(e,t,i){return this.handler.on(e,t,i),this},V.prototype.un=function(e,t){return this.handler.un(e,t),this},V.prototype.trigger=function(e,t){return this.handler.trigger(e,t),this},V.prototype.clear=function(){return this.storage.delRoot(),this.painter.clear(),this},V.prototype.dispose=function(){this.animation.stop(),this.clear(),this.storage.dispose(),this.painter.dispose(),this.handler.dispose(),this.animation=this.storage=this.painter=this.handler=null,m.delInstance(this.id)},m}),i(\"zrender/config\",[],function(){var e={EVENT:{RESIZE:\"resize\",CLICK:\"click\",DBLCLICK:\"dblclick\",MOUSEWHEEL:\"mousewheel\",MOUSEMOVE:\"mousemove\",MOUSEOVER:\"mouseover\",MOUSEOUT:\"mouseout\",MOUSEDOWN:\"mousedown\",MOUSEUP:\"mouseup\",GLOBALOUT:\"globalout\",DRAGSTART:\"dragstart\",DRAGEND:\"dragend\",DRAGENTER:\"dragenter\",DRAGOVER:\"dragover\",DRAGLEAVE:\"dragleave\",DROP:\"drop\",touchClickDelay:300},elementClassName:\"zr-element\",catchBrushException:!1,debugMode:0,devicePixelRatio:Math.max(window.devicePixelRatio||1,1)};return e}),i(\"echarts/chart/island\",[\"require\",\"./base\",\"zrender/shape/Circle\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/event\",\"zrender/tool/color\",\"../util/accMath\",\"../chart\"],function(e){function t(e,t,n,a,r){i.call(this,e,t,n,a,r),this._nameConnector,this._valueConnector,this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth();var l=this;l.shapeHandler.onmousewheel=function(e){var t=e.target,i=e.event,n=s.getDelta(i);n=n>0?-1:1,t.style.r-=n,t.style.r=t.style.r<5?5:t.style.r;var a=o.get(t,\"value\"),r=a*l.option.island.calculateStep;a=r>1?Math.round(a-r*n):+(a-r*n).toFixed(2);var h=o.get(t,\"name\");t.style.text=h+\":\"+a,o.set(t,\"value\",a),o.set(t,\"name\",h),l.zr.modShape(t.id),l.zr.refreshNextFrame(),s.stop(i)}}var i=e(\"./base\"),n=e(\"zrender/shape/Circle\"),a=e(\"../config\");a.island={zlevel:0,z:5,r:15,calculateStep:.1};var o=e(\"../util/ecData\"),r=e(\"zrender/tool/util\"),s=e(\"zrender/tool/event\");return t.prototype={type:a.CHART_TYPE_ISLAND,_combine:function(t,i){var n=e(\"zrender/tool/color\"),a=e(\"../util/accMath\"),r=a.accAdd(o.get(t,\"value\"),o.get(i,\"value\")),s=o.get(t,\"name\")+this._nameConnector+o.get(i,\"name\");t.style.text=s+this._valueConnector+r,o.set(t,\"value\",r),o.set(t,\"name\",s),t.style.r=this.option.island.r,t.style.color=n.mix(t.style.color,i.style.color)},refresh:function(e){e&&(e.island=this.reformOption(e.island),this.option=e,this._nameConnector=this.option.nameConnector,this._valueConnector=this.option.valueConnector)},getOption:function(){return this.option},resize:function(){var e=this.zr.getWidth(),t=this.zr.getHeight(),i=e/(this._zrWidth||e),n=t/(this._zrHeight||t);if(1!==i||1!==n){this._zrWidth=e,this._zrHeight=t;for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.modShape(this.shapeList[a].id,{style:{x:Math.round(this.shapeList[a].style.x*i),y:Math.round(this.shapeList[a].style.y*n)}})}},add:function(e){var t=o.get(e,\"name\"),i=o.get(e,\"value\"),a=null!=o.get(e,\"series\")?o.get(e,\"series\").name:\"\",r=this.getFont(this.option.island.textStyle),s=this.option.island,l={zlevel:s.zlevel,z:s.z,style:{x:e.style.x,y:e.style.y,r:this.option.island.r,color:e.style.color||e.style.strokeColor,text:t+this._valueConnector+i,textFont:r},draggable:!0,hoverable:!0,onmousewheel:this.shapeHandler.onmousewheel,_type:\"island\"};\"#fff\"===l.style.color&&(l.style.color=e.style.strokeColor),this.setCalculable(l),l.dragEnableTime=0,o.pack(l,{name:a},-1,i,-1,t),l=new n(l),this.shapeList.push(l),this.zr.addShape(l)},del:function(e){this.zr.delShape(e.id);for(var t=[],i=0,n=this.shapeList.length;n>i;i++)this.shapeList[i].id!=e.id&&t.push(this.shapeList[i]);this.shapeList=t},ondrop:function(e,t){if(this.isDrop&&e.target){var i=e.target,n=e.dragged;this._combine(i,n),this.zr.modShape(i.id),t.dragIn=!0,this.isDrop=!1}},ondragend:function(e,t){var i=e.target;this.isDragend?t.dragIn&&(this.del(i),t.needRefresh=!0):t.dragIn||(i.style.x=s.getX(e.event),i.style.y=s.getY(e.event),this.add(i),t.needRefresh=!0),this.isDragend=!1}},r.inherits(t,i),e(\"../chart\").define(\"island\",t),t}),i(\"echarts/component/toolbox\",[\"require\",\"./base\",\"zrender/shape/Line\",\"zrender/shape/Image\",\"zrender/shape/Rectangle\",\"../util/shape/Icon\",\"../config\",\"zrender/tool/util\",\"zrender/config\",\"zrender/tool/event\",\"./dataView\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._magicType={},this._magicMap={},this._isSilence=!1,this._iconList,this._iconShapeMap={},this._featureTitle={},this._featureIcon={},this._featureColor={},this._featureOption={},this._enableColor=\"red\",this._disableColor=\"#ccc\",this._markShapeList=[];var r=this;r._onMark=function(e){r.__onMark(e)},r._onMarkUndo=function(e){r.__onMarkUndo(e)},r._onMarkClear=function(e){r.__onMarkClear(e)},r._onDataZoom=function(e){r.__onDataZoom(e)},r._onDataZoomReset=function(e){r.__onDataZoomReset(e)},r._onDataView=function(e){r.__onDataView(e)},r._onRestore=function(e){r.__onRestore(e)},r._onSaveAsImage=function(e){r.__onSaveAsImage(e)},r._onMagicType=function(e){r.__onMagicType(e)},r._onCustomHandler=function(e){r.__onCustomHandler(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onclick=function(e){return r.__onclick(e)}}var i=e(\"./base\"),n=e(\"zrender/shape/Line\"),a=e(\"zrender/shape/Image\"),o=e(\"zrender/shape/Rectangle\"),r=e(\"../util/shape/Icon\"),s=e(\"../config\");s.toolbox={zlevel:0,z:6,show:!1,orient:\"horizontal\",x:\"right\",y:\"top\",color:[\"#1e90ff\",\"#22bb22\",\"#4b0082\",\"#d2691e\"],disableColor:\"#ddd\",effectiveColor:\"red\",backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,itemGap:10,itemSize:16,showTitle:!0,feature:{mark:{show:!1,title:{mark:\"辅助线开关\",markUndo:\"删除辅助线\",markClear:\"清空辅助线\"},lineStyle:{width:1,color:\"#1e90ff\",type:\"dashed\"}},dataZoom:{show:!1,title:{dataZoom:\"区域缩放\",dataZoomReset:\"区域缩放后退\"}},dataView:{show:!1,title:\"数据视图\",readOnly:!1,lang:[\"数据视图\",\"关闭\",\"刷新\"]},magicType:{show:!1,title:{line:\"折线图切换\",bar:\"柱形图切换\",stack:\"堆积\",tiled:\"平铺\",force:\"力导向布局图切换\",chord:\"和弦图切换\",pie:\"饼图切换\",funnel:\"漏斗图切换\"},type:[]},restore:{show:!1,title:\"还原\"},saveAsImage:{show:!1,title:\"保存为图片\",type:\"png\",lang:[\"点击保存\"]}}};var l=e(\"zrender/tool/util\"),h=e(\"zrender/config\"),m=e(\"zrender/tool/event\"),V=\"stack\",U=\"tiled\";return t.prototype={type:s.COMPONENT_TYPE_TOOLBOX,_buildShape:function(){this._iconList=[];var e=this.option.toolbox;this._enableColor=e.effectiveColor,this._disableColor=e.disableColor;var t=e.feature,i=[];for(var n in t)if(t[n].show)switch(n){case\"mark\":i.push({key:n,name:\"mark\"}),i.push({key:n,name:\"markUndo\"}),i.push({key:n,name:\"markClear\"});break;case\"magicType\":for(var a=0,o=t[n].type.length;o>a;a++)t[n].title[t[n].type[a]+\"Chart\"]=t[n].title[t[n].type[a]],t[n].option&&(t[n].option[t[n].type[a]+\"Chart\"]=t[n].option[t[n].type[a]]),i.push({key:n,name:t[n].type[a]+\"Chart\"});break;case\"dataZoom\":i.push({key:n,name:\"dataZoom\"}),i.push({key:n,name:\"dataZoomReset\"});break;case\"saveAsImage\":this.canvasSupported&&i.push({key:n,name:\"saveAsImage\"});break;default:i.push({key:n,name:n})}if(i.length>0){for(var r,n,a=0,o=i.length;o>a;a++)r=i[a].name,n=i[a].key,this._iconList.push(r),this._featureTitle[r]=t[n].title[r]||t[n].title,t[n].icon&&(this._featureIcon[r]=t[n].icon[r]||t[n].icon),t[n].color&&(this._featureColor[r]=t[n].color[r]||t[n].color),t[n].option&&(this._featureOption[r]=t[n].option[r]||t[n].option);this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.addShape(this.shapeList[a]);this._iconShapeMap.mark&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear)),this._iconShapeMap.dataZoomReset&&0===this._zoomQueue.length&&this._iconDisable(this._iconShapeMap.dataZoomReset)}},_buildItem:function(){var t,i,n,o,s=this.option.toolbox,l=this._iconList.length,h=this._itemGroupLocation.x,m=this._itemGroupLocation.y,V=s.itemSize,U=s.itemGap,d=s.color instanceof Array?s.color:[s.color],p=this.getFont(s.textStyle);\"horizontal\"===s.orient?(i=this._itemGroupLocation.y/this.zr.getHeight()<.5?\"bottom\":\"top\",n=this._itemGroupLocation.x/this.zr.getWidth()<.5?\"left\":\"right\",o=this._itemGroupLocation.y/this.zr.getHeight()<.5?\"top\":\"bottom\"):i=this._itemGroupLocation.x/this.zr.getWidth()<.5?\"right\":\"left\",this._iconShapeMap={};for(var c=this,u=0;l>u;u++){switch(t={type:\"icon\",zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:h,y:m,width:V,height:V,iconType:this._iconList[u],lineWidth:1,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length],brushType:\"stroke\"},highlightStyle:{lineWidth:1,text:s.showTitle?this._featureTitle[this._iconList[u]]:void 0,textFont:p,textPosition:i,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length]},hoverable:!0,clickable:!0},this._featureIcon[this._iconList[u]]&&(t.style.image=this._featureIcon[this._iconList[u]].replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),t.style.opacity=.8,t.highlightStyle.opacity=1,t.type=\"image\"),\"horizontal\"===s.orient&&(0===u&&\"left\"===n&&(t.highlightStyle.textPosition=\"specific\",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h,t.highlightStyle.textY=\"top\"===o?m+V+10:m-10),u===l-1&&\"right\"===n&&(t.highlightStyle.textPosition=\"specific\",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h+V,t.highlightStyle.textY=\"top\"===o?m+V+10:m-10)),this._iconList[u]){case\"mark\":t.onclick=c._onMark;break;case\"markUndo\":t.onclick=c._onMarkUndo;break;case\"markClear\":t.onclick=c._onMarkClear;break;case\"dataZoom\":t.onclick=c._onDataZoom;break;case\"dataZoomReset\":t.onclick=c._onDataZoomReset;break;case\"dataView\":if(!this._dataView){var y=e(\"./dataView\");this._dataView=new y(this.ecTheme,this.messageCenter,this.zr,this.option,this.myChart)}t.onclick=c._onDataView;break;case\"restore\":t.onclick=c._onRestore;break;case\"saveAsImage\":t.onclick=c._onSaveAsImage;break;default:this._iconList[u].match(\"Chart\")?(t._name=this._iconList[u].replace(\"Chart\",\"\"),t.onclick=c._onMagicType):t.onclick=c._onCustomHandler}\"icon\"===t.type?t=new r(t):\"image\"===t.type&&(t=new a(t)),this.shapeList.push(t),this._iconShapeMap[this._iconList[u]]=t,\"horizontal\"===s.orient?h+=V+U:m+=V+U}},_buildBackground:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding);this.shapeList.push(new o({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-t[3],y:this._itemGroupLocation.y-t[0],width:this._itemGroupLocation.width+t[3]+t[1],height:this._itemGroupLocation.height+t[0]+t[2],brushType:0===e.borderWidth?\"fill\":\"both\",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_getItemGroupLocation:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding),i=this._iconList.length,n=e.itemGap,a=e.itemSize,o=0,r=0;\"horizontal\"===e.orient?(o=(a+n)*i-n,r=a):(r=(a+n)*i-n,o=a);var s,l=this.zr.getWidth();switch(e.x){case\"center\":s=Math.floor((l-o)/2);break;case\"left\":s=t[3]+e.borderWidth;break;case\"right\":s=l-o-t[1]-e.borderWidth;break;default:s=e.x-0,s=isNaN(s)?0:s}var h,m=this.zr.getHeight();switch(e.y){case\"top\":h=t[0]+e.borderWidth;break;case\"bottom\":h=m-r-t[2]-e.borderWidth;break;case\"center\":h=Math.floor((m-r)/2);break;default:h=e.y-0,h=isNaN(h)?0:h}return{x:s,y:h,width:o,height:r}},__onmousemove:function(e){this._marking&&(this._markShape.style.xEnd=m.getX(e.event),this._markShape.style.yEnd=m.getY(e.event),this.zr.addHoverShape(this._markShape)),this._zooming&&(this._zoomShape.style.width=m.getX(e.event)-this._zoomShape.style.x,this._zoomShape.style.height=m.getY(e.event)-this._zoomShape.style.y,this.zr.addHoverShape(this._zoomShape),this.dom.style.cursor=\"crosshair\",m.stop(e.event)),this._zoomStart&&\"pointer\"!=this.dom.style.cursor&&\"move\"!=this.dom.style.cursor&&(this.dom.style.cursor=\"crosshair\")},__onmousedown:function(e){if(!e.target){this._zooming=!0;var t=m.getX(e.event),i=m.getY(e.event),n=this.option.dataZoom||{};return this._zoomShape=new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:t,y:i,width:1,height:1,brushType:\"both\"},highlightStyle:{lineWidth:2,color:n.fillerColor||s.dataZoom.fillerColor,strokeColor:n.handleColor||s.dataZoom.handleColor,brushType:\"both\"}}),this.zr.addHoverShape(this._zoomShape),!0}},__onmouseup:function(){if(!this._zoomShape||Math.abs(this._zoomShape.style.width)<10||Math.abs(this._zoomShape.style.height)<10)return this._zooming=!1,!0;if(this._zooming&&this.component.dataZoom){this._zooming=!1;var e=this.component.dataZoom.rectZoom(this._zoomShape.style);e&&(this._zoomQueue.push({start:e.start,end:e.end,start2:e.start2,end2:e.end2}),this._iconEnable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame())}return!0},__onclick:function(e){if(!e.target)if(this._marking)this._marking=!1,this._markShapeList.push(this._markShape),this._iconEnable(this._iconShapeMap.markUndo),this._iconEnable(this._iconShapeMap.markClear),this.zr.addShape(this._markShape),this.zr.refreshNextFrame();else if(this._markStart){this._marking=!0;var t=m.getX(e.event),i=m.getY(e.event);this._markShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:t,yStart:i,xEnd:t,yEnd:i,lineWidth:this.query(this.option,\"toolbox.feature.mark.lineStyle.width\"),strokeColor:this.query(this.option,\"toolbox.feature.mark.lineStyle.color\"),lineType:this.query(this.option,\"toolbox.feature.mark.lineStyle.type\")}}),this.zr.addHoverShape(this._markShape)}},__onMark:function(e){var t=e.target;if(this._marking||this._markStart)this._resetMark(),this.zr.refreshNextFrame();else{this._resetZoom(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._markStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.CLICK,i._onclick)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10)}return!0},__onMarkUndo:function(){if(this._marking)this._marking=!1;else{var e=this._markShapeList.length;if(e>=1){var t=this._markShapeList[e-1];this.zr.delShape(t.id),this.zr.refreshNextFrame(),this._markShapeList.pop(),1===e&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear))}}return!0},__onMarkClear:function(){this._marking&&(this._marking=!1);var e=this._markShapeList.length;if(e>0){for(;e--;)this.zr.delShape(this._markShapeList.pop().id);this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear),this.zr.refreshNextFrame()}return!0},__onDataZoom:function(e){var t=e.target;if(this._zooming||this._zoomStart)this._resetZoom(),this.zr.refreshNextFrame(),this.dom.style.cursor=\"default\";else{this._resetMark(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._zoomStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.MOUSEDOWN,i._onmousedown)&&i.zr.on(h.EVENT.MOUSEUP,i._onmouseup)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10),this.dom.style.cursor=\"crosshair\"}return!0},__onDataZoomReset:function(){return this._zooming&&(this._zooming=!1),this._zoomQueue.pop(),this._zoomQueue.length>0?this.component.dataZoom.absoluteZoom(this._zoomQueue[this._zoomQueue.length-1]):(this.component.dataZoom.rectZoom(),this._iconDisable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame()),!0},_resetMark:function(){this._marking=!1,this._markStart&&(this._markStart=!1,this._iconShapeMap.mark&&this.zr.modShape(this._iconShapeMap.mark.id,{style:{strokeColor:this._iconShapeMap.mark.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.CLICK,this._onclick),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_resetZoom:function(){this._zooming=!1,this._zoomStart&&(this._zoomStart=!1,this._iconShapeMap.dataZoom&&this.zr.modShape(this._iconShapeMap.dataZoom.id,{style:{strokeColor:this._iconShapeMap.dataZoom.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.MOUSEDOWN,this._onmousedown),this.zr.un(h.EVENT.MOUSEUP,this._onmouseup),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_iconDisable:function(e){\"image\"!=e.type?this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{strokeColor:this._disableColor}}):this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{opacity:.3}})},_iconEnable:function(e){\"image\"!=e.type?this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{strokeColor:e.highlightStyle.strokeColor}}):this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{opacity:.8}})},__onDataView:function(){return this._dataView.show(this.option),!0},__onRestore:function(){return this._resetMark(),this._resetZoom(),this.messageCenter.dispatch(s.EVENT.RESTORE,null,null,this.myChart),!0},__onSaveAsImage:function(){var e=this.option.toolbox.feature.saveAsImage,t=e.type||\"png\";\"png\"!=t&&\"jpeg\"!=t&&(t=\"png\");var i;i=this.myChart.isConnected()?this.myChart.getConnectedDataURL(t):this.zr.toDataURL(\"image/\"+t,this.option.backgroundColor&&\"rgba(0,0,0,0)\"===this.option.backgroundColor.replace(\" \",\"\")?\"#fff\":this.option.backgroundColor);var n=document.createElement(\"div\");n.id=\"__echarts_download_wrap__\",n.style.cssText=\"position:fixed;z-index:99999;display:block;top:0;left:0;background-color:rgba(33,33,33,0.5);text-align:center;width:100%;height:100%;line-height:\"+document.documentElement.clientHeight+\"px;\";var a=document.createElement(\"a\");a.href=i,a.setAttribute(\"download\",(e.name?e.name:this.option.title&&(this.option.title.text||this.option.title.subtext)?this.option.title.text||this.option.title.subtext:\"ECharts\")+\".\"+t),a.innerHTML='<img style=\"vertical-align:middle\" src=\"'+i+'\" title=\"'+(window.ActiveXObject||\"ActiveXObject\"in window?\"右键->图片另存为\":e.lang?e.lang[0]:\"点击保存\")+'\"/>',n.appendChild(a),document.body.appendChild(n),a=null,n=null,setTimeout(function(){var e=document.getElementById(\"__echarts_download_wrap__\");e&&(e.onclick=function(){var e=document.getElementById(\"__echarts_download_wrap__\");e.onclick=null,e.innerHTML=\"\",document.body.removeChild(e),e=null},e=null)},500)},__onMagicType:function(e){this._resetMark();var t=e.target._name;return this._magicType[t]||(this._magicType[t]=!0,t===s.CHART_TYPE_LINE?this._magicType[s.CHART_TYPE_BAR]=!1:t===s.CHART_TYPE_BAR&&(this._magicType[s.CHART_TYPE_LINE]=!1),t===s.CHART_TYPE_PIE?this._magicType[s.CHART_TYPE_FUNNEL]=!1:t===s.CHART_TYPE_FUNNEL&&(this._magicType[s.CHART_TYPE_PIE]=!1),t===s.CHART_TYPE_FORCE?this._magicType[s.CHART_TYPE_CHORD]=!1:t===s.CHART_TYPE_CHORD&&(this._magicType[s.CHART_TYPE_FORCE]=!1),t===V?this._magicType[U]=!1:t===U&&(this._magicType[V]=!1),this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,e.event,{magicType:this._magicType},this.myChart)),!0},setMagicType:function(e){this._resetMark(),this._magicType=e,!this._isSilence&&this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,null,{magicType:this._magicType},this.myChart)},__onCustomHandler:function(e){var t=e.target.style.iconType,i=this.option.toolbox.feature[t].onclick;\"function\"==typeof i&&i.call(this,this.option)},reset:function(e,t){if(t&&this.clear(),this.query(e,\"toolbox.show\")&&this.query(e,\"toolbox.feature.magicType.show\")){var i=e.toolbox.feature.magicType.type,n=i.length;for(this._magicMap={};n--;)this._magicMap[i[n]]=!0;n=e.series.length;for(var a,o;n--;)a=e.series[n].type,this._magicMap[a]&&(o=e.xAxis instanceof Array?e.xAxis[e.series[n].xAxisIndex||0]:e.xAxis,o&&\"category\"===(o.type||\"category\")&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),o=e.yAxis instanceof Array?e.yAxis[e.series[n].yAxisIndex||0]:e.yAxis,o&&\"category\"===o.type&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),e.series[n].__type=a,e.series[n].__itemStyle=l.clone(e.series[n].itemStyle||{})),(this._magicMap[V]||this._magicMap[U])&&(e.series[n].__stack=e.series[n].stack)}this._magicType=t?{}:this._magicType||{};for(var r in this._magicType)if(this._magicType[r]){this.option=e,this.getMagicOption();break}var s=e.dataZoom;if(s&&s.show){var h=null!=s.start&&s.start>=0&&s.start<=100?s.start:0,m=null!=s.end&&s.end>=0&&s.end<=100?s.end:100;h>m&&(h+=m,m=h-m,h-=m),this._zoomQueue=[{start:h,end:m,start2:0,end2:100}]}else this._zoomQueue=[]},getMagicOption:function(){var e,t;if(this._magicType[s.CHART_TYPE_LINE]||this._magicType[s.CHART_TYPE_BAR]){for(var i=this._magicType[s.CHART_TYPE_LINE]?!1:!0,n=0,a=this.option.series.length;a>n;n++)t=this.option.series[n].type,(t==s.CHART_TYPE_LINE||t==s.CHART_TYPE_BAR)&&(e=this.option.xAxis instanceof Array?this.option.xAxis[this.option.series[n].xAxisIndex||0]:this.option.xAxis,e&&\"category\"===(e.type||\"category\")&&(e.boundaryGap=i?!0:e.__boundaryGap),e=this.option.yAxis instanceof Array?this.option.yAxis[this.option.series[n].yAxisIndex||0]:this.option.yAxis,e&&\"category\"===e.type&&(e.boundaryGap=i?!0:e.__boundaryGap));this._defaultMagic(s.CHART_TYPE_LINE,s.CHART_TYPE_BAR)}if(this._defaultMagic(s.CHART_TYPE_CHORD,s.CHART_TYPE_FORCE),this._defaultMagic(s.CHART_TYPE_PIE,s.CHART_TYPE_FUNNEL),this._magicType[V]||this._magicType[U])for(var n=0,a=this.option.series.length;a>n;n++)this._magicType[V]?(this.option.series[n].stack=\"_ECHARTS_STACK_KENER_2014_\",t=V):this._magicType[U]&&(this.option.series[n].stack=null,t=U),this._featureOption[t+\"Chart\"]&&l.merge(this.option.series[n],this._featureOption[t+\"Chart\"]||{},!0);return this.option},_defaultMagic:function(e,t){if(this._magicType[e]||this._magicType[t])for(var i=0,n=this.option.series.length;n>i;i++){var a=this.option.series[i].type;(a==e||a==t)&&(this.option.series[i].type=this._magicType[e]?e:t,this.option.series[i].itemStyle=l.clone(this.option.series[i].__itemStyle),a=this.option.series[i].type,this._featureOption[a+\"Chart\"]&&l.merge(this.option.series[i],this._featureOption[a+\"Chart\"]||{},!0))}},silence:function(e){this._isSilence=e},resize:function(){this._resetMark(),this.clear(),this.option&&this.option.toolbox&&this.option.toolbox.show&&this._buildShape(),this._dataView&&this._dataView.resize()},hideDataView:function(){this._dataView&&this._dataView.hide()},clear:function(e){this.zr&&(this.zr.delShape(this.shapeList),this.shapeList=[],e||(this.zr.delShape(this._markShapeList),this._markShapeList=[]))},onbeforDispose:function(){this._dataView&&(this._dataView.dispose(),this._dataView=null),this._markShapeList=null},refresh:function(e){e&&(this._resetMark(),this._resetZoom(),e.toolbox=this.reformOption(e.toolbox),this.option=e,this.clear(!0),e.toolbox.show&&this._buildShape(),this.hideDataView())}},l.inherits(t,i),e(\"../component\").define(\"toolbox\",t),t}),i(\"echarts/component\",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i(\"echarts/component/title\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Rectangle\",\"../config\",\"zrender/tool/util\",\"zrender/tool/area\",\"zrender/tool/color\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Rectangle\"),o=e(\"../config\");o.title={zlevel:0,z:6,show:!0,text:\"\",subtext:\"\",x:\"left\",y:\"top\",backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,itemGap:5,textStyle:{fontSize:18,fontWeight:\"bolder\",color:\"#333\"},subtextStyle:{color:\"#aaa\"}};var r=e(\"zrender/tool/util\"),s=e(\"zrender/tool/area\"),l=e(\"zrender/tool/color\");return t.prototype={type:o.COMPONENT_TYPE_TITLE,_buildShape:function(){if(this.titleOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e=this.titleOption.text,t=this.titleOption.link,i=this.titleOption.target,a=this.titleOption.subtext,o=this.titleOption.sublink,r=this.titleOption.subtarget,s=this.getFont(this.titleOption.textStyle),h=this.getFont(this.titleOption.subtextStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this._itemGroupLocation.width,d=this._itemGroupLocation.height,p={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V,color:this.titleOption.textStyle.color,text:e,textFont:s,textBaseline:\"top\"},highlightStyle:{color:l.lift(this.titleOption.textStyle.color,1),brushType:\"fill\"},hoverable:!1};t&&(p.hoverable=!0,p.clickable=!0,p.onclick=function(){i&&\"self\"==i?window.location=t:window.open(t)});var c={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V+d,color:this.titleOption.subtextStyle.color,text:a,textFont:h,textBaseline:\"bottom\"},highlightStyle:{color:l.lift(this.titleOption.subtextStyle.color,1),brushType:\"fill\"},hoverable:!1};switch(o&&(c.hoverable=!0,c.clickable=!0,c.onclick=function(){r&&\"self\"==r?window.location=o:window.open(o)}),this.titleOption.x){case\"center\":p.style.x=c.style.x=m+U/2,p.style.textAlign=c.style.textAlign=\"center\";break;case\"left\":p.style.x=c.style.x=m,p.style.textAlign=c.style.textAlign=\"left\";break;case\"right\":p.style.x=c.style.x=m+U,p.style.textAlign=c.style.textAlign=\"right\";break;default:m=this.titleOption.x-0,m=isNaN(m)?0:m,p.style.x=c.style.x=m}this.titleOption.textAlign&&(p.style.textAlign=c.style.textAlign=this.titleOption.textAlign),this.shapeList.push(new n(p)),\"\"!==a&&this.shapeList.push(new n(c))},_buildBackground:function(){var e=this.reformCssArray(this.titleOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.titleOption.borderWidth?\"fill\":\"both\",color:this.titleOption.backgroundColor,strokeColor:this.titleOption.borderColor,lineWidth:this.titleOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.titleOption.padding),i=this.titleOption.text,n=this.titleOption.subtext,a=this.getFont(this.titleOption.textStyle),o=this.getFont(this.titleOption.subtextStyle),r=Math.max(s.getTextWidth(i,a),s.getTextWidth(n,o)),l=s.getTextHeight(i,a)+(\"\"===n?0:this.titleOption.itemGap+s.getTextHeight(n,o)),h=this.zr.getWidth();switch(this.titleOption.x){case\"center\":e=Math.floor((h-r)/2);break;case\"left\":e=t[3]+this.titleOption.borderWidth;break;case\"right\":e=h-r-t[1]-this.titleOption.borderWidth;break;default:e=this.titleOption.x-0,e=isNaN(e)?0:e}var m,V=this.zr.getHeight();switch(this.titleOption.y){case\"top\":m=t[0]+this.titleOption.borderWidth;break;case\"bottom\":m=V-l-t[2]-this.titleOption.borderWidth;break;case\"center\":m=Math.floor((V-l)/2);break;default:m=this.titleOption.y-0,m=isNaN(m)?0:m}return{x:e,y:m,width:r,height:l}},refresh:function(e){e&&(this.option=e,this.option.title=this.reformOption(this.option.title),this.titleOption=this.option.title,this.titleOption.textStyle=this.getTextStyle(this.titleOption.textStyle),this.titleOption.subtextStyle=this.getTextStyle(this.titleOption.subtextStyle)),this.clear(),this._buildShape()}},r.inherits(t,i),e(\"../component\").define(\"title\",t),t}),i(\"echarts/component/tooltip\",[\"require\",\"./base\",\"../util/shape/Cross\",\"zrender/shape/Line\",\"zrender/shape/Rectangle\",\"../config\",\"../util/ecData\",\"zrender/config\",\"zrender/tool/event\",\"zrender/tool/area\",\"zrender/tool/color\",\"zrender/tool/util\",\"zrender/shape/Base\",\"../component\"],function(e){function t(e,t,o,r,s){i.call(this,e,t,o,r,s),this.dom=s.dom;var l=this;l._onmousemove=function(e){return l.__onmousemove(e)},l._onglobalout=function(e){return l.__onglobalout(e)},this.zr.on(h.EVENT.MOUSEMOVE,l._onmousemove),this.zr.on(h.EVENT.GLOBALOUT,l._onglobalout),l._hide=function(e){return l.__hide(e)},l._tryShow=function(e){return l.__tryShow(e)},l._refixed=function(e){return l.__refixed(e)},l._setContent=function(e,t){return l.__setContent(e,t)},this._tDom=this._tDom||document.createElement(\"div\"),this._tDom.onselectstart=function(){return!1},this._tDom.onmouseover=function(){l._mousein=!0},this._tDom.onmouseout=function(){l._mousein=!1},this._tDom.className=\"echarts-tooltip\",this._tDom.style.position=\"absolute\",this.hasAppend=!1,this._axisLineShape&&this.zr.delShape(this._axisLineShape.id),this._axisLineShape=new a({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisLineShape),this.zr.addShape(this._axisLineShape),this._axisShadowShape&&this.zr.delShape(this._axisShadowShape.id),this._axisShadowShape=new a({zlevel:this.getZlevelBase(),z:1,invisible:!0,hoverable:!1}),this.shapeList.push(this._axisShadowShape),this.zr.addShape(this._axisShadowShape),this._axisCrossShape&&this.zr.delShape(this._axisCrossShape.id),this._axisCrossShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisCrossShape),this.zr.addShape(this._axisCrossShape),this.showing=!1,this.refresh(r)}var i=e(\"./base\"),n=e(\"../util/shape/Cross\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Rectangle\"),r=new o({}),s=e(\"../config\");s.tooltip={zlevel:1,z:8,show:!0,showContent:!0,trigger:\"item\",islandFormatter:\"{a} <br/>{b} : {c}\",showDelay:20,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:\"rgba(0,0,0,0.7)\",borderColor:\"#333\",borderRadius:4,borderWidth:0,padding:5,axisPointer:{type:\"line\",lineStyle:{color:\"#48b\",width:2,type:\"solid\"},crossStyle:{color:\"#1e90ff\",width:1,type:\"dashed\"},shadowStyle:{color:\"rgba(150,150,150,0.3)\",width:\"auto\",type:\"default\"}},textStyle:{color:\"#fff\"}};var l=e(\"../util/ecData\"),h=e(\"zrender/config\"),m=e(\"zrender/tool/event\"),V=e(\"zrender/tool/area\"),U=e(\"zrender/tool/color\"),d=e(\"zrender/tool/util\"),p=e(\"zrender/shape/Base\");return t.prototype={type:s.COMPONENT_TYPE_TOOLTIP,_gCssText:\"position:absolute;display:block;border-style:solid;white-space:nowrap;\",_style:function(e){if(!e)return\"\";var t=[];if(e.transitionDuration){var i=\"left \"+e.transitionDuration+\"s,top \"+e.transitionDuration+\"s\";t.push(\"transition:\"+i),t.push(\"-moz-transition:\"+i),t.push(\"-webkit-transition:\"+i),t.push(\"-o-transition:\"+i)}e.backgroundColor&&(t.push(\"background-Color:\"+U.toHex(e.backgroundColor)),t.push(\"filter:alpha(opacity=70)\"),t.push(\"background-Color:\"+e.backgroundColor)),null!=e.borderWidth&&t.push(\"border-width:\"+e.borderWidth+\"px\"),null!=e.borderColor&&t.push(\"border-color:\"+e.borderColor),null!=e.borderRadius&&(t.push(\"border-radius:\"+e.borderRadius+\"px\"),t.push(\"-moz-border-radius:\"+e.borderRadius+\"px\"),t.push(\"-webkit-border-radius:\"+e.borderRadius+\"px\"),t.push(\"-o-border-radius:\"+e.borderRadius+\"px\"));var n=e.textStyle;n&&(n.color&&t.push(\"color:\"+n.color),n.decoration&&t.push(\"text-decoration:\"+n.decoration),n.align&&t.push(\"text-align:\"+n.align),n.fontFamily&&t.push(\"font-family:\"+n.fontFamily),n.fontSize&&t.push(\"font-size:\"+n.fontSize+\"px\"),n.fontSize&&t.push(\"line-height:\"+Math.round(3*n.fontSize/2)+\"px\"),n.fontStyle&&t.push(\"font-style:\"+n.fontStyle),n.fontWeight&&t.push(\"font-weight:\"+n.fontWeight));var a=e.padding;return null!=a&&(a=this.reformCssArray(a),t.push(\"padding:\"+a[0]+\"px \"+a[1]+\"px \"+a[2]+\"px \"+a[3]+\"px\")),t=t.join(\";\")+\";\"},__hide:function(){this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,this._tDom&&(this._tDom.style.display=\"none\");var e=!1;this._axisLineShape.invisible||(this._axisLineShape.invisible=!0,\nthis.zr.modShape(this._axisLineShape.id),e=!0),this._axisShadowShape.invisible||(this._axisShadowShape.invisible=!0,this.zr.modShape(this._axisShadowShape.id),e=!0),this._axisCrossShape.invisible||(this._axisCrossShape.invisible=!0,this.zr.modShape(this._axisCrossShape.id),e=!0),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2),e&&this.zr.refreshNextFrame(),this.showing=!1},_show:function(e,t,i,n){var a=this._tDom.offsetHeight,o=this._tDom.offsetWidth;e&&(\"function\"==typeof e&&(e=e([t,i])),e instanceof Array&&(t=e[0],i=e[1])),t+o>this._zrWidth&&(t-=o+40),i+a>this._zrHeight&&(i-=a-20),20>i&&(i=0),this._tDom.style.cssText=this._gCssText+this._defaultCssText+(n?n:\"\")+\"left:\"+t+\"px;top:\"+i+\"px;\",(10>a||10>o)&&setTimeout(this._refixed,20),this.showing=!0},__refixed:function(){if(this._tDom){var e=\"\",t=this._tDom.offsetHeight,i=this._tDom.offsetWidth;this._tDom.offsetLeft+i>this._zrWidth&&(e+=\"left:\"+(this._zrWidth-i-20)+\"px;\"),this._tDom.offsetTop+t>this._zrHeight&&(e+=\"top:\"+(this._zrHeight-t-10)+\"px;\"),\"\"!==e&&(this._tDom.style.cssText+=e)}},__tryShow:function(){var e,t;if(this._curTarget){if(\"island\"===this._curTarget._type&&this.option.tooltip.show)return void this._showItemTrigger();var i=l.get(this._curTarget,\"series\"),n=l.get(this._curTarget,\"data\");e=this.deepQuery([n,i,this.option],\"tooltip.show\"),null!=i&&null!=n&&e?(t=this.deepQuery([n,i,this.option],\"tooltip.trigger\"),\"axis\"===t?this._showAxisTrigger(i.xAxisIndex,i.yAxisIndex,l.get(this._curTarget,\"dataIndex\")):this._showItemTrigger()):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}else this._findPolarTrigger()||this._findAxisTrigger()},_findAxisTrigger:function(){if(!this.component.xAxis||!this.component.yAxis)return void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));for(var e,t,i=this.option.series,n=0,a=i.length;a>n;n++)if(\"axis\"===this.deepQuery([i[n],this.option],\"tooltip.trigger\"))return e=i[n].xAxisIndex||0,t=i[n].yAxisIndex||0,this.component.xAxis.getAxis(e)&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex(\"x\",this.component.xAxis.getAxis(e))):this.component.yAxis.getAxis(t)&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex(\"y\",this.component.yAxis.getAxis(t))):void this._showAxisTrigger(e,t,-1);\"cross\"===this.option.tooltip.axisPointer.type&&this._showAxisTrigger(-1,-1,-1)},_findPolarTrigger:function(){if(!this.component.polar)return!1;var e,t=m.getX(this._event),i=m.getY(this._event),n=this.component.polar.getNearestIndex([t,i]);return n?(e=n.valueIndex,n=n.polarIndex):n=-1,-1!=n?this._showPolarTrigger(n,e):!1},_getNearestDataIndex:function(e,t){var i=-1,n=m.getX(this._event),a=m.getY(this._event);if(\"x\"===e){for(var o,r,s=this.component.grid.getXend(),l=t.getCoordByIndex(i);s>l&&(r=l,n>=l);)o=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:r-n>=n-o?i-=1:null==t.getNameByIndex(i)&&(i-=1),i}for(var h,V,U=this.component.grid.getY(),l=t.getCoordByIndex(i);l>U&&(h=l,l>=a);)V=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:a-h>=V-a?i-=1:null==t.getNameByIndex(i)&&(i-=1),i},_showAxisTrigger:function(e,t,i){if(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_IN_GRID,this._event,null,this.myChart),null==this.component.xAxis||null==this.component.yAxis||null==e||null==t)return clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));var n,a,o,r,l=this.option.series,h=[],V=[],U=\"\";if(\"axis\"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return;a=this.option.tooltip.formatter,o=this.option.tooltip.position}var d,p,c=-1!=e&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?\"xAxis\":-1!=t&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?\"yAxis\":!1;if(c){var u=\"xAxis\"==c?e:t;n=this.component[c].getAxis(u);for(var y=0,g=l.length;g>y;y++)this._isSelected(l[y].name)&&l[y][c+\"Index\"]===u&&\"axis\"===this.deepQuery([l[y],this.option],\"tooltip.trigger\")&&(r=this.query(l[y],\"tooltip.showContent\")||r,a=this.query(l[y],\"tooltip.formatter\")||a,o=this.query(l[y],\"tooltip.position\")||o,U+=this._style(this.query(l[y],\"tooltip\")),null!=l[y].stack&&\"xAxis\"==c?(h.unshift(l[y]),V.unshift(y)):(h.push(l[y]),V.push(y)));this.messageCenter.dispatch(s.EVENT.TOOLTIP_HOVER,this._event,{seriesIndex:V,dataIndex:i},this.myChart);var b;\"xAxis\"==c?(d=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),p=m.getY(this._event),b=[d,this.component.grid.getY(),d,this.component.grid.getYend()]):(d=m.getX(this._event),p=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),b=[this.component.grid.getX(),p,this.component.grid.getXend(),p]),this._styleAxisPointer(h,b[0],b[1],b[2],b[3],n.getGap(),d,p)}else d=m.getX(this._event),p=m.getY(this._event),this._styleAxisPointer(l,this.component.grid.getX(),p,this.component.grid.getXend(),p,0,d,p),i>=0?this._showItemTrigger(!0):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._tDom.style.display=\"none\");if(h.length>0){if(this._lastItemTriggerId=-1,this._lastDataIndex!=i||this._lastSeriesIndex!=V[0]){this._lastDataIndex=i,this._lastSeriesIndex=V[0];var f,k;if(\"function\"==typeof a){for(var x=[],y=0,g=h.length;g>y;y++)f=h[y].data[i],k=this.getDataFromOption(f,\"-\"),x.push({seriesIndex:V[y],seriesName:h[y].name||\"\",series:h[y],dataIndex:i,data:f,name:n.getNameByIndex(i),value:k,0:h[y].name||\"\",1:n.getNameByIndex(i),2:k,3:f});this._curTicket=\"axis:\"+i,this._tDom.innerHTML=a.call(this.myChart,x,this._curTicket,this._setContent)}else if(\"string\"==typeof a){this._curTicket=0/0,a=a.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\");for(var y=0,g=h.length;g>y;y++)a=a.replace(\"{a\"+y+\"}\",this._encodeHTML(h[y].name||\"\")),a=a.replace(\"{b\"+y+\"}\",this._encodeHTML(n.getNameByIndex(i))),f=h[y].data[i],f=this.getDataFromOption(f,\"-\"),a=a.replace(\"{c\"+y+\"}\",f instanceof Array?f:this.numAddCommas(f));this._tDom.innerHTML=a}else{this._curTicket=0/0,a=this._encodeHTML(n.getNameByIndex(i));for(var y=0,g=h.length;g>y;y++)a+=\"<br/>\"+this._encodeHTML(h[y].name||\"\")+\" : \",f=h[y].data[i],f=this.getDataFromOption(f,\"-\"),a+=f instanceof Array?f:this.numAddCommas(f);this._tDom.innerHTML=a}}if(r===!1||!this.option.tooltip.showContent)return;this.hasAppend||(this._tDom.style.left=this._zrWidth/2+\"px\",this._tDom.style.top=this._zrHeight/2+\"px\",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(o,d+10,p+10,U)}},_showPolarTrigger:function(e,t){if(null==this.component.polar||null==e||null==t||0>t)return!1;var i,n,a,o=this.option.series,r=[],s=[],l=\"\";if(\"axis\"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return!1;i=this.option.tooltip.formatter,n=this.option.tooltip.position}for(var h=this.option.polar[e].indicator[t].text,V=0,U=o.length;U>V;V++)this._isSelected(o[V].name)&&o[V].polarIndex===e&&\"axis\"===this.deepQuery([o[V],this.option],\"tooltip.trigger\")&&(a=this.query(o[V],\"tooltip.showContent\")||a,i=this.query(o[V],\"tooltip.formatter\")||i,n=this.query(o[V],\"tooltip.position\")||n,l+=this._style(this.query(o[V],\"tooltip\")),r.push(o[V]),s.push(V));if(r.length>0){for(var d,p,c,u=[],V=0,U=r.length;U>V;V++){d=r[V].data;for(var y=0,g=d.length;g>y;y++)p=d[y],this._isSelected(p.name)&&(p=null!=p?p:{name:\"\",value:{dataIndex:\"-\"}},c=this.getDataFromOption(p.value[t]),u.push({seriesIndex:s[V],seriesName:r[V].name||\"\",series:r[V],dataIndex:t,data:p,name:p.name,indicator:h,value:c,0:r[V].name||\"\",1:p.name,2:c,3:h}))}if(u.length<=0)return;if(this._lastItemTriggerId=-1,this._lastDataIndex!=t||this._lastSeriesIndex!=s[0])if(this._lastDataIndex=t,this._lastSeriesIndex=s[0],\"function\"==typeof i)this._curTicket=\"axis:\"+t,this._tDom.innerHTML=i.call(this.myChart,u,this._curTicket,this._setContent);else if(\"string\"==typeof i){i=i.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\").replace(\"{d}\",\"{d0}\");for(var V=0,U=u.length;U>V;V++)i=i.replace(\"{a\"+V+\"}\",this._encodeHTML(u[V].seriesName)),i=i.replace(\"{b\"+V+\"}\",this._encodeHTML(u[V].name)),i=i.replace(\"{c\"+V+\"}\",this.numAddCommas(u[V].value)),i=i.replace(\"{d\"+V+\"}\",this._encodeHTML(u[V].indicator));this._tDom.innerHTML=i}else{i=this._encodeHTML(u[0].name)+\"<br/>\"+this._encodeHTML(u[0].indicator)+\" : \"+this.numAddCommas(u[0].value);for(var V=1,U=u.length;U>V;V++)i+=\"<br/>\"+this._encodeHTML(u[V].name)+\"<br/>\",i+=this._encodeHTML(u[V].indicator)+\" : \"+this.numAddCommas(u[V].value);this._tDom.innerHTML=i}if(a===!1||!this.option.tooltip.showContent)return;return this.hasAppend||(this._tDom.style.left=this._zrWidth/2+\"px\",this._tDom.style.top=this._zrHeight/2+\"px\",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(n,m.getX(this._event),m.getY(this._event),l),!0}},_showItemTrigger:function(e){if(this._curTarget){var t,i,n,a=l.get(this._curTarget,\"series\"),o=l.get(this._curTarget,\"seriesIndex\"),r=l.get(this._curTarget,\"data\"),h=l.get(this._curTarget,\"dataIndex\"),V=l.get(this._curTarget,\"name\"),U=l.get(this._curTarget,\"value\"),d=l.get(this._curTarget,\"special\"),p=l.get(this._curTarget,\"special2\"),c=[r,a,this.option],u=\"\";if(\"island\"!=this._curTarget._type){var y=e?\"axis\":\"item\";this.option.tooltip.trigger===y&&(t=this.option.tooltip.formatter,i=this.option.tooltip.position),this.query(a,\"tooltip.trigger\")===y&&(n=this.query(a,\"tooltip.showContent\")||n,t=this.query(a,\"tooltip.formatter\")||t,i=this.query(a,\"tooltip.position\")||i,u+=this._style(this.query(a,\"tooltip\"))),n=this.query(r,\"tooltip.showContent\")||n,t=this.query(r,\"tooltip.formatter\")||t,i=this.query(r,\"tooltip.position\")||i,u+=this._style(this.query(r,\"tooltip\"))}else this._lastItemTriggerId=0/0,n=this.deepQuery(c,\"tooltip.showContent\"),t=this.deepQuery(c,\"tooltip.islandFormatter\"),i=this.deepQuery(c,\"tooltip.islandPosition\");this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId!==this._curTarget.id&&(this._lastItemTriggerId=this._curTarget.id,\"function\"==typeof t?(this._curTicket=(a.name||\"\")+\":\"+h,this._tDom.innerHTML=t.call(this.myChart,{seriesIndex:o,seriesName:a.name||\"\",series:a,dataIndex:h,data:r,name:V,value:U,percent:d,indicator:d,value2:p,indicator2:p,0:a.name||\"\",1:V,2:U,3:d,4:p,5:r,6:o,7:h},this._curTicket,this._setContent)):\"string\"==typeof t?(this._curTicket=0/0,t=t.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\"),t=t.replace(\"{a0}\",this._encodeHTML(a.name||\"\")).replace(\"{b0}\",this._encodeHTML(V)).replace(\"{c0}\",U instanceof Array?U:this.numAddCommas(U)),t=t.replace(\"{d}\",\"{d0}\").replace(\"{d0}\",d||\"\"),t=t.replace(\"{e}\",\"{e0}\").replace(\"{e0}\",l.get(this._curTarget,\"special2\")||\"\"),this._tDom.innerHTML=t):(this._curTicket=0/0,this._tDom.innerHTML=a.type===s.CHART_TYPE_RADAR&&d?this._itemFormatter.radar.call(this,a,V,U,d):a.type===s.CHART_TYPE_EVENTRIVER?this._itemFormatter.eventRiver.call(this,a,V,U,r):\"\"+(null!=a.name?this._encodeHTML(a.name)+\"<br/>\":\"\")+(\"\"===V?\"\":this._encodeHTML(V)+\" : \")+(U instanceof Array?U:this.numAddCommas(U))));var g=m.getX(this._event),b=m.getY(this._event);this.deepQuery(c,\"tooltip.axisPointer.show\")&&this.component.grid?this._styleAxisPointer([a],this.component.grid.getX(),b,this.component.grid.getXend(),b,0,g,b):this._hide(),n!==!1&&this.option.tooltip.showContent&&(this.hasAppend||(this._tDom.style.left=this._zrWidth/2+\"px\",this._tDom.style.top=this._zrHeight/2+\"px\",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(i,g+20,b-20,u))}},_itemFormatter:{radar:function(e,t,i,n){var a=\"\";a+=this._encodeHTML(\"\"===t?e.name||\"\":t),a+=\"\"===a?\"\":\"<br />\";for(var o=0;o<n.length;o++)a+=this._encodeHTML(n[o].text)+\" : \"+this.numAddCommas(i[o])+\"<br />\";return a},chord:function(e,t,i,n,a){if(null==a)return this._encodeHTML(t)+\" (\"+this.numAddCommas(i)+\")\";var o=this._encodeHTML(t),r=this._encodeHTML(n);return\"\"+(null!=e.name?this._encodeHTML(e.name)+\"<br/>\":\"\")+o+\" -> \"+r+\" (\"+this.numAddCommas(i)+\")<br />\"+r+\" -> \"+o+\" (\"+this.numAddCommas(a)+\")\"},eventRiver:function(e,t,i,n){var a=\"\";a+=this._encodeHTML(\"\"===e.name?\"\":e.name+\" : \"),a+=this._encodeHTML(t),a+=\"\"===a?\"\":\"<br />\",n=n.evolution;for(var o=0,r=n.length;r>o;o++)a+='<div style=\"padding-top:5px;\">',n[o].detail&&(n[o].detail.img&&(a+='<img src=\"'+n[o].detail.img+'\" style=\"float:left;width:40px;height:40px;\">'),a+='<div style=\"margin-left:45px;\">'+n[o].time+\"<br/>\",a+='<a href=\"'+n[o].detail.link+'\" target=\"_blank\">',a+=n[o].detail.text+\"</a></div>\",a+=\"</div>\");return a}},_styleAxisPointer:function(e,t,i,n,a,o,r,s){if(e.length>0){var l,h,m=this.option.tooltip.axisPointer,V=m.type,U={line:{},cross:{},shadow:{}};for(var d in U)U[d].color=m[d+\"Style\"].color,U[d].width=m[d+\"Style\"].width,U[d].type=m[d+\"Style\"].type;for(var p=0,c=e.length;c>p;p++)l=e[p],h=this.query(l,\"tooltip.axisPointer.type\"),V=h||V,h&&(U[h].color=this.query(l,\"tooltip.axisPointer.\"+h+\"Style.color\")||U[h].color,U[h].width=this.query(l,\"tooltip.axisPointer.\"+h+\"Style.width\")||U[h].width,U[h].type=this.query(l,\"tooltip.axisPointer.\"+h+\"Style.type\")||U[h].type);if(\"line\"===V){var u=U.line.width,y=t==n;this._axisLineShape.style={xStart:y?this.subPixelOptimize(t,u):t,yStart:y?i:this.subPixelOptimize(i,u),xEnd:y?this.subPixelOptimize(n,u):n,yEnd:y?a:this.subPixelOptimize(a,u),strokeColor:U.line.color,lineWidth:u,lineType:U.line.type},this._axisLineShape.invisible=!1,this.zr.modShape(this._axisLineShape.id)}else if(\"cross\"===V){var g=U.cross.width;this._axisCrossShape.style={brushType:\"stroke\",rect:this.component.grid.getArea(),x:this.subPixelOptimize(r,g),y:this.subPixelOptimize(s,g),text:(\"( \"+this.component.xAxis.getAxis(0).getValueFromCoord(r)+\" , \"+this.component.yAxis.getAxis(0).getValueFromCoord(s)+\" )\").replace(\"  , \",\" \").replace(\" ,  \",\" \"),textPosition:\"specific\",strokeColor:U.cross.color,lineWidth:g,lineType:U.cross.type},this.component.grid.getXend()-r>100?(this._axisCrossShape.style.textAlign=\"left\",this._axisCrossShape.style.textX=r+10):(this._axisCrossShape.style.textAlign=\"right\",this._axisCrossShape.style.textX=r-10),s-this.component.grid.getY()>50?(this._axisCrossShape.style.textBaseline=\"bottom\",this._axisCrossShape.style.textY=s-10):(this._axisCrossShape.style.textBaseline=\"top\",this._axisCrossShape.style.textY=s+10),this._axisCrossShape.invisible=!1,this.zr.modShape(this._axisCrossShape.id)}else\"shadow\"===V&&((null==U.shadow.width||\"auto\"===U.shadow.width||isNaN(U.shadow.width))&&(U.shadow.width=o),t===n?Math.abs(this.component.grid.getX()-t)<2?(U.shadow.width/=2,t=n+=U.shadow.width/2):Math.abs(this.component.grid.getXend()-t)<2&&(U.shadow.width/=2,t=n-=U.shadow.width/2):i===a&&(Math.abs(this.component.grid.getY()-i)<2?(U.shadow.width/=2,i=a+=U.shadow.width/2):Math.abs(this.component.grid.getYend()-i)<2&&(U.shadow.width/=2,i=a-=U.shadow.width/2)),this._axisShadowShape.style={xStart:t,yStart:i,xEnd:n,yEnd:a,strokeColor:U.shadow.color,lineWidth:U.shadow.width},this._axisShadowShape.invisible=!1,this.zr.modShape(this._axisShadowShape.id));this.zr.refreshNextFrame()}},__onmousemove:function(e){if(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),!this._mousein||!this._enterable){var t=e.target,i=m.getX(e.event),n=m.getY(e.event);if(t){this._curTarget=t,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n;var a;if(this._needAxisTrigger&&this.component.polar&&-1!=(a=this.component.polar.isInside([i,n])))for(var o=this.option.series,l=0,h=o.length;h>l;l++)if(o[l].polarIndex===a&&\"axis\"===this.deepQuery([o[l],this.option],\"tooltip.trigger\")){this._curTarget=null;break}this._showingTicket=setTimeout(this._tryShow,this._showDelay)}else this._curTarget=!1,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n,this._needAxisTrigger&&this.component.grid&&V.isInside(r,this.component.grid.getArea(),i,n)?this._showingTicket=setTimeout(this._tryShow,this._showDelay):this._needAxisTrigger&&this.component.polar&&-1!=this.component.polar.isInside([i,n])?this._showingTicket=setTimeout(this._tryShow,this._showDelay):(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_OUT_GRID,this._event,null,this.myChart),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}},__onglobalout:function(){clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay)},__setContent:function(e,t){this._tDom&&(e===this._curTicket&&(this._tDom.innerHTML=t),setTimeout(this._refixed,20))},ontooltipHover:function(e,t){if(!this._lastTipShape||this._lastTipShape&&this._lastTipShape.dataIndex!=e.dataIndex){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this.shapeList.length=2);for(var i=0,n=t.length;n>i;i++)t[i].zlevel=this.getZlevelBase(),t[i].z=this.getZBase(),t[i].style=p.prototype.getHighlightStyle(t[i].style,t[i].highlightStyle),t[i].draggable=!1,t[i].hoverable=!1,t[i].clickable=!1,t[i].ondragend=null,t[i].ondragover=null,t[i].ondrop=null,this.shapeList.push(t[i]),this.zr.addShape(t[i]);this._lastTipShape={dataIndex:e.dataIndex,tipShape:t}}},ondragend:function(){this._hide()},onlegendSelected:function(e){this._selectedMap=e.selected},_setSelectedMap:function(){this._selectedMap=this.component.legend?d.clone(this.component.legend.getSelectedMap()):{}},_isSelected:function(e){return null!=this._selectedMap[e]?this._selectedMap[e]:!0},showTip:function(e){if(e){var t,i=this.option.series;if(null!=e.seriesIndex)t=e.seriesIndex;else for(var n=e.seriesName,a=0,o=i.length;o>a;a++)if(i[a].name===n){t=a;break}var r=i[t];if(null!=r){var m=this.myChart.chart[r.type],V=\"axis\"===this.deepQuery([r,this.option],\"tooltip.trigger\");if(m)if(V){var U=e.dataIndex;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_RADAR:if(null==this.component.polar||r.data[0].value.length<=U)return;var d=r.polarIndex||0,p=this.component.polar.getVector(d,U,\"max\");this._event={zrenderX:p[0],zrenderY:p[1]},this._showPolarTrigger(d,U)}}else{var c,u,y=m.shapeList;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_TREEMAP:case s.CHART_TYPE_SCATTER:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if(null==y[a]._mark&&l.get(y[a],\"seriesIndex\")==t&&l.get(y[a],\"dataIndex\")==U){this._curTarget=y[a],c=y[a].style.x,u=m.type!=s.CHART_TYPE_K?y[a].style.y:y[a].style.y[0];break}break;case s.CHART_TYPE_RADAR:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if(\"polygon\"===y[a].type&&l.get(y[a],\"seriesIndex\")==t&&l.get(y[a],\"dataIndex\")==U){this._curTarget=y[a];var p=this.component.polar.getCenter(r.polarIndex||0);c=p[0],u=p[1];break}break;case s.CHART_TYPE_PIE:for(var g=e.name,a=0,o=y.length;o>a;a++)if(\"sector\"===y[a].type&&l.get(y[a],\"seriesIndex\")==t&&l.get(y[a],\"name\")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;c=this._curTarget.style.x+Math.cos(f)*b.r/1.5,u=this._curTarget.style.y-Math.sin(f)*b.r/1.5;break}break;case s.CHART_TYPE_MAP:for(var g=e.name,k=r.mapType,a=0,o=y.length;o>a;a++)if(\"text\"===y[a].type&&y[a]._mapType===k&&y[a].style._name===g){this._curTarget=y[a],c=this._curTarget.style.x+this._curTarget.position[0],u=this._curTarget.style.y+this._curTarget.position[1];break}break;case s.CHART_TYPE_CHORD:for(var g=e.name,a=0,o=y.length;o>a;a++)if(\"sector\"===y[a].type&&l.get(y[a],\"name\")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;return c=this._curTarget.style.x+Math.cos(f)*(b.r-2),u=this._curTarget.style.y-Math.sin(f)*(b.r-2),void this.zr.trigger(h.EVENT.MOUSEMOVE,{zrenderX:c,zrenderY:u})}break;case s.CHART_TYPE_FORCE:for(var g=e.name,a=0,o=y.length;o>a;a++)if(\"circle\"===y[a].type&&l.get(y[a],\"name\")==g){this._curTarget=y[a],c=this._curTarget.position[0],u=this._curTarget.position[1];break}}null!=c&&null!=u&&(this._event={zrenderX:c,zrenderY:u},this.zr.addHoverShape(this._curTarget),this.zr.refreshHover(),this._showItemTrigger())}}}},hideTip:function(){this._hide()},refresh:function(e){if(this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2,this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,e){this.option=e,this.option.tooltip=this.reformOption(this.option.tooltip),this.option.tooltip.textStyle=d.merge(this.option.tooltip.textStyle,this.ecTheme.textStyle),this._needAxisTrigger=!1,\"axis\"===this.option.tooltip.trigger&&(this._needAxisTrigger=!0);for(var t=this.option.series,i=0,n=t.length;n>i;i++)if(\"axis\"===this.query(t[i],\"tooltip.trigger\")){this._needAxisTrigger=!0;break}this._showDelay=this.option.tooltip.showDelay,this._hideDelay=this.option.tooltip.hideDelay,this._defaultCssText=this._style(this.option.tooltip),this._setSelectedMap(),this._axisLineWidth=this.option.tooltip.axisPointer.lineStyle.width,this._enterable=this.option.tooltip.enterable,!this._enterable&&this._tDom.className.indexOf(h.elementClassName)<0&&(this._tDom.className+=\" \"+h.elementClassName)}if(this.showing){var a=this;setTimeout(function(){a.zr.trigger(h.EVENT.MOUSEMOVE,a.zr.handler._event)},50)}},onbeforDispose:function(){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove),this.zr.un(h.EVENT.GLOBALOUT,this._onglobalout),this.hasAppend&&this.dom.firstChild&&this.dom.firstChild.removeChild(this._tDom),this._tDom=null},_encodeHTML:function(e){return String(e).replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}},d.inherits(t,i),e(\"../component\").define(\"tooltip\",t),t}),i(\"echarts/component/legend\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Rectangle\",\"zrender/shape/Sector\",\"../util/shape/Icon\",\"../util/shape/Candle\",\"../config\",\"zrender/tool/util\",\"zrender/tool/area\",\"../component\"],function(e){function t(e,t,n,a,o){if(!this.query(a,\"legend.data\"))return void console.error(\"option.legend.data has not been defined.\");i.call(this,e,t,n,a,o);var r=this;r._legendSelected=function(e){r.__legendSelected(e)},r._dispatchHoverLink=function(e){return r.__dispatchHoverLink(e)},this._colorIndex=0,this._colorMap={},this._selectedMap={},this._hasDataMap={},this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Rectangle\"),o=e(\"zrender/shape/Sector\"),r=e(\"../util/shape/Icon\"),s=e(\"../util/shape/Candle\"),l=e(\"../config\");l.legend={zlevel:0,z:4,show:!0,orient:\"horizontal\",x:\"center\",y:\"top\",backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,textStyle:{color:\"#333\"},selectedMode:!0};var h=e(\"zrender/tool/util\"),m=e(\"zrender/tool/area\");t.prototype={type:l.COMPONENT_TYPE_LEGEND,_buildShape:function(){if(this.legendOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e,t,i,a,o,s,l,V,U=this.legendOption.data,d=U.length,p=this.legendOption.textStyle,c=this.zr.getWidth(),u=this.zr.getHeight(),y=this._itemGroupLocation.x,g=this._itemGroupLocation.y,b=this.legendOption.itemWidth,f=this.legendOption.itemHeight,k=this.legendOption.itemGap;\"vertical\"===this.legendOption.orient&&\"right\"===this.legendOption.x&&(y=this._itemGroupLocation.x+this._itemGroupLocation.width-b);for(var x=0;d>x;x++)o=h.merge(U[x].textStyle||{},p),s=this.getFont(o),e=this._getName(U[x]),l=this._getFormatterName(e),\"\"!==e?(t=U[x].icon||this._getSomethingByName(e).type,V=this.getColor(e),\"horizontal\"===this.legendOption.orient?200>c-y&&b+5+m.getTextWidth(l,s)+(x===d-1||\"\"===U[x+1]?0:k)>=c-y&&(y=this._itemGroupLocation.x,g+=f+k):200>u-g&&f+(x===d-1||\"\"===U[x+1]?0:k)>=u-g&&(\"right\"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y),i=this._getItemShapeByType(y,g,b,f,this._selectedMap[e]&&this._hasDataMap[e]?V:\"#ccc\",t,V),i._name=e,i=new r(i),a={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:y+b+5,y:g+f/2,color:this._selectedMap[e]?\"auto\"===o.color?V:o.color:\"#ccc\",text:l,textFont:s,textBaseline:\"middle\"},highlightStyle:{color:V,brushType:\"fill\"},hoverable:!!this.legendOption.selectedMode,clickable:!!this.legendOption.selectedMode},\"vertical\"===this.legendOption.orient&&\"right\"===this.legendOption.x&&(a.style.x-=b+10,a.style.textAlign=\"right\"),a._name=e,a=new n(a),this.legendOption.selectedMode&&(i.onclick=a.onclick=this._legendSelected,i.onmouseover=a.onmouseover=this._dispatchHoverLink,i.hoverConnect=a.id,a.hoverConnect=i.id),this.shapeList.push(i),this.shapeList.push(a),\"horizontal\"===this.legendOption.orient?y+=b+5+m.getTextWidth(l,s)+k:g+=f+k):\"horizontal\"===this.legendOption.orient?(y=this._itemGroupLocation.x,g+=f+k):(\"right\"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y);\"horizontal\"===this.legendOption.orient&&\"center\"===this.legendOption.x&&g!=this._itemGroupLocation.y&&this._mLineOptimize()},_getName:function(e){return\"undefined\"!=typeof e.name?e.name:e},_getFormatterName:function(e){var t,i=this.legendOption.formatter;return t=\"function\"==typeof i?i.call(this.myChart,e):\"string\"==typeof i?i.replace(\"{name}\",e):e},_getFormatterNameFromData:function(e){var t=this._getName(e);return this._getFormatterName(t)},_mLineOptimize:function(){for(var e=[],t=this._itemGroupLocation.x,i=2,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t?e.push((this._itemGroupLocation.width-(this.shapeList[i-1].style.x+m.getTextWidth(this.shapeList[i-1].style.text,this.shapeList[i-1].style.textFont)-t))/2):i===n-1&&e.push((this._itemGroupLocation.width-(this.shapeList[i].style.x+m.getTextWidth(this.shapeList[i].style.text,this.shapeList[i].style.textFont)-t))/2);for(var a=-1,i=1,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t&&a++,0!==e[a]&&(this.shapeList[i].style.x+=e[a])},_buildBackground:function(){var e=this.reformCssArray(this.legendOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.legendOption.borderWidth?\"fill\":\"both\",color:this.legendOption.backgroundColor,strokeColor:this.legendOption.borderColor,lineWidth:this.legendOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this.legendOption.data,t=e.length,i=this.legendOption.itemGap,n=this.legendOption.itemWidth+5,a=this.legendOption.itemHeight,o=this.legendOption.textStyle,r=this.getFont(o),s=0,l=0,V=this.reformCssArray(this.legendOption.padding),U=this.zr.getWidth()-V[1]-V[3],d=this.zr.getHeight()-V[0]-V[2],p=0,c=0;if(\"horizontal\"===this.legendOption.orient){l=a;for(var u=0;t>u;u++)if(\"\"!==this._getName(e[u])){var y=m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r);p+n+y+i>U?(p-=i,s=Math.max(s,p),l+=a+i,p=0):(p+=n+y+i,s=Math.max(s,p-i))}else p-=i,s=Math.max(s,p),l+=a+i,p=0}else{for(var u=0;t>u;u++)c=Math.max(c,m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r));c+=n,s=c;for(var u=0;t>u;u++)\"\"!==this._getName(e[u])?p+a+i>d?(s+=c+i,p-=i,l=Math.max(l,p),p=0):(p+=a+i,l=Math.max(l,p-i)):(s+=c+i,p-=i,l=Math.max(l,p),p=0)}U=this.zr.getWidth(),d=this.zr.getHeight();var g;switch(this.legendOption.x){case\"center\":g=Math.floor((U-s)/2);break;case\"left\":g=V[3]+this.legendOption.borderWidth;break;case\"right\":g=U-s-V[1]-V[3]-2*this.legendOption.borderWidth;break;default:g=this.parsePercent(this.legendOption.x,U)}var b;switch(this.legendOption.y){case\"top\":b=V[0]+this.legendOption.borderWidth;break;case\"bottom\":b=d-l-V[0]-V[2]-2*this.legendOption.borderWidth;break;case\"center\":b=Math.floor((d-l)/2);break;default:b=this.parsePercent(this.legendOption.y,d)}return{x:g,y:b,width:s,height:l,maxWidth:c}},_getSomethingByName:function(e){for(var t,i=this.option.series,n=0,a=i.length;a>n;n++){if(i[n].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:null,dataIndex:-1};if(i[n].type===l.CHART_TYPE_PIE||i[n].type===l.CHART_TYPE_RADAR||i[n].type===l.CHART_TYPE_CHORD||i[n].type===l.CHART_TYPE_FORCE||i[n].type===l.CHART_TYPE_FUNNEL||i[n].type===l.CHART_TYPE_TREEMAP){t=i[n].categories||i[n].data||i[n].nodes;for(var o=0,r=t.length;r>o;o++)if(t[o].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:t[o],dataIndex:o}}}return{type:\"bar\",series:null,seriesIndex:-1,data:null,dataIndex:-1}},_getItemShapeByType:function(e,t,i,n,a,o,r){var s,h=\"#ccc\"===a?r:a,m={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{iconType:\"legendicon\"+o,x:e,y:t,width:i,height:n,color:a,strokeColor:a,lineWidth:2},highlightStyle:{color:h,strokeColor:h,lineWidth:1},hoverable:this.legendOption.selectedMode,clickable:this.legendOption.selectedMode};if(o.match(\"image\")){var s=o.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\");o=\"image\"}switch(o){case\"line\":m.style.brushType=\"stroke\",m.highlightStyle.lineWidth=3;break;case\"radar\":case\"venn\":case\"tree\":case\"treemap\":case\"scatter\":m.highlightStyle.lineWidth=3;break;case\"k\":m.style.brushType=\"both\",m.highlightStyle.lineWidth=3,m.highlightStyle.color=m.style.color=this.deepQuery([this.ecTheme,l],\"k.itemStyle.normal.color\")||\"#fff\",m.style.strokeColor=\"#ccc\"!=a?this.deepQuery([this.ecTheme,l],\"k.itemStyle.normal.lineStyle.color\")||\"#ff3200\":a;break;case\"image\":m.style.iconType=\"image\",m.style.image=s,\"#ccc\"===a&&(m.style.opacity=.5)}return m},__legendSelected:function(e){var t=e.target._name;if(\"single\"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[t]=!this._selectedMap[t],this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,e.event,{selected:this._selectedMap,target:t},this.myChart)},__dispatchHoverLink:function(e){this.messageCenter.dispatch(l.EVENT.LEGEND_HOVERLINK,e.event,{target:e.target._name},this.myChart)},refresh:function(e){if(e){this.option=e||this.option,this.option.legend=this.reformOption(this.option.legend),this.legendOption=this.option.legend;var t,i,n,a,o=this.legendOption.data||[];if(this.legendOption.selected)for(var r in this.legendOption.selected)this._selectedMap[r]=\"undefined\"!=typeof this._selectedMap[r]?this._selectedMap[r]:this.legendOption.selected[r];for(var s=0,h=o.length;h>s;s++)t=this._getName(o[s]),\"\"!==t&&(i=this._getSomethingByName(t),i.series?(this._hasDataMap[t]=!0,a=!i.data||i.type!==l.CHART_TYPE_PIE&&i.type!==l.CHART_TYPE_FORCE&&i.type!==l.CHART_TYPE_FUNNEL?[i.series]:[i.data,i.series],n=this.getItemStyleColor(this.deepQuery(a,\"itemStyle.normal.color\"),i.seriesIndex,i.dataIndex,i.data),n&&i.type!=l.CHART_TYPE_K&&this.setColor(t,n),this._selectedMap[t]=null!=this._selectedMap[t]?this._selectedMap[t]:!0):this._hasDataMap[t]=!1)}this.clear(),this._buildShape()},getRelatedAmount:function(e){for(var t,i=0,n=this.option.series,a=0,o=n.length;o>a;a++)if(n[a].name===e&&i++,n[a].type===l.CHART_TYPE_PIE||n[a].type===l.CHART_TYPE_RADAR||n[a].type===l.CHART_TYPE_CHORD||n[a].type===l.CHART_TYPE_FORCE||n[a].type===l.CHART_TYPE_FUNNEL){t=n[a].type!=l.CHART_TYPE_FORCE?n[a].data:n[a].categories;for(var r=0,s=t.length;s>r;r++)t[r].name===e&&\"-\"!=t[r].value&&i++}return i},setColor:function(e,t){this._colorMap[e]=t},getColor:function(e){return this._colorMap[e]||(this._colorMap[e]=this.zr.getColor(this._colorIndex++)),this._colorMap[e]},hasColor:function(e){return this._colorMap[e]?this._colorMap[e]:!1},add:function(e,t){\nfor(var i=this.legendOption.data,n=0,a=i.length;a>n;n++)if(this._getName(i[n])===e)return;this.legendOption.data.push(e),this.setColor(e,t),this._selectedMap[e]=!0,this._hasDataMap[e]=!0},del:function(e){for(var t=this.legendOption.data,i=0,n=t.length;n>i;i++)if(this._getName(t[i])===e)return this.legendOption.data.splice(i,1)},getItemShape:function(e){if(null!=e)for(var t,i=0,n=this.shapeList.length;n>i;i++)if(t=this.shapeList[i],t._name===e&&\"text\"!=t.type)return t},setItemShape:function(e,t){for(var i,n=0,a=this.shapeList.length;a>n;n++)i=this.shapeList[n],i._name===e&&\"text\"!=i.type&&(this._selectedMap[e]||(t.style.color=\"#ccc\",t.style.strokeColor=\"#ccc\"),this.zr.modShape(i.id,t))},isSelected:function(e){return\"undefined\"!=typeof this._selectedMap[e]?this._selectedMap[e]:!0},getSelectedMap:function(){return this._selectedMap},setSelected:function(e,t){if(\"single\"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[e]=t,this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,null,{selected:this._selectedMap,target:e},this.myChart)},onlegendSelected:function(e,t){var i=e.selected;for(var n in i)this._selectedMap[n]!=i[n]&&(t.needRefresh=!0),this._selectedMap[n]=i[n]}};var V={line:function(e,t){var i=t.height/2;e.moveTo(t.x,t.y+i),e.lineTo(t.x+t.width,t.y+i)},pie:function(e,t){var i=t.x,n=t.y,a=t.width,r=t.height;o.prototype.buildPath(e,{x:i+a/2,y:n+r+2,r:r,r0:6,startAngle:45,endAngle:135})},eventRiver:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o),e.bezierCurveTo(i+a,n+o,i,n+4,i+a,n+4),e.lineTo(i+a,n),e.bezierCurveTo(i,n,i+a,n+o-4,i,n+o-4),e.lineTo(i,n+o)},k:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;s.prototype.buildPath(e,{x:i+a/2,y:[n+1,n+1,n+o-6,n+o],width:a-6})},bar:function(e,t){var i=t.x,n=t.y+1,a=t.width,o=t.height-2,r=3;e.moveTo(i+r,n),e.lineTo(i+a-r,n),e.quadraticCurveTo(i+a,n,i+a,n+r),e.lineTo(i+a,n+o-r),e.quadraticCurveTo(i+a,n+o,i+a-r,n+o),e.lineTo(i+r,n+o),e.quadraticCurveTo(i,n+o,i,n+o-r),e.lineTo(i,n+r),e.quadraticCurveTo(i,n,i+r,n)},force:function(e,t){r.prototype.iconLibrary.circle(e,t)},radar:function(e,t){var i=6,n=t.x+t.width/2,a=t.y+t.height/2,o=t.height/2,r=2*Math.PI/i,s=-Math.PI/2,l=n+o*Math.cos(s),h=a+o*Math.sin(s);e.moveTo(l,h),s+=r;for(var m=0,V=i-1;V>m;m++)e.lineTo(n+o*Math.cos(s),a+o*Math.sin(s)),s+=r;e.lineTo(l,h)}};V.chord=V.pie,V.map=V.bar;for(var U in V)r.prototype.iconLibrary[\"legendicon\"+U]=V[U];return h.inherits(t,i),e(\"../component\").define(\"legend\",t),t}),i(\"echarts/util/ecData\",[],function(){function e(e,t,i,n,a,o,r,s){var l;return\"undefined\"!=typeof n&&(l=null==n.value?n:n.value),e._echartsData={_series:t,_seriesIndex:i,_data:n,_dataIndex:a,_name:o,_value:l,_special:r,_special2:s},e._echartsData}function t(e,t){var i=e._echartsData;if(!t)return i;switch(t){case\"series\":case\"seriesIndex\":case\"data\":case\"dataIndex\":case\"name\":case\"value\":case\"special\":case\"special2\":return i&&i[\"_\"+t]}return null}function i(e,t,i){switch(e._echartsData=e._echartsData||{},t){case\"series\":case\"seriesIndex\":case\"data\":case\"dataIndex\":case\"name\":case\"value\":case\"special\":case\"special2\":e._echartsData[\"_\"+t]=i}}function n(e,t){t._echartsData={_series:e._echartsData._series,_seriesIndex:e._echartsData._seriesIndex,_data:e._echartsData._data,_dataIndex:e._echartsData._dataIndex,_name:e._echartsData._name,_value:e._echartsData._value,_special:e._echartsData._special,_special2:e._echartsData._special2}}return{pack:e,set:i,get:t,clone:n}}),i(\"echarts/chart\",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i(\"zrender/tool/color\",[\"require\",\"../tool/util\"],function(e){function t(e){D=e}function i(){D=N}function n(e,t){return e=0|e,t=t||D,t[e%t.length]}function a(e){B=e}function o(){H=B}function r(){return B}function s(e,t,i,n,a,o,r){O||(O=P.getContext());for(var s=O.createRadialGradient(e,t,i,n,a,o),l=0,h=r.length;h>l;l++)s.addColorStop(r[l][0],r[l][1]);return s.__nonRecursion=!0,s}function l(e,t,i,n,a){O||(O=P.getContext());for(var o=O.createLinearGradient(e,t,i,n),r=0,s=a.length;s>r;r++)o.addColorStop(a[r][0],a[r][1]);return o.__nonRecursion=!0,o}function h(e,t,i){e=p(e),t=p(t),e=I(e),t=I(t);for(var n=[],a=(t[0]-e[0])/i,o=(t[1]-e[1])/i,r=(t[2]-e[2])/i,s=(t[3]-e[3])/i,l=0,h=e[0],m=e[1],U=e[2],d=e[3];i>l;l++)n[l]=V([S(Math.floor(h),[0,255]),S(Math.floor(m),[0,255]),S(Math.floor(U),[0,255]),d.toFixed(4)-0],\"rgba\"),h+=a,m+=o,U+=r,d+=s;return h=t[0],m=t[1],U=t[2],d=t[3],n[l]=V([h,m,U,d],\"rgba\"),n}function m(e,t){var i=[],n=e.length;if(void 0===t&&(t=20),1===n)i=h(e[0],e[0],t);else if(n>1)for(var a=0,o=n-1;o>a;a++){var r=h(e[a],e[a+1],t);o-1>a&&r.pop(),i=i.concat(r)}return i}function V(e,t){if(t=t||\"rgb\",e&&(3===e.length||4===e.length)){if(e=C(e,function(e){return e>1?Math.ceil(e):e}),t.indexOf(\"hex\")>-1)return\"#\"+((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1);if(t.indexOf(\"hs\")>-1){var i=C(e.slice(1,3),function(e){return e+\"%\"});e[1]=i[0],e[2]=i[1]}return t.indexOf(\"a\")>-1?(3===e.length&&e.push(1),e[3]=S(e[3],[0,1]),t+\"(\"+e.slice(0,4).join(\",\")+\")\"):t+\"(\"+e.slice(0,3).join(\",\")+\")\"}}function U(e){e=L(e),e.indexOf(\"rgba\")<0&&(e=p(e));var t=[],i=0;return e.replace(/[\\d.]+/g,function(e){e=3>i?0|e:+e,t[i++]=e}),t}function d(e,t){if(!E(e))return e;var i=I(e),n=i[3];return\"undefined\"==typeof n&&(n=1),e.indexOf(\"hsb\")>-1?i=F(i):e.indexOf(\"hsl\")>-1&&(i=T(i)),t.indexOf(\"hsb\")>-1||t.indexOf(\"hsv\")>-1?i=A(i):t.indexOf(\"hsl\")>-1&&(i=M(i)),i[3]=n,V(i,t)}function p(e){return d(e,\"rgba\")}function c(e){return d(e,\"rgb\")}function u(e){return d(e,\"hex\")}function y(e){return d(e,\"hsva\")}function g(e){return d(e,\"hsv\")}function b(e){return d(e,\"hsba\")}function f(e){return d(e,\"hsb\")}function k(e){return d(e,\"hsla\")}function x(e){return d(e,\"hsl\")}function _(e){for(var t in G)if(u(G[t])===u(e))return t;return null}function L(e){return String(e).replace(/\\s+/g,\"\")}function W(e){if(G[e]&&(e=G[e]),e=L(e),e=e.replace(/hsv/i,\"hsb\"),/^#[\\da-f]{3}$/i.test(e)){e=parseInt(e.slice(1),16);var t=(3840&e)<<8,i=(240&e)<<4,n=15&e;e=\"#\"+((1<<24)+(t<<4)+t+(i<<4)+i+(n<<4)+n).toString(16).slice(1)}return e}function X(e,t){if(!E(e))return e;var i=t>0?1:-1;\"undefined\"==typeof t&&(t=0),t=Math.abs(t)>1?1:Math.abs(t),e=c(e);for(var n=I(e),a=0;3>a;a++)n[a]=1===i?n[a]*(1-t)|0:(255-n[a])*t+n[a]|0;return\"rgb(\"+n.join(\",\")+\")\"}function v(e){if(!E(e))return e;var t=I(p(e));return t=C(t,function(e){return 255-e}),V(t,\"rgb\")}function w(e,t,i){if(!E(e)||!E(t))return e;\"undefined\"==typeof i&&(i=.5),i=1-S(i,[0,1]);for(var n=2*i-1,a=I(p(e)),o=I(p(t)),r=a[3]-o[3],s=((n*r===-1?n:(n+r)/(1+n*r))+1)/2,l=1-s,h=[],m=0;3>m;m++)h[m]=a[m]*s+o[m]*l;var U=a[3]*i+o[3]*(1-i);return U=Math.max(0,Math.min(1,U)),1===a[3]&&1===o[3]?V(h,\"rgb\"):(h[3]=U,V(h,\"rgba\"))}function K(){return\"#\"+(Math.random().toString(16)+\"0000\").slice(2,8)}function I(e){e=W(e);var t=e.match(R);if(null===t)throw new Error(\"The color format error\");var i,n,a,o=[];if(t[2])i=t[2].replace(\"#\",\"\").split(\"\"),a=[i[0]+i[1],i[2]+i[3],i[4]+i[5]],o=C(a,function(e){return S(parseInt(e,16),[0,255])});else if(t[4]){var r=t[4].split(\",\");n=r[3],a=r.slice(0,3),o=C(a,function(e){return e=Math.floor(e.indexOf(\"%\")>0?2.55*parseInt(e,0):e),S(e,[0,255])}),\"undefined\"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}else if(t[5]||t[6]){var s=(t[5]||t[6]).split(\",\"),l=parseInt(s[0],0)/360,h=s[1],m=s[2];n=s[3],o=C([h,m],function(e){return S(parseFloat(e)/100,[0,1])}),o.unshift(l),\"undefined\"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}return o}function J(e,t){if(!E(e))return e;null===t&&(t=1);var i=I(p(e));return i[3]=S(Number(t).toFixed(4),[0,1]),V(i,\"rgba\")}function C(e,t){if(\"function\"!=typeof t)throw new TypeError;for(var i=e?e.length:0,n=0;i>n;n++)e[n]=t(e[n]);return e}function S(e,t){return e<=t[0]?e=t[0]:e>=t[1]&&(e=t[1]),e}function E(e){return e instanceof Array||\"string\"==typeof e}function F(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s=6*a;6===s&&(s=0);var l=0|s,h=r*(1-o),m=r*(1-o*(s-l)),V=r*(1-o*(1-(s-l))),U=0,d=0,p=0;0===l?(U=r,d=V,p=h):1===l?(U=m,d=r,p=h):2===l?(U=h,d=r,p=V):3===l?(U=h,d=m,p=r):4===l?(U=V,d=h,p=r):(U=r,d=h,p=m),t=255*U,i=255*d,n=255*p}return[t,i,n]}function T(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s;s=.5>r?r*(1+o):r+o-o*r;var l=2*r-s;t=255*z(l,s,a+1/3),i=255*z(l,s,a),n=255*z(l,s,a-1/3)}return[t,i,n]}function z(e,t,i){return 0>i&&(i+=1),i>1&&(i-=1),1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function A(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=s;if(0===l)t=0,i=0;else{i=l/s;var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}function M(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=(s+r)/2;if(0===l)t=0,i=0;else{i=.5>h?l/(s+r):l/(2-s-r);var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}var O,P=e(\"../tool/util\"),D=[\"#ff9277\",\" #dddd00\",\" #ffc877\",\" #bbe3ff\",\" #d5ffbb\",\"#bbbbff\",\" #ddb000\",\" #b0dd00\",\" #e2bbff\",\" #ffbbe3\",\"#ff7777\",\" #ff9900\",\" #83dd00\",\" #77e3ff\",\" #778fff\",\"#c877ff\",\" #ff77ab\",\" #ff6600\",\" #aa8800\",\" #77c7ff\",\"#ad77ff\",\" #ff77ff\",\" #dd0083\",\" #777700\",\" #00aa00\",\"#0088aa\",\" #8400dd\",\" #aa0088\",\" #dd0000\",\" #772e00\"],N=D,B=\"rgba(255,255,0,0.5)\",H=B,R=/^\\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,G={aliceblue:\"#f0f8ff\",antiquewhite:\"#faebd7\",aqua:\"#0ff\",aquamarine:\"#7fffd4\",azure:\"#f0ffff\",beige:\"#f5f5dc\",bisque:\"#ffe4c4\",black:\"#000\",blanchedalmond:\"#ffebcd\",blue:\"#00f\",blueviolet:\"#8a2be2\",brown:\"#a52a2a\",burlywood:\"#deb887\",cadetblue:\"#5f9ea0\",chartreuse:\"#7fff00\",chocolate:\"#d2691e\",coral:\"#ff7f50\",cornflowerblue:\"#6495ed\",cornsilk:\"#fff8dc\",crimson:\"#dc143c\",cyan:\"#0ff\",darkblue:\"#00008b\",darkcyan:\"#008b8b\",darkgoldenrod:\"#b8860b\",darkgray:\"#a9a9a9\",darkgrey:\"#a9a9a9\",darkgreen:\"#006400\",darkkhaki:\"#bdb76b\",darkmagenta:\"#8b008b\",darkolivegreen:\"#556b2f\",darkorange:\"#ff8c00\",darkorchid:\"#9932cc\",darkred:\"#8b0000\",darksalmon:\"#e9967a\",darkseagreen:\"#8fbc8f\",darkslateblue:\"#483d8b\",darkslategray:\"#2f4f4f\",darkslategrey:\"#2f4f4f\",darkturquoise:\"#00ced1\",darkviolet:\"#9400d3\",deeppink:\"#ff1493\",deepskyblue:\"#00bfff\",dimgray:\"#696969\",dimgrey:\"#696969\",dodgerblue:\"#1e90ff\",firebrick:\"#b22222\",floralwhite:\"#fffaf0\",forestgreen:\"#228b22\",fuchsia:\"#f0f\",gainsboro:\"#dcdcdc\",ghostwhite:\"#f8f8ff\",gold:\"#ffd700\",goldenrod:\"#daa520\",gray:\"#808080\",grey:\"#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\",lightgray:\"#d3d3d3\",lightgrey:\"#d3d3d3\",lightgreen:\"#90ee90\",lightpink:\"#ffb6c1\",lightsalmon:\"#ffa07a\",lightseagreen:\"#20b2aa\",lightskyblue:\"#87cefa\",lightslategray:\"#789\",lightslategrey:\"#789\",lightsteelblue:\"#b0c4de\",lightyellow:\"#ffffe0\",lime:\"#0f0\",limegreen:\"#32cd32\",linen:\"#faf0e6\",magenta:\"#f0f\",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\",oldlace:\"#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:\"#f00\",rosybrown:\"#bc8f8f\",royalblue:\"#4169e1\",saddlebrown:\"#8b4513\",salmon:\"#fa8072\",sandybrown:\"#f4a460\",seagreen:\"#2e8b57\",seashell:\"#fff5ee\",sienna:\"#a0522d\",silver:\"#c0c0c0\",skyblue:\"#87ceeb\",slateblue:\"#6a5acd\",slategray:\"#708090\",slategrey:\"#708090\",snow:\"#fffafa\",springgreen:\"#00ff7f\",steelblue:\"#4682b4\",tan:\"#d2b48c\",teal:\"#008080\",thistle:\"#d8bfd8\",tomato:\"#ff6347\",turquoise:\"#40e0d0\",violet:\"#ee82ee\",wheat:\"#f5deb3\",white:\"#fff\",whitesmoke:\"#f5f5f5\",yellow:\"#ff0\",yellowgreen:\"#9acd32\"};return{customPalette:t,resetPalette:i,getColor:n,getHighlightColor:r,customHighlight:a,resetHighlight:o,getRadialGradient:s,getLinearGradient:l,getGradientColors:m,getStepColors:h,reverse:v,mix:w,lift:X,trim:L,random:K,toRGB:c,toRGBA:p,toHex:u,toHSL:x,toHSLA:k,toHSB:f,toHSBA:b,toHSV:g,toHSVA:y,toName:_,toColor:V,toArray:U,alpha:J,getData:I}}),i(\"echarts/component/timeline\",[\"require\",\"./base\",\"zrender/shape/Rectangle\",\"../util/shape/Icon\",\"../util/shape/Chain\",\"../config\",\"zrender/tool/util\",\"zrender/tool/area\",\"zrender/tool/event\",\"../component\"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o);var r=this;if(r._onclick=function(e){return r.__onclick(e)},r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},r._setCurrentOption=function(){var e=r.timelineOption;r.currentIndex%=e.data.length;var t=r.options[r.currentIndex]||{};r.myChart._setOption(t,e.notMerge,!0),r.messageCenter.dispatch(s.EVENT.TIMELINE_CHANGED,null,{currentIndex:r.currentIndex,data:null!=e.data[r.currentIndex].name?e.data[r.currentIndex].name:e.data[r.currentIndex]},r.myChart)},r._onFrame=function(){r._setCurrentOption(),r._syncHandleShape(),r.timelineOption.autoPlay&&(r.playTicket=setTimeout(function(){return r.currentIndex+=1,!r.timelineOption.loop&&r.currentIndex>=r.timelineOption.data.length?(r.currentIndex=r.timelineOption.data.length-1,void r.stop()):void r._onFrame()},r.timelineOption.playInterval))},this.setTheme(!1),this.options=this.option.options,this.currentIndex=this.timelineOption.currentIndex%this.timelineOption.data.length,this.timelineOption.notMerge||0===this.currentIndex||(this.options[this.currentIndex]=l.merge(this.options[this.currentIndex],this.options[0])),this.timelineOption.show&&(this._buildShape(),this._syncHandleShape()),this._setCurrentOption(),this.timelineOption.autoPlay){var r=this;this.playTicket=setTimeout(function(){r.play()},null!=this.ecTheme.animationDuration?this.ecTheme.animationDuration:s.animationDuration)}}function i(e,t){var i=2,n=t.x+i,a=t.y+i+2,r=t.width-i,s=t.height-i,l=t.symbol;if(\"last\"===l)e.moveTo(n+r-2,a+s/3),e.lineTo(n+r-2,a),e.lineTo(n+2,a+s/2),e.lineTo(n+r-2,a+s),e.lineTo(n+r-2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if(\"next\"===l)e.moveTo(n+2,a+s/3),e.lineTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if(\"play\"===l)if(\"stop\"===t.status)e.moveTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a);else{var h=\"both\"===t.brushType?2:3;e.rect(n+2,a,h,s),e.rect(n+r-h-2,a,h,s)}else if(l.match(\"image\")){var m=\"\";m=l.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),l=o.prototype.iconLibrary.image,l(e,{x:n,y:a,width:r,height:s,image:m})}}var n=e(\"./base\"),a=e(\"zrender/shape/Rectangle\"),o=e(\"../util/shape/Icon\"),r=e(\"../util/shape/Chain\"),s=e(\"../config\");s.timeline={zlevel:0,z:4,show:!0,type:\"time\",notMerge:!1,realtime:!0,x:80,x2:80,y2:0,height:50,backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,controlPosition:\"left\",autoPlay:!1,loop:!0,playInterval:2e3,lineStyle:{width:1,color:\"#666\",type:\"dashed\"},label:{show:!0,interval:\"auto\",rotate:0,textStyle:{color:\"#333\"}},checkpointStyle:{symbol:\"auto\",symbolSize:\"auto\",color:\"auto\",borderColor:\"auto\",borderWidth:\"auto\",label:{show:!1,textStyle:{color:\"auto\"}}},controlStyle:{itemSize:15,itemGap:5,normal:{color:\"#333\"},emphasis:{color:\"#1e90ff\"}},symbol:\"emptyDiamond\",symbolSize:4,currentIndex:0};var l=e(\"zrender/tool/util\"),h=e(\"zrender/tool/area\"),m=e(\"zrender/tool/event\");return t.prototype={type:s.COMPONENT_TYPE_TIMELINE,_buildShape:function(){if(this._location=this._getLocation(),this._buildBackground(),this._buildControl(),this._chainPoint=this._getChainPoint(),this.timelineOption.label.show)for(var e=this._getInterval(),t=0,i=this._chainPoint.length;i>t;t+=e)this._chainPoint[t].showLabel=!0;this._buildChain(),this._buildHandle();for(var t=0,n=this.shapeList.length;n>t;t++)this.zr.addShape(this.shapeList[t])},_getLocation:function(){var e,t=this.timelineOption,i=this.reformCssArray(this.timelineOption.padding),n=this.zr.getWidth(),a=this.parsePercent(t.x,n),o=this.parsePercent(t.x2,n);null==t.width?(e=n-a-o,o=n-o):(e=this.parsePercent(t.width,n),o=a+e);var r,s,l=this.zr.getHeight(),h=this.parsePercent(t.height,l);return null!=t.y?(r=this.parsePercent(t.y,l),s=r+h):(s=l-this.parsePercent(t.y2,l),r=s-h),{x:a+i[3],y:r+i[0],x2:o-i[1],y2:s-i[2],width:e-i[1]-i[3],height:h-i[0]-i[2]}},_getReformedLabel:function(e){var t=this.timelineOption,i=null!=t.data[e].name?t.data[e].name:t.data[e],n=t.data[e].formatter||t.label.formatter;return n&&(\"function\"==typeof n?i=n.call(this.myChart,i):\"string\"==typeof n&&(i=n.replace(\"{value}\",i))),i},_getInterval:function(){var e=this._chainPoint,t=this.timelineOption,i=t.label.interval;if(\"auto\"===i){var n=t.label.textStyle.fontSize,a=t.data,o=t.data.length;if(o>3){var r,s,l=!1;for(i=0;!l&&o>i;){i++,l=!0;for(var m=i;o>m;m+=i){if(r=e[m].x-e[m-i].x,0!==t.label.rotate)s=n;else if(a[m].textStyle)s=h.getTextWidth(e[m].name,e[m].textFont);else{var V=e[m].name+\"\",U=(V.match(/\\w/g)||\"\").length,d=V.length-U;s=U*n*2/3+d*n}if(s>r){l=!1;break}}}}else i=1}else i=i-0+1;return i},_getChainPoint:function(){function e(e){return null!=h[e].name?h[e].name:h[e]+\"\"}var t,i=this.timelineOption,n=i.symbol.toLowerCase(),a=i.symbolSize,o=i.label.rotate,r=i.label.textStyle,s=this.getFont(r),h=i.data,m=this._location.x,V=this._location.y+this._location.height/4*3,U=this._location.x2-this._location.x,d=h.length,p=[];if(d>1){var c=U/d;if(c=c>50?50:20>c?5:c,U-=2*c,\"number\"===i.type)for(var u=0;d>u;u++)p.push(m+c+U/(d-1)*u);else{p[0]=new Date(e(0).replace(/-/g,\"/\")),p[d-1]=new Date(e(d-1).replace(/-/g,\"/\"))-p[0];for(var u=1;d>u;u++)p[u]=m+c+U*(new Date(e(u).replace(/-/g,\"/\"))-p[0])/p[d-1];p[0]=m+c}}else p.push(m+U/2);for(var y,g,b,f,k,x=[],u=0;d>u;u++)m=p[u],y=h[u].symbol&&h[u].symbol.toLowerCase()||n,y.match(\"empty\")?(y=y.replace(\"empty\",\"\"),b=!0):b=!1,y.match(\"star\")&&(g=y.replace(\"star\",\"\")-0||5,y=\"star\"),t=h[u].textStyle?l.merge(h[u].textStyle||{},r):r,f=t.align||\"center\",o?(f=o>0?\"right\":\"left\",k=[o*Math.PI/180,m,V-5]):k=!1,x.push({x:m,n:g,isEmpty:b,symbol:y,symbolSize:h[u].symbolSize||a,color:h[u].color,borderColor:h[u].borderColor,borderWidth:h[u].borderWidth,name:this._getReformedLabel(u),textColor:t.color,textAlign:f,textBaseline:t.baseline||\"middle\",textX:m,textY:V-(o?5:0),textFont:h[u].textStyle?this.getFont(t):s,rotation:k,showLabel:!1});return x},_buildBackground:function(){var e=this.timelineOption,t=this.reformCssArray(this.timelineOption.padding),i=this._location.width,n=this._location.height;(0!==e.borderWidth||\"rgba(0,0,0,0)\"!=e.backgroundColor.replace(/\\s/g,\"\"))&&this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x-t[3],y:this._location.y-t[0],width:i+t[1]+t[3],height:n+t[0]+t[2],brushType:0===e.borderWidth?\"fill\":\"both\",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_buildControl:function(){var e=this,t=this.timelineOption,i=t.lineStyle,n=t.controlStyle;if(\"none\"!==t.controlPosition){var a,r=n.itemSize,s=n.itemGap;\"left\"===t.controlPosition?(a=this._location.x,this._location.x+=3*(r+s)):(a=this._location.x2-(3*(r+s)-s),this._location.x2-=3*(r+s));var h=this._location.y,m={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{iconType:\"timelineControl\",symbol:\"last\",x:a,y:h,width:r,height:r,brushType:\"stroke\",color:n.normal.color,strokeColor:n.normal.color,lineWidth:i.width},highlightStyle:{color:n.emphasis.color,strokeColor:n.emphasis.color,lineWidth:i.width+1},clickable:!0};this._ctrLastShape=new o(m),this._ctrLastShape.onclick=function(){e.last()},this.shapeList.push(this._ctrLastShape),a+=r+s,this._ctrPlayShape=new o(l.clone(m)),this._ctrPlayShape.style.brushType=\"fill\",this._ctrPlayShape.style.symbol=\"play\",this._ctrPlayShape.style.status=this.timelineOption.autoPlay?\"playing\":\"stop\",this._ctrPlayShape.style.x=a,this._ctrPlayShape.onclick=function(){\"stop\"===e._ctrPlayShape.style.status?e.play():e.stop()},this.shapeList.push(this._ctrPlayShape),a+=r+s,this._ctrNextShape=new o(l.clone(m)),this._ctrNextShape.style.symbol=\"next\",this._ctrNextShape.style.x=a,this._ctrNextShape.onclick=function(){e.next()},this.shapeList.push(this._ctrNextShape)}},_buildChain:function(){var e=this.timelineOption,t=e.lineStyle;this._timelineShae={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:this._location.x,y:this.subPixelOptimize(this._location.y,t.width),width:this._location.x2-this._location.x,height:this._location.height,chainPoint:this._chainPoint,brushType:\"both\",strokeColor:t.color,lineWidth:t.width,lineType:t.type},hoverable:!1,clickable:!0,onclick:this._onclick},this._timelineShae=new r(this._timelineShae),this.shapeList.push(this._timelineShae)},_buildHandle:function(){var e=this._chainPoint[this.currentIndex],t=e.symbolSize+1;t=5>t?5:t,this._handleShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,hoverable:!1,draggable:!0,style:{iconType:\"diamond\",n:e.n,x:e.x-t,y:this._location.y+this._location.height/4-t,width:2*t,height:2*t,brushType:\"both\",textPosition:\"specific\",textX:e.x,textY:this._location.y-this._location.height/4,textAlign:\"center\",textBaseline:\"middle\"},highlightStyle:{},ondrift:this._ondrift,ondragend:this._ondragend},this._handleShape=new o(this._handleShape),this.shapeList.push(this._handleShape)},_syncHandleShape:function(){if(this.timelineOption.show){var e=this.timelineOption,t=e.checkpointStyle,i=this._chainPoint[this.currentIndex];this._handleShape.style.text=t.label.show?i.name:\"\",this._handleShape.style.textFont=i.textFont,this._handleShape.style.n=i.n,\"auto\"===t.symbol?this._handleShape.style.iconType=\"none\"!=i.symbol?i.symbol:\"diamond\":(this._handleShape.style.iconType=t.symbol,t.symbol.match(\"star\")&&(this._handleShape.style.n=t.symbol.replace(\"star\",\"\")-0||5,this._handleShape.style.iconType=\"star\"));var n;\"auto\"===t.symbolSize?(n=i.symbolSize+2,n=5>n?5:n):n=t.symbolSize-0,this._handleShape.style.color=\"auto\"===t.color?i.color?i.color:e.controlStyle.emphasis.color:t.color,this._handleShape.style.textColor=\"auto\"===t.label.textStyle.color?this._handleShape.style.color:t.label.textStyle.color,this._handleShape.highlightStyle.strokeColor=this._handleShape.style.strokeColor=\"auto\"===t.borderColor?i.borderColor?i.borderColor:\"#fff\":t.borderColor,this._handleShape.style.lineWidth=\"auto\"===t.borderWidth?i.borderWidth?i.borderWidth:0:t.borderWidth-0,this._handleShape.highlightStyle.lineWidth=this._handleShape.style.lineWidth+1,this.zr.animate(this._handleShape.id,\"style\").when(500,{x:i.x-n,textX:i.x,y:this._location.y+this._location.height/4-n,width:2*n,height:2*n}).start(\"ExponentialOut\")}},_findChainIndex:function(e){var t=this._chainPoint,i=t.length;if(e<=t[0].x)return 0;if(e>=t[i-1].x)return i-1;for(var n=0;i-1>n;n++)if(e>=t[n].x&&e<=t[n+1].x)return Math.abs(e-t[n].x)<Math.abs(e-t[n+1].x)?n:n+1},__onclick:function(e){var t=m.getX(e.event),i=this._findChainIndex(t);return i===this.currentIndex?!0:(this.currentIndex=i,this.timelineOption.autoPlay&&this.stop(),clearTimeout(this.playTicket),void this._onFrame())},__ondrift:function(e,t){this.timelineOption.autoPlay&&this.stop();var i,n=this._chainPoint,a=n.length;e.style.x+t<=n[0].x-n[0].symbolSize?(e.style.x=n[0].x-n[0].symbolSize,i=0):e.style.x+t>=n[a-1].x-n[a-1].symbolSize?(e.style.x=n[a-1].x-n[a-1].symbolSize,i=a-1):(e.style.x+=t,i=this._findChainIndex(e.style.x));var o=n[i],r=o.symbolSize+2;if(e.style.iconType=o.symbol,e.style.n=o.n,e.style.textX=e.style.x+r/2,e.style.y=this._location.y+this._location.height/4-r,e.style.width=2*r,e.style.height=2*r,e.style.text=o.name,i===this.currentIndex)return!0;if(this.currentIndex=i,this.timelineOption.realtime){clearTimeout(this.playTicket);var s=this;this.playTicket=setTimeout(function(){s._setCurrentOption()},200)}return!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.timelineOption.realtime&&this._setCurrentOption(),t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1,this._syncHandleShape())},last:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex-=1,this.currentIndex<0&&(this.currentIndex=this.timelineOption.data.length-1),this._onFrame(),this.currentIndex},next:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex+=1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},play:function(e,t){return this._ctrPlayShape&&\"playing\"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status=\"playing\",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=null!=t?t:!0,this.timelineOption.autoPlay||clearTimeout(this.playTicket),this.currentIndex=null!=e?e:this.currentIndex+1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},stop:function(){return this._ctrPlayShape&&\"stop\"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status=\"stop\",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=!1,clearTimeout(this.playTicket),this.currentIndex},resize:function(){this.timelineOption.show&&(this.clear(),this._buildShape(),this._syncHandleShape())},setTheme:function(e){this.timelineOption=this.reformOption(l.clone(this.option.timeline)),this.timelineOption.label.textStyle=this.getTextStyle(this.timelineOption.label.textStyle),this.timelineOption.checkpointStyle.label.textStyle=this.getTextStyle(this.timelineOption.checkpointStyle.label.textStyle),this.myChart.canvasSupported||(this.timelineOption.realtime=!1),this.timelineOption.show&&e&&(this.clear(),this._buildShape(),this._syncHandleShape())},onbeforDispose:function(){clearTimeout(this.playTicket)}},o.prototype.iconLibrary.timelineControl=i,l.inherits(t,n),e(\"../component\").define(\"timeline\",t),t}),i(\"zrender/shape/Image\",[\"require\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={type:\"image\",brush:function(e,t,i){var n=this.style||{};t&&(n=this.getHighlightStyle(n,this.highlightStyle||{}));var a=n.image,o=this;if(this._imageCache||(this._imageCache={}),\"string\"==typeof a){var r=a;this._imageCache[r]?a=this._imageCache[r]:(a=new Image,a.onload=function(){a.onload=null,o.modSelf(),i()},a.src=r,this._imageCache[r]=a)}if(a){if(\"IMG\"==a.nodeName.toUpperCase())if(window.ActiveXObject){if(\"complete\"!=a.readyState)return}else if(!a.complete)return;var s=n.width||a.width,l=n.height||a.height,h=n.x,m=n.y;if(!a.width||!a.height)return;if(e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.sWidth&&n.sHeight){var V=n.sx||0,U=n.sy||0;e.drawImage(a,V,U,n.sWidth,n.sHeight,h,m,s,l)}else if(n.sx&&n.sy){var V=n.sx,U=n.sy,d=s-V,p=l-U;e.drawImage(a,V,U,d,p,h,m,s,l)}else e.drawImage(a,h,m,s,l);n.width||(n.width=s),n.height||(n.height=l),this.style.width||(this.style.width=s),this.style.height||(this.style.height=l),this.drawText(e,n,this.style),e.restore()}},getRect:function(e){return{x:e.x,y:e.y,width:e.width,height:e.height}},clearCache:function(){this._imageCache={}}},e(\"../tool/util\").inherits(i,t),i}),i(\"zrender/loadingEffect/Bar\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/color\",\"../shape/Rectangle\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/color\"),o=e(\"../shape/Rectangle\");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:\"#888\"},backgroundColor:\"rgba(250, 250, 250, 0.8)\",effectOption:{x:0,y:this.canvasHeight/2-30,width:this.canvasWidth,height:5,brushType:\"fill\",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=new o({highlightStyle:n.clone(l)});return h.highlightStyle.color=l.color||a.getLinearGradient(l.x,l.y,l.x+l.width,l.y+l.height,[[0,\"#ff6400\"],[.5,\"#ffe100\"],[1,\"#b1ff00\"]]),null!=i.progress?(e(s),h.highlightStyle.width=this.adjust(i.progress,[0,1])*i.effectOption.width,e(h),e(r),void t()):(h.highlightStyle.width=0,setInterval(function(){e(s),h.highlightStyle.width<l.width?h.highlightStyle.width+=8:h.highlightStyle.width=0,e(h),e(r),t()},l.timeInterval))},t}),i(\"zrender/loadingEffect/Bubble\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/color\",\"../shape/Circle\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/color\"),o=e(\"../shape/Circle\");return n.inherits(t,i),t.prototype._start=function(e,t){for(var i=n.merge(this.options,{textStyle:{color:\"#888\"},backgroundColor:\"rgba(250, 250, 250, 0.8)\",effect:{n:50,lineWidth:2,brushType:\"stroke\",color:\"random\",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effect,h=l.n,m=l.brushType,V=l.lineWidth,U=[],d=this.canvasWidth,p=this.canvasHeight,c=0;h>c;c++){var u=\"random\"==l.color?a.alpha(a.random(),.3):l.color;U[c]=new o({highlightStyle:{x:Math.ceil(Math.random()*d),y:Math.ceil(Math.random()*p),r:Math.ceil(40*Math.random()),brushType:m,color:u,strokeColor:u,lineWidth:V},animationY:Math.ceil(20*Math.random())})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=U[i].highlightStyle;n.y-U[i].animationY+n.r<=0&&(U[i].highlightStyle.y=p+n.r,U[i].highlightStyle.x=Math.ceil(Math.random()*d)),U[i].highlightStyle.y-=U[i].animationY,e(U[i])}e(r),t()},l.timeInterval)},t}),i(\"zrender/loadingEffect/DynamicLine\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/color\",\"../shape/Line\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/color\"),o=e(\"../shape/Line\");return n.inherits(t,i),t.prototype._start=function(e,t){for(var i=n.merge(this.options,{textStyle:{color:\"#fff\"},backgroundColor:\"rgba(0, 0, 0, 0.8)\",effectOption:{n:30,lineWidth:1,color:\"random\",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=l.n,m=l.lineWidth,V=[],U=this.canvasWidth,d=this.canvasHeight,p=0;h>p;p++){var c=-Math.ceil(1e3*Math.random()),u=Math.ceil(400*Math.random()),y=Math.ceil(Math.random()*d),g=\"random\"==l.color?a.random():l.color;V[p]=new o({highlightStyle:{xStart:c,yStart:y,xEnd:c+u,yEnd:y,strokeColor:g,lineWidth:m},animationX:Math.ceil(100*Math.random()),len:u})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=V[i].highlightStyle;n.xStart>=U&&(V[i].len=Math.ceil(400*Math.random()),n.xStart=-400,n.xEnd=-400+V[i].len,n.yStart=Math.ceil(Math.random()*d),n.yEnd=n.yStart),n.xStart+=V[i].animationX,n.xEnd+=V[i].animationX,e(V[i])}e(r),t()},l.timeInterval)},t}),i(\"zrender/loadingEffect/Ring\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/color\",\"../shape/Ring\",\"../shape/Sector\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/color\"),o=e(\"../shape/Ring\"),r=e(\"../shape/Sector\");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:\"#07a\"},backgroundColor:\"rgba(250, 250, 250, 0.8)\",effect:{x:this.canvasWidth/2,y:this.canvasHeight/2,r0:60,r:100,color:\"#bbdcff\",brushType:\"fill\",textPosition:\"inside\",textFont:\"normal 30px verdana\",textColor:\"rgba(30, 144, 255, 0.6)\",timeInterval:100}}),s=i.effect,l=i.textStyle;\n\nnull==l.x&&(l.x=s.x),null==l.y&&(l.y=s.y+(s.r0+s.r)/2-5);for(var h=this.createTextShape(i.textStyle),m=this.createBackgroundShape(i.backgroundColor),V=s.x,U=s.y,d=s.r0+6,p=s.r-6,c=s.color,u=a.lift(c,.1),y=new o({highlightStyle:n.clone(s)}),g=[],b=a.getGradientColors([\"#ff6400\",\"#ffe100\",\"#97ff00\"],25),f=15,k=240,x=0;16>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:\"fill\",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x]],[1,b[2*x+1]]])})),k-=f;k=360;for(var x=0;4>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:\"fill\",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x+32]],[1,b[2*x+33]]])})),k-=f;var _=0;if(null!=i.progress){e(m),_=100*this.adjust(i.progress,[0,1]).toFixed(2)/5,y.highlightStyle.text=5*_+\"%\",e(y);for(var x=0;20>x;x++)g[x].highlightStyle.color=_>x?g[x]._color:u,e(g[x]);return e(h),void t()}return setInterval(function(){e(m),_+=_>=20?-20:1,e(y);for(var i=0;20>i;i++)g[i].highlightStyle.color=_>i?g[i]._color:u,e(g[i]);e(h),t()},s.timeInterval)},t}),i(\"zrender/loadingEffect/Spin\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/color\",\"../tool/area\",\"../shape/Sector\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/color\"),o=e(\"../tool/area\"),r=e(\"../shape/Sector\");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:\"#fff\",textAlign:\"start\"},backgroundColor:\"rgba(0, 0, 0, 0.8)\"}),s=this.createTextShape(i.textStyle),l=10,h=o.getTextWidth(s.highlightStyle.text,s.highlightStyle.textFont),m=o.getTextHeight(s.highlightStyle.text,s.highlightStyle.textFont),V=n.merge(this.options.effect||{},{r0:9,r:15,n:18,color:\"#fff\",timeInterval:100}),U=this.getLocation(this.options.textStyle,h+l+2*V.r,Math.max(2*V.r,m));V.x=U.x+V.r,V.y=s.highlightStyle.y=U.y+U.height/2,s.highlightStyle.x=V.x+V.r+l;for(var d=this.createBackgroundShape(i.backgroundColor),p=V.n,c=V.x,u=V.y,y=V.r0,g=V.r,b=V.color,f=[],k=Math.round(180/p),x=0;p>x;x++)f[x]=new r({highlightStyle:{x:c,y:u,r0:y,r:g,startAngle:k*x*2,endAngle:k*x*2+k,color:a.alpha(b,(x+1)/p),brushType:\"fill\"}});var _=[0,c,u];return setInterval(function(){e(d),_[0]-=.3;for(var i=0;p>i;i++)f[i].rotation=_,e(f[i]);e(s),t()},V.timeInterval)},t}),i(\"zrender/loadingEffect/Whirling\",[\"require\",\"./Base\",\"../tool/util\",\"../tool/area\",\"../shape/Ring\",\"../shape/Droplet\",\"../shape/Circle\"],function(e){function t(e){i.call(this,e)}var i=e(\"./Base\"),n=e(\"../tool/util\"),a=e(\"../tool/area\"),o=e(\"../shape/Ring\"),r=e(\"../shape/Droplet\"),s=e(\"../shape/Circle\");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:\"#888\",textAlign:\"start\"},backgroundColor:\"rgba(250, 250, 250, 0.8)\"}),l=this.createTextShape(i.textStyle),h=10,m=a.getTextWidth(l.highlightStyle.text,l.highlightStyle.textFont),V=a.getTextHeight(l.highlightStyle.text,l.highlightStyle.textFont),U=n.merge(this.options.effect||{},{r:18,colorIn:\"#fff\",colorOut:\"#555\",colorWhirl:\"#6cf\",timeInterval:50}),d=this.getLocation(this.options.textStyle,m+h+2*U.r,Math.max(2*U.r,V));U.x=d.x+U.r,U.y=l.highlightStyle.y=d.y+d.height/2,l.highlightStyle.x=U.x+U.r+h;var p=this.createBackgroundShape(i.backgroundColor),c=new r({highlightStyle:{a:Math.round(U.r/2),b:Math.round(U.r-U.r/6),brushType:\"fill\",color:U.colorWhirl}}),u=new s({highlightStyle:{r:Math.round(U.r/6),brushType:\"fill\",color:U.colorIn}}),y=new o({highlightStyle:{r0:Math.round(U.r-U.r/3),r:U.r,brushType:\"fill\",color:U.colorOut}}),g=[0,U.x,U.y];return c.highlightStyle.x=u.highlightStyle.x=y.highlightStyle.x=g[1],c.highlightStyle.y=u.highlightStyle.y=y.highlightStyle.y=g[2],setInterval(function(){e(p),e(y),g[0]-=.3,c.rotation=g,e(c),e(u),e(l),t()},U.timeInterval)},t}),i(\"echarts/theme/macarons\",[],function(){var e={color:[\"#2ec7c9\",\"#b6a2de\",\"#5ab1ef\",\"#ffb980\",\"#d87a80\",\"#8d98b3\",\"#e5cf0d\",\"#97b552\",\"#95706d\",\"#dc69aa\",\"#07a2a4\",\"#9a7fd1\",\"#588dd5\",\"#f5994e\",\"#c05050\",\"#59678c\",\"#c9ab00\",\"#7eb00a\",\"#6f5553\",\"#c14089\"],title:{textStyle:{fontWeight:\"normal\",color:\"#008acd\"}},dataRange:{itemWidth:15,color:[\"#5ab1ef\",\"#e0ffff\"]},toolbox:{color:[\"#1e90ff\",\"#1e90ff\",\"#1e90ff\",\"#1e90ff\"],effectiveColor:\"#ff4500\"},tooltip:{backgroundColor:\"rgba(50,50,50,0.5)\",axisPointer:{type:\"line\",lineStyle:{color:\"#008acd\"},crossStyle:{color:\"#008acd\"},shadowStyle:{color:\"rgba(200,200,200,0.2)\"}}},dataZoom:{dataBackgroundColor:\"#efefff\",fillerColor:\"rgba(182,162,222,0.2)\",handleColor:\"#008acd\"},grid:{borderColor:\"#eee\"},categoryAxis:{axisLine:{lineStyle:{color:\"#008acd\"}},splitLine:{lineStyle:{color:[\"#eee\"]}}},valueAxis:{axisLine:{lineStyle:{color:\"#008acd\"}},splitArea:{show:!0,areaStyle:{color:[\"rgba(250,250,250,0.1)\",\"rgba(200,200,200,0.1)\"]}},splitLine:{lineStyle:{color:[\"#eee\"]}}},polar:{axisLine:{lineStyle:{color:\"#ddd\"}},splitArea:{show:!0,areaStyle:{color:[\"rgba(250,250,250,0.2)\",\"rgba(200,200,200,0.2)\"]}},splitLine:{lineStyle:{color:\"#ddd\"}}},timeline:{lineStyle:{color:\"#008acd\"},controlStyle:{normal:{color:\"#008acd\"},emphasis:{color:\"#008acd\"}},symbol:\"emptyCircle\",symbolSize:3},bar:{itemStyle:{normal:{barBorderRadius:5},emphasis:{barBorderRadius:5}}},line:{smooth:!0,symbol:\"emptyCircle\",symbolSize:3},k:{itemStyle:{normal:{color:\"#d87a80\",color0:\"#2ec7c9\",lineStyle:{color:\"#d87a80\",color0:\"#2ec7c9\"}}}},scatter:{symbol:\"circle\",symbolSize:4},radar:{symbol:\"emptyCircle\",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:\"#ddd\"},label:{textStyle:{color:\"#d87a80\"}}},emphasis:{areaStyle:{color:\"#fe994e\"}}}},force:{itemStyle:{normal:{linkStyle:{color:\"#1e90ff\"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:\"rgba(128, 128, 128, 0.5)\",chordStyle:{lineStyle:{color:\"rgba(128, 128, 128, 0.5)\"}}},emphasis:{borderWidth:1,borderColor:\"rgba(128, 128, 128, 0.5)\",chordStyle:{lineStyle:{color:\"rgba(128, 128, 128, 0.5)\"}}}}},gauge:{axisLine:{lineStyle:{color:[[.2,\"#2ec7c9\"],[.8,\"#5ab1ef\"],[1,\"#d87a80\"]],width:10}},axisTick:{splitNumber:10,length:15,lineStyle:{color:\"auto\"}},splitLine:{length:22,lineStyle:{color:\"auto\"}},pointer:{width:5}},textStyle:{fontFamily:\"微软雅黑, Arial, Verdana, sans-serif\"}};return e}),i(\"echarts/theme/infographic\",[],function(){var e={color:[\"#C1232B\",\"#B5C334\",\"#FCCE10\",\"#E87C25\",\"#27727B\",\"#FE8463\",\"#9BCA63\",\"#FAD860\",\"#F3A43B\",\"#60C0DD\",\"#D7504B\",\"#C6E579\",\"#F4E001\",\"#F0805A\",\"#26C0C0\"],title:{textStyle:{fontWeight:\"normal\",color:\"#27727B\"}},dataRange:{x:\"right\",y:\"center\",itemWidth:5,itemHeight:25,color:[\"#C1232B\",\"#FCCE10\"]},toolbox:{color:[\"#C1232B\",\"#B5C334\",\"#FCCE10\",\"#E87C25\",\"#27727B\",\"#FE8463\",\"#9BCA63\",\"#FAD860\",\"#F3A43B\",\"#60C0DD\"],effectiveColor:\"#ff4500\"},tooltip:{backgroundColor:\"rgba(50,50,50,0.5)\",axisPointer:{type:\"line\",lineStyle:{color:\"#27727B\",type:\"dashed\"},crossStyle:{color:\"#27727B\"},shadowStyle:{color:\"rgba(200,200,200,0.3)\"}}},dataZoom:{dataBackgroundColor:\"rgba(181,195,52,0.3)\",fillerColor:\"rgba(181,195,52,0.2)\",handleColor:\"#27727B\"},grid:{borderWidth:0},categoryAxis:{axisLine:{lineStyle:{color:\"#27727B\"}},splitLine:{show:!1}},valueAxis:{axisLine:{show:!1},splitArea:{show:!1},splitLine:{lineStyle:{color:[\"#ccc\"],type:\"dashed\"}}},polar:{axisLine:{lineStyle:{color:\"#ddd\"}},splitArea:{show:!0,areaStyle:{color:[\"rgba(250,250,250,0.2)\",\"rgba(200,200,200,0.2)\"]}},splitLine:{lineStyle:{color:\"#ddd\"}}},timeline:{lineStyle:{color:\"#27727B\"},controlStyle:{normal:{color:\"#27727B\"},emphasis:{color:\"#27727B\"}},symbol:\"emptyCircle\",symbolSize:3},line:{itemStyle:{normal:{borderWidth:2,borderColor:\"#fff\",lineStyle:{width:3}},emphasis:{borderWidth:0}},symbol:\"circle\",symbolSize:3.5},k:{itemStyle:{normal:{color:\"#C1232B\",color0:\"#B5C334\",lineStyle:{width:1,color:\"#C1232B\",color0:\"#B5C334\"}}}},scatter:{itemStyle:{normal:{borderWidth:1,borderColor:\"rgba(200,200,200,0.5)\"},emphasis:{borderWidth:0}},symbol:\"star4\",symbolSize:4},radar:{symbol:\"emptyCircle\",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:\"#ddd\"},label:{textStyle:{color:\"#C1232B\"}}},emphasis:{areaStyle:{color:\"#fe994e\"},label:{textStyle:{color:\"rgb(100,0,0)\"}}}}},force:{itemStyle:{normal:{linkStyle:{color:\"#27727B\"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:\"rgba(128, 128, 128, 0.5)\",chordStyle:{lineStyle:{color:\"rgba(128, 128, 128, 0.5)\"}}},emphasis:{borderWidth:1,borderColor:\"rgba(128, 128, 128, 0.5)\",chordStyle:{lineStyle:{color:\"rgba(128, 128, 128, 0.5)\"}}}}},gauge:{center:[\"50%\",\"80%\"],radius:\"100%\",startAngle:180,endAngle:0,axisLine:{show:!0,lineStyle:{color:[[.2,\"#B5C334\"],[.8,\"#27727B\"],[1,\"#C1232B\"]],width:\"40%\"}},axisTick:{splitNumber:2,length:5,lineStyle:{color:\"#fff\"}},axisLabel:{textStyle:{color:\"#fff\",fontWeight:\"bolder\"}},splitLine:{length:\"5%\",lineStyle:{color:\"#fff\"}},pointer:{width:\"40%\",length:\"80%\",color:\"#fff\"},title:{offsetCenter:[0,-20],textStyle:{color:\"auto\",fontSize:20}},detail:{offsetCenter:[0,0],textStyle:{color:\"auto\",fontSize:40}}},textStyle:{fontFamily:\"微软雅黑, Arial, Verdana, sans-serif\"}};return e}),i(\"zrender/dep/excanvas\",[\"require\"],function(){return document.createElement(\"canvas\").getContext?G_vmlCanvasManager=!1:!function(){function e(){return this.context_||(this.context_=new f(this))}function t(e,t){var i=O.call(arguments,2);return function(){return e.apply(t,i.concat(O.call(arguments)))}}function i(e){return String(e).replace(/&/g,\"&amp;\").replace(/\"/g,\"&quot;\")}function n(e,t,i){e.namespaces[t]||e.namespaces.add(t,i,\"#default#VML\")}function a(e){if(n(e,\"g_vml_\",\"urn:schemas-microsoft-com:vml\"),n(e,\"g_o_\",\"urn:schemas-microsoft-com:office:office\"),!e.styleSheets.ex_canvas_){var t=e.createStyleSheet();t.owningElement.id=\"ex_canvas_\",t.cssText=\"canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}\"}}function o(e){var t=e.srcElement;switch(e.propertyName){case\"width\":t.getContext().clearRect(),t.style.width=t.attributes.width.nodeValue+\"px\",t.firstChild.style.width=t.clientWidth+\"px\";break;case\"height\":t.getContext().clearRect(),t.style.height=t.attributes.height.nodeValue+\"px\",t.firstChild.style.height=t.clientHeight+\"px\"}}function r(e){var t=e.srcElement;t.firstChild&&(t.firstChild.style.width=t.clientWidth+\"px\",t.firstChild.style.height=t.clientHeight+\"px\")}function s(){return[[1,0,0],[0,1,0],[0,0,1]]}function l(e,t){for(var i=s(),n=0;3>n;n++)for(var a=0;3>a;a++){for(var o=0,r=0;3>r;r++)o+=e[n][r]*t[r][a];i[n][a]=o}return i}function h(e,t){t.fillStyle=e.fillStyle,t.lineCap=e.lineCap,t.lineJoin=e.lineJoin,t.lineWidth=e.lineWidth,t.miterLimit=e.miterLimit,t.shadowBlur=e.shadowBlur,t.shadowColor=e.shadowColor,t.shadowOffsetX=e.shadowOffsetX,t.shadowOffsetY=e.shadowOffsetY,t.strokeStyle=e.strokeStyle,t.globalAlpha=e.globalAlpha,t.font=e.font,t.textAlign=e.textAlign,t.textBaseline=e.textBaseline,t.scaleX_=e.scaleX_,t.scaleY_=e.scaleY_,t.lineScale_=e.lineScale_}function m(e){var t=e.indexOf(\"(\",3),i=e.indexOf(\")\",t+1),n=e.substring(t+1,i).split(\",\");return(4!=n.length||\"a\"!=e.charAt(3))&&(n[3]=1),n}function V(e){return parseFloat(e)/100}function U(e,t,i){return Math.min(i,Math.max(t,e))}function d(e){var t,i,n,a,o,r;if(a=parseFloat(e[0])/360%360,0>a&&a++,o=U(V(e[1]),0,1),r=U(V(e[2]),0,1),0==o)t=i=n=r;else{var s=.5>r?r*(1+o):r+o-r*o,l=2*r-s;t=p(l,s,a+1/3),i=p(l,s,a),n=p(l,s,a-1/3)}return\"#\"+D[Math.floor(255*t)]+D[Math.floor(255*i)]+D[Math.floor(255*n)]}function p(e,t,i){return 0>i&&i++,i>1&&i--,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function c(e){if(e in R)return R[e];var t,i=1;if(e=String(e),\"#\"==e.charAt(0))t=e;else if(/^rgb/.test(e)){for(var n,a=m(e),t=\"#\",o=0;3>o;o++)n=-1!=a[o].indexOf(\"%\")?Math.floor(255*V(a[o])):+a[o],t+=D[U(n,0,255)];i=+a[3]}else if(/^hsl/.test(e)){var a=m(e);t=d(a),i=a[3]}else t=H[e]||e;return R[e]={color:t,alpha:i}}function u(e){if(Y[e])return Y[e];var t,i=document.createElement(\"div\"),n=i.style;try{n.font=e,t=n.fontFamily.split(\",\")[0]}catch(a){}return Y[e]={style:n.fontStyle||G.style,variant:n.fontVariant||G.variant,weight:n.fontWeight||G.weight,size:n.fontSize||G.size,family:t||G.family}}function y(e,t){var i={};for(var n in e)i[n]=e[n];var a=parseFloat(t.currentStyle.fontSize),o=parseFloat(e.size);return i.size=\"number\"==typeof e.size?e.size:-1!=e.size.indexOf(\"px\")?o:-1!=e.size.indexOf(\"em\")?a*o:-1!=e.size.indexOf(\"%\")?a/100*o:-1!=e.size.indexOf(\"pt\")?o/.75:a,i}function g(e){return e.style+\" \"+e.variant+\" \"+e.weight+\" \"+e.size+\"px '\"+e.family+\"'\"}function b(e){return Q[e]||\"square\"}function f(e){this.m_=s(),this.mStack_=[],this.aStack_=[],this.currentPath_=[],this.strokeStyle=\"#000\",this.fillStyle=\"#000\",this.lineWidth=1,this.lineJoin=\"miter\",this.lineCap=\"butt\",this.miterLimit=1*A,this.globalAlpha=1,this.font=\"12px 微软雅黑\",this.textAlign=\"left\",this.textBaseline=\"alphabetic\",this.canvas=e;var t=\"width:\"+e.clientWidth+\"px;height:\"+e.clientHeight+\"px;overflow:hidden;position:absolute\",i=e.ownerDocument.createElement(\"div\");i.style.cssText=t,e.appendChild(i);var n=i.cloneNode(!1);n.style.backgroundColor=\"#fff\",n.style.filter=\"alpha(opacity=0)\",e.appendChild(n),this.element_=i,this.scaleX_=1,this.scaleY_=1,this.lineScale_=1}function k(e,t,i,n){e.currentPath_.push({type:\"bezierCurveTo\",cp1x:t.x,cp1y:t.y,cp2x:i.x,cp2y:i.y,x:n.x,y:n.y}),e.currentX_=n.x,e.currentY_=n.y}function x(e,t){var i=c(e.strokeStyle),n=i.color,a=i.alpha*e.globalAlpha,o=e.lineScale_*e.lineWidth;1>o&&(a*=o),t.push(\"<g_vml_:stroke\",' opacity=\"',a,'\"',' joinstyle=\"',e.lineJoin,'\"',' miterlimit=\"',e.miterLimit,'\"',' endcap=\"',b(e.lineCap),'\"',' weight=\"',o,'px\"',' color=\"',n,'\" />')}function _(e,t,i,n){var a=e.fillStyle,o=e.scaleX_,r=e.scaleY_,s=n.x-i.x,l=n.y-i.y;if(a instanceof v){var h=0,m={x:0,y:0},V=0,U=1;if(\"gradient\"==a.type_){var d=a.x0_/o,p=a.y0_/r,u=a.x1_/o,y=a.y1_/r,g=L(e,d,p),b=L(e,u,y),f=b.x-g.x,k=b.y-g.y;h=180*Math.atan2(f,k)/Math.PI,0>h&&(h+=360),1e-6>h&&(h=0)}else{var g=L(e,a.x0_,a.y0_);m={x:(g.x-i.x)/s,y:(g.y-i.y)/l},s/=o*A,l/=r*A;var x=C.max(s,l);V=2*a.r0_/x,U=2*a.r1_/x-V}var _=a.colors_;_.sort(function(e,t){return e.offset-t.offset});for(var W=_.length,X=_[0].color,K=_[W-1].color,I=_[0].alpha*e.globalAlpha,J=_[W-1].alpha*e.globalAlpha,S=[],E=0;W>E;E++){var F=_[E];S.push(F.offset*U+V+\" \"+F.color)}t.push('<g_vml_:fill type=\"',a.type_,'\"',' method=\"none\" focus=\"100%\"',' color=\"',X,'\"',' color2=\"',K,'\"',' colors=\"',S.join(\",\"),'\"',' opacity=\"',J,'\"',' g_o_:opacity2=\"',I,'\"',' angle=\"',h,'\"',' focusposition=\"',m.x,\",\",m.y,'\" />')}else if(a instanceof w){if(s&&l){var T=-i.x,z=-i.y;t.push(\"<g_vml_:fill\",' position=\"',T/s*o*o,\",\",z/l*r*r,'\"',' type=\"tile\"',' src=\"',a.src_,'\" />')}}else{var M=c(e.fillStyle),O=M.color,P=M.alpha*e.globalAlpha;t.push('<g_vml_:fill color=\"',O,'\" opacity=\"',P,'\" />')}}function L(e,t,i){var n=e.m_;return{x:A*(t*n[0][0]+i*n[1][0]+n[2][0])-M,y:A*(t*n[0][1]+i*n[1][1]+n[2][1])-M}}function W(e){return isFinite(e[0][0])&&isFinite(e[0][1])&&isFinite(e[1][0])&&isFinite(e[1][1])&&isFinite(e[2][0])&&isFinite(e[2][1])}function X(e,t,i){if(W(t)&&(e.m_=t,e.scaleX_=Math.sqrt(t[0][0]*t[0][0]+t[0][1]*t[0][1]),e.scaleY_=Math.sqrt(t[1][0]*t[1][0]+t[1][1]*t[1][1]),i)){var n=t[0][0]*t[1][1]-t[0][1]*t[1][0];e.lineScale_=z(T(n))}}function v(e){this.type_=e,this.x0_=0,this.y0_=0,this.r0_=0,this.x1_=0,this.y1_=0,this.r1_=0,this.colors_=[]}function w(e,t){switch(I(e),t){case\"repeat\":case null:case\"\":this.repetition_=\"repeat\";break;case\"repeat-x\":case\"repeat-y\":case\"no-repeat\":this.repetition_=t;break;default:K(\"SYNTAX_ERR\")}this.src_=e.src,this.width_=e.width,this.height_=e.height}function K(e){throw new J(e)}function I(e){e&&1==e.nodeType&&\"IMG\"==e.tagName||K(\"TYPE_MISMATCH_ERR\"),\"complete\"!=e.readyState&&K(\"INVALID_STATE_ERR\")}function J(e){this.code=this[e],this.message=e+\": DOM Exception \"+this.code}var C=Math,S=C.round,E=C.sin,F=C.cos,T=C.abs,z=C.sqrt,A=10,M=A/2,O=(+navigator.userAgent.match(/MSIE ([\\d.]+)?/)[1],Array.prototype.slice);a(document);var P={init:function(e){var i=e||document;i.createElement(\"canvas\"),i.attachEvent(\"onreadystatechange\",t(this.init_,this,i))},init_:function(e){for(var t=e.getElementsByTagName(\"canvas\"),i=0;i<t.length;i++)this.initElement(t[i])},initElement:function(t){if(!t.getContext){t.getContext=e,a(t.ownerDocument),t.innerHTML=\"\",t.attachEvent(\"onpropertychange\",o),t.attachEvent(\"onresize\",r);var i=t.attributes;i.width&&i.width.specified?t.style.width=i.width.nodeValue+\"px\":t.width=t.clientWidth,i.height&&i.height.specified?t.style.height=i.height.nodeValue+\"px\":t.height=t.clientHeight}return t}};P.init();for(var D=[],N=0;16>N;N++)for(var B=0;16>B;B++)D[16*N+B]=N.toString(16)+B.toString(16);var H={aliceblue:\"#F0F8FF\",antiquewhite:\"#FAEBD7\",aquamarine:\"#7FFFD4\",azure:\"#F0FFFF\",beige:\"#F5F5DC\",bisque:\"#FFE4C4\",black:\"#000000\",blanchedalmond:\"#FFEBCD\",blueviolet:\"#8A2BE2\",brown:\"#A52A2A\",burlywood:\"#DEB887\",cadetblue:\"#5F9EA0\",chartreuse:\"#7FFF00\",chocolate:\"#D2691E\",coral:\"#FF7F50\",cornflowerblue:\"#6495ED\",cornsilk:\"#FFF8DC\",crimson:\"#DC143C\",cyan:\"#00FFFF\",darkblue:\"#00008B\",darkcyan:\"#008B8B\",darkgoldenrod:\"#B8860B\",darkgray:\"#A9A9A9\",darkgreen:\"#006400\",darkgrey:\"#A9A9A9\",darkkhaki:\"#BDB76B\",darkmagenta:\"#8B008B\",darkolivegreen:\"#556B2F\",darkorange:\"#FF8C00\",darkorchid:\"#9932CC\",darkred:\"#8B0000\",darksalmon:\"#E9967A\",darkseagreen:\"#8FBC8F\",darkslateblue:\"#483D8B\",darkslategray:\"#2F4F4F\",darkslategrey:\"#2F4F4F\",darkturquoise:\"#00CED1\",darkviolet:\"#9400D3\",deeppink:\"#FF1493\",deepskyblue:\"#00BFFF\",dimgray:\"#696969\",dimgrey:\"#696969\",dodgerblue:\"#1E90FF\",firebrick:\"#B22222\",floralwhite:\"#FFFAF0\",forestgreen:\"#228B22\",gainsboro:\"#DCDCDC\",ghostwhite:\"#F8F8FF\",gold:\"#FFD700\",goldenrod:\"#DAA520\",grey:\"#808080\",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\",lightgreen:\"#90EE90\",lightgrey:\"#D3D3D3\",lightpink:\"#FFB6C1\",lightsalmon:\"#FFA07A\",lightseagreen:\"#20B2AA\",lightskyblue:\"#87CEFA\",lightslategray:\"#778899\",lightslategrey:\"#778899\",lightsteelblue:\"#B0C4DE\",lightyellow:\"#FFFFE0\",limegreen:\"#32CD32\",linen:\"#FAF0E6\",magenta:\"#FF00FF\",mediumaquamarine:\"#66CDAA\",mediumblue:\"#0000CD\",mediumorchid:\"#BA55D3\",mediumpurple:\"#9370DB\",mediumseagreen:\"#3CB371\",mediumslateblue:\"#7B68EE\",mediumspringgreen:\"#00FA9A\",mediumturquoise:\"#48D1CC\",mediumvioletred:\"#C71585\",midnightblue:\"#191970\",mintcream:\"#F5FFFA\",mistyrose:\"#FFE4E1\",moccasin:\"#FFE4B5\",navajowhite:\"#FFDEAD\",oldlace:\"#FDF5E6\",olivedrab:\"#6B8E23\",orange:\"#FFA500\",orangered:\"#FF4500\",orchid:\"#DA70D6\",palegoldenrod:\"#EEE8AA\",palegreen:\"#98FB98\",paleturquoise:\"#AFEEEE\",palevioletred:\"#DB7093\",papayawhip:\"#FFEFD5\",peachpuff:\"#FFDAB9\",peru:\"#CD853F\",pink:\"#FFC0CB\",plum:\"#DDA0DD\",powderblue:\"#B0E0E6\",rosybrown:\"#BC8F8F\",royalblue:\"#4169E1\",saddlebrown:\"#8B4513\",salmon:\"#FA8072\",sandybrown:\"#F4A460\",seagreen:\"#2E8B57\",seashell:\"#FFF5EE\",sienna:\"#A0522D\",skyblue:\"#87CEEB\",slateblue:\"#6A5ACD\",slategray:\"#708090\",slategrey:\"#708090\",snow:\"#FFFAFA\",springgreen:\"#00FF7F\",steelblue:\"#4682B4\",tan:\"#D2B48C\",thistle:\"#D8BFD8\",tomato:\"#FF6347\",turquoise:\"#40E0D0\",violet:\"#EE82EE\",wheat:\"#F5DEB3\",whitesmoke:\"#F5F5F5\",yellowgreen:\"#9ACD32\"},R={},G={style:\"normal\",variant:\"normal\",weight:\"normal\",size:12,family:\"微软雅黑\"},Y={},Q={butt:\"flat\",round:\"round\"},Z=f.prototype;Z.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null),this.element_.innerHTML=\"\"},Z.beginPath=function(){this.currentPath_=[]},Z.moveTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:\"moveTo\",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.lineTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:\"lineTo\",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.bezierCurveTo=function(e,t,i,n,a,o){var r=L(this,a,o),s=L(this,e,t),l=L(this,i,n);k(this,s,l,r)},Z.quadraticCurveTo=function(e,t,i,n){var a=L(this,e,t),o=L(this,i,n),r={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)},s={x:r.x+(o.x-this.currentX_)/3,y:r.y+(o.y-this.currentY_)/3};k(this,r,s,o)},Z.arc=function(e,t,i,n,a,o){i*=A;var r=o?\"at\":\"wa\",s=e+F(n)*i-M,l=t+E(n)*i-M,h=e+F(a)*i-M,m=t+E(a)*i-M;s!=h||o||(s+=.125);var V=L(this,e,t),U=L(this,s,l),d=L(this,h,m);this.currentPath_.push({type:r,x:V.x,y:V.y,radius:i,xStart:U.x,yStart:U.y,xEnd:d.x,yEnd:d.y})},Z.rect=function(e,t,i,n){this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath()},Z.strokeRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.stroke(),this.currentPath_=a},Z.fillRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.fill(),this.currentPath_=a},Z.createLinearGradient=function(e,t,i,n){var a=new v(\"gradient\");return a.x0_=e,a.y0_=t,a.x1_=i,a.y1_=n,a},Z.createRadialGradient=function(e,t,i,n,a,o){var r=new v(\"gradientradial\");return r.x0_=e,r.y0_=t,r.r0_=i,r.x1_=n,r.y1_=a,r.r1_=o,r},Z.drawImage=function(e){var t,i,n,a,o,r,s,l,h=e.runtimeStyle.width,m=e.runtimeStyle.height;e.runtimeStyle.width=\"auto\",e.runtimeStyle.height=\"auto\";var V=e.width,U=e.height;if(e.runtimeStyle.width=h,e.runtimeStyle.height=m,3==arguments.length)t=arguments[1],i=arguments[2],o=r=0,s=n=V,l=a=U;else if(5==arguments.length)t=arguments[1],i=arguments[2],n=arguments[3],a=arguments[4],o=r=0,s=V,l=U;else{if(9!=arguments.length)throw Error(\"Invalid number of arguments\");o=arguments[1],r=arguments[2],s=arguments[3],l=arguments[4],t=arguments[5],i=arguments[6],n=arguments[7],a=arguments[8]}var d=L(this,t,i),p=[],c=10,u=10,y=b=1;if(p.push(\" <g_vml_:group\",' coordsize=\"',A*c,\",\",A*u,'\"',' coordorigin=\"0,0\"',' style=\"width:',c,\"px;height:\",u,\"px;position:absolute;\"),1!=this.m_[0][0]||this.m_[0][1]||1!=this.m_[1][1]||this.m_[1][0]){var g=[],y=this.scaleX_,b=this.scaleY_;g.push(\"M11=\",this.m_[0][0]/y,\",\",\"M12=\",this.m_[1][0]/b,\",\",\"M21=\",this.m_[0][1]/y,\",\",\"M22=\",this.m_[1][1]/b,\",\",\"Dx=\",S(d.x/A),\",\",\"Dy=\",S(d.y/A),\"\");var f=d,k=L(this,t+n,i),x=L(this,t,i+a),_=L(this,t+n,i+a);f.x=C.max(f.x,k.x,x.x,_.x),f.y=C.max(f.y,k.y,x.y,_.y),p.push(\"padding:0 \",S(f.x/A),\"px \",S(f.y/A),\"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(\",g.join(\"\"),\", SizingMethod='clip');\")}else p.push(\"top:\",S(d.y/A),\"px;left:\",S(d.x/A),\"px;\");p.push(' \">'),(o||r)&&p.push('<div style=\"overflow: hidden; width:',Math.ceil((n+o*n/s)*y),\"px;\",\" height:\",Math.ceil((a+r*a/l)*b),\"px;\",\" filter:progid:DxImageTransform.Microsoft.Matrix(Dx=\",-o*n/s*y,\",Dy=\",-r*a/l*b,');\">'),p.push('<div style=\"width:',Math.round(y*V*n/s),\"px;\",\" height:\",Math.round(b*U*a/l),\"px;\",\" filter:\"),this.globalAlpha<1&&p.push(\" progid:DXImageTransform.Microsoft.Alpha(opacity=\"+100*this.globalAlpha+\")\"),p.push(\" progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\",e.src,',sizingMethod=scale)\">'),(o||r)&&p.push(\"</div>\"),p.push(\"</div></div>\"),this.element_.insertAdjacentHTML(\"BeforeEnd\",p.join(\"\"))},Z.stroke=function(e){var t=[],i=10,n=10;t.push(\"<g_vml_:shape\",' filled=\"',!!e,'\"',' style=\"position:absolute;width:',i,\"px;height:\",n,'px;\"',' coordorigin=\"0,0\"',' coordsize=\"',A*i,\",\",A*n,'\"',' stroked=\"',!e,'\"',' path=\"');for(var a={x:null,y:null},o={x:null,y:null},r=0;r<this.currentPath_.length;r++){var s,l=this.currentPath_[r];switch(l.type){case\"moveTo\":s=l,t.push(\" m \",S(l.x),\",\",S(l.y));break;case\"lineTo\":t.push(\" l \",S(l.x),\",\",S(l.y));break;case\"close\":t.push(\" x \"),l=null;break;case\"bezierCurveTo\":t.push(\" c \",S(l.cp1x),\",\",S(l.cp1y),\",\",S(l.cp2x),\",\",S(l.cp2y),\",\",S(l.x),\",\",S(l.y));break;case\"at\":case\"wa\":t.push(\" \",l.type,\" \",S(l.x-this.scaleX_*l.radius),\",\",S(l.y-this.scaleY_*l.radius),\" \",S(l.x+this.scaleX_*l.radius),\",\",S(l.y+this.scaleY_*l.radius),\" \",S(l.xStart),\",\",S(l.yStart),\" \",S(l.xEnd),\",\",S(l.yEnd))}l&&((null==a.x||l.x<a.x)&&(a.x=l.x),(null==o.x||l.x>o.x)&&(o.x=l.x),(null==a.y||l.y<a.y)&&(a.y=l.y),(null==o.y||l.y>o.y)&&(o.y=l.y))}t.push(' \">'),e?_(this,t,a,o):x(this,t),t.push(\"</g_vml_:shape>\"),this.element_.insertAdjacentHTML(\"beforeEnd\",t.join(\"\"))},Z.fill=function(){this.stroke(!0)},Z.closePath=function(){this.currentPath_.push({type:\"close\"})},Z.save=function(){var e={};h(this,e),this.aStack_.push(e),this.mStack_.push(this.m_),this.m_=l(s(),this.m_)},Z.restore=function(){this.aStack_.length&&(h(this.aStack_.pop(),this),this.m_=this.mStack_.pop())},Z.translate=function(e,t){var i=[[1,0,0],[0,1,0],[e,t,1]];X(this,l(i,this.m_),!1)},Z.rotate=function(e){var t=F(e),i=E(e),n=[[t,i,0],[-i,t,0],[0,0,1]];X(this,l(n,this.m_),!1)},Z.scale=function(e,t){var i=[[e,0,0],[0,t,0],[0,0,1]];X(this,l(i,this.m_),!0)},Z.transform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,l(r,this.m_),!0)},Z.setTransform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,r,!0)},Z.drawText_=function(e,t,n,a,o){var r=this.m_,s=1e3,l=0,h=s,m={x:0,y:0},V=[],U=y(u(this.font),this.element_),d=g(U),p=this.element_.currentStyle,c=this.textAlign.toLowerCase();switch(c){case\"left\":case\"center\":case\"right\":break;case\"end\":c=\"ltr\"==p.direction?\"right\":\"left\";break;case\"start\":c=\"rtl\"==p.direction?\"right\":\"left\";break;default:c=\"left\"}switch(this.textBaseline){case\"hanging\":case\"top\":m.y=U.size/1.75;break;case\"middle\":break;default:case null:case\"alphabetic\":case\"ideographic\":case\"bottom\":m.y=-U.size/2.25}switch(c){case\"right\":l=s,h=.05;break;case\"center\":l=h=s/2}var b=L(this,t+m.x,n+m.y);V.push('<g_vml_:line from=\"',-l,' 0\" to=\"',h,' 0.05\" ',' coordsize=\"100 100\" coordorigin=\"0 0\"',' filled=\"',!o,'\" stroked=\"',!!o,'\" style=\"position:absolute;width:1px;height:1px;\">'),o?x(this,V):_(this,V,{x:-l,y:0},{x:h,y:U.size});var f=r[0][0].toFixed(3)+\",\"+r[1][0].toFixed(3)+\",\"+r[0][1].toFixed(3)+\",\"+r[1][1].toFixed(3)+\",0,0\",k=S(b.x/A)+\",\"+S(b.y/A);V.push('<g_vml_:skew on=\"t\" matrix=\"',f,'\" ',' offset=\"',k,'\" origin=\"',l,' 0\" />','<g_vml_:path textpathok=\"true\" />','<g_vml_:textpath on=\"true\" string=\"',i(e),'\" style=\"v-text-align:',c,\";font:\",i(d),'\" /></g_vml_:line>'),this.element_.insertAdjacentHTML(\"beforeEnd\",V.join(\"\"))},Z.fillText=function(e,t,i,n){this.drawText_(e,t,i,n,!1)},Z.strokeText=function(e,t,i,n){this.drawText_(e,t,i,n,!0)},Z.measureText=function(e){if(!this.textMeasureEl_){var t='<span style=\"position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;\"></span>';this.element_.insertAdjacentHTML(\"beforeEnd\",t),this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML=\"\";try{this.textMeasureEl_.style.font=this.font}catch(n){}return this.textMeasureEl_.appendChild(i.createTextNode(e)),{width:this.textMeasureEl_.offsetWidth}},Z.clip=function(){},Z.arcTo=function(){},Z.createPattern=function(e,t){return new w(e,t)},v.prototype.addColorStop=function(e,t){t=c(t),this.colors_.push({offset:e,color:t.color,alpha:t.alpha})};var q=J.prototype=new Error;q.INDEX_SIZE_ERR=1,q.DOMSTRING_SIZE_ERR=2,q.HIERARCHY_REQUEST_ERR=3,q.WRONG_DOCUMENT_ERR=4,q.INVALID_CHARACTER_ERR=5,q.NO_DATA_ALLOWED_ERR=6,q.NO_MODIFICATION_ALLOWED_ERR=7,q.NOT_FOUND_ERR=8,q.NOT_SUPPORTED_ERR=9,q.INUSE_ATTRIBUTE_ERR=10,q.INVALID_STATE_ERR=11,q.SYNTAX_ERR=12,q.INVALID_MODIFICATION_ERR=13,q.NAMESPACE_ERR=14,q.INVALID_ACCESS_ERR=15,q.VALIDATION_ERR=16,q.TYPE_MISMATCH_ERR=17,G_vmlCanvasManager=P,CanvasRenderingContext2D=f,CanvasGradient=v,CanvasPattern=w,DOMException=J}(),G_vmlCanvasManager}),i(\"zrender/mixin/Eventful\",[\"require\"],function(){var e=function(){this._handlers={}};return e.prototype.one=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!0,ctx:i||this}),this):this},e.prototype.bind=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!1,ctx:i||this}),this):this},e.prototype.unbind=function(e,t){var i=this._handlers;if(!e)return this._handlers={},this;if(t){if(i[e]){for(var n=[],a=0,o=i[e].length;o>a;a++)i[e][a].h!=t&&n.push(i[e][a]);i[e]=n}i[e]&&0===i[e].length&&delete i[e]}else delete i[e];return this},e.prototype.dispatch=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>3&&(t=Array.prototype.slice.call(t,1));for(var n=this._handlers[e],a=n.length,o=0;a>o;){switch(i){case 1:n[o].h.call(n[o].ctx);break;case 2:n[o].h.call(n[o].ctx,t[1]);break;case 3:n[o].h.call(n[o].ctx,t[1],t[2]);break;default:n[o].h.apply(n[o].ctx,t)}n[o].one?(n.splice(o,1),a--):o++}}return this},e.prototype.dispatchWithContext=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>4&&(t=Array.prototype.slice.call(t,1,t.length-1));for(var n=t[t.length-1],a=this._handlers[e],o=a.length,r=0;o>r;){switch(i){case 1:a[r].h.call(n);break;case 2:a[r].h.call(n,t[1]);break;case 3:a[r].h.call(n,t[1],t[2]);break;default:a[r].h.apply(n,t)}a[r].one?(a.splice(r,1),o--):r++}}return this},e}),i(\"zrender/tool/log\",[\"require\",\"../config\"],function(e){var t=e(\"../config\");return function(){if(0!==t.debugMode)if(1==t.debugMode)for(var e in arguments)throw new Error(arguments[e]);else if(t.debugMode>1)for(var e in arguments)console.log(arguments[e])}}),i(\"zrender/tool/guid\",[],function(){var e=2311;return function(){return\"zrender__\"+e++}}),i(\"zrender/Handler\",[\"require\",\"./config\",\"./tool/env\",\"./tool/event\",\"./tool/util\",\"./tool/vector\",\"./tool/matrix\",\"./mixin/Eventful\"],function(e){\"use strict\";function t(e,t){return function(i,n){return e.call(t,i,n)}}function i(e,t){return function(i,n,a){return e.call(t,i,n,a)}}function n(e){for(var i=d.length;i--;){var n=d[i];e[\"_\"+n+\"Handler\"]=t(c[n],e)}}function a(e,t,i){if(this._draggingTarget&&this._draggingTarget.id==e.id||e.isSilent())return!1;var n=this._event;if(e.isCover(t,i)){e.hoverable&&this.storage.addHover(e);for(var a=e.parent;a;){if(a.clipShape&&!a.clipShape.isCover(this._mouseX,this._mouseY))return!1;a=a.parent}return this._lastHover!=e&&(this._processOutShape(n),this._processDragLeave(n),this._lastHover=e,this._processDragEnter(n)),this._processOverShape(n),this._processDragOver(n),this._hasfound=1,!0}return!1}var o=e(\"./config\"),r=e(\"./tool/env\"),s=e(\"./tool/event\"),l=e(\"./tool/util\"),h=e(\"./tool/vector\"),m=e(\"./tool/matrix\"),V=o.EVENT,U=e(\"./mixin/Eventful\"),d=[\"resize\",\"click\",\"dblclick\",\"mousewheel\",\"mousemove\",\"mouseout\",\"mouseup\",\"mousedown\",\"touchstart\",\"touchend\",\"touchmove\"],p=function(e){if(window.G_vmlCanvasManager)return!0;e=e||window.event;var t=e.toElement||e.relatedTarget||e.srcElement||e.target;return t&&t.className.match(o.elementClassName)},c={resize:function(e){e=e||window.event,this._lastHover=null,this._isMouseDown=0,this.dispatch(V.RESIZE,e)},click:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.CLICK,e),this._mousemoveHandler(e)}},dblclick:function(e,t){if(p(e)||t){e=e||window.event,e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.DBLCLICK,e),this._mousemoveHandler(e)}},mousewheel:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.wheelDelta||-e.detail,n=i>0?1.1:1/1.1,a=!1,o=this._mouseX,r=this._mouseY;this.painter.eachBuildinLayer(function(t){var i=t.position;if(t.zoomable){t.__zoom=t.__zoom||1;var l=t.__zoom;l*=n,l=Math.max(Math.min(t.maxZoom,l),t.minZoom),n=l/t.__zoom,t.__zoom=l,i[0]-=(o-i[0])*(n-1),i[1]-=(r-i[1])*(n-1),t.scale[0]*=n,t.scale[1]*=n,t.dirty=!0,a=!0,s.stop(e)}}),a&&this.painter.refresh(),this._dispatchAgency(this._lastHover,V.MOUSEWHEEL,e),this._mousemoveHandler(e)}},mousemove:function(e,t){if((p(e)||t)&&!this.painter.isLoading()){e=this._zrenderEventFixed(e),this._lastX=this._mouseX,this._lastY=this._mouseY,this._mouseX=s.getX(e),this._mouseY=s.getY(e);var i=this._mouseX-this._lastX,n=this._mouseY-this._lastY;this._processDragStart(e),this._hasfound=0,this._event=e,this._iterateAndFindHover(),this._hasfound||((!this._draggingTarget||this._lastHover&&this._lastHover!=this._draggingTarget)&&(this._processOutShape(e),\nthis._processDragLeave(e)),this._lastHover=null,this.storage.delHover(),this.painter.clearHover());var a=\"default\";if(this._draggingTarget)this.storage.drift(this._draggingTarget.id,i,n),this._draggingTarget.modSelf(),this.storage.addHover(this._draggingTarget),this._clickThreshold++;else if(this._isMouseDown){var o=!1;this.painter.eachBuildinLayer(function(e){e.panable&&(a=\"move\",e.position[0]+=i,e.position[1]+=n,o=!0,e.dirty=!0)}),o&&this.painter.refresh()}this._draggingTarget||this._hasfound&&this._lastHover.draggable?a=\"move\":this._hasfound&&this._lastHover.clickable&&(a=\"pointer\"),this.root.style.cursor=a,this._dispatchAgency(this._lastHover,V.MOUSEMOVE,e),(this._draggingTarget||this._hasfound||this.storage.hasHoverShape())&&this.painter.refreshHover()}},mouseout:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.toElement||e.relatedTarget;if(i!=this.root)for(;i&&9!=i.nodeType;){if(i==this.root)return void this._mousemoveHandler(e);i=i.parentNode}e.zrenderX=this._lastX,e.zrenderY=this._lastY,this.root.style.cursor=\"default\",this._isMouseDown=0,this._processOutShape(e),this._processDrop(e),this._processDragEnd(e),this.painter.isLoading()||this.painter.refreshHover(),this.dispatch(V.GLOBALOUT,e)}},mousedown:function(e,t){if(p(e)||t){if(this._clickThreshold=0,2==this._lastDownButton)return this._lastDownButton=e.button,void(this._mouseDownTarget=null);this._lastMouseDownMoment=new Date,e=this._zrenderEventFixed(e),this._isMouseDown=1,this._mouseDownTarget=this._lastHover,this._dispatchAgency(this._lastHover,V.MOUSEDOWN,e),this._lastDownButton=e.button}},mouseup:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e),this.root.style.cursor=\"default\",this._isMouseDown=0,this._mouseDownTarget=null,this._dispatchAgency(this._lastHover,V.MOUSEUP,e),this._processDrop(e),this._processDragEnd(e))},touchstart:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._lastTouchMoment=new Date,this._mobileFindFixed(e),this._mousedownHandler(e))},touchmove:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._mousemoveHandler(e),this._isDragging&&s.stop(e))},touchend:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e,!0),this._mouseupHandler(e);var i=new Date;i-this._lastTouchMoment<V.touchClickDelay&&(this._mobileFindFixed(e),this._clickHandler(e),i-this._lastClickMoment<V.touchClickDelay/2&&(this._dblclickHandler(e),this._lastHover&&this._lastHover.clickable&&s.stop(e)),this._lastClickMoment=i),this.painter.clearHover()}}},u=function(e,t,o){U.call(this),this.root=e,this.storage=t,this.painter=o,this._lastX=this._lastY=this._mouseX=this._mouseY=0,this._findHover=i(a,this),this._domHover=o.getDomHover(),n(this),window.addEventListener?(window.addEventListener(\"resize\",this._resizeHandler),r.os.tablet||r.os.phone?(e.addEventListener(\"touchstart\",this._touchstartHandler),e.addEventListener(\"touchmove\",this._touchmoveHandler),e.addEventListener(\"touchend\",this._touchendHandler)):(e.addEventListener(\"click\",this._clickHandler),e.addEventListener(\"dblclick\",this._dblclickHandler),e.addEventListener(\"mousewheel\",this._mousewheelHandler),e.addEventListener(\"mousemove\",this._mousemoveHandler),e.addEventListener(\"mousedown\",this._mousedownHandler),e.addEventListener(\"mouseup\",this._mouseupHandler)),e.addEventListener(\"DOMMouseScroll\",this._mousewheelHandler),e.addEventListener(\"mouseout\",this._mouseoutHandler)):(window.attachEvent(\"onresize\",this._resizeHandler),e.attachEvent(\"onclick\",this._clickHandler),e.ondblclick=this._dblclickHandler,e.attachEvent(\"onmousewheel\",this._mousewheelHandler),e.attachEvent(\"onmousemove\",this._mousemoveHandler),e.attachEvent(\"onmouseout\",this._mouseoutHandler),e.attachEvent(\"onmousedown\",this._mousedownHandler),e.attachEvent(\"onmouseup\",this._mouseupHandler))};u.prototype.on=function(e,t,i){return this.bind(e,t,i),this},u.prototype.un=function(e,t){return this.unbind(e,t),this},u.prototype.trigger=function(e,t){switch(e){case V.RESIZE:case V.CLICK:case V.DBLCLICK:case V.MOUSEWHEEL:case V.MOUSEMOVE:case V.MOUSEDOWN:case V.MOUSEUP:case V.MOUSEOUT:this[\"_\"+e+\"Handler\"](t,!0)}},u.prototype.dispose=function(){var e=this.root;window.removeEventListener?(window.removeEventListener(\"resize\",this._resizeHandler),r.os.tablet||r.os.phone?(e.removeEventListener(\"touchstart\",this._touchstartHandler),e.removeEventListener(\"touchmove\",this._touchmoveHandler),e.removeEventListener(\"touchend\",this._touchendHandler)):(e.removeEventListener(\"click\",this._clickHandler),e.removeEventListener(\"dblclick\",this._dblclickHandler),e.removeEventListener(\"mousewheel\",this._mousewheelHandler),e.removeEventListener(\"mousemove\",this._mousemoveHandler),e.removeEventListener(\"mousedown\",this._mousedownHandler),e.removeEventListener(\"mouseup\",this._mouseupHandler)),e.removeEventListener(\"DOMMouseScroll\",this._mousewheelHandler),e.removeEventListener(\"mouseout\",this._mouseoutHandler)):(window.detachEvent(\"onresize\",this._resizeHandler),e.detachEvent(\"onclick\",this._clickHandler),e.detachEvent(\"dblclick\",this._dblclickHandler),e.detachEvent(\"onmousewheel\",this._mousewheelHandler),e.detachEvent(\"onmousemove\",this._mousemoveHandler),e.detachEvent(\"onmouseout\",this._mouseoutHandler),e.detachEvent(\"onmousedown\",this._mousedownHandler),e.detachEvent(\"onmouseup\",this._mouseupHandler)),this.root=this._domHover=this.storage=this.painter=null,this.un()},u.prototype._processDragStart=function(e){var t=this._lastHover;if(this._isMouseDown&&t&&t.draggable&&!this._draggingTarget&&this._mouseDownTarget==t){if(t.dragEnableTime&&new Date-this._lastMouseDownMoment<t.dragEnableTime)return;var i=t;this._draggingTarget=i,this._isDragging=1,i.invisible=!0,this.storage.mod(i.id),this._dispatchAgency(i,V.DRAGSTART,e),this.painter.refresh()}},u.prototype._processDragEnter=function(e){this._draggingTarget&&this._dispatchAgency(this._lastHover,V.DRAGENTER,e,this._draggingTarget)},u.prototype._processDragOver=function(e){this._draggingTarget&&this._dispatchAgency(this._lastHover,V.DRAGOVER,e,this._draggingTarget)},u.prototype._processDragLeave=function(e){this._draggingTarget&&this._dispatchAgency(this._lastHover,V.DRAGLEAVE,e,this._draggingTarget)},u.prototype._processDrop=function(e){this._draggingTarget&&(this._draggingTarget.invisible=!1,this.storage.mod(this._draggingTarget.id),this.painter.refresh(),this._dispatchAgency(this._lastHover,V.DROP,e,this._draggingTarget))},u.prototype._processDragEnd=function(e){this._draggingTarget&&(this._dispatchAgency(this._draggingTarget,V.DRAGEND,e),this._lastHover=null),this._isDragging=0,this._draggingTarget=null},u.prototype._processOverShape=function(e){this._dispatchAgency(this._lastHover,V.MOUSEOVER,e)},u.prototype._processOutShape=function(e){this._dispatchAgency(this._lastHover,V.MOUSEOUT,e)},u.prototype._dispatchAgency=function(e,t,i,n){var a=\"on\"+t,o={type:t,event:i,target:e,cancelBubble:!1},r=e;for(n&&(o.dragged=n);r&&(r[a]&&(o.cancelBubble=r[a](o)),r.dispatch(t,o),r=r.parent,!o.cancelBubble););if(e)o.cancelBubble||this.dispatch(t,o);else if(!n){var s={type:t,event:i};this.dispatch(t,s),this.painter.eachOtherLayer(function(e){\"function\"==typeof e[a]&&e[a](s),e.dispatch&&e.dispatch(t,s)})}},u.prototype._iterateAndFindHover=function(){var e=m.create();return function(){for(var t,i,n=this.storage.getShapeList(),a=[0,0],o=n.length-1;o>=0;o--){var r=n[o];if(t!==r.zlevel&&(i=this.painter.getLayer(r.zlevel,i),a[0]=this._mouseX,a[1]=this._mouseY,i.needTransform&&(m.invert(e,i.transform),h.applyTransform(a,a,e))),this._findHover(r,a[0],a[1]))break}}}();var y=[{x:10},{x:-20},{x:10,y:10},{y:-20}];return u.prototype._mobileFindFixed=function(e){this._lastHover=null,this._mouseX=e.zrenderX,this._mouseY=e.zrenderY,this._event=e,this._iterateAndFindHover();for(var t=0;!this._lastHover&&t<y.length;t++){var i=y[t];i.x&&(this._mouseX+=i.x),i.y&&(this._mouseY+=i.y),this._iterateAndFindHover()}this._lastHover&&(e.zrenderX=this._mouseX,e.zrenderY=this._mouseY)},u.prototype._zrenderEventFixed=function(e,t){if(e.zrenderFixed)return e;if(t){var i=\"touchend\"!=e.type?e.targetTouches[0]:e.changedTouches[0];if(i){var n=this.painter._domRoot.getBoundingClientRect();e.zrenderX=i.clientX-n.left,e.zrenderY=i.clientY-n.top}}else{e=e||window.event;var a=e.toElement||e.relatedTarget||e.srcElement||e.target;a&&a!=this._domHover&&(e.zrenderX=(\"undefined\"!=typeof e.offsetX?e.offsetX:e.layerX)+a.offsetLeft,e.zrenderY=(\"undefined\"!=typeof e.offsetY?e.offsetY:e.layerY)+a.offsetTop)}return e.zrenderFixed=1,e},l.merge(u.prototype,U.prototype,!0),u}),i(\"zrender/Painter\",[\"require\",\"./config\",\"./tool/util\",\"./tool/log\",\"./loadingEffect/Base\",\"./Layer\",\"./shape/Image\"],function(e){\"use strict\";function t(){return!1}function i(){}function n(e){return e?e.isBuildin?!0:\"function\"!=typeof e.resize||\"function\"!=typeof e.refresh?!1:!0:!1}var a=e(\"./config\"),o=e(\"./tool/util\"),r=e(\"./tool/log\"),s=e(\"./loadingEffect/Base\"),l=e(\"./Layer\"),h=function(e,i){this.root=e,e.style[\"-webkit-tap-highlight-color\"]=\"transparent\",e.style[\"-webkit-user-select\"]=\"none\",e.style[\"user-select\"]=\"none\",e.style[\"-webkit-touch-callout\"]=\"none\",this.storage=i,e.innerHTML=\"\",this._width=this._getWidth(),this._height=this._getHeight();var n=document.createElement(\"div\");this._domRoot=n,n.style.position=\"relative\",n.style.overflow=\"hidden\",n.style.width=this._width+\"px\",n.style.height=this._height+\"px\",e.appendChild(n),this._layers={},this._zlevelList=[],this._layerConfig={},this._loadingEffect=new s({}),this.shapeToImage=this._createShapeToImageProcessor(),this._bgDom=document.createElement(\"div\"),this._bgDom.style.cssText=[\"position:absolute;left:0px;top:0px;width:\",this._width,\"px;height:\",this._height+\"px;\",\"-webkit-user-select:none;user-select;none;\",\"-webkit-touch-callout:none;\"].join(\"\"),this._bgDom.setAttribute(\"data-zr-dom-id\",\"bg\"),this._bgDom.className=a.elementClassName,n.appendChild(this._bgDom),this._bgDom.onselectstart=t;var o=new l(\"_zrender_hover_\",this);this._layers.hover=o,n.appendChild(o.dom),o.initContext(),o.dom.onselectstart=t,o.dom.style[\"-webkit-user-select\"]=\"none\",o.dom.style[\"user-select\"]=\"none\",o.dom.style[\"-webkit-touch-callout\"]=\"none\",this.refreshNextFrame=null};return h.prototype.render=function(e){return this.isLoading()&&this.hideLoading(),this.refresh(e,!0),this},h.prototype.refresh=function(e,t){var i=this.storage.getShapeList(!0);this._paintList(i,t);for(var n=0;n<this._zlevelList.length;n++){var a=this._zlevelList[n],o=this._layers[a];!o.isBuildin&&o.refresh&&o.refresh()}return\"function\"==typeof e&&e(),this},h.prototype._preProcessLayer=function(e){e.unusedCount++,e.updateTransform()},h.prototype._postProcessLayer=function(e){e.dirty=!1,1==e.unusedCount&&e.clear()},h.prototype._paintList=function(e,t){\"undefined\"==typeof t&&(t=!1),this._updateLayerStatus(e);var i,n,o;this.eachBuildinLayer(this._preProcessLayer);for(var s=0,l=e.length;l>s;s++){var h=e[s];if(n!==h.zlevel&&(i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),n=h.zlevel,i=this.getLayer(n),i.isBuildin||r(\"ZLevel \"+n+\" has been used by unkown layer \"+i.id),o=i.ctx,i.unusedCount=0,(i.dirty||t)&&i.clear(),i.needTransform&&(o.save(),i.setTransform(o))),(i.dirty||t)&&!h.invisible&&(!h.onbrush||h.onbrush&&!h.onbrush(o,!1)))if(a.catchBrushException)try{h.brush(o,!1,this.refreshNextFrame)}catch(m){r(m,\"brush error of \"+h.type,h)}else h.brush(o,!1,this.refreshNextFrame);h.__dirty=!1}i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),this.eachBuildinLayer(this._postProcessLayer)},h.prototype.getLayer=function(e){var t=this._layers[e];return t||(t=new l(e,this),t.isBuildin=!0,this._layerConfig[e]&&o.merge(t,this._layerConfig[e],!0),t.updateTransform(),this.insertLayer(e,t),t.initContext()),t},h.prototype.insertLayer=function(e,t){if(this._layers[e])return void r(\"ZLevel \"+e+\" has been used already\");if(!n(t))return void r(\"Layer of zlevel \"+e+\" is not valid\");var i=this._zlevelList.length,a=null,o=-1;if(i>0&&e>this._zlevelList[0]){for(o=0;i-1>o&&!(this._zlevelList[o]<e&&this._zlevelList[o+1]>e);o++);a=this._layers[this._zlevelList[o]]}this._zlevelList.splice(o+1,0,e);var s=a?a.dom:this._bgDom;s.nextSibling?s.parentNode.insertBefore(t.dom,s.nextSibling):s.parentNode.appendChild(t.dom),this._layers[e]=t},h.prototype.eachLayer=function(e,t){for(var i=0;i<this._zlevelList.length;i++){var n=this._zlevelList[i];e.call(t,this._layers[n],n)}},h.prototype.eachBuildinLayer=function(e,t){for(var i=0;i<this._zlevelList.length;i++){var n=this._zlevelList[i],a=this._layers[n];a.isBuildin&&e.call(t,a,n)}},h.prototype.eachOtherLayer=function(e,t){for(var i=0;i<this._zlevelList.length;i++){var n=this._zlevelList[i],a=this._layers[n];a.isBuildin||e.call(t,a,n)}},h.prototype.getLayers=function(){return this._layers},h.prototype._updateLayerStatus=function(e){var t=this._layers,i={};this.eachBuildinLayer(function(e,t){i[t]=e.elCount,e.elCount=0});for(var n=0,a=e.length;a>n;n++){var o=e[n],r=o.zlevel,s=t[r];if(s){if(s.elCount++,s.dirty)continue;s.dirty=o.__dirty}}this.eachBuildinLayer(function(e,t){i[t]!==e.elCount&&(e.dirty=!0)})},h.prototype.refreshShapes=function(e,t){for(var i=0,n=e.length;n>i;i++){var a=e[i];a.modSelf()}return this.refresh(t),this},h.prototype.setLoadingEffect=function(e){return this._loadingEffect=e,this},h.prototype.clear=function(){return this.eachBuildinLayer(this._clearLayer),this},h.prototype._clearLayer=function(e){e.clear()},h.prototype.modLayer=function(e,t){if(t){this._layerConfig[e]?o.merge(this._layerConfig[e],t,!0):this._layerConfig[e]=t;var i=this._layers[e];i&&o.merge(i,this._layerConfig[e],!0)}},h.prototype.delLayer=function(e){var t=this._layers[e];t&&(this.modLayer(e,{position:t.position,rotation:t.rotation,scale:t.scale}),t.dom.parentNode.removeChild(t.dom),delete this._layers[e],this._zlevelList.splice(o.indexOf(this._zlevelList,e),1))},h.prototype.refreshHover=function(){this.clearHover();for(var e=this.storage.getHoverShapes(!0),t=0,i=e.length;i>t;t++)this._brushHover(e[t]);var n=this._layers.hover.ctx;return n.flush&&n.flush(),this.storage.delHover(),this},h.prototype.clearHover=function(){var e=this._layers.hover;return e&&e.clear(),this},h.prototype.showLoading=function(e){return this._loadingEffect&&this._loadingEffect.stop(),e&&this.setLoadingEffect(e),this._loadingEffect.start(this),this.loading=!0,this},h.prototype.hideLoading=function(){return this._loadingEffect.stop(),this.clearHover(),this.loading=!1,this},h.prototype.isLoading=function(){return this.loading},h.prototype.resize=function(){var e=this._domRoot;e.style.display=\"none\";var t=this._getWidth(),i=this._getHeight();if(e.style.display=\"\",this._width!=t||i!=this._height){this._width=t,this._height=i,e.style.width=t+\"px\",e.style.height=i+\"px\";for(var n in this._layers)this._layers[n].resize(t,i);this.refresh(null,!0)}return this},h.prototype.clearLayer=function(e){var t=this._layers[e];t&&t.clear()},h.prototype.dispose=function(){this.isLoading()&&this.hideLoading(),this.root.innerHTML=\"\",this.root=this.storage=this._domRoot=this._layers=null},h.prototype.getDomHover=function(){return this._layers.hover.dom},h.prototype.toDataURL=function(e,t,i){if(window.G_vmlCanvasManager)return null;var n=new l(\"image\",this);this._bgDom.appendChild(n.dom),n.initContext();var o=n.ctx;n.clearColor=t||\"#fff\",n.clear();var s=this;this.storage.iterShape(function(e){if(!e.invisible&&(!e.onbrush||e.onbrush&&!e.onbrush(o,!1)))if(a.catchBrushException)try{e.brush(o,!1,s.refreshNextFrame)}catch(t){r(t,\"brush error of \"+e.type,e)}else e.brush(o,!1,s.refreshNextFrame)},{normal:\"up\",update:!0});var h=n.dom.toDataURL(e,i);return o=null,this._bgDom.removeChild(n.dom),h},h.prototype.getWidth=function(){return this._width},h.prototype.getHeight=function(){return this._height},h.prototype._getWidth=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientWidth||parseInt(t.width,10))-parseInt(t.paddingLeft,10)-parseInt(t.paddingRight,10)).toFixed(0)-0},h.prototype._getHeight=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientHeight||parseInt(t.height,10))-parseInt(t.paddingTop,10)-parseInt(t.paddingBottom,10)).toFixed(0)-0},h.prototype._brushHover=function(e){var t=this._layers.hover.ctx;if(!e.onbrush||e.onbrush&&!e.onbrush(t,!0)){var i=this.getLayer(e.zlevel);if(i.needTransform&&(t.save(),i.setTransform(t)),a.catchBrushException)try{e.brush(t,!0,this.refreshNextFrame)}catch(n){r(n,\"hoverBrush error of \"+e.type,e)}else e.brush(t,!0,this.refreshNextFrame);i.needTransform&&t.restore()}},h.prototype._shapeToImage=function(t,i,n,a,o){var r=document.createElement(\"canvas\"),s=r.getContext(\"2d\");r.style.width=n+\"px\",r.style.height=a+\"px\",r.setAttribute(\"width\",n*o),r.setAttribute(\"height\",a*o),s.clearRect(0,0,n*o,a*o);var l={position:i.position,rotation:i.rotation,scale:i.scale};i.position=[0,0,0],i.rotation=0,i.scale=[1,1],i&&i.brush(s,!1);var h=e(\"./shape/Image\"),m=new h({id:t,style:{x:0,y:0,image:r}});return null!=l.position&&(m.position=i.position=l.position),null!=l.rotation&&(m.rotation=i.rotation=l.rotation),null!=l.scale&&(m.scale=i.scale=l.scale),m},h.prototype._createShapeToImageProcessor=function(){if(window.G_vmlCanvasManager)return i;var e=this;return function(t,i,n,o){return e._shapeToImage(t,i,n,o,a.devicePixelRatio)}},h}),i(\"zrender/Storage\",[\"require\",\"./tool/util\",\"./Group\"],function(e){\"use strict\";function t(e,t){return e.zlevel==t.zlevel?e.z==t.z?e.__renderidx-t.__renderidx:e.z-t.z:e.zlevel-t.zlevel}var i=e(\"./tool/util\"),n=e(\"./Group\"),a={hover:!1,normal:\"down\",update:!1},o=function(){this._elements={},this._hoverElements=[],this._roots=[],this._shapeList=[],this._shapeListOffset=0};return o.prototype.iterShape=function(e,t){if(t||(t=a),t.hover)for(var i=0,n=this._hoverElements.length;n>i;i++){var o=this._hoverElements[i];if(o.updateTransform(),e(o))return this}switch(t.update&&this.updateShapeList(),t.normal){case\"down\":for(var n=this._shapeList.length;n--;)if(e(this._shapeList[n]))return this;break;default:for(var i=0,n=this._shapeList.length;n>i;i++)if(e(this._shapeList[i]))return this}return this},o.prototype.getHoverShapes=function(e){for(var i=[],n=0,a=this._hoverElements.length;a>n;n++){i.push(this._hoverElements[n]);var o=this._hoverElements[n].hoverConnect;if(o){var r;o=o instanceof Array?o:[o];for(var s=0,l=o.length;l>s;s++)r=o[s].id?o[s]:this.get(o[s]),r&&i.push(r)}}if(i.sort(t),e)for(var n=0,a=i.length;a>n;n++)i[n].updateTransform();return i},o.prototype.getShapeList=function(e){return e&&this.updateShapeList(),this._shapeList},o.prototype.updateShapeList=function(){this._shapeListOffset=0;for(var e=0,i=this._roots.length;i>e;e++){var n=this._roots[e];this._updateAndAddShape(n)}this._shapeList.length=this._shapeListOffset;for(var e=0,i=this._shapeList.length;i>e;e++)this._shapeList[e].__renderidx=e;this._shapeList.sort(t)},o.prototype._updateAndAddShape=function(e,t){if(!e.ignore)if(e.updateTransform(),e.clipShape&&(e.clipShape.parent=e,e.clipShape.updateTransform(),t?(t=t.slice(),t.push(e.clipShape)):t=[e.clipShape]),\"group\"==e.type){for(var i=0;i<e._children.length;i++){var n=e._children[i];n.__dirty=e.__dirty||n.__dirty,this._updateAndAddShape(n,t)}e.__dirty=!1}else e.__clipShapes=t,this._shapeList[this._shapeListOffset++]=e},o.prototype.mod=function(e,t){if(\"string\"==typeof e&&(e=this._elements[e]),e&&(e.modSelf(),t))if(t.parent||t._storage||t.__clipShapes){var n={};for(var a in t)\"parent\"!==a&&\"_storage\"!==a&&\"__clipShapes\"!==a&&t.hasOwnProperty(a)&&(n[a]=t[a]);i.merge(e,n,!0)}else i.merge(e,t,!0);return this},o.prototype.drift=function(e,t,i){var n=this._elements[e];return n&&(n.needTransform=!0,\"horizontal\"===n.draggable?i=0:\"vertical\"===n.draggable&&(t=0),(!n.ondrift||n.ondrift&&!n.ondrift(t,i))&&n.drift(t,i)),this},o.prototype.addHover=function(e){return e.updateNeedTransform(),this._hoverElements.push(e),this},o.prototype.delHover=function(){return this._hoverElements=[],this},o.prototype.hasHoverShape=function(){return this._hoverElements.length>0},o.prototype.addRoot=function(e){this._elements[e.id]||(e instanceof n&&e.addChildrenToStorage(this),this.addToMap(e),this._roots.push(e))},o.prototype.delRoot=function(e){if(\"undefined\"==typeof e){for(var t=0;t<this._roots.length;t++){var a=this._roots[t];a instanceof n&&a.delChildrenFromStorage(this)}return this._elements={},this._hoverElements=[],this._roots=[],this._shapeList=[],void(this._shapeListOffset=0)}if(e instanceof Array)for(var t=0,o=e.length;o>t;t++)this.delRoot(e[t]);else{var r;r=\"string\"==typeof e?this._elements[e]:e;var s=i.indexOf(this._roots,r);s>=0&&(this.delFromMap(r.id),this._roots.splice(s,1),r instanceof n&&r.delChildrenFromStorage(this))}},o.prototype.addToMap=function(e){return e instanceof n&&(e._storage=this),e.modSelf(),this._elements[e.id]=e,this},o.prototype.get=function(e){return this._elements[e]},o.prototype.delFromMap=function(e){var t=this._elements[e];return t&&(delete this._elements[e],t instanceof n&&(t._storage=null)),this},o.prototype.dispose=function(){this._elements=this._renderList=this._roots=this._hoverElements=null},o}),i(\"zrender/animation/Animation\",[\"require\",\"./Clip\",\"../tool/color\",\"../tool/util\",\"../tool/event\"],function(e){\"use strict\";function t(e,t){return e[t]}function i(e,t,i){e[t]=i}function n(e,t,i){return(t-e)*i+e}function a(e,t,i,a,o){var r=e.length;if(1==o)for(var s=0;r>s;s++)a[s]=n(e[s],t[s],i);else for(var l=e[0].length,s=0;r>s;s++)for(var h=0;l>h;h++)a[s][h]=n(e[s][h],t[s][h],i)}function o(e){switch(typeof e){case\"undefined\":case\"string\":return!1}return\"undefined\"!=typeof e.length}function r(e,t,i,n,a,o,r,l,h){var m=e.length;if(1==h)for(var V=0;m>V;V++)l[V]=s(e[V],t[V],i[V],n[V],a,o,r);else for(var U=e[0].length,V=0;m>V;V++)for(var d=0;U>d;d++)l[V][d]=s(e[V][d],t[V][d],i[V][d],n[V][d],a,o,r)}function s(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}function l(e){if(o(e)){var t=e.length;if(o(e[0])){for(var i=[],n=0;t>n;n++)i.push(c.call(e[n]));return i}return c.call(e)}return e}function h(e){return e[0]=Math.floor(e[0]),e[1]=Math.floor(e[1]),e[2]=Math.floor(e[2]),\"rgba(\"+e.join(\",\")+\")\"}var m=e(\"./Clip\"),V=e(\"../tool/color\"),U=e(\"../tool/util\"),d=e(\"../tool/event\").Dispatcher,p=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},c=Array.prototype.slice,u=function(e){e=e||{},this.stage=e.stage||{},this.onframe=e.onframe||function(){},this._clips=[],this._running=!1,this._time=0,d.call(this)};u.prototype={add:function(e){this._clips.push(e)},remove:function(e){if(e.__inStep)e.__needsRemove=!0;else{var t=U.indexOf(this._clips,e);t>=0&&this._clips.splice(t,1)}},_update:function(){for(var e=(new Date).getTime(),t=e-this._time,i=this._clips,n=i.length,a=[],o=[],r=0;n>r;r++){var s=i[r];s.__inStep=!0;var l=s.step(e);s.__inStep=!1,l&&(a.push(l),o.push(s))}for(var r=0;n>r;)i[r].__needsRemove?(i[r]=i[n-1],i.pop(),n--):r++;n=a.length;for(var r=0;n>r;r++)o[r].fire(a[r]);this._time=e,this.onframe(t),this.dispatch(\"frame\",t),this.stage.update&&this.stage.update()},start:function(){function e(){t._running&&(p(e),t._update())}var t=this;this._running=!0,this._time=(new Date).getTime(),p(e)},stop:function(){this._running=!1},clear:function(){this._clips=[]},animate:function(e,t){t=t||{};var i=new y(e,t.loop,t.getter,t.setter);return i.animation=this,i},constructor:u},U.merge(u.prototype,d.prototype,!0);var y=function(e,n,a,o){this._tracks={},this._target=e,this._loop=n||!1,this._getter=a||t,this._setter=o||i,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};return y.prototype={when:function(e,t){for(var i in t)this._tracks[i]||(this._tracks[i]=[],0!==e&&this._tracks[i].push({time:0,value:l(this._getter(this._target,i))})),this._tracks[i].push({time:parseInt(e,10),value:t[i]});return this},during:function(e){return this._onframeList.push(e),this},start:function(e){var t=this,i=this._setter,l=this._getter,U=\"spline\"===e,d=function(){if(t._clipCount--,0===t._clipCount){t._tracks={};for(var e=t._doneList.length,i=0;e>i;i++)t._doneList[i].call(t)}},p=function(p,c){var u=p.length;if(u){var y=p[0].value,g=o(y),b=!1,f=g&&o(y[0])?2:1;p.sort(function(e,t){return e.time-t.time});var k;if(u){k=p[u-1].time;for(var x=[],_=[],L=0;u>L;L++){x.push(p[L].time/k);var W=p[L].value;\"string\"==typeof W&&(W=V.toArray(W),0===W.length&&(W[0]=W[1]=W[2]=0,W[3]=1),b=!0),_.push(W)}var X,L,v,w,K,I,J,C=0,S=0;if(b)var E=[0,0,0,0];var F=function(e,o){if(S>o){for(X=Math.min(C+1,u-1),L=X;L>=0&&!(x[L]<=o);L--);L=Math.min(L,u-2)}else{for(L=C;u>L&&!(x[L]>o);L++);L=Math.min(L-1,u-2)}C=L,S=o;var m=x[L+1]-x[L];if(0!==m){if(v=(o-x[L])/m,U)if(K=_[L],w=_[0===L?L:L-1],I=_[L>u-2?u-1:L+1],J=_[L>u-3?u-1:L+2],g)r(w,K,I,J,v,v*v,v*v*v,l(e,c),f);else{var V;b?(V=r(w,K,I,J,v,v*v,v*v*v,E,1),V=h(E)):V=s(w,K,I,J,v,v*v,v*v*v),i(e,c,V)}else if(g)a(_[L],_[L+1],v,l(e,c),f);else{var V;b?(a(_[L],_[L+1],v,E,1),V=h(E)):V=n(_[L],_[L+1],v),i(e,c,V)}for(L=0;L<t._onframeList.length;L++)t._onframeList[L](e,o)}},T=new m({target:t._target,life:k,loop:t._loop,delay:t._delay,onframe:F,ondestroy:d});e&&\"spline\"!==e&&(T.easing=e),t._clipList.push(T),t._clipCount++,t.animation.add(T)}}};for(var c in this._tracks)p(this._tracks[c],c);return this},stop:function(){for(var e=0;e<this._clipList.length;e++){var t=this._clipList[e];this.animation.remove(t)}this._clipList=[]},delay:function(e){return this._delay=e,this},done:function(e){return e&&this._doneList.push(e),this}},u}),i(\"zrender/tool/vector\",[],function(){var e=\"undefined\"==typeof Float32Array?Array:Float32Array,t={create:function(t,i){var n=new e(2);return n[0]=t||0,n[1]=i||0,n},copy:function(e,t){return e[0]=t[0],e[1]=t[1],e},clone:function(t){var i=new e(2);return i[0]=t[0],i[1]=t[1],i},set:function(e,t,i){return e[0]=t,e[1]=i,e},add:function(e,t,i){return e[0]=t[0]+i[0],e[1]=t[1]+i[1],e},scaleAndAdd:function(e,t,i,n){return e[0]=t[0]+i[0]*n,e[1]=t[1]+i[1]*n,e},sub:function(e,t,i){return e[0]=t[0]-i[0],e[1]=t[1]-i[1],e},len:function(e){return Math.sqrt(this.lenSquare(e))},lenSquare:function(e){return e[0]*e[0]+e[1]*e[1]},mul:function(e,t,i){return e[0]=t[0]*i[0],e[1]=t[1]*i[1],e},div:function(e,t,i){return e[0]=t[0]/i[0],e[1]=t[1]/i[1],e},dot:function(e,t){return e[0]*t[0]+e[1]*t[1]},scale:function(e,t,i){return e[0]=t[0]*i,e[1]=t[1]*i,e},normalize:function(e,i){var n=t.len(i);return 0===n?(e[0]=0,e[1]=0):(e[0]=i[0]/n,e[1]=i[1]/n),e},distance:function(e,t){return Math.sqrt((e[0]-t[0])*(e[0]-t[0])+(e[1]-t[1])*(e[1]-t[1]))},distanceSquare:function(e,t){return(e[0]-t[0])*(e[0]-t[0])+(e[1]-t[1])*(e[1]-t[1])},negate:function(e,t){return e[0]=-t[0],e[1]=-t[1],e},lerp:function(e,t,i,n){return e[0]=t[0]+n*(i[0]-t[0]),e[1]=t[1]+n*(i[1]-t[1]),e},applyTransform:function(e,t,i){var n=t[0],a=t[1];return e[0]=i[0]*n+i[2]*a+i[4],e[1]=i[1]*n+i[3]*a+i[5],e},min:function(e,t,i){return e[0]=Math.min(t[0],i[0]),e[1]=Math.min(t[1],i[1]),e},max:function(e,t,i){return e[0]=Math.max(t[0],i[0]),e[1]=Math.max(t[1],i[1]),e}};return t.length=t.len,t.lengthSquare=t.lenSquare,t.dist=t.distance,t.distSquare=t.distanceSquare,t}),i(\"zrender/tool/matrix\",[],function(){var e=\"undefined\"==typeof Float32Array?Array:Float32Array,t={create:function(){var i=new e(6);return t.identity(i),i},identity:function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e[4]=0,e[5]=0,e},copy:function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e},mul:function(e,t,i){return e[0]=t[0]*i[0]+t[2]*i[1],e[1]=t[1]*i[0]+t[3]*i[1],e[2]=t[0]*i[2]+t[2]*i[3],e[3]=t[1]*i[2]+t[3]*i[3],e[4]=t[0]*i[4]+t[2]*i[5]+t[4],e[5]=t[1]*i[4]+t[3]*i[5]+t[5],e},translate:function(e,t,i){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4]+i[0],e[5]=t[5]+i[1],e},rotate:function(e,t,i){var n=t[0],a=t[2],o=t[4],r=t[1],s=t[3],l=t[5],h=Math.sin(i),m=Math.cos(i);return e[0]=n*m+r*h,e[1]=-n*h+r*m,e[2]=a*m+s*h,e[3]=-a*h+m*s,e[4]=m*o+h*l,e[5]=m*l-h*o,e},scale:function(e,t,i){var n=i[0],a=i[1];return e[0]=t[0]*n,e[1]=t[1]*a,e[2]=t[2]*n,e[3]=t[3]*a,e[4]=t[4]*n,e[5]=t[5]*a,e},invert:function(e,t){var i=t[0],n=t[2],a=t[4],o=t[1],r=t[3],s=t[5],l=i*r-o*n;return l?(l=1/l,e[0]=r*l,e[1]=-o*l,e[2]=-n*l,e[3]=i*l,e[4]=(n*s-r*a)*l,e[5]=(o*a-i*s)*l,e):null}};return t}),i(\"zrender/loadingEffect/Base\",[\"require\",\"../tool/util\",\"../shape/Text\",\"../shape/Rectangle\"],function(e){function t(e){this.setOptions(e)}var i=e(\"../tool/util\"),n=e(\"../shape/Text\"),a=e(\"../shape/Rectangle\"),o=\"Loading...\",r=\"normal 16px Arial\";return t.prototype.createTextShape=function(e){return new n({highlightStyle:i.merge({x:this.canvasWidth/2,y:this.canvasHeight/2,text:o,textAlign:\"center\",textBaseline:\"middle\",textFont:r,color:\"#333\",brushType:\"fill\"},e,!0)})},t.prototype.createBackgroundShape=function(e){return new a({highlightStyle:{x:0,y:0,width:this.canvasWidth,height:this.canvasHeight,brushType:\"fill\",color:e}})},t.prototype.start=function(e){function t(t){e.storage.addHover(t)}function i(){e.refreshHover()}this.canvasWidth=e._width,this.canvasHeight=e._height,this.loadingTimer=this._start(t,i)},t.prototype._start=function(){return setInterval(function(){},1e4)},t.prototype.stop=function(){clearInterval(this.loadingTimer)},t.prototype.setOptions=function(e){this.options=e||{}},t.prototype.adjust=function(e,t){return e<=t[0]?e=t[0]:e>=t[1]&&(e=t[1]),e},t.prototype.getLocation=function(e,t,i){var n=null!=e.x?e.x:\"center\";switch(n){case\"center\":n=Math.floor((this.canvasWidth-t)/2);break;case\"left\":n=0;break;case\"right\":n=this.canvasWidth-t}var a=null!=e.y?e.y:\"center\";switch(a){case\"center\":a=Math.floor((this.canvasHeight-i)/2);break;case\"top\":a=0;break;case\"bottom\":a=this.canvasHeight-i}return{x:n,y:a,width:t,height:i}},t}),i(\"zrender/Layer\",[\"require\",\"./mixin/Transformable\",\"./tool/util\",\"./config\"],function(e){function t(){return!1}function i(e,t,i){var n=document.createElement(t),a=i.getWidth(),o=i.getHeight();return n.style.position=\"absolute\",n.style.left=0,n.style.top=0,n.style.width=a+\"px\",n.style.height=o+\"px\",n.width=a*r.devicePixelRatio,n.height=o*r.devicePixelRatio,n.setAttribute(\"data-zr-dom-id\",e),n}var n=e(\"./mixin/Transformable\"),a=e(\"./tool/util\"),o=window.G_vmlCanvasManager,r=e(\"./config\"),s=function(e,a){this.id=e,this.dom=i(e,\"canvas\",a),this.dom.onselectstart=t,this.dom.style[\"-webkit-user-select\"]=\"none\",this.dom.style[\"user-select\"]=\"none\",this.dom.style[\"-webkit-touch-callout\"]=\"none\",this.dom.style[\"-webkit-tap-highlight-color\"]=\"rgba(0,0,0,0)\",this.dom.className=r.elementClassName,o&&o.initElement(this.dom),this.domBack=null,this.ctxBack=null,this.painter=a,this.unusedCount=0,this.config=null,this.dirty=!0,this.elCount=0,this.clearColor=0,this.motionBlur=!1,this.lastFrameAlpha=.7,this.zoomable=!1,this.panable=!1,this.maxZoom=1/0,this.minZoom=0,n.call(this)};return s.prototype.initContext=function(){this.ctx=this.dom.getContext(\"2d\");var e=r.devicePixelRatio;1!=e&&this.ctx.scale(e,e)},s.prototype.createBackBuffer=function(){if(!o){this.domBack=i(\"back-\"+this.id,\"canvas\",this.painter),this.ctxBack=this.domBack.getContext(\"2d\");var e=r.devicePixelRatio;1!=e&&this.ctxBack.scale(e,e)}},s.prototype.resize=function(e,t){var i=r.devicePixelRatio;this.dom.style.width=e+\"px\",this.dom.style.height=t+\"px\",this.dom.setAttribute(\"width\",e*i),this.dom.setAttribute(\"height\",t*i),1!=i&&this.ctx.scale(i,i),this.domBack&&(this.domBack.setAttribute(\"width\",e*i),this.domBack.setAttribute(\"height\",t*i),1!=i&&this.ctxBack.scale(i,i))},s.prototype.clear=function(){var e=this.dom,t=this.ctx,i=e.width,n=e.height,a=this.clearColor&&!o,s=this.motionBlur&&!o,l=this.lastFrameAlpha,h=r.devicePixelRatio;if(s&&(this.domBack||this.createBackBuffer(),this.ctxBack.globalCompositeOperation=\"copy\",this.ctxBack.drawImage(e,0,0,i/h,n/h)),t.clearRect(0,0,i/h,n/h),a&&(t.save(),t.fillStyle=this.clearColor,t.fillRect(0,0,i/h,n/h),t.restore()),s){var m=this.domBack;t.save(),t.globalAlpha=l,t.drawImage(m,0,0,i/h,n/h),t.restore()}},a.merge(s.prototype,n.prototype),s}),i(\"zrender/shape/Text\",[\"require\",\"../tool/area\",\"./Base\",\"../tool/util\"],function(e){\nvar t=e(\"../tool/area\"),i=e(\"./Base\"),n=function(e){i.call(this,e)};return n.prototype={type:\"text\",brush:function(e,i){var n=this.style;if(i&&(n=this.getHighlightStyle(n,this.highlightStyle||{})),\"undefined\"!=typeof n.text&&n.text!==!1){e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.textFont&&(e.font=n.textFont),e.textAlign=n.textAlign||\"start\",e.textBaseline=n.textBaseline||\"middle\";var a,o=(n.text+\"\").split(\"\\n\"),r=t.getTextHeight(\"国\",n.textFont),s=this.getRect(n),l=n.x;a=\"top\"==n.textBaseline?s.y:\"bottom\"==n.textBaseline?s.y+r:s.y+r/2;for(var h=0,m=o.length;m>h;h++){if(n.maxWidth)switch(n.brushType){case\"fill\":e.fillText(o[h],l,a,n.maxWidth);break;case\"stroke\":e.strokeText(o[h],l,a,n.maxWidth);break;case\"both\":e.fillText(o[h],l,a,n.maxWidth),e.strokeText(o[h],l,a,n.maxWidth);break;default:e.fillText(o[h],l,a,n.maxWidth)}else switch(n.brushType){case\"fill\":e.fillText(o[h],l,a);break;case\"stroke\":e.strokeText(o[h],l,a);break;case\"both\":e.fillText(o[h],l,a),e.strokeText(o[h],l,a);break;default:e.fillText(o[h],l,a)}a+=r}e.restore()}},getRect:function(e){if(e.__rect)return e.__rect;var i=t.getTextWidth(e.text,e.textFont),n=t.getTextHeight(e.text,e.textFont),a=e.x;\"end\"==e.textAlign||\"right\"==e.textAlign?a-=i:\"center\"==e.textAlign&&(a-=i/2);var o;return o=\"top\"==e.textBaseline?e.y:\"bottom\"==e.textBaseline?e.y-n:e.y-n/2,e.__rect={x:a,y:o,width:i,height:n},e.__rect}},e(\"../tool/util\").inherits(n,i),n}),i(\"zrender/shape/Rectangle\",[\"require\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={type:\"rectangle\",_buildRadiusPath:function(e,t){var i,n,a,o,r=t.x,s=t.y,l=t.width,h=t.height,m=t.radius;\"number\"==typeof m?i=n=a=o=m:m instanceof Array?1===m.length?i=n=a=o=m[0]:2===m.length?(i=a=m[0],n=o=m[1]):3===m.length?(i=m[0],n=o=m[1],a=m[2]):(i=m[0],n=m[1],a=m[2],o=m[3]):i=n=a=o=0;var V;i+n>l&&(V=i+n,i*=l/V,n*=l/V),a+o>l&&(V=a+o,a*=l/V,o*=l/V),n+a>h&&(V=n+a,n*=h/V,a*=h/V),i+o>h&&(V=i+o,i*=h/V,o*=h/V),e.moveTo(r+i,s),e.lineTo(r+l-n,s),0!==n&&e.quadraticCurveTo(r+l,s,r+l,s+n),e.lineTo(r+l,s+h-a),0!==a&&e.quadraticCurveTo(r+l,s+h,r+l-a,s+h),e.lineTo(r+o,s+h),0!==o&&e.quadraticCurveTo(r,s+h,r,s+h-o),e.lineTo(r,s+i),0!==i&&e.quadraticCurveTo(r,s,r+i,s)},buildPath:function(e,t){t.radius?this._buildRadiusPath(e,t):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y)),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-t/2),y:Math.round(e.y-t/2),width:e.width+t,height:e.height+t},e.__rect}},e(\"../tool/util\").inherits(i,t),i}),i(\"zrender/tool/area\",[\"require\",\"./util\",\"./curve\"],function(e){\"use strict\";function t(e){return e%=C,0>e&&(e+=C),e}function i(e,t,i,o){if(!t||!e)return!1;var r=e.type;L=L||W.getContext();var s=n(e,t,i,o);if(\"undefined\"!=typeof s)return s;if(e.buildPath&&L.isPointInPath)return a(e,L,t,i,o);switch(r){case\"ellipse\":return!0;case\"trochoid\":var l=\"out\"==t.location?t.r1+t.r2+t.d:t.r1-t.r2+t.d;return d(t,i,o,l);case\"rose\":return d(t,i,o,t.maxr);default:return!1}}function n(e,t,i,n){var a=e.type;switch(a){case\"bezier-curve\":return\"undefined\"==typeof t.cpX2?l(t.xStart,t.yStart,t.cpX1,t.cpY1,t.xEnd,t.yEnd,t.lineWidth,i,n):s(t.xStart,t.yStart,t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd,t.lineWidth,i,n);case\"line\":return r(t.xStart,t.yStart,t.xEnd,t.yEnd,t.lineWidth,i,n);case\"polyline\":return m(t.pointList,t.lineWidth,i,n);case\"ring\":return V(t.x,t.y,t.r0,t.r,i,n);case\"circle\":return d(t.x,t.y,t.r,i,n);case\"sector\":var o=t.startAngle*Math.PI/180,h=t.endAngle*Math.PI/180;return t.clockWise||(o=-o,h=-h),p(t.x,t.y,t.r0,t.r,o,h,!t.clockWise,i,n);case\"path\":return t.pathArray&&k(t.pathArray,Math.max(t.lineWidth,5),t.brushType,i,n);case\"polygon\":case\"star\":case\"isogon\":return c(t.pointList,i,n);case\"text\":var u=t.__rect||e.getRect(t);return U(u.x,u.y,u.width,u.height,i,n);case\"rectangle\":case\"image\":return U(t.x,t.y,t.width,t.height,i,n)}}function a(e,t,i,n,a){return t.beginPath(),e.buildPath(t,i),t.closePath(),t.isPointInPath(n,a)}function o(e,t,n,a){return!i(e,t,n,a)}function r(e,t,i,n,a,o,r){if(0===a)return!1;var s=Math.max(a,5),l=0,h=e;if(r>t+s&&r>n+s||t-s>r&&n-s>r||o>e+s&&o>i+s||e-s>o&&i-s>o)return!1;if(e===i)return Math.abs(o-e)<=s/2;l=(t-n)/(e-i),h=(e*n-i*t)/(e-i);var m=l*o-r+h,V=m*m/(l*l+1);return s/2*s/2>=V}function s(e,t,i,n,a,o,r,s,l,h,m){if(0===l)return!1;var V=Math.max(l,5);if(m>t+V&&m>n+V&&m>o+V&&m>s+V||t-V>m&&n-V>m&&o-V>m&&s-V>m||h>e+V&&h>i+V&&h>a+V&&h>r+V||e-V>h&&i-V>h&&a-V>h&&r-V>h)return!1;var U=X.cubicProjectPoint(e,t,i,n,a,o,r,s,h,m,null);return V/2>=U}function l(e,t,i,n,a,o,r,s,l){if(0===r)return!1;var h=Math.max(r,5);if(l>t+h&&l>n+h&&l>o+h||t-h>l&&n-h>l&&o-h>l||s>e+h&&s>i+h&&s>a+h||e-h>s&&i-h>s&&a-h>s)return!1;var m=X.quadraticProjectPoint(e,t,i,n,a,o,s,l,null);return h/2>=m}function h(e,i,n,a,o,r,s,l,h){if(0===s)return!1;var m=Math.max(s,5);l-=e,h-=i;var V=Math.sqrt(l*l+h*h);if(V-m>n||n>V+m)return!1;if(Math.abs(a-o)>=C)return!0;if(r){var U=a;a=t(o),o=t(U)}else a=t(a),o=t(o);a>o&&(o+=C);var d=Math.atan2(h,l);return 0>d&&(d+=C),d>=a&&o>=d||d+C>=a&&o>=d+C}function m(e,t,i,n){for(var t=Math.max(t,10),a=0,o=e.length-1;o>a;a++){var s=e[a][0],l=e[a][1],h=e[a+1][0],m=e[a+1][1];if(r(s,l,h,m,t,i,n))return!0}return!1}function V(e,t,i,n,a,o){var r=(a-e)*(a-e)+(o-t)*(o-t);return n*n>r&&r>i*i}function U(e,t,i,n,a,o){return a>=e&&e+i>=a&&o>=t&&t+n>=o}function d(e,t,i,n,a){return i*i>(n-e)*(n-e)+(a-t)*(a-t)}function p(e,t,i,n,a,o,r,s,l){return h(e,t,(i+n)/2,a,o,r,n-i,s,l)}function c(e,t,i){for(var n=e.length,a=0,o=0,r=n-1;n>o;o++){var s=e[r][0],l=e[r][1],h=e[o][0],m=e[o][1];a+=u(s,l,h,m,t,i),r=o}return 0!==a}function u(e,t,i,n,a,o){if(o>t&&o>n||t>o&&n>o)return 0;if(n==t)return 0;var r=t>n?1:-1,s=(o-t)/(n-t),l=s*(i-e)+e;return l>a?r:0}function y(){var e=E[0];E[0]=E[1],E[1]=e}function g(e,t,i,n,a,o,r,s,l,h){if(h>t&&h>n&&h>o&&h>s||t>h&&n>h&&o>h&&s>h)return 0;var m=X.cubicRootAt(t,n,o,s,h,S);if(0===m)return 0;for(var V,U,d=0,p=-1,c=0;m>c;c++){var u=S[c],g=X.cubicAt(e,i,a,r,u);l>g||(0>p&&(p=X.cubicExtrema(t,n,o,s,E),E[1]<E[0]&&p>1&&y(),V=X.cubicAt(t,n,o,s,E[0]),p>1&&(U=X.cubicAt(t,n,o,s,E[1]))),d+=2==p?u<E[0]?t>V?1:-1:u<E[1]?V>U?1:-1:U>s?1:-1:u<E[0]?t>V?1:-1:V>s?1:-1)}return d}function b(e,t,i,n,a,o,r,s){if(s>t&&s>n&&s>o||t>s&&n>s&&o>s)return 0;var l=X.quadraticRootAt(t,n,o,s,S);if(0===l)return 0;var h=X.quadraticExtremum(t,n,o);if(h>=0&&1>=h){for(var m=0,V=X.quadraticAt(t,n,o,h),U=0;l>U;U++){var d=X.quadraticAt(e,i,a,S[U]);r>d||(m+=S[U]<h?t>V?1:-1:V>o?1:-1)}return m}var d=X.quadraticAt(e,i,a,S[0]);return r>d?0:t>o?1:-1}function f(e,i,n,a,o,r,s,l){if(l-=i,l>n||-n>l)return 0;var h=Math.sqrt(n*n-l*l);if(S[0]=-h,S[1]=h,Math.abs(a-o)>=C){a=0,o=C;var m=r?1:-1;return s>=S[0]+e&&s<=S[1]+e?m:0}if(r){var h=a;a=t(o),o=t(h)}else a=t(a),o=t(o);a>o&&(o+=C);for(var V=0,U=0;2>U;U++){var d=S[U];if(d+e>s){var p=Math.atan2(l,d),m=r?1:-1;0>p&&(p=C+p),(p>=a&&o>=p||p+C>=a&&o>=p+C)&&(p>Math.PI/2&&p<1.5*Math.PI&&(m=-m),V+=m)}}return V}function k(e,t,i,n,a){var o=0,m=0,V=0,U=0,d=0,p=!0,c=!0;i=i||\"fill\";for(var y=\"stroke\"===i||\"both\"===i,k=\"fill\"===i||\"both\"===i,x=0;x<e.length;x++){var _=e[x],L=_.points;if(p||\"M\"===_.command){if(x>0&&(k&&(o+=u(m,V,U,d,n,a)),0!==o))return!0;U=L[L.length-2],d=L[L.length-1],p=!1,c&&\"A\"!==_.command&&(c=!1,m=U,V=d)}switch(_.command){case\"M\":m=L[0],V=L[1];break;case\"L\":if(y&&r(m,V,L[0],L[1],t,n,a))return!0;k&&(o+=u(m,V,L[0],L[1],n,a)),m=L[0],V=L[1];break;case\"C\":if(y&&s(m,V,L[0],L[1],L[2],L[3],L[4],L[5],t,n,a))return!0;k&&(o+=g(m,V,L[0],L[1],L[2],L[3],L[4],L[5],n,a)),m=L[4],V=L[5];break;case\"Q\":if(y&&l(m,V,L[0],L[1],L[2],L[3],t,n,a))return!0;k&&(o+=b(m,V,L[0],L[1],L[2],L[3],n,a)),m=L[2],V=L[3];break;case\"A\":var W=L[0],X=L[1],v=L[2],w=L[3],K=L[4],I=L[5],J=Math.cos(K)*v+W,C=Math.sin(K)*w+X;c?(c=!1,U=J,d=C):o+=u(m,V,J,C);var S=(n-W)*w/v+W;if(y&&h(W,X,w,K,K+I,1-L[7],t,S,a))return!0;k&&(o+=f(W,X,w,K,K+I,1-L[7],S,a)),m=Math.cos(K+I)*v+W,V=Math.sin(K+I)*w+X;break;case\"z\":if(y&&r(m,V,U,d,t,n,a))return!0;p=!0}}return k&&(o+=u(m,V,U,d,n,a)),0!==o}function x(e,t){var i=e+\":\"+t;if(v[i])return v[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+\"\").split(\"\\n\");for(var n=0,a=0,o=e.length;o>a;a++)n=Math.max(L.measureText(e[a]).width,n);return L.restore(),v[i]=n,++K>J&&(K=0,v={}),n}function _(e,t){var i=e+\":\"+t;if(w[i])return w[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+\"\").split(\"\\n\");var n=(L.measureText(\"国\").width+2)*e.length;return L.restore(),w[i]=n,++I>J&&(I=0,w={}),n}var L,W=e(\"./util\"),X=e(\"./curve\"),v={},w={},K=0,I=0,J=5e3,C=2*Math.PI,S=[-1,-1,-1],E=[-1,-1];return{isInside:i,isOutside:o,getTextWidth:x,getTextHeight:_,isInsidePath:k,isInsidePolygon:c,isInsideSector:p,isInsideCircle:d,isInsideLine:r,isInsideRect:U,isInsidePolyline:m,isInsideCubicStroke:s,isInsideQuadraticStroke:l}}),i(\"zrender/shape/Base\",[\"require\",\"../tool/matrix\",\"../tool/guid\",\"../tool/util\",\"../tool/log\",\"../mixin/Transformable\",\"../mixin/Eventful\",\"../tool/area\",\"../tool/color\"],function(e){function t(t,n,a,o,r,s,l){r&&(t.font=r),t.textAlign=s,t.textBaseline=l;var h=i(n,a,o,r,s,l);n=(n+\"\").split(\"\\n\");var m=e(\"../tool/area\").getTextHeight(\"国\",r);switch(l){case\"top\":o=h.y;break;case\"bottom\":o=h.y+m;break;default:o=h.y+m/2}for(var V=0,U=n.length;U>V;V++)t.fillText(n[V],a,o),o+=m}function i(t,i,n,a,o,r){var s=e(\"../tool/area\"),l=s.getTextWidth(t,a),h=s.getTextHeight(\"国\",a);switch(t=(t+\"\").split(\"\\n\"),o){case\"end\":case\"right\":i-=l;break;case\"center\":i-=l/2}switch(r){case\"top\":break;case\"bottom\":n-=h*t.length;break;default:n-=h*t.length/2}return{x:i,y:n,width:l,height:h*t.length}}var n=window.G_vmlCanvasManager,a=e(\"../tool/matrix\"),o=e(\"../tool/guid\"),r=e(\"../tool/util\"),s=e(\"../tool/log\"),l=e(\"../mixin/Transformable\"),h=e(\"../mixin/Eventful\"),m=function(e){e=e||{},this.id=e.id||o();for(var t in e)this[t]=e[t];this.style=this.style||{},this.highlightStyle=this.highlightStyle||null,this.parent=null,this.__dirty=!0,this.__clipShapes=[],l.call(this),h.call(this)};m.prototype.invisible=!1,m.prototype.ignore=!1,m.prototype.zlevel=0,m.prototype.draggable=!1,m.prototype.clickable=!1,m.prototype.hoverable=!0,m.prototype.z=0,m.prototype.brush=function(e,t){var i=this.beforeBrush(e,t);switch(e.beginPath(),this.buildPath(e,i),i.brushType){case\"both\":e.fill();case\"stroke\":i.lineWidth>0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},m.prototype.beforeBrush=function(e,t){var i=this.style;return this.brushTypeOnly&&(i.brushType=this.brushTypeOnly),t&&(i=this.getHighlightStyle(i,this.highlightStyle||{},this.brushTypeOnly)),\"stroke\"==this.brushTypeOnly&&(i.strokeColor=i.strokeColor||i.color),e.save(),this.doClip(e),this.setContext(e,i),this.setTransform(e),i},m.prototype.afterBrush=function(e){e.restore()};var V=[[\"color\",\"fillStyle\"],[\"strokeColor\",\"strokeStyle\"],[\"opacity\",\"globalAlpha\"],[\"lineCap\",\"lineCap\"],[\"lineJoin\",\"lineJoin\"],[\"miterLimit\",\"miterLimit\"],[\"lineWidth\",\"lineWidth\"],[\"shadowBlur\",\"shadowBlur\"],[\"shadowColor\",\"shadowColor\"],[\"shadowOffsetX\",\"shadowOffsetX\"],[\"shadowOffsetY\",\"shadowOffsetY\"]];m.prototype.setContext=function(e,t){for(var i=0,n=V.length;n>i;i++){var a=V[i][0],o=t[a],r=V[i][1];\"undefined\"!=typeof o&&(e[r]=o)}};var U=a.create();return m.prototype.doClip=function(e){if(this.__clipShapes&&!n)for(var t=0;t<this.__clipShapes.length;t++){var i=this.__clipShapes[t];if(i.needTransform){var o=i.transform;a.invert(U,o),e.transform(o[0],o[1],o[2],o[3],o[4],o[5])}if(e.beginPath(),i.buildPath(e,i.style),e.clip(),i.needTransform){var o=U;e.transform(o[0],o[1],o[2],o[3],o[4],o[5])}}},m.prototype.getHighlightStyle=function(t,i,n){var a={};for(var o in t)a[o]=t[o];var r=e(\"../tool/color\"),s=r.getHighlightColor();\"stroke\"!=t.brushType?(a.strokeColor=s,a.lineWidth=(t.lineWidth||1)+this.getHighlightZoom(),a.brushType=\"both\"):\"stroke\"!=n?(a.strokeColor=s,a.lineWidth=(t.lineWidth||1)+this.getHighlightZoom()):a.strokeColor=i.strokeColor||r.mix(t.strokeColor,r.toRGB(s));for(var o in i)\"undefined\"!=typeof i[o]&&(a[o]=i[o]);return a},m.prototype.getHighlightZoom=function(){return\"text\"!=this.type?6:2},m.prototype.drift=function(e,t){this.position[0]+=e,this.position[1]+=t},m.prototype.buildPath=function(){s(\"buildPath not implemented in \"+this.type)},m.prototype.getRect=function(){s(\"getRect not implemented in \"+this.type)},m.prototype.isCover=function(t,i){var n=this.transformCoordToLocal(t,i);return t=n[0],i=n[1],this.isCoverRect(t,i)?e(\"../tool/area\").isInside(this,this.style,t,i):!1},m.prototype.isCoverRect=function(e,t){var i=this.style.__rect;return i||(i=this.style.__rect=this.getRect(this.style)),e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height},m.prototype.drawText=function(e,i,n){if(\"undefined\"!=typeof i.text&&i.text!==!1){var a=i.textColor||i.color||i.strokeColor;e.fillStyle=a;var o,r,s,l,h=10,m=i.textPosition||this.textPosition||\"top\";switch(m){case\"inside\":case\"top\":case\"bottom\":case\"left\":case\"right\":if(this.getRect){var V=(n||i).__rect||this.getRect(n||i);switch(m){case\"inside\":s=V.x+V.width/2,l=V.y+V.height/2,o=\"center\",r=\"middle\",\"stroke\"!=i.brushType&&a==i.color&&(e.fillStyle=\"#fff\");break;case\"left\":s=V.x-h,l=V.y+V.height/2,o=\"end\",r=\"middle\";break;case\"right\":s=V.x+V.width+h,l=V.y+V.height/2,o=\"start\",r=\"middle\";break;case\"top\":s=V.x+V.width/2,l=V.y-h,o=\"center\",r=\"bottom\";break;case\"bottom\":s=V.x+V.width/2,l=V.y+V.height+h,o=\"center\",r=\"top\"}}break;case\"start\":case\"end\":var U=i.pointList||[[i.xStart||0,i.yStart||0],[i.xEnd||0,i.yEnd||0]],d=U.length;if(2>d)return;var p,c,u,y;switch(m){case\"start\":p=U[1][0],c=U[0][0],u=U[1][1],y=U[0][1];break;case\"end\":p=U[d-2][0],c=U[d-1][0],u=U[d-2][1],y=U[d-1][1]}s=c,l=y;var g=Math.atan((u-y)/(c-p))/Math.PI*180;0>c-p?g+=180:0>u-y&&(g+=360),h=5,g>=30&&150>=g?(o=\"center\",r=\"bottom\",l-=h):g>150&&210>g?(o=\"right\",r=\"middle\",s-=h):g>=210&&330>=g?(o=\"center\",r=\"top\",l+=h):(o=\"left\",r=\"middle\",s+=h);break;case\"specific\":s=i.textX||0,l=i.textY||0,o=\"start\",r=\"middle\"}null!=s&&null!=l&&t(e,i.text,s,l,i.textFont,i.textAlign||o,i.textBaseline||r)}},m.prototype.modSelf=function(){this.__dirty=!0,this.style&&(this.style.__rect=null),this.highlightStyle&&(this.highlightStyle.__rect=null)},m.prototype.isSilent=function(){return!(this.hoverable||this.draggable||this.clickable||this.onmousemove||this.onmouseover||this.onmouseout||this.onmousedown||this.onmouseup||this.onclick||this.ondragenter||this.ondragover||this.ondragleave||this.ondrop)},r.merge(m.prototype,l.prototype,!0),r.merge(m.prototype,h.prototype,!0),m}),i(\"zrender/tool/curve\",[\"require\",\"./vector\"],function(e){function t(e){return e>-u&&u>e}function i(e){return e>u||-u>e}function n(e,t,i,n,a){var o=1-a;return o*o*(o*e+3*a*t)+a*a*(a*n+3*o*i)}function a(e,t,i,n,a){var o=1-a;return 3*(((t-e)*o+2*(i-t)*a)*o+(n-i)*a*a)}function o(e,i,n,a,o,r){var s=a+3*(i-n)-e,l=3*(n-2*i+e),h=3*(i-e),m=e-o,V=l*l-3*s*h,U=l*h-9*s*m,d=h*h-3*l*m,p=0;if(t(V)&&t(U))if(t(l))r[0]=0;else{var c=-h/l;c>=0&&1>=c&&(r[p++]=c)}else{var u=U*U-4*V*d;if(t(u)){var b=U/V,c=-l/s+b,f=-b/2;c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f)}else if(u>0){var k=Math.sqrt(u),x=V*l+1.5*s*(-U+k),_=V*l+1.5*s*(-U-k);x=0>x?-Math.pow(-x,g):Math.pow(x,g),_=0>_?-Math.pow(-_,g):Math.pow(_,g);var c=(-l-(x+_))/(3*s);c>=0&&1>=c&&(r[p++]=c)}else{var L=(2*V*l-3*s*U)/(2*Math.sqrt(V*V*V)),W=Math.acos(L)/3,X=Math.sqrt(V),v=Math.cos(W),c=(-l-2*X*v)/(3*s),f=(-l+X*(v+y*Math.sin(W)))/(3*s),w=(-l+X*(v-y*Math.sin(W)))/(3*s);c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f),w>=0&&1>=w&&(r[p++]=w)}}return p}function r(e,n,a,o,r){var s=6*a-12*n+6*e,l=9*n+3*o-3*e-9*a,h=3*n-3*e,m=0;if(t(l)){if(i(s)){var V=-h/s;V>=0&&1>=V&&(r[m++]=V)}}else{var U=s*s-4*l*h;if(t(U))r[0]=-s/(2*l);else if(U>0){var d=Math.sqrt(U),V=(-s+d)/(2*l),p=(-s-d)/(2*l);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function s(e,t,i,n,a,o){var r=(t-e)*a+e,s=(i-t)*a+t,l=(n-i)*a+i,h=(s-r)*a+r,m=(l-s)*a+s,V=(m-h)*a+h;o[0]=e,o[1]=r,o[2]=h,o[3]=V,o[4]=V,o[5]=m,o[6]=l,o[7]=n}function l(e,t,i,a,o,r,s,l,h,m,V){var U,d=.005,p=1/0;b[0]=h,b[1]=m;for(var y=0;1>y;y+=.05){f[0]=n(e,i,o,s,y),f[1]=n(t,a,r,l,y);var g=c.distSquare(b,f);p>g&&(U=y,p=g)}p=1/0;for(var x=0;32>x&&!(u>d);x++){var _=U-d,L=U+d;f[0]=n(e,i,o,s,_),f[1]=n(t,a,r,l,_);var g=c.distSquare(f,b);if(_>=0&&p>g)U=_,p=g;else{k[0]=n(e,i,o,s,L),k[1]=n(t,a,r,l,L);var W=c.distSquare(k,b);1>=L&&p>W?(U=L,p=W):d*=.5}}return V&&(V[0]=n(e,i,o,s,U),V[1]=n(t,a,r,l,U)),Math.sqrt(p)}function h(e,t,i,n){var a=1-n;return a*(a*e+2*n*t)+n*n*i}function m(e,t,i,n){return 2*((1-n)*(t-e)+n*(i-t))}function V(e,n,a,o,r){var s=e-2*n+a,l=2*(n-e),h=e-o,m=0;if(t(s)){if(i(l)){var V=-h/l;V>=0&&1>=V&&(r[m++]=V)}}else{var U=l*l-4*s*h;if(t(U)){var V=-l/(2*s);V>=0&&1>=V&&(r[m++]=V)}else if(U>0){var d=Math.sqrt(U),V=(-l+d)/(2*s),p=(-l-d)/(2*s);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function U(e,t,i){var n=e+i-2*t;return 0===n?.5:(e-t)/n}function d(e,t,i,n,a){var o=(t-e)*n+e,r=(i-t)*n+t,s=(r-o)*n+o;a[0]=e,a[1]=o,a[2]=s,a[3]=s,a[4]=r,a[5]=i}function p(e,t,i,n,a,o,r,s,l){var m,V=.005,U=1/0;b[0]=r,b[1]=s;for(var d=0;1>d;d+=.05){f[0]=h(e,i,a,d),f[1]=h(t,n,o,d);var p=c.distSquare(b,f);U>p&&(m=d,U=p)}U=1/0;for(var y=0;32>y&&!(u>V);y++){var g=m-V,x=m+V;f[0]=h(e,i,a,g),f[1]=h(t,n,o,g);var p=c.distSquare(f,b);if(g>=0&&U>p)m=g,U=p;else{k[0]=h(e,i,a,x),k[1]=h(t,n,o,x);var _=c.distSquare(k,b);1>=x&&U>_?(m=x,U=_):V*=.5}}return l&&(l[0]=h(e,i,a,m),l[1]=h(t,n,o,m)),Math.sqrt(U)}var c=e(\"./vector\"),u=1e-4,y=Math.sqrt(3),g=1/3,b=c.create(),f=c.create(),k=c.create();return{cubicAt:n,cubicDerivativeAt:a,cubicRootAt:o,cubicExtrema:r,cubicSubdivide:s,cubicProjectPoint:l,quadraticAt:h,quadraticDerivativeAt:m,quadraticRootAt:V,quadraticExtremum:U,quadraticSubdivide:d,quadraticProjectPoint:p}}),i(\"zrender/mixin/Transformable\",[\"require\",\"../tool/matrix\",\"../tool/vector\"],function(e){\"use strict\";function t(e){return e>-s&&s>e}function i(e){return e>s||-s>e}var n=e(\"../tool/matrix\"),a=e(\"../tool/vector\"),o=[0,0],r=n.translate,s=5e-5,l=function(){this.position||(this.position=[0,0]),\"undefined\"==typeof this.rotation&&(this.rotation=[0,0,0]),this.scale||(this.scale=[1,1,0,0]),this.needLocalTransform=!1,this.needTransform=!1};return l.prototype={constructor:l,updateNeedTransform:function(){this.needLocalTransform=i(this.rotation[0])||i(this.position[0])||i(this.position[1])||i(this.scale[0]-1)||i(this.scale[1]-1)},updateTransform:function(){this.updateNeedTransform();var e=this.parent&&this.parent.needTransform;if(this.needTransform=this.needLocalTransform||e,this.needTransform){var t=this.transform||n.create();if(n.identity(t),this.needLocalTransform){var a=this.scale;if(i(a[0])||i(a[1])){o[0]=-a[2]||0,o[1]=-a[3]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.scale(t,t,a),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}if(this.rotation instanceof Array){if(0!==this.rotation[0]){o[0]=-this.rotation[1]||0,o[1]=-this.rotation[2]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.rotate(t,t,this.rotation[0]),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}}else 0!==this.rotation&&n.rotate(t,t,this.rotation);(i(this.position[0])||i(this.position[1]))&&r(t,t,this.position)}e&&(this.needLocalTransform?n.mul(t,this.parent.transform,t):n.copy(t,this.parent.transform)),this.transform=t,this.invTransform=this.invTransform||n.create(),n.invert(this.invTransform,t)}},setTransform:function(e){if(this.needTransform){var t=this.transform;e.transform(t[0],t[1],t[2],t[3],t[4],t[5])}},lookAt:function(){var e=a.create();return function(i){this.transform||(this.transform=n.create());var o=this.transform;if(a.sub(e,i,this.position),!t(e[0])||!t(e[1])){a.normalize(e,e);var r=this.scale;o[2]=e[0]*r[1],o[3]=e[1]*r[1],o[0]=e[1]*r[0],o[1]=-e[0]*r[0],o[4]=this.position[0],o[5]=this.position[1],this.decomposeTransform()}}}(),decomposeTransform:function(){if(this.transform){var e=this.transform,t=e[0]*e[0]+e[1]*e[1],n=this.position,a=this.scale,o=this.rotation;i(t-1)&&(t=Math.sqrt(t));var r=e[2]*e[2]+e[3]*e[3];i(r-1)&&(r=Math.sqrt(r)),n[0]=e[4],n[1]=e[5],a[0]=t,a[1]=r,a[2]=a[3]=0,o[0]=Math.atan2(-e[1]/r,e[0]/t),o[1]=o[2]=0}},transformCoordToLocal:function(e,t){var i=[e,t];return this.needTransform&&this.invTransform&&a.applyTransform(i,i,this.invTransform),i}},l}),i(\"zrender/Group\",[\"require\",\"./tool/guid\",\"./tool/util\",\"./mixin/Transformable\",\"./mixin/Eventful\"],function(e){var t=e(\"./tool/guid\"),i=e(\"./tool/util\"),n=e(\"./mixin/Transformable\"),a=e(\"./mixin/Eventful\"),o=function(e){e=e||{},this.id=e.id||t();for(var i in e)this[i]=e[i];this.type=\"group\",this.clipShape=null,this._children=[],this._storage=null,this.__dirty=!0,n.call(this),a.call(this)};return o.prototype.ignore=!1,o.prototype.children=function(){return this._children.slice()},o.prototype.childAt=function(e){return this._children[e]},o.prototype.addChild=function(e){e!=this&&e.parent!=this&&(e.parent&&e.parent.removeChild(e),this._children.push(e),e.parent=this,this._storage&&this._storage!==e._storage&&(this._storage.addToMap(e),e instanceof o&&e.addChildrenToStorage(this._storage)))},o.prototype.removeChild=function(e){var t=i.indexOf(this._children,e);t>=0&&this._children.splice(t,1),e.parent=null,this._storage&&(this._storage.delFromMap(e.id),e instanceof o&&e.delChildrenFromStorage(this._storage))},o.prototype.clearChildren=function(){for(var e=0;e<this._children.length;e++){var t=this._children[e];this._storage&&(this._storage.delFromMap(t.id),t instanceof o&&t.delChildrenFromStorage(this._storage))}this._children.length=0},o.prototype.eachChild=function(e,t){for(var i=!!t,n=0;n<this._children.length;n++){var a=this._children[n];i?e.call(t,a):e(a)}},o.prototype.traverse=function(e,t){for(var i=!!t,n=0;n<this._children.length;n++){var a=this._children[n];i?e.call(t,a):e(a),\"group\"===a.type&&a.traverse(e,t)}},o.prototype.addChildrenToStorage=function(e){for(var t=0;t<this._children.length;t++){var i=this._children[t];e.addToMap(i),i instanceof o&&i.addChildrenToStorage(e)}},o.prototype.delChildrenFromStorage=function(e){for(var t=0;t<this._children.length;t++){var i=this._children[t];e.delFromMap(i.id),i instanceof o&&i.delChildrenFromStorage(e)}},o.prototype.modSelf=function(){this.__dirty=!0},i.merge(o.prototype,n.prototype,!0),i.merge(o.prototype,a.prototype,!0),o}),i(\"zrender/animation/Clip\",[\"require\",\"./easing\"],function(e){function t(e){this._targetPool=e.target||{},this._targetPool instanceof Array||(this._targetPool=[this._targetPool]),this._life=e.life||1e3,this._delay=e.delay||0,this._startTime=(new Date).getTime()+this._delay,this._endTime=this._startTime+1e3*this._life,this.loop=\"undefined\"==typeof e.loop?!1:e.loop,this.gap=e.gap||0,this.easing=e.easing||\"Linear\",this.onframe=e.onframe,this.ondestroy=e.ondestroy,this.onrestart=e.onrestart}var i=e(\"./easing\");return t.prototype={step:function(e){var t=(e-this._startTime)/this._life;if(!(0>t)){t=Math.min(t,1);var n=\"string\"==typeof this.easing?i[this.easing]:this.easing,a=\"function\"==typeof n?n(t):t;return this.fire(\"frame\",a),1==t?this.loop?(this.restart(),\"restart\"):(this.__needsRemove=!0,\"destroy\"):null}},restart:function(){var e=(new Date).getTime(),t=(e-this._startTime)%this._life;this._startTime=(new Date).getTime()-t+this.gap,this.__needsRemove=!1},fire:function(e,t){for(var i=0,n=this._targetPool.length;n>i;i++)this[\"on\"+e]&&this[\"on\"+e](this._targetPool[i],t)},constructor:t},t}),i(\"zrender/animation/easing\",[],function(){var e={Linear:function(e){return e},QuadraticIn:function(e){return e*e},QuadraticOut:function(e){return e*(2-e)},QuadraticInOut:function(e){return(e*=2)<1?.5*e*e:-.5*(--e*(e-2)-1)},CubicIn:function(e){return e*e*e},CubicOut:function(e){return--e*e*e+1},CubicInOut:function(e){return(e*=2)<1?.5*e*e*e:.5*((e-=2)*e*e+2)},QuarticIn:function(e){return e*e*e*e},QuarticOut:function(e){return 1- --e*e*e*e},QuarticInOut:function(e){return(e*=2)<1?.5*e*e*e*e:-.5*((e-=2)*e*e*e-2)},QuinticIn:function(e){return e*e*e*e*e},QuinticOut:function(e){return--e*e*e*e*e+1},QuinticInOut:function(e){return(e*=2)<1?.5*e*e*e*e*e:.5*((e-=2)*e*e*e*e+2)},SinusoidalIn:function(e){return 1-Math.cos(e*Math.PI/2)},SinusoidalOut:function(e){return Math.sin(e*Math.PI/2)},SinusoidalInOut:function(e){return.5*(1-Math.cos(Math.PI*e))},ExponentialIn:function(e){return 0===e?0:Math.pow(1024,e-1)},ExponentialOut:function(e){return 1===e?1:1-Math.pow(2,-10*e)},ExponentialInOut:function(e){return 0===e?0:1===e?1:(e*=2)<1?.5*Math.pow(1024,e-1):.5*(-Math.pow(2,-10*(e-1))+2)},CircularIn:function(e){return 1-Math.sqrt(1-e*e)},CircularOut:function(e){return Math.sqrt(1- --e*e)},CircularInOut:function(e){return(e*=2)<1?-.5*(Math.sqrt(1-e*e)-1):.5*(Math.sqrt(1-(e-=2)*e)+1)},ElasticIn:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),-(i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)))},ElasticOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*e)*Math.sin(2*(e-t)*Math.PI/n)+1)},ElasticInOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),(e*=2)<1?-.5*i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n):i*Math.pow(2,-10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)*.5+1)},BackIn:function(e){var t=1.70158;return e*e*((t+1)*e-t)},BackOut:function(e){var t=1.70158;return--e*e*((t+1)*e+t)+1},BackInOut:function(e){var t=2.5949095;return(e*=2)<1?.5*e*e*((t+1)*e-t):.5*((e-=2)*e*((t+1)*e+t)+2)},BounceIn:function(t){return 1-e.BounceOut(1-t)},BounceOut:function(e){return 1/2.75>e?7.5625*e*e:2/2.75>e?7.5625*(e-=1.5/2.75)*e+.75:2.5/2.75>e?7.5625*(e-=2.25/2.75)*e+.9375:7.5625*(e-=2.625/2.75)*e+.984375},BounceInOut:function(t){return.5>t?.5*e.BounceIn(2*t):.5*e.BounceOut(2*t-1)+.5}};return e}),i(\"echarts/chart/base\",[\"require\",\"zrender/shape/Image\",\"../util/shape/Icon\",\"../util/shape/MarkLine\",\"../util/shape/Symbol\",\"zrender/shape/Polyline\",\"zrender/shape/ShapeBundle\",\"../config\",\"../util/ecData\",\"../util/ecAnimation\",\"../util/ecEffect\",\"../util/accMath\",\"../component/base\",\"../layout/EdgeBundling\",\"zrender/tool/util\",\"zrender/tool/area\"],function(e){function t(e){return null!=e.x&&null!=e.y}function i(e,t,i,n,a){p.call(this,e,t,i,n,a);var o=this;this.selectedMap={},this.lastShapeList=[],this.shapeHandler={onclick:function(){o.isClick=!0},ondragover:function(e){var t=e.target;t.highlightStyle=t.highlightStyle||{};var i=t.highlightStyle,n=i.brushTyep,a=i.strokeColor,r=i.lineWidth;i.brushType=\"stroke\",i.strokeColor=o.ecTheme.calculableColor||h.calculableColor,i.lineWidth=\"icon\"===t.type?30:10,o.zr.addHoverShape(t),setTimeout(function(){i&&(i.brushType=n,i.strokeColor=a,i.lineWidth=r)},20)},ondrop:function(e){null!=m.get(e.dragged,\"data\")&&(o.isDrop=!0)},ondragend:function(){o.isDragend=!0}}}var n=e(\"zrender/shape/Image\"),a=e(\"../util/shape/Icon\"),o=e(\"../util/shape/MarkLine\"),r=e(\"../util/shape/Symbol\"),s=e(\"zrender/shape/Polyline\"),l=e(\"zrender/shape/ShapeBundle\"),h=e(\"../config\"),m=e(\"../util/ecData\"),V=e(\"../util/ecAnimation\"),U=e(\"../util/ecEffect\"),d=e(\"../util/accMath\"),p=e(\"../component/base\"),c=e(\"../layout/EdgeBundling\"),u=e(\"zrender/tool/util\"),y=e(\"zrender/tool/area\");return i.prototype={setCalculable:function(e){return e.dragEnableTime=this.ecTheme.DRAG_ENABLE_TIME||h.DRAG_ENABLE_TIME,e.ondragover=this.shapeHandler.ondragover,e.ondragend=this.shapeHandler.ondragend,e.ondrop=this.shapeHandler.ondrop,e},ondrop:function(e,t){if(this.isDrop&&e.target&&!t.dragIn){var i,n=e.target,a=e.dragged,o=m.get(n,\"seriesIndex\"),r=m.get(n,\"dataIndex\"),s=this.series,l=this.component.legend;if(-1===r){if(m.get(a,\"seriesIndex\")==o)return t.dragOut=t.dragIn=t.needRefresh=!0,void(this.isDrop=!1);i={value:m.get(a,\"value\"),name:m.get(a,\"name\")},this.type===h.CHART_TYPE_PIE&&i.value<0&&(i.value=0);for(var V=!1,U=s[o].data,p=0,c=U.length;c>p;p++)U[p].name===i.name&&\"-\"===U[p].value&&(s[o].data[p].value=i.value,V=!0);!V&&s[o].data.push(i),l&&l.add(i.name,a.style.color||a.style.strokeColor)}else i=s[o].data[r]||\"-\",null!=i.value?(s[o].data[r].value=\"-\"!=i.value?d.accAdd(s[o].data[r].value,m.get(a,\"value\")):m.get(a,\"value\"),(this.type===h.CHART_TYPE_FUNNEL||this.type===h.CHART_TYPE_PIE)&&(l&&1===l.getRelatedAmount(i.name)&&this.component.legend.del(i.name),i.name+=this.option.nameConnector+m.get(a,\"name\"),l&&l.add(i.name,a.style.color||a.style.strokeColor))):s[o].data[r]=\"-\"!=i?d.accAdd(s[o].data[r],m.get(a,\"value\")):m.get(a,\"value\");t.dragIn=t.dragIn||!0,this.isDrop=!1;var u=this;setTimeout(function(){u.zr.trigger(\"mousemove\",e.event)},300)}},ondragend:function(e,t){if(this.isDragend&&e.target&&!t.dragOut){var i=e.target,n=m.get(i,\"seriesIndex\"),a=m.get(i,\"dataIndex\"),o=this.series;if(null!=o[n].data[a].value){o[n].data[a].value=\"-\";var r=o[n].data[a].name,s=this.component.legend;s&&0===s.getRelatedAmount(r)&&s.del(r)}else o[n].data[a]=\"-\";t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},onlegendSelected:function(e,t){var i=e.selected;for(var n in this.selectedMap)this.selectedMap[n]!=i[n]&&(t.needRefresh=!0),this.selectedMap[n]=i[n]},_buildPosition:function(){this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this._sIndex2ColorMap={},this.selectedMap={},this.xMarkMap={};for(var e,t,i,n,a=this.series,o={top:[],bottom:[],left:[],right:[],other:[]},r=0,s=a.length;s>r;r++)a[r].type===this.type&&(a[r]=this.reformOption(a[r]),this.legendHoverLink=a[r].legendHoverLink||this.legendHoverLink,e=a[r].xAxisIndex,t=a[r].yAxisIndex,i=this.component.xAxis.getAxis(e),n=this.component.yAxis.getAxis(t),i.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[i.getPosition()].push(r):n.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[n.getPosition()].push(r):o.other.push(r));for(var l in o)o[l].length>0&&this._buildSinglePosition(l,o[l]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){switch(e){case\"bottom\":case\"top\":this._buildHorizontal(t,a,n,this.xMarkMap);break;case\"left\":case\"right\":this._buildVertical(t,a,n,this.xMarkMap);break;case\"other\":this._buildOther(t,a,n,this.xMarkMap)}for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n,a,o=this.series,r=0,s={},l=\"__kener__stack__\",m=this.component.legend,V=[],U=0,d=0,p=e.length;p>d;d++){if(t=o[e[d]],n=t.name,this._sIndex2ShapeMap[e[d]]=this._sIndex2ShapeMap[e[d]]||this.query(t,\"symbol\")||this._symbol[d%this._symbol.length],m){if(this.selectedMap[n]=m.isSelected(n),this._sIndex2ColorMap[e[d]]=m.getColor(n),a=m.getItemShape(n)){var c=a.style;if(this.type==h.CHART_TYPE_LINE)c.iconType=\"legendLineIcon\",c.symbol=this._sIndex2ShapeMap[e[d]];else if(t.itemStyle.normal.barBorderWidth>0){var u=a.highlightStyle;c.brushType=\"both\",c.x+=1,c.y+=1,c.width-=2,c.height-=2,c.strokeColor=u.strokeColor=t.itemStyle.normal.barBorderColor,u.lineWidth=3}m.setItemShape(n,a)}}else this.selectedMap[n]=!0,this._sIndex2ColorMap[e[d]]=this.zr.getColor(e[d]);this.selectedMap[n]&&(i=t.stack||l+e[d],null==s[i]?(s[i]=r,V[r]=[e[d]],r++):V[s[i]].push(e[d])),U=Math.max(U,t.data.length)}return{locationMap:V,maxDataLength:U}},_calculMarkMapXY:function(e,t,i){for(var n=this.series,a=0,o=t.length;o>a;a++)for(var r=0,s=t[a].length;s>r;r++){var l=t[a][r],h=\"xy\"==i?0:\"\",m=this.component.grid,V=e[l];if(\"-1\"!=i.indexOf(\"x\")){V[\"counter\"+h]>0&&(V[\"average\"+h]=V[\"sum\"+h]/V[\"counter\"+h]);var U=this.component.xAxis.getAxis(n[l].xAxisIndex||0).getCoord(V[\"average\"+h]);V[\"averageLine\"+h]=[[U,m.getYend()],[U,m.getY()]],V[\"minLine\"+h]=[[V[\"minX\"+h],m.getYend()],[V[\"minX\"+h],m.getY()]],V[\"maxLine\"+h]=[[V[\"maxX\"+h],m.getYend()],[V[\"maxX\"+h],m.getY()]],V.isHorizontal=!1}if(h=\"xy\"==i?1:\"\",\"-1\"!=i.indexOf(\"y\")){V[\"counter\"+h]>0&&(V[\"average\"+h]=V[\"sum\"+h]/V[\"counter\"+h]);var d=this.component.yAxis.getAxis(n[l].yAxisIndex||0).getCoord(V[\"average\"+h]);V[\"averageLine\"+h]=[[m.getX(),d],[m.getXend(),d]],V[\"minLine\"+h]=[[m.getX(),V[\"minY\"+h]],[m.getXend(),V[\"minY\"+h]]],V[\"maxLine\"+h]=[[m.getX(),V[\"maxY\"+h]],[m.getXend(),V[\"maxY\"+h]]],V.isHorizontal=!0}}},addLabel:function(e,t,i,n,a){var o=[i,t],r=this.deepMerge(o,\"itemStyle.normal.label\"),s=this.deepMerge(o,\"itemStyle.emphasis.label\"),l=r.textStyle||{},h=s.textStyle||{};\n\nif(r.show){var m=e.style;m.text=this._getLabelText(t,i,n,\"normal\"),m.textPosition=null==r.position?\"horizontal\"===a?\"right\":\"top\":r.position,m.textColor=l.color,m.textFont=this.getFont(l),m.textAlign=l.align,m.textBaseline=l.baseline}if(s.show){var V=e.highlightStyle;V.text=this._getLabelText(t,i,n,\"emphasis\"),V.textPosition=r.show?e.style.textPosition:null==s.position?\"horizontal\"===a?\"right\":\"top\":s.position,V.textColor=h.color,V.textFont=this.getFont(h),V.textAlign=h.align,V.textBaseline=h.baseline}return e},_getLabelText:function(e,t,i,n){var a=this.deepQuery([t,e],\"itemStyle.\"+n+\".label.formatter\");a||\"emphasis\"!==n||(a=this.deepQuery([t,e],\"itemStyle.normal.label.formatter\"));var o=this.getDataFromOption(t,\"-\");return a?\"function\"==typeof a?a.call(this.myChart,{seriesName:e.name,series:e,name:i,value:o,data:t,status:n}):\"string\"==typeof a?a=a.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\").replace(\"{a0}\",e.name).replace(\"{b0}\",i).replace(\"{c0}\",this.numAddCommas(o)):void 0:o instanceof Array?null!=o[2]?this.numAddCommas(o[2]):o[0]+\" , \"+o[1]:this.numAddCommas(o)},buildMark:function(e){var t=this.series[e];this.selectedMap[t.name]&&(t.markLine&&this._buildMarkLine(e),t.markPoint&&this._buildMarkPoint(e))},_buildMarkPoint:function(e){for(var t,i,n=(this.markAttachStyle||{})[e],a=this.series[e],o=u.clone(a.markPoint),r=0,s=o.data.length;s>r;r++)t=o.data[r],i=this.getMarkCoord(e,t),t.x=null!=t.x?t.x:i[0],t.y=null!=t.y?t.y:i[1],!t.type||\"max\"!==t.type&&\"min\"!==t.type||(t.value=i[3],t.name=t.name||t.type,t.symbolSize=t.symbolSize||y.getTextWidth(i[3],this.getFont())/2+5);for(var l=this._markPoint(e,o),r=0,s=l.length;s>r;r++){var m=l[r];m.zlevel=a.zlevel,m.z=a.z+1;for(var V in n)m[V]=u.clone(n[V]);this.shapeList.push(m)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var r=0,s=l.length;s>r;r++)this.zr.addShape(l[r])},_buildMarkLine:function(e){for(var t,i=(this.markAttachStyle||{})[e],n=this.series[e],a=u.clone(n.markLine),o=0,r=a.data.length;r>o;o++){var s=a.data[o];!s.type||\"max\"!==s.type&&\"min\"!==s.type&&\"average\"!==s.type?t=[this.getMarkCoord(e,s[0]),this.getMarkCoord(e,s[1])]:(t=this.getMarkCoord(e,s),a.data[o]=[u.clone(s),{}],a.data[o][0].name=s.name||s.type,a.data[o][0].value=\"average\"!==s.type?t[3]:+t[3].toFixed(null!=a.precision?a.precision:this.deepQuery([this.ecTheme,h],\"markLine.precision\")),t=t[2],s=[{},{}]),null!=t&&null!=t[0]&&null!=t[1]&&(a.data[o][0].x=null!=s[0].x?s[0].x:t[0][0],a.data[o][0].y=null!=s[0].y?s[0].y:t[0][1],a.data[o][1].x=null!=s[1].x?s[1].x:t[1][0],a.data[o][1].y=null!=s[1].y?s[1].y:t[1][1])}var m=this._markLine(e,a),V=a.large;if(V){var U=new l({style:{shapeList:m}}),d=m[0];if(d){u.merge(U.style,d.style),u.merge(U.highlightStyle={},d.highlightStyle),U.style.brushType=\"stroke\",U.zlevel=n.zlevel,U.z=n.z+1,U.hoverable=!1;for(var p in i)U[p]=u.clone(i[p])}this.shapeList.push(U),this.zr.addShape(U),U._mark=\"largeLine\";var c=a.effect;c.show&&(U.effect=c)}else{for(var o=0,r=m.length;r>o;o++){var y=m[o];y.zlevel=n.zlevel,y.z=n.z+1;for(var p in i)y[p]=u.clone(i[p]);this.shapeList.push(y)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var o=0,r=m.length;r>o;o++)this.zr.addShape(m[o])}},_markPoint:function(e,t){var i=this.series[e],n=this.component;u.merge(u.merge(t,u.clone(this.ecTheme.markPoint||{})),u.clone(h.markPoint)),t.name=i.name;var a,o,r,s,l,V,U,d=[],p=t.data,c=n.dataRange,y=n.legend,g=this.zr.getWidth(),b=this.zr.getHeight();if(t.large)a=this.getLargeMarkPointShape(e,t),a._mark=\"largePoint\",a&&d.push(a);else for(var f=0,k=p.length;k>f;f++)null!=p[f].x&&null!=p[f].y&&(r=null!=p[f].value?p[f].value:\"\",y&&(o=y.getColor(i.name)),c&&(o=isNaN(r)?o:c.getColor(r),s=[p[f],t],l=this.deepQuery(s,\"itemStyle.normal.color\")||o,V=this.deepQuery(s,\"itemStyle.emphasis.color\")||l,null==l&&null==V)||(o=null==o?this.zr.getColor(e):o,p[f].tooltip=p[f].tooltip||t.tooltip||{trigger:\"item\"},p[f].name=null!=p[f].name?p[f].name:\"\",p[f].value=r,a=this.getSymbolShape(t,e,p[f],f,p[f].name,this.parsePercent(p[f].x,g),this.parsePercent(p[f].y,b),\"pin\",o,\"rgba(0,0,0,0)\",\"horizontal\"),a._mark=\"point\",U=this.deepMerge([p[f],t],\"effect\"),U.show&&(a.effect=U),i.type===h.CHART_TYPE_MAP&&(a._geo=this.getMarkGeo(p[f])),m.pack(a,i,e,p[f],f,p[f].name,r),d.push(a)));return d},_markLine:function(){function e(e,t){e[t]=e[t]instanceof Array?e[t].length>1?e[t]:[e[t][0],e[t][0]]:[e[t],e[t]]}return function(i,n){var a=this.series[i],o=this.component,r=o.dataRange,s=o.legend;u.merge(u.merge(n,u.clone(this.ecTheme.markLine||{})),u.clone(h.markLine));var l=s?s.getColor(a.name):this.zr.getColor(i);e(n,\"symbol\"),e(n,\"symbolSize\"),e(n,\"symbolRotate\");for(var V=n.data,U=[],d=this.zr.getWidth(),p=this.zr.getHeight(),y=0;y<V.length;y++){var g=V[y];if(t(g[0])&&t(g[1])){var b=this.deepMerge(g),f=[b,n],k=l,x=null!=b.value?b.value:\"\";if(r){k=isNaN(x)?k:r.getColor(x);var _=this.deepQuery(f,\"itemStyle.normal.color\")||k,L=this.deepQuery(f,\"itemStyle.emphasis.color\")||_;if(null==_&&null==L)continue}g[0].tooltip=b.tooltip||n.tooltip||{trigger:\"item\"},g[0].name=g[0].name||\"\",g[1].name=g[1].name||\"\",g[0].value=x,U.push({points:[[this.parsePercent(g[0].x,d),this.parsePercent(g[0].y,p)],[this.parsePercent(g[1].x,d),this.parsePercent(g[1].y,p)]],rawData:g,color:k})}}var W=this.query(n,\"bundling.enable\");if(W){var X=new c;X.maxTurningAngle=this.query(n,\"bundling.maxTurningAngle\")/180*Math.PI,U=X.run(U)}n.name=a.name;for(var v=[],y=0,w=U.length;w>y;y++){var K=U[y],I=K.rawEdge||K,g=I.rawData,x=null!=g.value?g.value:\"\",J=this.getMarkLineShape(n,i,g,y,K.points,W,I.color);J._mark=\"line\";var C=this.deepMerge([g[0],g[1],n],\"effect\");C.show&&(J.effect=C,J.effect.large=n.large),a.type===h.CHART_TYPE_MAP&&(J._geo=[this.getMarkGeo(g[0]),this.getMarkGeo(g[1])]),m.pack(J,a,i,g[0],y,g[0].name+(\"\"!==g[1].name?\" > \"+g[1].name:\"\"),x),v.push(J)}return v}}(),getMarkCoord:function(){return[0,0]},getSymbolShape:function(e,t,i,o,r,s,l,h,V,U,d){var p=[i,e],c=this.getDataFromOption(i,\"-\");h=this.deepQuery(p,\"symbol\")||h;var u=this.deepQuery(p,\"symbolSize\");u=\"function\"==typeof u?u(c):u,\"number\"==typeof u&&(u=[u,u]);var y=this.deepQuery(p,\"symbolRotate\"),g=this.deepMerge(p,\"itemStyle.normal\"),b=this.deepMerge(p,\"itemStyle.emphasis\"),f=null!=g.borderWidth?g.borderWidth:g.lineStyle&&g.lineStyle.width;null==f&&(f=h.match(\"empty\")?2:0);var k=null!=b.borderWidth?b.borderWidth:b.lineStyle&&b.lineStyle.width;null==k&&(k=f+2);var x=this.getItemStyleColor(g.color,t,o,i),_=this.getItemStyleColor(b.color,t,o,i),L=u[0],W=u[1],X=new a({style:{iconType:h.replace(\"empty\",\"\").toLowerCase(),x:s-L,y:l-W,width:2*L,height:2*W,brushType:\"both\",color:h.match(\"empty\")?U:x||V,strokeColor:g.borderColor||x||V,lineWidth:f},highlightStyle:{color:h.match(\"empty\")?U:_||x||V,strokeColor:b.borderColor||g.borderColor||_||x||V,lineWidth:k},clickable:this.deepQuery(p,\"clickable\")});return h.match(\"image\")&&(X.style.image=h.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),X=new n({style:X.style,highlightStyle:X.highlightStyle,clickable:this.deepQuery(p,\"clickable\")})),null!=y&&(X.rotation=[y*Math.PI/180,s,l]),h.match(\"star\")&&(X.style.iconType=\"star\",X.style.n=h.replace(\"empty\",\"\").replace(\"star\",\"\")-0||5),\"none\"===h&&(X.invisible=!0,X.hoverable=!1),X=this.addLabel(X,e,i,r,d),h.match(\"empty\")&&(null==X.style.textColor&&(X.style.textColor=X.style.strokeColor),null==X.highlightStyle.textColor&&(X.highlightStyle.textColor=X.highlightStyle.strokeColor)),m.pack(X,e,t,i,o,r),X._x=s,X._y=l,X._dataIndex=o,X._seriesIndex=t,X},getMarkLineShape:function(e,t,i,n,a,r,l){var h=null!=i[0].value?i[0].value:\"-\",m=null!=i[1].value?i[1].value:\"-\",V=[i[0].symbol||e.symbol[0],i[1].symbol||e.symbol[1]],U=[i[0].symbolSize||e.symbolSize[0],i[1].symbolSize||e.symbolSize[1]];U[0]=\"function\"==typeof U[0]?U[0](h):U[0],U[1]=\"function\"==typeof U[1]?U[1](m):U[1];var d=[this.query(i[0],\"symbolRotate\")||e.symbolRotate[0],this.query(i[1],\"symbolRotate\")||e.symbolRotate[1]],p=[i[0],i[1],e],c=this.deepMerge(p,\"itemStyle.normal\");c.color=this.getItemStyleColor(c.color,t,n,i);var u=this.deepMerge(p,\"itemStyle.emphasis\");u.color=this.getItemStyleColor(u.color,t,n,i);var y=c.lineStyle,g=u.lineStyle,b=y.width;null==b&&(b=c.borderWidth);var f=g.width;null==f&&(f=null!=u.borderWidth?u.borderWidth:b+2);var k=this.deepQuery(p,\"smoothness\");this.deepQuery(p,\"smooth\")||(k=0);var x=r?s:o,_=new x({style:{symbol:V,symbolSize:U,symbolRotate:d,brushType:\"both\",lineType:y.type,shadowColor:y.shadowColor||y.color||c.borderColor||c.color||l,shadowBlur:y.shadowBlur,shadowOffsetX:y.shadowOffsetX,shadowOffsetY:y.shadowOffsetY,color:c.color||l,strokeColor:y.color||c.borderColor||c.color||l,lineWidth:b,symbolBorderColor:c.borderColor||c.color||l,symbolBorder:c.borderWidth},highlightStyle:{shadowColor:g.shadowColor,shadowBlur:g.shadowBlur,shadowOffsetX:g.shadowOffsetX,shadowOffsetY:g.shadowOffsetY,color:u.color||c.color||l,strokeColor:g.color||y.color||u.borderColor||c.borderColor||u.color||c.color||l,lineWidth:f,symbolBorderColor:u.borderColor||c.borderColor||u.color||c.color||l,symbolBorder:null==u.borderWidth?c.borderWidth+2:u.borderWidth},clickable:this.deepQuery(p,\"clickable\")}),L=_.style;return r?(L.pointList=a,L.smooth=k):(L.xStart=a[0][0],L.yStart=a[0][1],L.xEnd=a[1][0],L.yEnd=a[1][1],L.curveness=k,_.updatePoints(_.style)),_=this.addLabel(_,e,i[0],i[0].name+\" : \"+i[1].name)},getLargeMarkPointShape:function(e,t){var i,n,a,o,s,l,h=this.series[e],m=this.component,V=t.data,U=m.dataRange,d=m.legend,p=[V[0],t];if(d&&(n=d.getColor(h.name)),!U||(a=null!=V[0].value?V[0].value:\"\",n=isNaN(a)?n:U.getColor(a),o=this.deepQuery(p,\"itemStyle.normal.color\")||n,s=this.deepQuery(p,\"itemStyle.emphasis.color\")||o,null!=o||null!=s)){n=this.deepMerge(p,\"itemStyle.normal\").color||n;var c=this.deepQuery(p,\"symbol\")||\"circle\";c=c.replace(\"empty\",\"\").replace(/\\d/g,\"\"),l=this.deepMerge([V[0],t],\"effect\");var u=window.devicePixelRatio||1;return i=new r({style:{pointList:V,color:n,strokeColor:n,shadowColor:l.shadowColor||n,shadowBlur:(null!=l.shadowBlur?l.shadowBlur:8)*u,size:this.deepQuery(p,\"symbolSize\"),iconType:c,brushType:\"fill\",lineWidth:1},draggable:!1,hoverable:!1}),l.show&&(i.effect=l),i}},backupShapeList:function(){this.shapeList&&this.shapeList.length>0?(this.lastShapeList=this.shapeList,this.shapeList=[]):this.lastShapeList=[]},addShapeList:function(){var e,t,i=this.option.animationThreshold/(this.canvasSupported?2:4),n=this.lastShapeList,a=this.shapeList,o=n.length>0,r=o?this.query(this.option,\"animationDurationUpdate\"):this.query(this.option,\"animationDuration\"),s=this.query(this.option,\"animationEasing\"),l={},m={};if(this.option.animation&&!this.option.renderAsImage&&a.length<i&&!this.motionlessOnce){for(var V=0,U=n.length;U>V;V++)t=this._getAnimationKey(n[V]),t.match(\"undefined\")?this.zr.delShape(n[V].id):(t+=n[V].type,l[t]?this.zr.delShape(n[V].id):l[t]=n[V]);for(var V=0,U=a.length;U>V;V++)t=this._getAnimationKey(a[V]),t.match(\"undefined\")?this.zr.addShape(a[V]):(t+=a[V].type,m[t]=a[V]);for(t in l)m[t]||this.zr.delShape(l[t].id);for(t in m)l[t]?(this.zr.delShape(l[t].id),this._animateMod(l[t],m[t],r,s,0,o)):(e=this.type!=h.CHART_TYPE_LINE&&this.type!=h.CHART_TYPE_RADAR||0===t.indexOf(\"icon\")?0:r/2,this._animateMod(!1,m[t],r,s,e,o));this.zr.refresh(),this.animationEffect()}else{this.motionlessOnce=!1,this.zr.delShape(n);for(var V=0,U=a.length;U>V;V++)this.zr.addShape(a[V])}},_getAnimationKey:function(e){return this.type!=h.CHART_TYPE_MAP&&this.type!=h.CHART_TYPE_TREEMAP&&this.type!=h.CHART_TYPE_VENN&&this.type!=h.CHART_TYPE_TREE?m.get(e,\"seriesIndex\")+\"_\"+m.get(e,\"dataIndex\")+(e._mark?e._mark:\"\")+(this.type===h.CHART_TYPE_RADAR?m.get(e,\"special\"):\"\"):m.get(e,\"seriesIndex\")+\"_\"+m.get(e,\"dataIndex\")+(e._mark?e._mark:\"undefined\")},_animateMod:function(e,t,i,n,a,o){switch(t.type){case\"polyline\":case\"half-smooth-polygon\":V.pointList(this.zr,e,t,i,n);break;case\"rectangle\":V.rectangle(this.zr,e,t,i,n);break;case\"image\":case\"icon\":V.icon(this.zr,e,t,i,n,a);break;case\"candle\":o?this.zr.addShape(t):V.candle(this.zr,e,t,i,n);break;case\"ring\":case\"sector\":case\"circle\":o?\"sector\"===t.type?V.sector(this.zr,e,t,i,n):this.zr.addShape(t):V.ring(this.zr,e,t,i+(m.get(t,\"dataIndex\")||0)%20*100,n);break;case\"text\":V.text(this.zr,e,t,i,n);break;case\"polygon\":o?V.pointList(this.zr,e,t,i,n):V.polygon(this.zr,e,t,i,n);break;case\"ribbon\":V.ribbon(this.zr,e,t,i,n);break;case\"gauge-pointer\":V.gaugePointer(this.zr,e,t,i,n);break;case\"mark-line\":V.markline(this.zr,e,t,i,n);break;case\"bezier-curve\":case\"line\":V.line(this.zr,e,t,i,n);break;default:this.zr.addShape(t)}},animationMark:function(e,t,i){for(var i=i||this.shapeList,n=0,a=i.length;a>n;n++)i[n]._mark&&this._animateMod(!1,i[n],e,t,0,!0);this.animationEffect(i)},animationEffect:function(e){if(!e&&this.clearEffectShape(),e=e||this.shapeList,null!=e){var t=h.EFFECT_ZLEVEL;this.canvasSupported&&this.zr.modLayer(t,{motionBlur:!0,lastFrameAlpha:this.option.effectBlendAlpha||h.effectBlendAlpha});for(var i,n=0,a=e.length;a>n;n++)i=e[n],i._mark&&i.effect&&i.effect.show&&U[i._mark]&&(U[i._mark](this.zr,this.effectList,i,t),this.effectList[this.effectList.length-1]._mark=i._mark)}},clearEffectShape:function(e){var t=this.effectList;if(this.zr&&t&&t.length>0){e&&this.zr.modLayer(h.EFFECT_ZLEVEL,{motionBlur:!1}),this.zr.delShape(t);for(var i=0;i<t.length;i++)t[i].effectAnimator&&t[i].effectAnimator.stop()}this.effectList=[]},addMark:function(e,t,i){var n=this.series[e];if(this.selectedMap[n.name]){var a=this.query(this.option,\"animationDurationUpdate\"),o=this.query(this.option,\"animationEasing\"),r=n[i].data,s=this.shapeList.length;if(n[i].data=t.data,this[\"_build\"+i.replace(\"m\",\"M\")](e),this.option.animation&&!this.option.renderAsImage)this.animationMark(a,o,this.shapeList.slice(s));else{for(var l=s,h=this.shapeList.length;h>l;l++)this.zr.addShape(this.shapeList[l]);this.zr.refreshNextFrame()}n[i].data=r}},delMark:function(e,t,i){i=i.replace(\"mark\",\"\").replace(\"large\",\"\").toLowerCase();var n=this.series[e];if(this.selectedMap[n.name]){for(var a=!1,o=[this.shapeList,this.effectList],r=2;r--;)for(var s=0,l=o[r].length;l>s;s++)if(o[r][s]._mark==i&&m.get(o[r][s],\"seriesIndex\")==e&&m.get(o[r][s],\"name\")==t){this.zr.delShape(o[r][s].id),o[r].splice(s,1),a=!0;break}a&&this.zr.refreshNextFrame()}}},u.inherits(i,p),i}),i(\"zrender/shape/Circle\",[\"require\",\"./Base\",\"../tool/util\"],function(e){\"use strict\";var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={type:\"circle\",buildPath:function(e,t){e.moveTo(t.x+t.r,t.y),e.arc(t.x,t.y,t.r,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e(\"../tool/util\").inherits(i,t),i}),i(\"echarts/util/accMath\",[],function(){function e(e,t){var i=e.toString(),n=t.toString(),a=0;try{a=n.split(\".\")[1].length}catch(o){}try{a-=i.split(\".\")[1].length}catch(o){}return(i.replace(\".\",\"\")-0)/(n.replace(\".\",\"\")-0)*Math.pow(10,a)}function t(e,t){var i=e.toString(),n=t.toString(),a=0;try{a+=i.split(\".\")[1].length}catch(o){}try{a+=n.split(\".\")[1].length}catch(o){}return(i.replace(\".\",\"\")-0)*(n.replace(\".\",\"\")-0)/Math.pow(10,a)}function i(e,t){var i=0,n=0;try{i=e.toString().split(\".\")[1].length}catch(a){}try{n=t.toString().split(\".\")[1].length}catch(a){}var o=Math.pow(10,Math.max(i,n));return(Math.round(e*o)+Math.round(t*o))/o}function n(e,t){return i(e,-t)}return{accDiv:e,accMul:t,accAdd:i,accSub:n}}),i(\"echarts/util/shape/Icon\",[\"require\",\"zrender/tool/util\",\"zrender/shape/Star\",\"zrender/shape/Heart\",\"zrender/shape/Droplet\",\"zrender/shape/Image\",\"zrender/shape/Base\"],function(e){function t(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o),e.moveTo(i+13*a,n+10*o),e.lineTo(i+13*a,n+t.height)}function i(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o)}function n(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+4*a,n+15*o),e.lineTo(i+9*a,n+13*o),e.lineTo(i+14*a,n+8*o),e.lineTo(i+11*a,n+5*o),e.lineTo(i+6*a,n+10*o),e.lineTo(i+4*a,n+15*o),e.moveTo(i+5*a,n),e.lineTo(i+11*a,n),e.moveTo(i+5*a,n+o),e.lineTo(i+11*a,n+o),e.moveTo(i,n+2*o),e.lineTo(i+t.width,n+2*o),e.moveTo(i,n+5*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+13*a,n+t.height),e.lineTo(i+t.width,n+5*o)}function a(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+3*o),e.lineTo(i+6*a,n+3*o),e.moveTo(i+3*a,n),e.lineTo(i+3*a,n+6*o),e.moveTo(i+3*a,n+8*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n+3*o),e.lineTo(i+8*a,n+3*o)}function o(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+6*a,n),e.lineTo(i+2*a,n+3*o),e.lineTo(i+6*a,n+6*o),e.moveTo(i+2*a,n+3*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+14*a,n+11*o),e.moveTo(i+2*a,n+5*o),e.lineTo(i+2*a,n+13*o),e.lineTo(i+14*a,n+13*o),e.moveTo(i+10*a,n+10*o),e.lineTo(i+14*a,n+13*o),e.lineTo(i+10*a,n+t.height)}function r(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16,r=t.width/2;e.lineWidth=1.5,e.arc(i+r,n+r,r-a,0,2*Math.PI/3),e.moveTo(i+3*a,n+t.height),e.lineTo(i+0*a,n+12*o),e.lineTo(i+5*a,n+11*o),e.moveTo(i,n+8*o),e.arc(i+r,n+r,r-a,Math.PI,5*Math.PI/3),e.moveTo(i+13*a,n),e.lineTo(i+t.width,n+4*o),e.lineTo(i+11*a,n+5*o)}function s(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+2*a,n+14*o),e.lineTo(i+7*a,n+6*o),e.lineTo(i+11*a,n+11*o),e.lineTo(i+15*a,n+2*o)}function l(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+3*a,n+14*o),e.lineTo(i+3*a,n+6*o),e.lineTo(i+4*a,n+6*o),e.lineTo(i+4*a,n+14*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+7*a,n+2*o),e.lineTo(i+8*a,n+2*o),e.lineTo(i+8*a,n+14*o),e.moveTo(i+11*a,n+14*o),e.lineTo(i+11*a,n+9*o),e.lineTo(i+12*a,n+9*o),e.lineTo(i+12*a,n+14*o)}function h(e,t){var i=t.x,n=t.y,a=t.width-2,o=t.height-2,r=Math.min(a,o)/2;n+=2,e.moveTo(i+r+3,n+r-3),e.arc(i+r+3,n+r-3,r-1,0,-Math.PI/2,!0),e.lineTo(i+r+3,n+r-3),e.moveTo(i+r,n),e.lineTo(i+r,n+r),e.arc(i+r,n+r,r,-Math.PI/2,2*Math.PI,!0),e.lineTo(i+r,n+r),e.lineWidth=1.5}function m(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;n-=o,e.moveTo(i+1*a,n+2*o),e.lineTo(i+15*a,n+2*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+2*a,n+3*o),e.moveTo(i+3*a,n+6*o),e.lineTo(i+13*a,n+6*o),e.lineTo(i+12*a,n+7*o),e.lineTo(i+4*a,n+7*o),e.moveTo(i+5*a,n+10*o),e.lineTo(i+11*a,n+10*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+9*a,n+14*o),e.lineTo(i+8*a,n+15*o),e.lineTo(i+7*a,n+15*o)}function V(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=a/16,s=o/16,l=2*Math.min(r,s);e.moveTo(i+r+l,n+s+l),e.arc(i+r,n+s,l,Math.PI/4,3*Math.PI),e.lineTo(i+7*r-l,n+6*s-l),e.arc(i+7*r,n+6*s,l,Math.PI/4*5,4*Math.PI),e.arc(i+7*r,n+6*s,l/2,Math.PI/4*5,4*Math.PI),e.moveTo(i+7*r-l/2,n+6*s+l),e.lineTo(i+r+l,n+14*s-l),e.arc(i+r,n+14*s,l,-Math.PI/4,2*Math.PI),e.moveTo(i+7*r+l/2,n+6*s),e.lineTo(i+14*r-l,n+10*s-l/2),e.moveTo(i+16*r,n+10*s),e.arc(i+14*r,n+10*s,l,0,3*Math.PI),e.lineWidth=1.5}function U(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.min(a,o)/2;e.moveTo(i+a,n+o/2),e.arc(i+r,n+r,r,0,2*Math.PI),e.arc(i+r,n,r,Math.PI/4,Math.PI/5*4),e.arc(i,n+r,r,-Math.PI/3,Math.PI/3),e.arc(i+a,n+o,r,Math.PI,Math.PI/2*3),e.lineWidth=1.5}function d(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(o/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i,n+r*l+s,a,2)}function p(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(a/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i+r*l+s,n,2,o)}function c(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+15*a,n+t.height),e.lineTo(i+15*a,n),e.lineTo(i+a,n),e.moveTo(i+3*a,n+3*a),e.lineTo(i+13*a,n+3*a),e.moveTo(i+3*a,n+6*a),e.lineTo(i+13*a,n+6*a),e.moveTo(i+3*a,n+9*a),e.lineTo(i+13*a,n+9*a),e.moveTo(i+3*a,n+12*a),e.lineTo(i+9*a,n+12*a)}function u(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n),e.lineTo(i,n),e.moveTo(i+4*a,n),e.lineTo(i+4*a,n+8*o),e.lineTo(i+12*a,n+8*o),e.lineTo(i+12*a,n),e.moveTo(i+6*a,n+11*o),e.lineTo(i+6*a,n+13*o),e.lineTo(i+10*a,n+13*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o)}function y(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o/2),e.lineTo(i+a,n+o/2),e.moveTo(i+a/2,n),e.lineTo(i+a/2,n+o)}function g(e,t){var i=t.width/2,n=t.height/2,a=Math.min(i,n);e.moveTo(t.x+i+a,t.y+n),e.arc(t.x+i,t.y+n,a,0,2*Math.PI),e.closePath()}function b(e,t){e.rect(t.x,t.y,t.width,t.height),e.closePath()}function f(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o+r),e.lineTo(a-r,o+r),e.lineTo(a,o-r),e.closePath()}function k(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o),e.lineTo(a,o+r),e.lineTo(a-r,o),e.lineTo(a,o-r),e.closePath()}function x(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+8*a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+8*a,n+t.height/4*3),e.lineTo(i+15*a,n+t.height),e.lineTo(i+8*a,n),e.closePath()}function _(t,i){var n=e(\"zrender/shape/Star\"),a=i.width/2,o=i.height/2;n.prototype.buildPath(t,{x:i.x+a,y:i.y+o,r:Math.min(a,o),n:i.n||5})}function L(t,i){var n=e(\"zrender/shape/Heart\");n.prototype.buildPath(t,{x:i.x+i.width/2,y:i.y+.2*i.height,a:i.width/2,b:.8*i.height})}function W(t,i){var n=e(\"zrender/shape/Droplet\");n.prototype.buildPath(t,{x:i.x+.5*i.width,y:i.y+.5*i.height,a:.5*i.width,b:.8*i.height})}function X(e,t){var i=t.x,n=t.y-t.height/2*1.5,a=t.width/2,o=t.height/2,r=Math.min(a,o);e.arc(i+a,n+o,r,Math.PI/5*4,Math.PI/5),e.lineTo(i+a,n+o+1.5*r),e.closePath()}function v(t,i,n){var a=e(\"zrender/shape/Image\");this._imageShape=this._imageShape||new a({style:{}});for(var o in i)this._imageShape.style[o]=i[o];this._imageShape.brush(t,!1,n)}function w(e){I.call(this,e)}var K=e(\"zrender/tool/util\"),I=e(\"zrender/shape/Base\");return w.prototype={type:\"icon\",iconLibrary:{mark:t,markUndo:i,markClear:n,dataZoom:a,dataZoomReset:o,restore:r,lineChart:s,barChart:l,pieChart:h,funnelChart:m,forceChart:V,chordChart:U,stackChart:d,tiledChart:p,dataView:c,saveAsImage:u,cross:y,circle:g,rectangle:b,triangle:f,diamond:k,arrow:x,star:_,heart:L,droplet:W,pin:X,image:v},brush:function(t,i,n){var a=i?this.highlightStyle:this.style;a=a||{};var o=a.iconType||this.style.iconType;if(\"image\"===o){var r=e(\"zrender/shape/Image\");r.prototype.brush.call(this,t,i,n)}else{var a=this.beforeBrush(t,i);switch(t.beginPath(),this.buildPath(t,a,n),a.brushType){case\"both\":t.fill();case\"stroke\":a.lineWidth>0&&t.stroke();break;default:t.fill()}this.drawText(t,a,this.style),this.afterBrush(t)}},buildPath:function(e,t,i){this.iconLibrary[t.iconType]?this.iconLibrary[t.iconType].call(this,e,t,i):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y),e.closePath())},getRect:function(e){return e.__rect?e.__rect:(e.__rect={x:Math.round(e.x),y:Math.round(e.y-(\"pin\"==e.iconType?e.height/2*1.5:0)),width:e.width,height:e.height*(\"pin\"===e.iconType?1.25:1)},e.__rect)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.__rect;n||(n=this.style.__rect=this.getRect(this.style));var a=n.height<8||n.width<8?4:0;return e>=n.x-a&&e<=n.x+n.width+a&&t>=n.y-a&&t<=n.y+n.height+a}},K.inherits(w,I),w}),i(\"echarts/util/shape/MarkLine\",[\"require\",\"zrender/shape/Base\",\"./Icon\",\"zrender/shape/Line\",\"zrender/shape/BezierCurve\",\"zrender/tool/area\",\"zrender/shape/util/dashedLineTo\",\"zrender/tool/util\",\"zrender/tool/curve\"],function(e){function t(e){i.call(this,e),this.style.curveness>0&&this.updatePoints(this.style),this.highlightStyle.curveness>0&&this.updatePoints(this.highlightStyle)}var i=e(\"zrender/shape/Base\"),n=e(\"./Icon\"),a=e(\"zrender/shape/Line\"),o=new a({}),r=e(\"zrender/shape/BezierCurve\"),s=new r({}),l=e(\"zrender/tool/area\"),h=e(\"zrender/shape/util/dashedLineTo\"),m=e(\"zrender/tool/util\"),V=e(\"zrender/tool/curve\");return t.prototype={type:\"mark-line\",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildPath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i,0),this.brushSymbol(e,i,1),this.drawText(e,i,this.style),e.restore()},buildPath:function(e,t){var i=t.lineType||\"solid\";if(e.moveTo(t.xStart,t.yStart),t.curveness>0){var n=null;switch(i){case\"dashed\":n=[5,5];break;case\"dotted\":n=[1,1]}n&&e.setLineDash&&e.setLineDash(n),e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)}else if(\"solid\"==i)e.lineTo(t.xEnd,t.yEnd);else{var a=(t.lineWidth||1)*(\"dashed\"==t.lineType?5:1);h(e,t.xStart,t.yStart,t.xEnd,t.yEnd,a)}},updatePoints:function(e){var t=e.curveness||0,i=1,n=e.xStart,a=e.yStart,o=e.xEnd,r=e.yEnd,s=(n+o)/2-i*(a-r)*t,l=(a+r)/2-i*(o-n)*t;e.cpX1=s,e.cpY1=l},brushSymbol:function(e,t,i){if(\"none\"!=t.symbol[i]){e.save(),e.beginPath(),e.lineWidth=t.symbolBorder,e.strokeStyle=t.symbolBorderColor;var a=t.symbol[i].replace(\"empty\",\"\").toLowerCase();t.symbol[i].match(\"empty\")&&(e.fillStyle=\"#fff\");var o=t.xStart,r=t.yStart,s=t.xEnd,l=t.yEnd,h=0===i?o:s,m=0===i?r:l,U=t.curveness||0,d=null!=t.symbolRotate[i]?t.symbolRotate[i]-0:0;if(d=d/180*Math.PI,\"arrow\"==a&&0===d)if(0===U){var p=0===i?-1:1;d=Math.PI/2+Math.atan2(p*(l-r),p*(s-o))}else{var c=t.cpX1,u=t.cpY1,y=V.quadraticDerivativeAt,g=y(o,c,s,i),b=y(r,u,l,i);d=Math.PI/2+Math.atan2(b,g)}e.translate(h,m),0!==d&&e.rotate(d);var f=t.symbolSize[i];n.prototype.buildPath(e,{x:-f,y:-f,width:2*f,height:2*f,iconType:a}),e.closePath(),e.fill(),e.stroke(),e.restore()}},getRect:function(e){return e.curveness>0?s.getRect(e):o.getRect(e),e.__rect},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)?this.style.curveness>0?l.isInside(s,this.style,e,t):l.isInside(o,this.style,e,t):!1}},m.inherits(t,i),t}),i(\"echarts/util/shape/Symbol\",[\"require\",\"zrender/shape/Base\",\"zrender/shape/Polygon\",\"zrender/tool/util\",\"./normalIsCover\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/shape/Polygon\"),a=new n({}),o=e(\"zrender/tool/util\");return t.prototype={type:\"symbol\",buildPath:function(e,t){var i=t.pointList,n=i.length;if(0!==n)for(var a,o,r,s,l,h=1e4,m=Math.ceil(n/h),V=i[0]instanceof Array,U=t.size?t.size:2,d=U,p=U/2,c=2*Math.PI,u=0;m>u;u++){e.beginPath(),a=u*h,o=a+h,o=o>n?n:o;for(var y=a;o>y;y++)if(t.random&&(r=t[\"randomMap\"+y%20]/100,d=U*r*r,p=d/2),V?(s=i[y][0],l=i[y][1]):(s=i[y].x,l=i[y].y),3>d)e.rect(s-p,l-p,d,d);else switch(t.iconType){case\"circle\":e.moveTo(s,l),e.arc(s,l,p,0,c,!0);break;case\"diamond\":e.moveTo(s,l-p),e.lineTo(s+p/3,l-p/3),e.lineTo(s+p,l),e.lineTo(s+p/3,l+p/3),e.lineTo(s,l+p),e.lineTo(s-p/3,l+p/3),e.lineTo(s-p,l),e.lineTo(s-p/3,l-p/3),e.lineTo(s,l-p);break;default:e.rect(s-p,l-p,d,d)}if(e.closePath(),m-1>u)switch(t.brushType){case\"both\":e.fill(),t.lineWidth>0&&e.stroke();break;case\"stroke\":t.lineWidth>0&&e.stroke();break;default:e.fill()}}},getRect:function(e){return e.__rect||a.getRect(e)},isCover:e(\"./normalIsCover\")},o.inherits(t,i),t}),i(\"zrender/shape/Polyline\",[\"require\",\"./Base\",\"./util/smoothSpline\",\"./util/smoothBezier\",\"./util/dashedLineTo\",\"./Polygon\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=e(\"./util/smoothSpline\"),n=e(\"./util/smoothBezier\"),a=e(\"./util/dashedLineTo\"),o=function(e){this.brushTypeOnly=\"stroke\",this.textPosition=\"end\",t.call(this,e)};return o.prototype={type:\"polyline\",buildPath:function(e,t){var n=t.pointList;if(!(n.length<2)){var o=Math.min(t.pointList.length,Math.round(t.pointListLength||t.pointList.length));if(t.smooth&&\"spline\"!==t.smooth){t.controlPointList||this.updateControlPoints(t);var r=t.controlPointList;e.moveTo(n[0][0],n[0][1]);for(var s,l,h,m=0;o-1>m;m++)s=r[2*m],l=r[2*m+1],h=n[m+1],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if(\"spline\"===t.smooth&&(n=i(n),o=n.length),t.lineType&&\"solid\"!=t.lineType){if(\"dashed\"==t.lineType||\"dotted\"==t.lineType){var V=(t.lineWidth||1)*(\"dashed\"==t.lineType?5:1);e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)a(e,n[m-1][0],n[m-1][1],n[m][0],n[m][1],V)}}else{e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)e.lineTo(n[m][0],n[m][1])}}},updateControlPoints:function(e){e.controlPointList=n(e.pointList,e.smooth,!1,e.smoothConstraint)},getRect:function(t){return e(\"./Polygon\").prototype.getRect(t)}},e(\"../tool/util\").inherits(o,t),o}),i(\"zrender/shape/ShapeBundle\",[\"require\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={constructor:i,type:\"shape-bundle\",brush:function(e,t){var i=this.beforeBrush(e,t);e.beginPath();for(var n=0;n<i.shapeList.length;n++){var a=i.shapeList[n],o=a.style;t&&(o=a.getHighlightStyle(o,a.highlightStyle||{},a.brushTypeOnly)),a.buildPath(e,o)}switch(i.brushType){case\"both\":e.fill();case\"stroke\":i.lineWidth>0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},getRect:function(e){if(e.__rect)return e.__rect;for(var t=1/0,i=-(1/0),n=1/0,a=-(1/0),o=0;o<e.shapeList.length;o++)var r=e.shapeList[o],s=r.getRect(r.style),t=Math.min(s.x,t),n=Math.min(s.y,n),i=Math.max(s.x+s.width,i),a=Math.max(s.y+s.height,a);return e.__rect={x:t,y:n,width:i-t,height:a-n},e.__rect},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);if(e=i[0],t=i[1],this.isCoverRect(e,t))for(var n=0;n<this.style.shapeList.length;n++){var a=this.style.shapeList[n];if(a.isCover(e,t))return!0}return!1}},e(\"../tool/util\").inherits(i,t),i}),i(\"echarts/util/ecAnimation\",[\"require\",\"zrender/tool/util\",\"zrender/tool/curve\",\"zrender/shape/Polygon\"],function(e){function t(e,t,i,n,a){var o,r=i.style.pointList,s=r.length;if(!t){if(o=[],\"vertical\"!=i._orient)for(var l=r[0][1],h=0;s>h;h++)o[h]=[r[h][0],l];else for(var m=r[0][0],h=0;s>h;h++)o[h]=[m,r[h][1]];\"half-smooth-polygon\"==i.type&&(o[s-1]=p.clone(r[s-1]),o[s-2]=p.clone(r[s-2])),t={style:{pointList:o}}}o=t.style.pointList;var V=o.length;i.style.pointList=V==s?o:s>V?o.concat(r.slice(V)):o.slice(0,s),e.addShape(i),i.__animating=!0,e.animate(i.id,\"style\").when(n,{pointList:r}).during(function(){i.updateControlPoints&&i.updateControlPoints(i.style)}).done(function(){i.__animating=!1}).start(a)}function i(e,t){for(var i=arguments.length,n=2;i>n;n++){var a=arguments[n];e.style[a]=t.style[a]}}function n(e,t,n,a,o){var r=n.style;t||(t={position:n.position,style:{x:r.x,y:\"vertical\"==n._orient?r.y+r.height:r.y,width:\"vertical\"==n._orient?r.width:0,height:\"vertical\"!=n._orient?r.height:0}});var s=r.x,l=r.y,h=r.width,m=r.height,V=[n.position[0],n.position[1]];i(n,t,\"x\",\"y\",\"width\",\"height\"),n.position=t.position,e.addShape(n),(V[0]!=t.position[0]||V[1]!=t.position[1])&&e.animate(n.id,\"\").when(a,{position:V}).start(o),n.__animating=!0,e.animate(n.id,\"style\").when(a,{x:s,y:l,width:h,height:m}).done(function(){n.__animating=!1}).start(o)}function a(e,t,i,n,a){if(!t){var o=i.style.y;t={style:{y:[o[0],o[0],o[0],o[0]]}}}var r=i.style.y;i.style.y=t.style.y,e.addShape(i),i.__animating=!0,e.animate(i.id,\"style\").when(n,{y:r}).done(function(){i.__animating=!1}).start(a)}function o(e,t,i,n,a){var o=i.style.x,r=i.style.y,s=i.style.r0,l=i.style.r;i.__animating=!0,\"r\"!=i._animationAdd?(i.style.r0=0,i.style.r=0,i.rotation=[2*Math.PI,o,r],e.addShape(i),e.animate(i.id,\"style\").when(n,{r0:s,r:l}).done(function(){i.__animating=!1}).start(a),e.animate(i.id,\"\").when(n,{rotation:[0,o,r]}).start(a)):(i.style.r0=i.style.r,e.addShape(i),e.animate(i.id,\"style\").when(n,{r0:s}).done(function(){i.__animating=!1}).start(a))}function r(e,t,n,a,o){t||(t=\"r\"!=n._animationAdd?{\nstyle:{startAngle:n.style.startAngle,endAngle:n.style.startAngle}}:{style:{r0:n.style.r}});var r=n.style.startAngle,s=n.style.endAngle;i(n,t,\"startAngle\",\"endAngle\"),e.addShape(n),n.__animating=!0,e.animate(n.id,\"style\").when(a,{startAngle:r,endAngle:s}).done(function(){n.__animating=!1}).start(o)}function s(e,t,n,a,o){t||(t={style:{x:\"left\"==n.style.textAlign?n.style.x+100:n.style.x-100,y:n.style.y}});var r=n.style.x,s=n.style.y;i(n,t,\"x\",\"y\"),e.addShape(n),n.__animating=!0,e.animate(n.id,\"style\").when(a,{x:r,y:s}).done(function(){n.__animating=!1}).start(o)}function l(t,i,n,a,o){var r=e(\"zrender/shape/Polygon\").prototype.getRect(n.style),s=r.x+r.width/2,l=r.y+r.height/2;n.scale=[.1,.1,s,l],t.addShape(n),n.__animating=!0,t.animate(n.id,\"\").when(a,{scale:[1,1,s,l]}).done(function(){n.__animating=!1}).start(o)}function h(e,t,n,a,o){t||(t={style:{source0:0,source1:n.style.source1>0?360:-360,target0:0,target1:n.style.target1>0?360:-360}});var r=n.style.source0,s=n.style.source1,l=n.style.target0,h=n.style.target1;t.style&&i(n,t,\"source0\",\"source1\",\"target0\",\"target1\"),e.addShape(n),n.__animating=!0,e.animate(n.id,\"style\").when(a,{source0:r,source1:s,target0:l,target1:h}).done(function(){n.__animating=!1}).start(o)}function m(e,t,i,n,a){t||(t={style:{angle:i.style.startAngle}});var o=i.style.angle;i.style.angle=t.style.angle,e.addShape(i),i.__animating=!0,e.animate(i.id,\"style\").when(n,{angle:o}).done(function(){i.__animating=!1}).start(a)}function V(e,t,i,a,o,r){if(i.style._x=i.style.x,i.style._y=i.style.y,i.style._width=i.style.width,i.style._height=i.style.height,t)n(e,t,i,a,o);else{var s=i._x||0,l=i._y||0;i.scale=[.01,.01,s,l],e.addShape(i),i.__animating=!0,e.animate(i.id,\"\").delay(r).when(a,{scale:[1,1,s,l]}).done(function(){i.__animating=!1}).start(o||\"QuinticOut\")}}function U(e,t,n,a,o){t||(t={style:{xStart:n.style.xStart,yStart:n.style.yStart,xEnd:n.style.xStart,yEnd:n.style.yStart}});var r=n.style.xStart,s=n.style.xEnd,l=n.style.yStart,h=n.style.yEnd;i(n,t,\"xStart\",\"xEnd\",\"yStart\",\"yEnd\"),e.addShape(n),n.__animating=!0,e.animate(n.id,\"style\").when(a,{xStart:r,xEnd:s,yStart:l,yEnd:h}).done(function(){n.__animating=!1}).start(o)}function d(e,t,i,n,a){a=a||\"QuinticOut\",i.__animating=!0,e.addShape(i);var o=i.style,r=function(){i.__animating=!1},s=o.xStart,l=o.yStart,h=o.xEnd,m=o.yEnd;if(o.curveness>0){i.updatePoints(o);var V={p:0},U=o.cpX1,d=o.cpY1,p=[],u=[],y=c.quadraticSubdivide;e.animation.animate(V).when(n,{p:1}).during(function(){y(s,U,h,V.p,p),y(l,d,m,V.p,u),o.cpX1=p[1],o.cpY1=u[1],o.xEnd=p[2],o.yEnd=u[2],e.modShape(i)}).done(r).start(a)}else e.animate(i.id,\"style\").when(0,{xEnd:s,yEnd:l}).when(n,{xEnd:h,yEnd:m}).done(r).start(a)}var p=e(\"zrender/tool/util\"),c=e(\"zrender/tool/curve\");return{pointList:t,rectangle:n,candle:a,ring:o,sector:r,text:s,polygon:l,ribbon:h,gaugePointer:m,icon:V,line:U,markline:d}}),i(\"echarts/util/ecEffect\",[\"require\",\"../util/ecData\",\"zrender/shape/Circle\",\"zrender/shape/Image\",\"zrender/tool/curve\",\"../util/shape/Icon\",\"../util/shape/Symbol\",\"zrender/shape/ShapeBundle\",\"zrender/shape/Polyline\",\"zrender/tool/vector\",\"zrender/tool/env\"],function(e){function t(e,t,i,n){var a,r=i.effect,l=r.color||i.style.strokeColor||i.style.color,m=r.shadowColor||l,V=r.scaleSize,U=r.bounceDistance,d=\"undefined\"!=typeof r.shadowBlur?r.shadowBlur:V;\"image\"!==i.type?(a=new h({zlevel:n,style:{brushType:\"stroke\",iconType:\"droplet\"!=i.style.iconType?i.style.iconType:\"circle\",x:d+1,y:d+1,n:i.style.n,width:i.style._width*V,height:i.style._height*V,lineWidth:1,strokeColor:l,shadowColor:m,shadowBlur:d},draggable:!1,hoverable:!1}),\"pin\"==i.style.iconType&&(a.style.y+=a.style.height/2*1.5),p&&(a.style.image=e.shapeToImage(a,a.style.width+2*d+2,a.style.height+2*d+2).style.image,a=new s({zlevel:a.zlevel,style:a.style,draggable:!1,hoverable:!1}))):a=new s({zlevel:n,style:i.style,draggable:!1,hoverable:!1}),o.clone(i,a),a.position=i.position,t.push(a),e.addShape(a);var c=\"image\"!==i.type?window.devicePixelRatio||1:1,u=(a.style.width/c-i.style._width)/2;a.style.x=i.style._x-u,a.style.y=i.style._y-u,\"pin\"==i.style.iconType&&(a.style.y-=i.style.height/2*1.5);var y=100*(r.period+10*Math.random());e.modShape(i.id,{invisible:!0});var g=a.style.x+a.style.width/2/c,b=a.style.y+a.style.height/2/c;\"scale\"===r.type?(e.modShape(a.id,{scale:[.1,.1,g,b]}),e.animate(a.id,\"\",r.loop).when(y,{scale:[1,1,g,b]}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()):e.animate(a.id,\"style\",r.loop).when(y,{y:a.style.y-U}).when(2*y,{y:a.style.y}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()}function i(e,t,i,n){var a=i.effect,o=a.color||i.style.strokeColor||i.style.color,r=a.scaleSize,s=a.shadowColor||o,l=\"undefined\"!=typeof a.shadowBlur?a.shadowBlur:2*r,h=window.devicePixelRatio||1,V=new m({zlevel:n,position:i.position,scale:i.scale,style:{pointList:i.style.pointList,iconType:i.style.iconType,color:o,strokeColor:o,shadowColor:s,shadowBlur:l*h,random:!0,brushType:\"fill\",lineWidth:1,size:i.style.size},draggable:!1,hoverable:!1});t.push(V),e.addShape(V),e.modShape(i.id,{invisible:!0});for(var U=Math.round(100*a.period),d={},p={},c=0;20>c;c++)V.style[\"randomMap\"+c]=0,d={},d[\"randomMap\"+c]=100,p={},p[\"randomMap\"+c]=0,V.style[\"randomMap\"+c]=100*Math.random(),e.animate(V.id,\"style\",!0).when(U,d).when(2*U,p).when(3*U,d).when(4*U,d).delay(Math.random()*U*c).start()}function n(e,t,i,n,a){var s=i.effect,h=i.style,m=s.color||h.strokeColor||h.color,V=s.shadowColor||h.strokeColor||m,c=h.lineWidth*s.scaleSize,u=\"undefined\"!=typeof s.shadowBlur?s.shadowBlur:c,y=new r({zlevel:n,style:{x:u,y:u,r:c,color:m,shadowColor:V,shadowBlur:u},hoverable:!1}),g=0;if(p&&!a){var n=y.zlevel;y=e.shapeToImage(y,2*(c+u),2*(c+u)),y.zlevel=n,y.hoverable=!1,g=u}a||(o.clone(i,y),y.position=i.position,t.push(y),e.addShape(y));var b=function(){a||(i.effect.show=!1,e.delShape(y.id)),y.effectAnimator=null};if(i instanceof U){for(var f=[0],k=0,x=h.pointList,_=h.controlPointList,L=1;L<x.length;L++){if(_){var W=_[2*(L-1)],X=_[2*(L-1)+1];k+=d.dist(x[L-1],W)+d.dist(W,X)+d.dist(X,x[L])}else k+=d.dist(x[L-1],x[L]);f.push(k)}for(var v={p:0},w=e.animation.animate(v,{loop:s.loop}),L=0;L<f.length;L++)w.when(f[L]*s.period,{p:L});w.during(function(){var t,i,n=Math.floor(v.p);if(n==x.length-1)t=x[n][0],i=x[n][1];else{var o=v.p-n,r=x[n],s=x[n+1];if(_){var h=_[2*n],m=_[2*n+1];t=l.cubicAt(r[0],h[0],m[0],s[0],o),i=l.cubicAt(r[1],h[1],m[1],s[1],o)}else t=(s[0]-r[0])*o+r[0],i=(s[1]-r[1])*o+r[1]}y.style.x=t,y.style.y=i,a||e.modShape(y)}).done(b).start(),w.duration=k*s.period,y.effectAnimator=w}else{var K=h.xStart-g,I=h.yStart-g,J=h.xEnd-g,C=h.yEnd-g;y.style.x=K,y.style.y=I;var S=(J-K)*(J-K)+(C-I)*(C-I),E=Math.round(Math.sqrt(Math.round(S*s.period*s.period)));if(i.style.curveness>0){var F=h.cpX1-g,T=h.cpY1-g;y.effectAnimator=e.animation.animate(y,{loop:s.loop}).when(E,{p:1}).during(function(t,i){y.style.x=l.quadraticAt(K,F,J,i),y.style.y=l.quadraticAt(I,T,C,i),a||e.modShape(y)}).done(b).start()}else y.effectAnimator=e.animation.animate(y.style,{loop:s.loop}).when(E,{x:J,y:C}).during(function(){a||e.modShape(y)}).done(b).start();y.effectAnimator.duration=E}return y}function a(e,t,i,a){var o=new V({style:{shapeList:[]},zlevel:a,hoverable:!1}),r=i.style.shapeList,s=i.effect;o.position=i.position;for(var l=0,h=[],m=0;m<r.length;m++){r[m].effect=s;var U=n(e,null,r[m],a,!0),d=U.effectAnimator;o.style.shapeList.push(U),d.duration>l&&(l=d.duration),0===m&&(o.style.color=U.style.color,o.style.shadowBlur=U.style.shadowBlur,o.style.shadowColor=U.style.shadowColor),h.push(d)}t.push(o),e.addShape(o);var p=function(){for(var e=0;e<h.length;e++)h[e].stop()};if(l){o.__dummy=0;var c=e.animate(o.id,\"\",s.loop).when(l,{__dummy:1}).during(function(){e.modShape(o)}).done(function(){i.effect.show=!1,e.delShape(o.id)}).start(),u=c.stop;c.stop=function(){p(),u.call(this)}}}var o=e(\"../util/ecData\"),r=e(\"zrender/shape/Circle\"),s=e(\"zrender/shape/Image\"),l=e(\"zrender/tool/curve\"),h=e(\"../util/shape/Icon\"),m=e(\"../util/shape/Symbol\"),V=e(\"zrender/shape/ShapeBundle\"),U=e(\"zrender/shape/Polyline\"),d=e(\"zrender/tool/vector\"),p=e(\"zrender/tool/env\").canvasSupported;return{point:t,largePoint:i,line:n,largeLine:a}}),i(\"echarts/component/base\",[\"require\",\"../config\",\"../util/ecData\",\"../util/ecQuery\",\"../util/number\",\"zrender/tool/util\",\"zrender/tool/env\"],function(e){function t(e,t,a,o,r){this.ecTheme=e,this.messageCenter=t,this.zr=a,this.option=o,this.series=o.series,this.myChart=r,this.component=r.component,this.shapeList=[],this.effectList=[];var s=this;s._onlegendhoverlink=function(e){if(s.legendHoverLink)for(var t,a=e.target,o=s.shapeList.length-1;o>=0;o--)t=s.type==i.CHART_TYPE_PIE||s.type==i.CHART_TYPE_FUNNEL?n.get(s.shapeList[o],\"name\"):(n.get(s.shapeList[o],\"series\")||{}).name,t!=a||s.shapeList[o].invisible||s.shapeList[o].__animating||s.zr.addHoverShape(s.shapeList[o])},t&&t.bind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink)}var i=e(\"../config\"),n=e(\"../util/ecData\"),a=e(\"../util/ecQuery\"),o=e(\"../util/number\"),r=e(\"zrender/tool/util\");return t.prototype={canvasSupported:e(\"zrender/tool/env\").canvasSupported,_getZ:function(e){if(null!=this[e])return this[e];var t=this.ecTheme[this.type];return t&&null!=t[e]?t[e]:(t=i[this.type],t&&null!=t[e]?t[e]:0)},getZlevelBase:function(){return this._getZ(\"zlevel\")},getZBase:function(){return this._getZ(\"z\")},reformOption:function(e){return e=r.merge(r.merge(e||{},r.clone(this.ecTheme[this.type]||{})),r.clone(i[this.type]||{})),this.z=e.z,this.zlevel=e.zlevel,e},reformCssArray:function(e){if(!(e instanceof Array))return[e,e,e,e];switch(e.length+\"\"){case\"4\":return e;case\"3\":return[e[0],e[1],e[2],e[1]];case\"2\":return[e[0],e[1],e[0],e[1]];case\"1\":return[e[0],e[0],e[0],e[0]];case\"0\":return[0,0,0,0]}},getShapeById:function(e){for(var t=0,i=this.shapeList.length;i>t;t++)if(this.shapeList[t].id===e)return this.shapeList[t];return null},getFont:function(e){var t=this.getTextStyle(r.clone(e));return t.fontStyle+\" \"+t.fontWeight+\" \"+t.fontSize+\"px \"+t.fontFamily},getTextStyle:function(e){return r.merge(r.merge(e||{},this.ecTheme.textStyle),i.textStyle)},getItemStyleColor:function(e,t,i,n){return\"function\"==typeof e?e.call(this.myChart,{seriesIndex:t,series:this.series[t],dataIndex:i,data:n}):e},getDataFromOption:function(e,t){return null!=e?null!=e.value?e.value:e:t},subPixelOptimize:function(e,t){return e=t%2===1?Math.floor(e)+.5:Math.round(e)},resize:function(){this.refresh&&this.refresh(),this.clearEffectShape&&this.clearEffectShape(!0);var e=this;setTimeout(function(){e.animationEffect&&e.animationEffect()},200)},clear:function(){this.clearEffectShape&&this.clearEffectShape(),this.zr&&this.zr.delShape(this.shapeList),this.shapeList=[]},dispose:function(){this.onbeforDispose&&this.onbeforDispose(),this.clear(),this.shapeList=null,this.effectList=null,this.messageCenter&&this.messageCenter.unbind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink),this.onafterDispose&&this.onafterDispose()},query:a.query,deepQuery:a.deepQuery,deepMerge:a.deepMerge,parsePercent:o.parsePercent,parseCenter:o.parseCenter,parseRadius:o.parseRadius,numAddCommas:o.addCommas,getPrecision:o.getPrecision},t}),i(\"echarts/layout/EdgeBundling\",[\"require\",\"../data/KDTree\",\"zrender/tool/vector\"],function(e){function t(e,t){e=e.array,t=t.array;var i=t[0]-e[0],n=t[1]-e[1],a=t[2]-e[2],o=t[3]-e[3];return i*i+n*n+a*a+o*o}function i(e){this.points=[e.mp0,e.mp1],this.group=e}function n(e){var t=e.points;t[0][1]<t[1][1]||e instanceof i?(this.array=[t[0][0],t[0][1],t[1][0],t[1][1]],this._startPoint=t[0],this._endPoint=t[1]):(this.array=[t[1][0],t[1][1],t[0][0],t[0][1]],this._startPoint=t[1],this._endPoint=t[0]),this.ink=m(t[0],t[1]),this.edge=e,this.group=null}function a(){this.edgeList=[],this.mp0=l(),this.mp1=l(),this.ink=0}function o(){this.maxNearestEdge=6,this.maxTurningAngle=Math.PI/4,this.maxIteration=20}var r=e(\"../data/KDTree\"),s=e(\"zrender/tool/vector\"),l=s.create,h=s.distSquare,m=s.dist,V=s.copy,U=s.clone;return n.prototype.getStartPoint=function(){return this._startPoint},n.prototype.getEndPoint=function(){return this._endPoint},a.prototype.addEdge=function(e){e.group=this,this.edgeList.push(e)},a.prototype.removeEdge=function(e){e.group=null,this.edgeList.splice(this.edgeList.indexOf(e),1)},o.prototype={constructor:o,run:function(e){function t(e,t){return h(e,t)<1e-10}function n(e,i){for(var n=[],a=0,o=0;o<e.length;o++)a>0&&t(e[o],n[a-1])||(n[a++]=U(e[o]));return i[0]&&!t(n[0],i[0])&&(n=n.reverse()),n}for(var a=this._iterate(e),o=0;o++<this.maxIteration;){for(var r=[],s=0;s<a.groups.length;s++)r.push(new i(a.groups[s]));var l=this._iterate(r);if(l.savedInk<=0)break;a=l}var m=[],V=function(e,t){for(var a,o=0;o<e.length;o++){var r=e[o];if(r.edgeList[0]&&r.edgeList[0].edge instanceof i){for(var s=[],l=0;l<r.edgeList.length;l++)s.push(r.edgeList[l].edge.group);a=t?t.slice():[],a.unshift(r.mp0),a.push(r.mp1),V(s,a)}else for(var l=0;l<r.edgeList.length;l++){var h=r.edgeList[l];a=t?t.slice():[],a.unshift(r.mp0),a.push(r.mp1),a.unshift(h.getStartPoint()),a.push(h.getEndPoint()),m.push({points:n(a,h.edge.points),rawEdge:h.edge})}}};return V(a.groups),m},_iterate:function(e){for(var i=[],o=[],s=0,h=0;h<e.length;h++){var m=new n(e[h]);i.push(m)}for(var U=new r(i,4),d=[],p=l(),c=l(),u=0,y=l(),g=l(),b=0,h=0;h<i.length;h++){var m=i[h];if(!m.group){U.nearestN(m,this.maxNearestEdge,t,d);for(var f=0,k=null,x=null,_=0;_<d.length;_++){var L=d[_],W=0;L.group?L.group!==x&&(x=L.group,u=this._calculateGroupEdgeInk(L.group,m,p,c),W=L.group.ink+m.ink-u):(u=this._calculateEdgeEdgeInk(m,L,p,c),W=L.ink+m.ink-u),W>f&&(f=W,k=L,V(g,c),V(y,p),b=u)}if(k){s+=f;var X;k.group||(X=new a,o.push(X),X.addEdge(k)),X=k.group,V(X.mp0,y),V(X.mp1,g),X.ink=b,k.group.addEdge(m)}else{var X=new a;o.push(X),V(X.mp0,m.getStartPoint()),V(X.mp1,m.getEndPoint()),X.ink=m.ink,X.addEdge(m)}}}return{groups:o,edges:i,savedInk:s}},_calculateEdgeEdgeInk:function(){var e=[],t=[];return function(i,n,a,o){e[0]=i.getStartPoint(),e[1]=n.getStartPoint(),t[0]=i.getEndPoint(),t[1]=n.getEndPoint(),this._calculateMeetPoints(e,t,a,o);var r=m(e[0],a)+m(a,o)+m(o,t[0])+m(e[1],a)+m(o,t[1]);return r}}(),_calculateGroupEdgeInk:function(e,t,i,n){for(var a=[],o=[],r=0;r<e.edgeList.length;r++){var s=e.edgeList[r];a.push(s.getStartPoint()),o.push(s.getEndPoint())}a.push(t.getStartPoint()),o.push(t.getEndPoint()),this._calculateMeetPoints(a,o,i,n);for(var l=m(i,n),r=0;r<a.length;r++)l+=m(a[r],i)+m(o[r],n);return l},_calculateMeetPoints:function(){var e=l(),t=l();return function(i,n,a,o){s.set(e,0,0),s.set(t,0,0);for(var r=i.length,l=0;r>l;l++)s.add(e,e,i[l]);s.scale(e,e,1/r),r=n.length;for(var l=0;r>l;l++)s.add(t,t,n[l]);s.scale(t,t,1/r),this._limitTurningAngle(i,e,t,a),this._limitTurningAngle(n,t,e,o)}}(),_limitTurningAngle:function(){var e=l(),t=l(),i=l(),n=l();return function(a,o,r,l){var V=Math.cos(this.maxTurningAngle),U=Math.tan(this.maxTurningAngle);s.sub(e,o,r),s.normalize(e,e),s.copy(l,o);for(var d=0,p=0;p<a.length;p++){var c=a[p];s.sub(t,c,o);var u=s.len(t);s.scale(t,t,1/u);var y=s.dot(t,e);if(V>y){s.scaleAndAdd(i,o,e,u*y);var g=m(i,c),b=g/U;s.scaleAndAdd(n,i,e,-b);var f=h(n,o);f>d&&(d=f,s.copy(l,n))}}}}()},o}),i(\"zrender/shape/Star\",[\"require\",\"../tool/math\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"../tool/math\"),i=t.sin,n=t.cos,a=Math.PI,o=e(\"./Base\"),r=function(e){o.call(this,e)};return r.prototype={type:\"star\",buildPath:function(e,t){var o=t.n;if(o&&!(2>o)){var r=t.x,s=t.y,l=t.r,h=t.r0;null==h&&(h=o>4?l*n(2*a/o)/n(a/o):l/3);var m=a/o,V=-a/2,U=r+l*n(V),d=s+l*i(V);V+=m;var p=t.pointList=[];p.push([U,d]);for(var c,u=0,y=2*o-1;y>u;u++)c=u%2===0?h:l,p.push([r+c*n(V),s+c*i(V)]),V+=m;p.push([U,d]),e.moveTo(p[0][0],p[0][1]);for(var u=0;u<p.length;u++)e.lineTo(p[u][0],p[u][1]);e.closePath()}},getRect:function(e){if(e.__rect)return e.__rect;var t;return t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e(\"../tool/util\").inherits(r,o),r}),i(\"zrender/shape/Heart\",[\"require\",\"./Base\",\"./util/PathProxy\",\"../tool/area\",\"../tool/util\"],function(e){\"use strict\";var t=e(\"./Base\"),i=e(\"./util/PathProxy\"),n=e(\"../tool/area\"),a=function(e){t.call(this,e),this._pathProxy=new i};return a.prototype={type:\"heart\",buildPath:function(e,t){var n=this._pathProxy||new i;n.begin(e),n.moveTo(t.x,t.y),n.bezierCurveTo(t.x+t.a/2,t.y-2*t.b/3,t.x+2*t.a,t.y+t.b/3,t.x,t.y+t.b),n.bezierCurveTo(t.x-2*t.a,t.y+t.b/3,t.x-t.a/2,t.y-2*t.b/3,t.x,t.y),n.closePath()},getRect:function(e){return e.__rect?e.__rect:(this._pathProxy.isEmpty()||this.buildPath(null,e),this._pathProxy.fastBoundingRect())},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)?n.isInsidePath(this._pathProxy.pathCommands,this.style.lineWidth,this.style.brushType,e,t):void 0}},e(\"../tool/util\").inherits(a,t),a}),i(\"zrender/shape/Droplet\",[\"require\",\"./Base\",\"./util/PathProxy\",\"../tool/area\",\"../tool/util\"],function(e){\"use strict\";var t=e(\"./Base\"),i=e(\"./util/PathProxy\"),n=e(\"../tool/area\"),a=function(e){t.call(this,e),this._pathProxy=new i};return a.prototype={type:\"droplet\",buildPath:function(e,t){var n=this._pathProxy||new i;n.begin(e),n.moveTo(t.x,t.y+t.a),n.bezierCurveTo(t.x+t.a,t.y+t.a,t.x+3*t.a/2,t.y-t.a/3,t.x,t.y-t.b),n.bezierCurveTo(t.x-3*t.a/2,t.y-t.a/3,t.x-t.a,t.y+t.a,t.x,t.y+t.a),n.closePath()},getRect:function(e){return e.__rect?e.__rect:(this._pathProxy.isEmpty()||this.buildPath(null,e),this._pathProxy.fastBoundingRect())},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)?n.isInsidePath(this._pathProxy.pathCommands,this.style.lineWidth,this.style.brushType,e,t):void 0}},e(\"../tool/util\").inherits(a,t),a}),i(\"zrender/tool/math\",[],function(){function e(e,t){return Math.sin(t?e*a:e)}function t(e,t){return Math.cos(t?e*a:e)}function i(e){return e*a}function n(e){return e/a}var a=Math.PI/180;return{sin:e,cos:t,degreeToRadian:i,radianToDegree:n}}),i(\"zrender/shape/util/PathProxy\",[\"require\",\"../../tool/vector\"],function(e){var t=e(\"../../tool/vector\"),i=function(e,t){this.command=e,this.points=t||null},n=function(){this.pathCommands=[],this._ctx=null,this._min=[],this._max=[]};return n.prototype.fastBoundingRect=function(){var e=this._min,i=this._max;e[0]=e[1]=1/0,i[0]=i[1]=-(1/0);for(var n=0;n<this.pathCommands.length;n++){var a=this.pathCommands[n],o=a.points;switch(a.command){case\"M\":t.min(e,e,o),t.max(i,i,o);break;case\"L\":t.min(e,e,o),t.max(i,i,o);break;case\"C\":for(var r=0;6>r;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case\"Q\":for(var r=0;4>r;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case\"A\":var s=o[0],l=o[1],h=o[2],m=o[3];e[0]=Math.min(e[0],e[0],s-h),e[1]=Math.min(e[1],e[1],l-m),i[0]=Math.max(i[0],i[0],s+h),i[1]=Math.max(i[1],i[1],l+m)}}return{x:e[0],y:e[1],width:i[0]-e[0],height:i[1]-e[1]}},n.prototype.begin=function(e){return this._ctx=e||null,this.pathCommands.length=0,this},n.prototype.moveTo=function(e,t){return this.pathCommands.push(new i(\"M\",[e,t])),this._ctx&&this._ctx.moveTo(e,t),this},n.prototype.lineTo=function(e,t){return this.pathCommands.push(new i(\"L\",[e,t])),this._ctx&&this._ctx.lineTo(e,t),this},n.prototype.bezierCurveTo=function(e,t,n,a,o,r){return this.pathCommands.push(new i(\"C\",[e,t,n,a,o,r])),this._ctx&&this._ctx.bezierCurveTo(e,t,n,a,o,r),this},n.prototype.quadraticCurveTo=function(e,t,n,a){return this.pathCommands.push(new i(\"Q\",[e,t,n,a])),this._ctx&&this._ctx.quadraticCurveTo(e,t,n,a),this},n.prototype.arc=function(e,t,n,a,o,r){return this.pathCommands.push(new i(\"A\",[e,t,n,n,a,o-a,0,r?0:1])),this._ctx&&this._ctx.arc(e,t,n,a,o,r),this},n.prototype.arcTo=function(e,t,i,n,a){return this._ctx&&this._ctx.arcTo(e,t,i,n,a),this},n.prototype.rect=function(e,t,i,n){return this._ctx&&this._ctx.rect(e,t,i,n),this},n.prototype.closePath=function(){return this.pathCommands.push(new i(\"z\")),this._ctx&&this._ctx.closePath(),this},n.prototype.isEmpty=function(){return 0===this.pathCommands.length},n.PathSegment=i,n}),i(\"zrender/shape/Line\",[\"require\",\"./Base\",\"./util/dashedLineTo\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=e(\"./util/dashedLineTo\"),n=function(e){this.brushTypeOnly=\"stroke\",this.textPosition=\"end\",t.call(this,e)};return n.prototype={type:\"line\",buildPath:function(e,t){if(t.lineType&&\"solid\"!=t.lineType){if(\"dashed\"==t.lineType||\"dotted\"==t.lineType){var n=(t.lineWidth||1)*(\"dashed\"==t.lineType?5:1);i(e,t.xStart,t.yStart,t.xEnd,t.yEnd,n)}}else e.moveTo(t.xStart,t.yStart),e.lineTo(t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=e.lineWidth||1;return e.__rect={x:Math.min(e.xStart,e.xEnd)-t,y:Math.min(e.yStart,e.yEnd)-t,width:Math.abs(e.xStart-e.xEnd)+t,height:Math.abs(e.yStart-e.yEnd)+t},e.__rect}},e(\"../tool/util\").inherits(n,t),n}),i(\"zrender/shape/BezierCurve\",[\"require\",\"./Base\",\"../tool/util\"],function(e){\"use strict\";var t=e(\"./Base\"),i=function(e){this.brushTypeOnly=\"stroke\",this.textPosition=\"end\",t.call(this,e)};return i.prototype={type:\"bezier-curve\",buildPath:function(e,t){e.moveTo(t.xStart,t.yStart),\"undefined\"!=typeof t.cpX2&&\"undefined\"!=typeof t.cpY2?e.bezierCurveTo(t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd):e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=Math.min(e.xStart,e.xEnd,e.cpX1),i=Math.min(e.yStart,e.yEnd,e.cpY1),n=Math.max(e.xStart,e.xEnd,e.cpX1),a=Math.max(e.yStart,e.yEnd,e.cpY1),o=e.cpX2,r=e.cpY2;\"undefined\"!=typeof o&&\"undefined\"!=typeof r&&(t=Math.min(t,o),i=Math.min(i,r),n=Math.max(n,o),a=Math.max(a,r));var s=e.lineWidth||1;return e.__rect={x:t-s,y:i-s,width:n-t+s,height:a-i+s},e.__rect}},e(\"../tool/util\").inherits(i,t),i}),i(\"zrender/shape/util/dashedLineTo\",[],function(){var e=[5,5];return function(t,i,n,a,o,r){if(t.setLineDash)return e[0]=e[1]=r,t.setLineDash(e),t.moveTo(i,n),void t.lineTo(a,o);r=\"number\"!=typeof r?5:r;var s=a-i,l=o-n,h=Math.floor(Math.sqrt(s*s+l*l)/r);s/=h,l/=h;for(var m=!0,V=0;h>V;++V)m?t.moveTo(i,n):t.lineTo(i,n),m=!m,i+=s,n+=l;t.lineTo(a,o)}}),i(\"zrender/shape/Polygon\",[\"require\",\"./Base\",\"./util/smoothSpline\",\"./util/smoothBezier\",\"./util/dashedLineTo\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=e(\"./util/smoothSpline\"),n=e(\"./util/smoothBezier\"),a=e(\"./util/dashedLineTo\"),o=function(e){t.call(this,e)};return o.prototype={type:\"polygon\",buildPath:function(e,t){var o=t.pointList;if(!(o.length<2)){if(t.smooth&&\"spline\"!==t.smooth){var r=n(o,t.smooth,!0,t.smoothConstraint);e.moveTo(o[0][0],o[0][1]);for(var s,l,h,m=o.length,V=0;m>V;V++)s=r[2*V],l=r[2*V+1],h=o[(V+1)%m],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if(\"spline\"===t.smooth&&(o=i(o,!0)),t.lineType&&\"solid\"!=t.lineType){if(\"dashed\"==t.lineType||\"dotted\"==t.lineType){var U=t._dashLength||(t.lineWidth||1)*(\"dashed\"==t.lineType?5:1);t._dashLength=U,e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)a(e,o[V-1][0],o[V-1][1],o[V][0],o[V][1],U);a(e,o[o.length-1][0],o[o.length-1][1],o[0][0],o[0][1],U)}}else{e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)e.lineTo(o[V][0],o[V][1]);e.lineTo(o[0][0],o[0][1])}e.closePath()}},getRect:function(e){if(e.__rect)return e.__rect;for(var t=Number.MAX_VALUE,i=Number.MIN_VALUE,n=Number.MAX_VALUE,a=Number.MIN_VALUE,o=e.pointList,r=0,s=o.length;s>r;r++)o[r][0]<t&&(t=o[r][0]),o[r][0]>i&&(i=o[r][0]),o[r][1]<n&&(n=o[r][1]),o[r][1]>a&&(a=o[r][1]);var l;return l=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(t-l/2),y:Math.round(n-l/2),width:i-t+l,height:a-n+l},e.__rect}},e(\"../tool/util\").inherits(o,t),o}),i(\"echarts/util/shape/normalIsCover\",[],function(){return function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)}}),i(\"zrender/shape/util/smoothSpline\",[\"require\",\"../../tool/vector\"],function(e){function t(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}var i=e(\"../../tool/vector\");return function(e,n){for(var a=e.length,o=[],r=0,s=1;a>s;s++)r+=i.distance(e[s-1],e[s]);var l=r/5;l=a>l?a:l;for(var s=0;l>s;s++){var h,m,V,U=s/(l-1)*(n?a:a-1),d=Math.floor(U),p=U-d,c=e[d%a];n?(h=e[(d-1+a)%a],m=e[(d+1)%a],V=e[(d+2)%a]):(h=e[0===d?d:d-1],m=e[d>a-2?a-1:d+1],V=e[d>a-3?a-1:d+2]);var u=p*p,y=p*u;o.push([t(h[0],c[0],m[0],V[0],p,u,y),t(h[1],c[1],m[1],V[1],p,u,y)])}return o}}),i(\"zrender/shape/util/smoothBezier\",[\"require\",\"../../tool/vector\"],function(e){var t=e(\"../../tool/vector\");return function(e,i,n,a){var o,r,s,l,h=[],m=[],V=[],U=[],d=!!a;if(d){s=[1/0,1/0],l=[-(1/0),-(1/0)];for(var p=0,c=e.length;c>p;p++)t.min(s,s,e[p]),t.max(l,l,e[p]);t.min(s,s,a[0]),t.max(l,l,a[1])}for(var p=0,c=e.length;c>p;p++){var o,r,u=e[p];if(n)o=e[p?p-1:c-1],r=e[(p+1)%c];else{if(0===p||p===c-1){h.push(t.clone(e[p]));continue}o=e[p-1],r=e[p+1]}t.sub(m,r,o),t.scale(m,m,i);var y=t.distance(u,o),g=t.distance(u,r),b=y+g;0!==b&&(y/=b,g/=b),t.scale(V,m,-y),t.scale(U,m,g);var f=t.add([],u,V),k=t.add([],u,U);d&&(t.max(f,f,s),t.min(f,f,l),t.max(k,k,s),t.min(k,k,l)),h.push(f),h.push(k)}return n&&h.push(t.clone(h.shift())),h}}),i(\"echarts/util/ecQuery\",[\"require\",\"zrender/tool/util\"],function(e){function t(e,t){if(\"undefined\"!=typeof e){if(!t)return e;t=t.split(\".\");for(var i=t.length,n=0;i>n;){if(e=e[t[n]],\"undefined\"==typeof e)return;n++}return e}}function i(e,i){for(var n,a=0,o=e.length;o>a;a++)if(n=t(e[a],i),\"undefined\"!=typeof n)return n}function n(e,i){for(var n,o=e.length;o--;){var r=t(e[o],i);\"undefined\"!=typeof r&&(\"undefined\"==typeof n?n=a.clone(r):a.merge(n,r,!0))}return n}var a=e(\"zrender/tool/util\");return{query:t,deepQuery:i,deepMerge:n}}),i(\"echarts/util/number\",[],function(){function e(e){return e.replace(/^\\s+/,\"\").replace(/\\s+$/,\"\")}function t(t,i){return\"string\"==typeof t?e(t).match(/%$/)?parseFloat(t)/100*i:parseFloat(t):t}function i(e,i){return[t(i[0],e.getWidth()),t(i[1],e.getHeight())]}function n(e,i){i instanceof Array||(i=[0,i]);var n=Math.min(e.getWidth(),e.getHeight())/2;return[t(i[0],n),t(i[1],n)]}function a(e){return isNaN(e)?\"-\":(e=(e+\"\").split(\".\"),e[0].replace(/(\\d{1,3})(?=(?:\\d{3})+(?!\\d))/g,\"$1,\")+(e.length>1?\".\"+e[1]:\"\"))}function o(e){for(var t=1,i=0;Math.round(e*t)/t!==e;)t*=10,i++;return i}return{parsePercent:t,parseCenter:i,parseRadius:n,addCommas:a,getPrecision:o}}),i(\"echarts/data/KDTree\",[\"require\",\"./quickSelect\"],function(e){function t(e,t){this.left=null,this.right=null,this.axis=e,this.data=t}var i=e(\"./quickSelect\"),n=function(e,t){e.length&&(t||(t=e[0].array.length),this.dimension=t,this.root=this._buildTree(e,0,e.length-1,0),this._stack=[],this._nearstNList=[])};return n.prototype._buildTree=function(e,n,a,o){if(n>a)return null;var r=Math.floor((n+a)/2);r=i(e,n,a,r,function(e,t){return e.array[o]-t.array[o]});var s=e[r],l=new t(o,s);return o=(o+1)%this.dimension,a>n&&(l.left=this._buildTree(e,n,r-1,o),l.right=this._buildTree(e,r+1,a,o)),l},n.prototype.nearest=function(e,t){var i=this.root,n=this._stack,a=0,o=1/0,r=null;for(i.data!==e&&(o=t(i.data,e),r=i),e.array[i.axis]<i.data.array[i.axis]?(i.right&&(n[a++]=i.right),i.left&&(n[a++]=i.left)):(i.left&&(n[a++]=i.left),i.right&&(n[a++]=i.right));a--;){i=n[a];var s=e.array[i.axis]-i.data.array[i.axis],l=0>s,h=!1;s*=s,o>s&&(s=t(i.data,e),o>s&&i.data!==e&&(o=s,r=i),h=!0),l?(h&&i.right&&(n[a++]=i.right),i.left&&(n[a++]=i.left)):(h&&i.left&&(n[a++]=i.left),i.right&&(n[a++]=i.right))}return r.data},n.prototype._addNearest=function(e,t,i){for(var n=this._nearstNList,a=e-1;a>0&&!(t>=n[a-1].dist);a--)n[a].dist=n[a-1].dist,n[a].node=n[a-1].node;n[a].dist=t,n[a].node=i},n.prototype.nearestN=function(e,t,i,n){if(0>=t)return n.length=0,n;for(var a=this.root,o=this._stack,r=0,s=this._nearstNList,l=0;t>l;l++)s[l]||(s[l]={}),s[l].dist=0,s[l].node=null;var h=i(a.data,e),m=0;for(a.data!==e&&(m++,this._addNearest(m,h,a)),e.array[a.axis]<a.data.array[a.axis]?(a.right&&(o[r++]=a.right),a.left&&(o[r++]=a.left)):(a.left&&(o[r++]=a.left),a.right&&(o[r++]=a.right));r--;){a=o[r];var h=e.array[a.axis]-a.data.array[a.axis],V=0>h,U=!1;h*=h,(t>m||h<s[m-1].dist)&&(h=i(a.data,e),(t>m||h<s[m-1].dist)&&a.data!==e&&(t>m&&m++,this._addNearest(m,h,a)),U=!0),V?(U&&a.right&&(o[r++]=a.right),a.left&&(o[r++]=a.left)):(U&&a.left&&(o[r++]=a.left),a.right&&(o[r++]=a.right))}for(var l=0;m>l;l++)n[l]=s[l].node.data;return n.length=m,n},n}),i(\"echarts/data/quickSelect\",[\"require\"],function(){function e(e,t){return e-t}function t(e,t,i){var n=e[t];e[t]=e[i],e[i]=n}function i(e,i,n,a,o){for(var r=i;n>i;){var r=Math.round((n+i)/2),s=e[r];t(e,r,n),r=i;for(var l=i;n-1>=l;l++)o(s,e[l])>=0&&(t(e,l,r),r++);if(t(e,n,r),r===a)return r;a>r?i=r+1:n=r-1}return i}function n(t,n,a,o,r){return arguments.length<=3&&(o=n,r=2==arguments.length?e:a,n=0,a=t.length-1),i(t,n,a,o,r)}return n}),i(\"echarts/component/dataView\",[\"require\",\"./base\",\"../config\",\"zrender/tool/util\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._tDom=document.createElement(\"div\"),this._textArea=document.createElement(\"textArea\"),this._buttonRefresh=document.createElement(\"button\"),this._buttonRefresh.setAttribute(\"type\",\"button\"),this._buttonClose=document.createElement(\"button\"),this._buttonClose.setAttribute(\"type\",\"button\"),this._hasShow=!1,this._zrHeight=n.getHeight(),this._zrWidth=n.getWidth(),this._tDom.className=\"echarts-dataview\",this.hide(),this.dom.firstChild.appendChild(this._tDom),window.addEventListener?(this._tDom.addEventListener(\"click\",this._stop),this._tDom.addEventListener(\"mousewheel\",this._stop),this._tDom.addEventListener(\"mousemove\",this._stop),this._tDom.addEventListener(\"mousedown\",this._stop),this._tDom.addEventListener(\"mouseup\",this._stop),this._tDom.addEventListener(\"touchstart\",this._stop),this._tDom.addEventListener(\"touchmove\",this._stop),this._tDom.addEventListener(\"touchend\",this._stop)):(this._tDom.attachEvent(\"onclick\",this._stop),this._tDom.attachEvent(\"onmousewheel\",this._stop),this._tDom.attachEvent(\"onmousemove\",this._stop),this._tDom.attachEvent(\"onmousedown\",this._stop),this._tDom.attachEvent(\"onmouseup\",this._stop))}var i=e(\"./base\"),n=e(\"../config\"),a=e(\"zrender/tool/util\");return t.prototype={type:n.COMPONENT_TYPE_DATAVIEW,_lang:[\"Data View\",\"close\",\"refresh\"],_gCssText:\"position:absolute;display:block;overflow:hidden;transition:height 0.8s,background-color 1s;-moz-transition:height 0.8s,background-color 1s;-webkit-transition:height 0.8s,background-color 1s;-o-transition:height 0.8s,background-color 1s;z-index:1;left:0;top:0;\",hide:function(){this._sizeCssText=\"width:\"+this._zrWidth+\"px;height:0px;background-color:#f0ffff;\",this._tDom.style.cssText=this._gCssText+this._sizeCssText},show:function(e){this._hasShow=!0;var t=this.query(this.option,\"toolbox.feature.dataView.lang\")||this._lang;this.option=e,this._tDom.innerHTML='<p style=\"padding:8px 0;margin:0 0 10px 0;border-bottom:1px solid #eee\">'+(t[0]||this._lang[0])+\"</p>\";var i=this.query(this.option,\"toolbox.feature.dataView.optionToContent\");\"function\"!=typeof i?this._textArea.value=this._optionToContent():(this._textArea=document.createElement(\"div\"),this._textArea.innerHTML=i(this.option)),this._textArea.style.cssText=\"display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:\"+(this._zrHeight-100)+\"px;\",this._tDom.appendChild(this._textArea),this._buttonClose.style.cssText=\"float:right;padding:1px 6px;\",this._buttonClose.innerHTML=t[1]||this._lang[1];var n=this;this._buttonClose.onclick=function(){n.hide()},this._tDom.appendChild(this._buttonClose),this.query(this.option,\"toolbox.feature.dataView.readOnly\")===!1?(this._buttonRefresh.style.cssText=\"float:right;margin-right:10px;padding:1px 6px;\",this._buttonRefresh.innerHTML=t[2]||this._lang[2],this._buttonRefresh.onclick=function(){n._save()},this._textArea.readOnly=!1,this._textArea.style.cursor=\"default\"):(this._buttonRefresh.style.cssText=\"display:none\",\nthis._textArea.readOnly=!0,this._textArea.style.cursor=\"text\"),this._tDom.appendChild(this._buttonRefresh),this._sizeCssText=\"width:\"+this._zrWidth+\"px;height:\"+this._zrHeight+\"px;background-color:#fff;\",this._tDom.style.cssText=this._gCssText+this._sizeCssText},_optionToContent:function(){var e,t,i,a,o,r,s=[],l=\"\";if(this.option.xAxis)for(s=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],e=0,a=s.length;a>e;e++)if(\"category\"==(s[e].type||\"category\")){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(\", \")+\"\\n\\n\"}if(this.option.yAxis)for(s=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],e=0,a=s.length;a>e;e++)if(\"category\"==s[e].type){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(\", \")+\"\\n\\n\"}var h,m=this.option.series;for(e=0,a=m.length;a>e;e++){for(r=[],t=0,i=m[e].data.length;i>t;t++)o=m[e].data[t],h=m[e].type==n.CHART_TYPE_PIE||m[e].type==n.CHART_TYPE_MAP?(o.name||\"-\")+\":\":\"\",m[e].type==n.CHART_TYPE_SCATTER&&(o=this.getDataFromOption(o).join(\", \")),r.push(h+this.getDataFromOption(o));l+=(m[e].name||\"-\")+\" : \\n\",l+=r.join(m[e].type==n.CHART_TYPE_SCATTER?\"\\n\":\", \"),l+=\"\\n\\n\"}return l},_save:function(){var e=this.query(this.option,\"toolbox.feature.dataView.contentToOption\");if(\"function\"!=typeof e){for(var t=this._textArea.value.split(\"\\n\"),i=[],a=0,o=t.length;o>a;a++)t[a]=this._trim(t[a]),\"\"!==t[a]&&i.push(t[a]);this._contentToOption(i)}else e(this._textArea,this.option);this.hide();var r=this;setTimeout(function(){r.messageCenter&&r.messageCenter.dispatch(n.EVENT.DATA_VIEW_CHANGED,null,{option:r.option},r.myChart)},r.canvasSupported?800:100)},_contentToOption:function(e){var t,i,a,o,r,s,l,h=[],m=0;if(this.option.xAxis)for(h=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],t=0,o=h.length;o>t;t++)if(\"category\"==(h[t].type||\"category\")){for(s=e[m].split(\",\"),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||\"\"),r=h[t].data[i],\"undefined\"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}if(this.option.yAxis)for(h=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],t=0,o=h.length;o>t;t++)if(\"category\"==h[t].type){for(s=e[m].split(\",\"),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||\"\"),r=h[t].data[i],\"undefined\"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}var V=this.option.series;for(t=0,o=V.length;o>t;t++)if(m++,V[t].type==n.CHART_TYPE_SCATTER)for(var i=0,a=V[t].data.length;a>i;i++)s=e[m],l=s.replace(\" \",\"\").split(\",\"),\"undefined\"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l,m++;else{s=e[m].split(\",\");for(var i=0,a=V[t].data.length;a>i;i++)l=(s[i]||\"\").replace(/.*:/,\"\"),l=this._trim(l),l=\"-\"!=l&&\"\"!==l?l-0:\"-\",\"undefined\"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l;m++}},_trim:function(e){var t=new RegExp(\"(^[\\\\s\\\\t\\\\xa0\\\\u3000]+)|([\\\\u3000\\\\xa0\\\\s\\\\t]+$)\",\"g\");return e.replace(t,\"\")},_stop:function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},resize:function(){this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._tDom.offsetHeight>10&&(this._sizeCssText=\"width:\"+this._zrWidth+\"px;height:\"+this._zrHeight+\"px;background-color:#fff;\",this._tDom.style.cssText=this._gCssText+this._sizeCssText,this._textArea.style.cssText=\"display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:\"+(this._zrHeight-100)+\"px;\")},dispose:function(){window.removeEventListener?(this._tDom.removeEventListener(\"click\",this._stop),this._tDom.removeEventListener(\"mousewheel\",this._stop),this._tDom.removeEventListener(\"mousemove\",this._stop),this._tDom.removeEventListener(\"mousedown\",this._stop),this._tDom.removeEventListener(\"mouseup\",this._stop),this._tDom.removeEventListener(\"touchstart\",this._stop),this._tDom.removeEventListener(\"touchmove\",this._stop),this._tDom.removeEventListener(\"touchend\",this._stop)):(this._tDom.detachEvent(\"onclick\",this._stop),this._tDom.detachEvent(\"onmousewheel\",this._stop),this._tDom.detachEvent(\"onmousemove\",this._stop),this._tDom.detachEvent(\"onmousedown\",this._stop),this._tDom.detachEvent(\"onmouseup\",this._stop)),this._buttonRefresh.onclick=null,this._buttonClose.onclick=null,this._hasShow&&(this._tDom.removeChild(this._textArea),this._tDom.removeChild(this._buttonRefresh),this._tDom.removeChild(this._buttonClose)),this._textArea=null,this._buttonRefresh=null,this._buttonClose=null,this.dom.firstChild.removeChild(this._tDom),this._tDom=null}},a.inherits(t,i),e(\"../component\").define(\"dataView\",t),t}),i(\"echarts/util/shape/Cross\",[\"require\",\"zrender/shape/Base\",\"zrender/shape/Line\",\"zrender/tool/util\",\"./normalIsCover\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/shape/Line\"),a=e(\"zrender/tool/util\");return t.prototype={type:\"cross\",buildPath:function(e,t){var i=t.rect;t.xStart=i.x,t.xEnd=i.x+i.width,t.yStart=t.yEnd=t.y,n.prototype.buildPath(e,t),t.xStart=t.xEnd=t.x,t.yStart=i.y,t.yEnd=i.y+i.height,n.prototype.buildPath(e,t)},getRect:function(e){return e.rect},isCover:e(\"./normalIsCover\")},a.inherits(t,i),t}),i(\"zrender/shape/Sector\",[\"require\",\"../tool/math\",\"../tool/computeBoundingBox\",\"../tool/vector\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"../tool/math\"),i=e(\"../tool/computeBoundingBox\"),n=e(\"../tool/vector\"),a=e(\"./Base\"),o=n.create(),r=n.create(),s=n.create(),l=n.create(),h=function(e){a.call(this,e)};return h.prototype={type:\"sector\",buildPath:function(e,i){var n=i.x,a=i.y,o=i.r0||0,r=i.r,s=i.startAngle,l=i.endAngle,h=i.clockWise||!1;s=t.degreeToRadian(s),l=t.degreeToRadian(l),h||(s=-s,l=-l);var m=t.cos(s),V=t.sin(s);e.moveTo(m*o+n,V*o+a),e.lineTo(m*r+n,V*r+a),e.arc(n,a,r,s,l,!h),e.lineTo(t.cos(l)*o+n,t.sin(l)*o+a),0!==o&&e.arc(n,a,o,l,s,h),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var a=e.x,h=e.y,m=e.r0||0,V=e.r,U=t.degreeToRadian(e.startAngle),d=t.degreeToRadian(e.endAngle),p=e.clockWise;return p||(U=-U,d=-d),m>1?i.arc(a,h,m,U,d,!p,o,s):(o[0]=s[0]=a,o[1]=s[1]=h),i.arc(a,h,V,U,d,!p,r,l),n.min(o,o,r),n.max(s,s,l),e.__rect={x:o[0],y:o[1],width:s[0]-o[0],height:s[1]-o[1]},e.__rect}},e(\"../tool/util\").inherits(h,a),h}),i(\"echarts/util/shape/Candle\",[\"require\",\"zrender/shape/Base\",\"zrender/tool/util\",\"./normalIsCover\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/tool/util\");return t.prototype={type:\"candle\",_numberOrder:function(e,t){return t-e},buildPath:function(e,t){var i=n.clone(t.y).sort(this._numberOrder);e.moveTo(t.x,i[3]),e.lineTo(t.x,i[2]),e.moveTo(t.x-t.width/2,i[2]),e.rect(t.x-t.width/2,i[2],t.width,i[1]-i[2]),e.moveTo(t.x,i[1]),e.lineTo(t.x,i[0])},getRect:function(e){if(!e.__rect){var t=0;(\"stroke\"==e.brushType||\"fill\"==e.brushType)&&(t=e.lineWidth||1);var i=n.clone(e.y).sort(this._numberOrder);e.__rect={x:Math.round(e.x-e.width/2-t/2),y:Math.round(i[3]-t/2),width:e.width+t,height:i[0]-i[3]+t}}return e.__rect},isCover:e(\"./normalIsCover\")},n.inherits(t,i),t}),i(\"zrender/tool/computeBoundingBox\",[\"require\",\"./vector\",\"./curve\"],function(e){function t(e,t,i){if(0!==e.length){for(var n=e[0][0],a=e[0][0],o=e[0][1],r=e[0][1],s=1;s<e.length;s++){var l=e[s];l[0]<n&&(n=l[0]),l[0]>a&&(a=l[0]),l[1]<o&&(o=l[1]),l[1]>r&&(r=l[1])}t[0]=n,t[1]=o,i[0]=a,i[1]=r}}function i(e,t,i,n,a,r){var s=[];o.cubicExtrema(e[0],t[0],i[0],n[0],s);for(var l=0;l<s.length;l++)s[l]=o.cubicAt(e[0],t[0],i[0],n[0],s[l]);var h=[];o.cubicExtrema(e[1],t[1],i[1],n[1],h);for(var l=0;l<h.length;l++)h[l]=o.cubicAt(e[1],t[1],i[1],n[1],h[l]);s.push(e[0],n[0]),h.push(e[1],n[1]);var m=Math.min.apply(null,s),V=Math.max.apply(null,s),U=Math.min.apply(null,h),d=Math.max.apply(null,h);a[0]=m,a[1]=U,r[0]=V,r[1]=d}function n(e,t,i,n,a){var r=o.quadraticExtremum(e[0],t[0],i[0]),s=o.quadraticExtremum(e[1],t[1],i[1]);r=Math.max(Math.min(r,1),0),s=Math.max(Math.min(s,1),0);var l=1-r,h=1-s,m=l*l*e[0]+2*l*r*t[0]+r*r*i[0],V=l*l*e[1]+2*l*r*t[1]+r*r*i[1],U=h*h*e[0]+2*h*s*t[0]+s*s*i[0],d=h*h*e[1]+2*h*s*t[1]+s*s*i[1];n[0]=Math.min(e[0],i[0],m,U),n[1]=Math.min(e[1],i[1],V,d),a[0]=Math.max(e[0],i[0],m,U),a[1]=Math.max(e[1],i[1],V,d)}var a=e(\"./vector\"),o=e(\"./curve\"),r=a.create(),s=a.create(),l=a.create(),h=function(e,t,i,n,o,h,m,V){if(Math.abs(n-o)>=2*Math.PI)return m[0]=e-i,m[1]=t-i,V[0]=e+i,void(V[1]=t+i);if(r[0]=Math.cos(n)*i+e,r[1]=Math.sin(n)*i+t,s[0]=Math.cos(o)*i+e,s[1]=Math.sin(o)*i+t,a.min(m,r,s),a.max(V,r,s),n%=2*Math.PI,0>n&&(n+=2*Math.PI),o%=2*Math.PI,0>o&&(o+=2*Math.PI),n>o&&!h?o+=2*Math.PI:o>n&&h&&(n+=2*Math.PI),h){var U=o;o=n,n=U}for(var d=0;o>d;d+=Math.PI/2)d>n&&(l[0]=Math.cos(d)*i+e,l[1]=Math.sin(d)*i+t,a.min(m,l,m),a.max(V,l,V))};return t.cubeBezier=i,t.quadraticBezier=n,t.arc=h,t}),i(\"echarts/util/shape/Chain\",[\"require\",\"zrender/shape/Base\",\"./Icon\",\"zrender/shape/util/dashedLineTo\",\"zrender/tool/util\",\"zrender/tool/matrix\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"./Icon\"),a=e(\"zrender/shape/util/dashedLineTo\"),o=e(\"zrender/tool/util\"),r=e(\"zrender/tool/matrix\");return t.prototype={type:\"chain\",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildLinePath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i),e.restore()},buildLinePath:function(e,t){var i=t.x,n=t.y+5,o=t.width,r=t.height/2-10;if(e.moveTo(i,n),e.lineTo(i,n+r),e.moveTo(i+o,n),e.lineTo(i+o,n+r),e.moveTo(i,n+r/2),t.lineType&&\"solid\"!=t.lineType){if(\"dashed\"==t.lineType||\"dotted\"==t.lineType){var s=(t.lineWidth||1)*(\"dashed\"==t.lineType?5:1);a(e,i,n+r/2,i+o,n+r/2,s)}}else e.lineTo(i+o,n+r/2)},brushSymbol:function(e,t){var i=t.y+t.height/4;e.save();for(var a,o=t.chainPoint,r=0,s=o.length;s>r;r++){if(a=o[r],\"none\"!=a.symbol){e.beginPath();var l=a.symbolSize;n.prototype.buildPath(e,{iconType:a.symbol,x:a.x-l,y:i-l,width:2*l,height:2*l,n:a.n}),e.fillStyle=a.isEmpty?\"#fff\":t.strokeColor,e.closePath(),e.fill(),e.stroke()}a.showLabel&&(e.font=a.textFont,e.fillStyle=a.textColor,e.textAlign=a.textAlign,e.textBaseline=a.textBaseline,a.rotation?(e.save(),this._updateTextTransform(e,a.rotation),e.fillText(a.name,a.textX,a.textY),e.restore()):e.fillText(a.name,a.textX,a.textY))}e.restore()},_updateTextTransform:function(e,t){var i=r.create();if(r.identity(i),0!==t[0]){var n=t[1]||0,a=t[2]||0;(n||a)&&r.translate(i,i,[-n,-a]),r.rotate(i,i,t[0]),(n||a)&&r.translate(i,i,[n,a])}e.transform.apply(e,i)},isCover:function(e,t){var i=this.style;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?!0:!1}},o.inherits(t,i),t}),i(\"zrender/shape/Ring\",[\"require\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={type:\"ring\",buildPath:function(e,t){e.arc(t.x,t.y,t.r,0,2*Math.PI,!1),e.moveTo(t.x+t.r0,t.y),e.arc(t.x,t.y,t.r0,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e(\"../tool/util\").inherits(i,t),i}),i(\"echarts/component/axis\",[\"require\",\"./base\",\"zrender/shape/Line\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"./categoryAxis\",\"./valueAxis\",\"../component\"],function(e){function t(e,t,n,a,o,r){i.call(this,e,t,n,a,o),this.axisType=r,this._axisList=[],this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Line\"),a=e(\"../config\"),o=e(\"../util/ecData\"),r=e(\"zrender/tool/util\"),s=e(\"zrender/tool/color\");return t.prototype={type:a.COMPONENT_TYPE_AXIS,axisBase:{_buildAxisLine:function(){var e=this.option.axisLine.lineStyle.width,t=e/2,i={_axisShape:\"axisLine\",zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1},a=this.grid;switch(this.option.position){case\"left\":i.style={xStart:a.getX()-t,yStart:a.getYend(),xEnd:a.getX()-t,yEnd:a.getY(),lineCap:\"round\"};break;case\"right\":i.style={xStart:a.getXend()+t,yStart:a.getYend(),xEnd:a.getXend()+t,yEnd:a.getY(),lineCap:\"round\"};break;case\"bottom\":i.style={xStart:a.getX(),yStart:a.getYend()+t,xEnd:a.getXend(),yEnd:a.getYend()+t,lineCap:\"round\"};break;case\"top\":i.style={xStart:a.getX(),yStart:a.getY()-t,xEnd:a.getXend(),yEnd:a.getY()-t,lineCap:\"round\"}}var o=i.style;\"\"!==this.option.name&&(o.text=this.option.name,o.textPosition=this.option.nameLocation,o.textFont=this.getFont(this.option.nameTextStyle),this.option.nameTextStyle.align&&(o.textAlign=this.option.nameTextStyle.align),this.option.nameTextStyle.baseline&&(o.textBaseline=this.option.nameTextStyle.baseline),this.option.nameTextStyle.color&&(o.textColor=this.option.nameTextStyle.color)),o.strokeColor=this.option.axisLine.lineStyle.color,o.lineWidth=e,this.isHorizontal()?o.yStart=o.yEnd=this.subPixelOptimize(o.yEnd,e):o.xStart=o.xEnd=this.subPixelOptimize(o.xEnd,e),o.lineType=this.option.axisLine.lineStyle.type,i=new n(i),this.shapeList.push(i)},_axisLabelClickable:function(e,t){return e?(o.pack(t,void 0,-1,void 0,-1,t.style.text),t.hoverable=!0,t.clickable=!0,t.highlightStyle={color:s.lift(t.style.color,1),brushType:\"fill\"},t):t},refixAxisShape:function(e,t){if(this.option.axisLine.onZero){var i;if(this.isHorizontal()&&null!=t)for(var n=0,a=this.shapeList.length;a>n;n++)\"axisLine\"===this.shapeList[n]._axisShape?(this.shapeList[n].style.yStart=this.shapeList[n].style.yEnd=this.subPixelOptimize(t,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):\"axisTick\"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.yEnd-this.shapeList[n].style.yStart,this.shapeList[n].style.yStart=t-i,this.shapeList[n].style.yEnd=t,this.zr.modShape(this.shapeList[n].id));if(!this.isHorizontal()&&null!=e)for(var n=0,a=this.shapeList.length;a>n;n++)\"axisLine\"===this.shapeList[n]._axisShape?(this.shapeList[n].style.xStart=this.shapeList[n].style.xEnd=this.subPixelOptimize(e,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):\"axisTick\"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.xEnd-this.shapeList[n].style.xStart,this.shapeList[n].style.xStart=e,this.shapeList[n].style.xEnd=e+i,this.zr.modShape(this.shapeList[n].id))}},getPosition:function(){return this.option.position},isHorizontal:function(){return\"bottom\"===this.option.position||\"top\"===this.option.position}},reformOption:function(e){if(!e||e instanceof Array&&0===e.length?e=[{type:a.COMPONENT_TYPE_AXIS_VALUE}]:e instanceof Array||(e=[e]),e.length>2&&(e=[e[0],e[1]]),\"xAxis\"===this.axisType){(!e[0].position||\"bottom\"!=e[0].position&&\"top\"!=e[0].position)&&(e[0].position=\"bottom\"),e.length>1&&(e[1].position=\"bottom\"===e[0].position?\"top\":\"bottom\");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||\"category\",e[t].xAxisIndex=t,e[t].yAxisIndex=-1}else{(!e[0].position||\"left\"!=e[0].position&&\"right\"!=e[0].position)&&(e[0].position=\"left\"),e.length>1&&(e[1].position=\"left\"===e[0].position?\"right\":\"left\");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||\"value\",e[t].xAxisIndex=-1,e[t].yAxisIndex=t}return e},refresh:function(t){var i;t&&(this.option=t,\"xAxis\"===this.axisType?(this.option.xAxis=this.reformOption(t.xAxis),i=this.option.xAxis):(this.option.yAxis=this.reformOption(t.yAxis),i=this.option.yAxis),this.series=t.series);for(var n=e(\"./categoryAxis\"),a=e(\"./valueAxis\"),o=Math.max(i&&i.length||0,this._axisList.length),r=0;o>r;r++)!this._axisList[r]||!t||i[r]&&this._axisList[r].type==i[r].type||(this._axisList[r].dispose&&this._axisList[r].dispose(),this._axisList[r]=!1),this._axisList[r]?this._axisList[r].refresh&&this._axisList[r].refresh(i?i[r]:!1,this.series):i&&i[r]&&(this._axisList[r]=\"category\"===i[r].type?new n(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase):new a(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase,this.series))},getAxis:function(e){return this._axisList[e]},getAxisCount:function(){return this._axisList.length},clear:function(){for(var e=0,t=this._axisList.length;t>e;e++)this._axisList[e].dispose&&this._axisList[e].dispose();this._axisList=[]}},r.inherits(t,i),e(\"../component\").define(\"axis\",t),t}),i(\"echarts/component/grid\",[\"require\",\"./base\",\"zrender/shape/Rectangle\",\"../config\",\"zrender/tool/util\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Rectangle\"),a=e(\"../config\");a.grid={zlevel:0,z:0,x:80,y:60,x2:80,y2:60,backgroundColor:\"rgba(0,0,0,0)\",borderWidth:1,borderColor:\"#ccc\"};var o=e(\"zrender/tool/util\");return t.prototype={type:a.COMPONENT_TYPE_GRID,getX:function(){return this._x},getY:function(){return this._y},getWidth:function(){return this._width},getHeight:function(){return this._height},getXend:function(){return this._x+this._width},getYend:function(){return this._y+this._height},getArea:function(){return{x:this._x,y:this._y,width:this._width,height:this._height}},getBbox:function(){return[[this._x,this._y],[this.getXend(),this.getYend()]]},refixAxisShape:function(e){for(var t,i,n,o=e.xAxis._axisList.concat(e.yAxis?e.yAxis._axisList:[]),r=o.length;r--;)n=o[r],n.type==a.COMPONENT_TYPE_AXIS_VALUE&&n._min<0&&n._max>=0&&(n.isHorizontal()?t=n.getCoord(0):i=n.getCoord(0));if(\"undefined\"!=typeof t||\"undefined\"!=typeof i)for(r=o.length;r--;)o[r].refixAxisShape(t,i)},refresh:function(e){if(e||this._zrWidth!=this.zr.getWidth()||this._zrHeight!=this.zr.getHeight()){this.clear(),this.option=e||this.option,this.option.grid=this.reformOption(this.option.grid);var t=this.option.grid;this._zrWidth=this.zr.getWidth(),this._zrHeight=this.zr.getHeight(),this._x=this.parsePercent(t.x,this._zrWidth),this._y=this.parsePercent(t.y,this._zrHeight);var i=this.parsePercent(t.x2,this._zrWidth),a=this.parsePercent(t.y2,this._zrHeight);this._width=\"undefined\"==typeof t.width?this._zrWidth-this._x-i:this.parsePercent(t.width,this._zrWidth),this._width=this._width<=0?10:this._width,this._height=\"undefined\"==typeof t.height?this._zrHeight-this._y-a:this.parsePercent(t.height,this._zrHeight),this._height=this._height<=0?10:this._height,this._x=this.subPixelOptimize(this._x,t.borderWidth),this._y=this.subPixelOptimize(this._y,t.borderWidth),this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._x,y:this._y,width:this._width,height:this._height,brushType:t.borderWidth>0?\"both\":\"fill\",color:t.backgroundColor,strokeColor:t.borderColor,lineWidth:t.borderWidth}})),this.zr.addShape(this.shapeList[0])}}},o.inherits(t,i),e(\"../component\").define(\"grid\",t),t}),i(\"echarts/component/dataZoom\",[\"require\",\"./base\",\"zrender/shape/Rectangle\",\"zrender/shape/Polygon\",\"../util/shape/Icon\",\"../config\",\"../util/date\",\"zrender/tool/util\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},this._fillerSize=30,this._isSilence=!1,this._zoom={},this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this._handleSize=this.zoomOption.handleSize,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom.show&&this._buildShape(),this._syncData()}var i=e(\"./base\"),n=e(\"zrender/shape/Rectangle\"),a=e(\"zrender/shape/Polygon\"),o=e(\"../util/shape/Icon\"),r=e(\"../config\");r.dataZoom={zlevel:0,z:4,show:!1,orient:\"horizontal\",backgroundColor:\"rgba(0,0,0,0)\",dataBackgroundColor:\"#eee\",fillerColor:\"rgba(144,197,237,0.2)\",handleColor:\"rgba(70,130,180,0.8)\",handleSize:8,showDetail:!0,realtime:!0};var s=e(\"../util/date\"),l=e(\"zrender/tool/util\");return t.prototype={type:r.COMPONENT_TYPE_DATAZOOM,_buildShape:function(){this._buildBackground(),this._buildFiller(),this._buildHandle(),this._buildFrame();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncFrameShape()},_getLocation:function(){var e,t,i,n,a=this.component.grid;return\"horizontal\"==this.zoomOption.orient?(i=this.zoomOption.width||a.getWidth(),n=this.zoomOption.height||this._fillerSize,e=null!=this.zoomOption.x?this.zoomOption.x:a.getX(),t=null!=this.zoomOption.y?this.zoomOption.y:this.zr.getHeight()-n-2):(i=this.zoomOption.width||this._fillerSize,n=this.zoomOption.height||a.getHeight(),e=null!=this.zoomOption.x?this.zoomOption.x:2,t=null!=this.zoomOption.y?this.zoomOption.y:a.getY()),{x:e,y:t,width:i,height:n}},_getZoom:function(){var e=this.option.series,t=this.option.xAxis;!t||t instanceof Array||(t=[t],this.option.xAxis=t);var i=this.option.yAxis;!i||i instanceof Array||(i=[i],this.option.yAxis=i);var n,a,o=[],s=this.zoomOption.xAxisIndex;if(t&&null==s){n=[];for(var l=0,h=t.length;h>l;l++)(\"category\"==t[l].type||null==t[l].type)&&n.push(l)}else n=s instanceof Array?s:null!=s?[s]:[];if(s=this.zoomOption.yAxisIndex,i&&null==s){a=[];for(var l=0,h=i.length;h>l;l++)\"category\"==i[l].type&&a.push(l)}else a=s instanceof Array?s:null!=s?[s]:[];for(var m,l=0,h=e.length;h>l;l++)if(m=e[l],m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR||m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_K){for(var V=0,U=n.length;U>V;V++)if(n[V]==(m.xAxisIndex||0)){o.push(l);break}for(var V=0,U=a.length;U>V;V++)if(a[V]==(m.yAxisIndex||0)){o.push(l);break}null==this.zoomOption.xAxisIndex&&null==this.zoomOption.yAxisIndex&&m.data&&this.getDataFromOption(m.data[0])instanceof Array&&(m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR)&&o.push(l)}var d=null!=this._zoom.start?this._zoom.start:null!=this.zoomOption.start?this.zoomOption.start:0,p=null!=this._zoom.end?this._zoom.end:null!=this.zoomOption.end?this.zoomOption.end:100;d>p&&(d+=p,p=d-p,d-=p);var c=Math.round((p-d)/100*(\"horizontal\"==this.zoomOption.orient?this._location.width:this._location.height));return{start:d,end:p,start2:0,end2:100,size:c,xAxisIndex:n,yAxisIndex:a,seriesIndex:o,scatterMap:this._zoom.scatterMap||{}}},_backupData:function(){this._originalData={xAxis:{},yAxis:{},series:{}};for(var e=this.option.xAxis,t=this._zoom.xAxisIndex,i=0,n=t.length;n>i;i++)this._originalData.xAxis[t[i]]=e[t[i]].data;for(var a=this.option.yAxis,o=this._zoom.yAxisIndex,i=0,n=o.length;n>i;i++)this._originalData.yAxis[o[i]]=a[o[i]].data;for(var s,l=this.option.series,h=this._zoom.seriesIndex,i=0,n=h.length;n>i;i++)s=l[h[i]],this._originalData.series[h[i]]=s.data,s.data&&this.getDataFromOption(s.data[0])instanceof Array&&(s.type==r.CHART_TYPE_SCATTER||s.type==r.CHART_TYPE_LINE||s.type==r.CHART_TYPE_BAR)&&(this._backupScale(),this._calculScatterMap(h[i]))},_calculScatterMap:function(t){this._zoom.scatterMap=this._zoom.scatterMap||{},this._zoom.scatterMap[t]=this._zoom.scatterMap[t]||{};var i=e(\"../component\"),n=i.get(\"axis\"),a=l.clone(this.option.xAxis);\"category\"==a[0].type&&(a[0].type=\"value\"),a[1]&&\"category\"==a[1].type&&(a[1].type=\"value\");var o=new n(this.ecTheme,null,!1,{xAxis:a,series:this.option.series},this,\"xAxis\"),r=this.option.series[t].xAxisIndex||0;this._zoom.scatterMap[t].x=o.getAxis(r).getExtremum(),o.dispose(),a=l.clone(this.option.yAxis),\"category\"==a[0].type&&(a[0].type=\"value\"),a[1]&&\"category\"==a[1].type&&(a[1].type=\"value\"),o=new n(this.ecTheme,null,!1,{yAxis:a,series:this.option.series},this,\"yAxis\"),r=this.option.series[t].yAxisIndex||0,this._zoom.scatterMap[t].y=o.getAxis(r).getExtremum(),o.dispose()},_buildBackground:function(){var e=this._location.width,t=this._location.height;this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x,y:this._location.y,width:e,height:t,color:this.zoomOption.backgroundColor}}));for(var i=0,o=this._originalData.xAxis,s=this._zoom.xAxisIndex,l=0,h=s.length;h>l;l++)i=Math.max(i,o[s[l]].length);for(var m=this._originalData.yAxis,V=this._zoom.yAxisIndex,l=0,h=V.length;h>l;l++)i=Math.max(i,m[V[l]].length);for(var U,d=this._zoom.seriesIndex[0],p=this._originalData.series[d],c=Number.MIN_VALUE,u=Number.MAX_VALUE,l=0,h=p.length;h>l;l++)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),c=Math.max(c,U),u=Math.min(u,U);var y=c-u,g=[],b=e/(i-(i>1?1:0)),f=t/(i-(i>1?1:0)),k=1;\"horizontal\"==this.zoomOption.orient&&1>b?k=Math.floor(3*i/e):\"vertical\"==this.zoomOption.orient&&1>f&&(k=Math.floor(3*i/t));for(var l=0,h=i;h>l;l+=k)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),g.push(\"horizontal\"==this.zoomOption.orient?[this._location.x+b*l,this._location.y+t-1-Math.round((U-u)/y*(t-10))]:[this._location.x+1+Math.round((U-u)/y*(e-10)),this._location.y+f*(h-l-1)]);\"horizontal\"==this.zoomOption.orient?(g.push([this._location.x+e,this._location.y+t]),g.push([this._location.x,this._location.y+t])):(g.push([this._location.x,this._location.y]),g.push([this._location.x,this._location.y+t])),this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:g,color:this.zoomOption.dataBackgroundColor},hoverable:!1}))},_buildFiller:function(){this._fillerShae={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,_type:\"filler\"},this._fillerShae.style=\"horizontal\"==this.zoomOption.orient?{x:this._location.x+Math.round(this._zoom.start/100*this._location.width)+this._handleSize,y:this._location.y,width:this._zoom.size-2*this._handleSize,height:this._location.height,color:this.zoomOption.fillerColor,text:\":::\",textPosition:\"inside\"}:{x:this._location.x,y:this._location.y+Math.round(this._zoom.start/100*this._location.height)+this._handleSize,width:this._location.width,height:this._zoom.size-2*this._handleSize,color:this.zoomOption.fillerColor,text:\"::\",textPosition:\"inside\"},this._fillerShae.highlightStyle={brushType:\"fill\",color:\"rgba(0,0,0,0)\"},this._fillerShae=new n(this._fillerShae),this.shapeList.push(this._fillerShae)},_buildHandle:function(){var e=this.zoomOption.showDetail?this._getDetail():{start:\"\",end:\"\"};this._startShape={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,style:{iconType:\"rectangle\",x:this._location.x,y:this._location.y,width:this._handleSize,height:this._handleSize,color:this.zoomOption.handleColor,text:\"=\",textPosition:\"inside\"},highlightStyle:{text:e.start,brushType:\"fill\",textPosition:\"left\"},ondrift:this._ondrift,ondragend:this._ondragend},\"horizontal\"==this.zoomOption.orient?(this._startShape.style.height=this._location.height,this._endShape=l.clone(this._startShape),this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition=\"right\"):(this._startShape.style.width=this._location.width,this._endShape=l.clone(this._startShape),this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startShape.highlightStyle.textPosition=\"bottom\",this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition=\"top\"),this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_buildFrame:function(){var e=this.subPixelOptimize(this._location.x,1),t=this.subPixelOptimize(this._location.y,1);this._startFrameShape={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:e,y:t,width:this._location.width-(e>this._location.x?1:0),height:this._location.height-(t>this._location.y?1:0),lineWidth:1,brushType:\"stroke\",strokeColor:this.zoomOption.handleColor}},this._endFrameShape=l.clone(this._startFrameShape),this._startFrameShape=new n(this._startFrameShape),this._endFrameShape=new n(this._endFrameShape),this.shapeList.push(this._startFrameShape),this.shapeList.push(this._endFrameShape)},_syncHandleShape:function(){\"horizontal\"==this.zoomOption.orient?(this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._zoom.start=(this._startShape.style.x-this._location.x)/this._location.width*100,this._zoom.end=(this._endShape.style.x+this._handleSize-this._location.x)/this._location.width*100):(this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._zoom.start=(this._location.y+this._location.height-this._startShape.style.y)/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-this._endShape.style.y-this._handleSize)/this._location.height*100),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFillerShape:function(){var e,t;\"horizontal\"==this.zoomOption.orient?(e=this._startShape.style.x,t=this._endShape.style.x,this._fillerShae.style.x=Math.min(e,t)+this._handleSize,this._fillerShae.style.width=Math.abs(e-t)-this._handleSize,this._zoom.start=(Math.min(e,t)-this._location.x)/this._location.width*100,this._zoom.end=(Math.max(e,t)+this._handleSize-this._location.x)/this._location.width*100):(e=this._startShape.style.y,t=this._endShape.style.y,this._fillerShae.style.y=Math.min(e,t)+this._handleSize,this._fillerShae.style.height=Math.abs(e-t)-this._handleSize,this._zoom.start=(this._location.y+this._location.height-Math.max(e,t))/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-Math.min(e,t)-this._handleSize)/this._location.height*100),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFrameShape:function(){\"horizontal\"==this.zoomOption.orient?(this._startFrameShape.style.width=this._fillerShae.style.x-this._location.x,this._endFrameShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endFrameShape.style.width=this._location.x+this._location.width-this._endFrameShape.style.x):(this._startFrameShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startFrameShape.style.height=this._location.y+this._location.height-this._startFrameShape.style.y,this._endFrameShape.style.height=this._fillerShae.style.y-this._location.y),this.zr.modShape(this._startFrameShape.id),this.zr.modShape(this._endFrameShape.id)},_syncShape:function(){this.zoomOption.show&&(\"horizontal\"==this.zoomOption.orient?(this._startShape.style.x=this._location.x+this._zoom.start/100*this._location.width,this._endShape.style.x=this._location.x+this._zoom.end/100*this._location.width-this._handleSize,this._fillerShae.style.x=this._startShape.style.x+this._handleSize,this._fillerShae.style.width=this._endShape.style.x-this._startShape.style.x-this._handleSize):(this._startShape.style.y=this._location.y+this._location.height-this._zoom.start/100*this._location.height,this._endShape.style.y=this._location.y+this._location.height-this._zoom.end/100*this._location.height-this._handleSize,this._fillerShae.style.y=this._endShape.style.y+this._handleSize,this._fillerShae.style.height=this._startShape.style.y-this._endShape.style.y-this._handleSize),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refresh())},_syncData:function(e){var t,i,n,a,o;for(var s in this._originalData){t=this._originalData[s];for(var l in t)o=t[l],null!=o&&(a=o.length,i=Math.floor(this._zoom.start/100*a),n=Math.ceil(this._zoom.end/100*a),this.getDataFromOption(o[0])instanceof Array&&this.option[s][l].type!=r.CHART_TYPE_K?(this._setScale(),this.option[s][l].data=this._synScatterData(l,o)):this.option[s][l].data=o.slice(i,n))}this._isSilence||!this.zoomOption.realtime&&!e||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart)},_synScatterData:function(e,t){if(0===this._zoom.start&&100==this._zoom.end&&0===this._zoom.start2&&100==this._zoom.end2)return t;var i,n,a,o,r,s=[],l=this._zoom.scatterMap[e];\n\n\"horizontal\"==this.zoomOption.orient?(i=l.x.max-l.x.min,n=this._zoom.start/100*i+l.x.min,a=this._zoom.end/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start2/100*i+l.y.min,r=this._zoom.end2/100*i+l.y.min):(i=l.x.max-l.x.min,n=this._zoom.start2/100*i+l.x.min,a=this._zoom.end2/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start/100*i+l.y.min,r=this._zoom.end/100*i+l.y.min);var h;(h=l.x.dataMappingMethods)&&(n=h.coord2Value(n),a=h.coord2Value(a)),(h=l.y.dataMappingMethods)&&(o=h.coord2Value(o),r=h.coord2Value(r));for(var m,V=0,U=t.length;U>V;V++)m=t[V].value||t[V],m[0]>=n&&m[0]<=a&&m[1]>=o&&m[1]<=r&&s.push(t[V]);return s},_setScale:function(){var e=0!==this._zoom.start||100!==this._zoom.end||0!==this._zoom.start2||100!==this._zoom.end2,t={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var i in t)for(var n=0,a=t[i].length;a>n;n++)t[i][n].scale=e||t[i][n]._scale},_backupScale:function(){var e={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var t in e)for(var i=0,n=e[t].length;n>i;i++)e[t][i]._scale=e[t][i].scale},_getDetail:function(){for(var e=[\"xAxis\",\"yAxis\"],t=0,i=e.length;i>t;t++){var n=this._originalData[e[t]];for(var a in n){var o=n[a];if(null!=o){var r=o.length,l=Math.floor(this._zoom.start/100*r),h=Math.ceil(this._zoom.end/100*r);return h-=h>0?1:0,{start:this.getDataFromOption(o[l]),end:this.getDataFromOption(o[h])}}}}e=\"horizontal\"==this.zoomOption.orient?\"xAxis\":\"yAxis\";var m=this._zoom.seriesIndex[0],V=this.option.series[m][e+\"Index\"]||0,U=this.option[e][V].type,d=this._zoom.scatterMap[m][e.charAt(0)].min,p=this._zoom.scatterMap[m][e.charAt(0)].max,c=p-d;if(\"value\"==U)return{start:d+c*this._zoom.start/100,end:d+c*this._zoom.end/100};if(\"time\"==U){p=d+c*this._zoom.end/100,d+=c*this._zoom.start/100;var u=s.getAutoFormatter(d,p).formatter;return{start:s.format(u,d),end:s.format(u,p)}}return{start:\"\",end:\"\"}},__ondrift:function(e,t,i){this.zoomOption.zoomLock&&(e=this._fillerShae);var n=\"filler\"==e._type?this._handleSize:0;if(\"horizontal\"==this.zoomOption.orient?e.style.x+t-n<=this._location.x?e.style.x=this._location.x+n:e.style.x+t+e.style.width+n>=this._location.x+this._location.width?e.style.x=this._location.x+this._location.width-e.style.width-n:e.style.x+=t:e.style.y+i-n<=this._location.y?e.style.y=this._location.y+n:e.style.y+i+e.style.height+n>=this._location.y+this._location.height?e.style.y=this._location.y+this._location.height-e.style.height-n:e.style.y+=i,\"filler\"==e._type?this._syncHandleShape():this._syncFillerShape(),this.zoomOption.realtime&&this._syncData(),this.zoomOption.showDetail){var a=this._getDetail();this._startShape.style.text=this._startShape.highlightStyle.text=a.start,this._endShape.style.text=this._endShape.highlightStyle.text=a.end,this._startShape.style.textPosition=this._startShape.highlightStyle.textPosition,this._endShape.style.textPosition=this._endShape.highlightStyle.textPosition}return!0},__ondragend:function(){this.zoomOption.showDetail&&(this._startShape.style.text=this._endShape.style.text=\"=\",this._startShape.style.textPosition=this._endShape.style.textPosition=\"inside\",this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.refreshNextFrame()),this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.zoomOption.realtime&&this._syncData(),t.dragOut=!0,t.dragIn=!0,this._isSilence||this.zoomOption.realtime||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart),t.needRefresh=!1,this.isDragend=!1)},ondataZoom:function(e,t){t.needRefresh=!0},absoluteZoom:function(e){this._zoom.start=e.start,this._zoom.end=e.end,this._zoom.start2=e.start2,this._zoom.end2=e.end2,this._syncShape(),this._syncData(!0)},rectZoom:function(e){if(!e)return this._zoom.start=this._zoom.start2=0,this._zoom.end=this._zoom.end2=100,this._syncShape(),this._syncData(!0),this._zoom;var t=this.component.grid.getArea(),i={x:e.x,y:e.y,width:e.width,height:e.height};if(i.width<0&&(i.x+=i.width,i.width=-i.width),i.height<0&&(i.y+=i.height,i.height=-i.height),i.x>t.x+t.width||i.y>t.y+t.height)return!1;i.x<t.x&&(i.x=t.x),i.x+i.width>t.x+t.width&&(i.width=t.x+t.width-i.x),i.y+i.height>t.y+t.height&&(i.height=t.y+t.height-i.y);var n,a=(i.x-t.x)/t.width,o=1-(i.x+i.width-t.x)/t.width,r=1-(i.y+i.height-t.y)/t.height,s=(i.y-t.y)/t.height;return\"horizontal\"==this.zoomOption.orient?(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*a,this._zoom.end-=n*o,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*r,this._zoom.end2-=n*s):(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*r,this._zoom.end-=n*s,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*a,this._zoom.end2-=n*o),this._syncShape(),this._syncData(!0),this._zoom},syncBackupData:function(e){for(var t,i,n=this._originalData.series,a=e.series,o=0,r=a.length;r>o;o++){i=a[o].data||a[o].eventList,t=n[o]?Math.floor(this._zoom.start/100*n[o].length):0;for(var s=0,l=i.length;l>s;s++)n[o]&&(n[o][s+t]=i[s])}},syncOption:function(e){this.silence(!0),this.option=e,this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom&&this.option.dataZoom.show&&this._buildShape(),this._syncData(),this.silence(!1)},silence:function(e){this._isSilence=e},getRealDataIndex:function(e,t){if(!this._originalData||0===this._zoom.start&&100==this._zoom.end)return t;var i=this._originalData.series;return i[e]?Math.floor(this._zoom.start/100*i[e].length)+t:-1},resize:function(){this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this.option.dataZoom.show&&this._buildShape()}},l.inherits(t,i),e(\"../component\").define(\"dataZoom\",t),t}),i(\"echarts/component/categoryAxis\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Rectangle\",\"../config\",\"zrender/tool/util\",\"zrender/tool/area\",\"../component\"],function(e){function t(e,t,n,a,o,r){if(a.data.length<1)return void console.error(\"option.data.length < 1.\");i.call(this,e,t,n,a,o),this.grid=this.component.grid;for(var s in r)this[s]=r[s];this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Rectangle\"),r=e(\"../config\");r.categoryAxis={zlevel:0,z:0,show:!0,position:\"bottom\",name:\"\",nameLocation:\"end\",nameTextStyle:{},boundaryGap:!0,axisLine:{show:!0,onZero:!0,lineStyle:{color:\"#48b\",width:2,type:\"solid\"}},axisTick:{show:!0,interval:\"auto\",inside:!1,length:5,lineStyle:{color:\"#333\",width:1}},axisLabel:{show:!0,interval:\"auto\",rotate:0,margin:8,textStyle:{color:\"#333\"}},splitLine:{show:!0,lineStyle:{color:[\"#ccc\"],width:1,type:\"solid\"}},splitArea:{show:!1,areaStyle:{color:[\"rgba(250,250,250,0.3)\",\"rgba(200,200,200,0.3)\"]}}};var s=e(\"zrender/tool/util\"),l=e(\"zrender/tool/area\");return t.prototype={type:r.COMPONENT_TYPE_AXIS_CATEGORY,_getReformedLabel:function(e){var t=this.getDataFromOption(this.option.data[e]),i=this.option.data[e].formatter||this.option.axisLabel.formatter;return i&&(\"function\"==typeof i?t=i.call(this.myChart,t):\"string\"==typeof i&&(t=i.replace(\"{value}\",t))),t},_getInterval:function(){var e=this.option.axisLabel.interval;if(\"auto\"==e){var t=this.option.axisLabel.textStyle.fontSize,i=this.option.data,n=this.option.data.length;if(this.isHorizontal())if(n>3){var a,o,r=this.getGap(),h=!1,m=Math.floor(.5/r);for(m=1>m?1:m,e=Math.floor(15/r);!h&&n>e;){e+=m,h=!0,a=Math.floor(r*e);for(var V=Math.floor((n-1)/e)*e;V>=0;V-=e){if(0!==this.option.axisLabel.rotate)o=t;else if(i[V].textStyle)o=l.getTextWidth(this._getReformedLabel(V),this.getFont(s.merge(i[V].textStyle,this.option.axisLabel.textStyle)));else{var U=this._getReformedLabel(V)+\"\",d=(U.match(/\\w/g)||\"\").length,p=U.length-d;o=d*t*2/3+p*t}if(o>a){h=!1;break}}}}else e=1;else if(n>3){var r=this.getGap();for(e=Math.floor(11/r);t>r*e-6&&n>e;)e++}else e=1}else e=\"function\"==typeof e?1:e-0+1;return e},_buildShape:function(){if(this._interval=this._getInterval(),this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width,l=\"function\"==typeof n.interval?n.interval:\"auto\"==n.interval&&\"function\"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,h=l?1:\"auto\"==n.interval?this._interval:n.interval-0+1,m=n.onGap,V=m?this.getGap()/2:\"undefined\"==typeof m&&this.option.boundaryGap?this.getGap()/2:0,U=V>0?-h:0;if(this.isHorizontal())for(var d,p=\"bottom\"==this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(d=this.subPixelOptimize(this.getCoordByIndex(c)+(c>=0?V:0),s),e={_axisShape:\"axisTick\",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:d,yStart:p,xEnd:d,yEnd:p+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)));else for(var u,y=\"left\"==this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-(c>=0?V:0),s),e={_axisShape:\"axisTick\",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:y+o,yEnd:u,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)))},_buildAxisLabel:function(){var e,t,i=this.option.data,a=this.option.data.length,o=this.option.axisLabel,r=o.rotate,l=o.margin,h=o.clickable,m=o.textStyle,V=\"function\"==typeof o.interval?o.interval:!1;if(this.isHorizontal()){var U,d;\"bottom\"==this.option.position?(U=this.grid.getYend()+l,d=\"top\"):(U=this.grid.getY()-l,d=\"bottom\");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||\"\"===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoordByIndex(p),y:U,color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||\"center\",textBaseline:t.baseline||d}},r&&(e.style.textAlign=r>0?\"bottom\"==this.option.position?\"right\":\"left\":\"bottom\"==this.option.position?\"left\":\"right\",e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}else{var c,u;\"left\"==this.option.position?(c=this.grid.getX()-l,u=\"right\"):(c=this.grid.getXend()+l,u=\"left\");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||\"\"===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:c,y:this.getCoordByIndex(p),color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||u,textBaseline:t.baseline||0===p&&\"\"!==this.option.name?\"bottom\":p==a-1&&\"\"!==this.option.name?\"top\":\"middle\"}},r&&(e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}},_buildSplitLine:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length,h=\"function\"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,m=n.onGap,V=m?this.getGap()/2:\"undefined\"==typeof m&&this.option.boundaryGap?this.getGap()/2:0;if(i-=m||\"undefined\"==typeof m&&this.option.boundaryGap?1:0,this.isHorizontal())for(var U,d=this.grid.getY(),p=this.grid.getYend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(U=this.subPixelOptimize(this.getCoordByIndex(c)+V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:d,xEnd:U,yEnd:p,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)));else for(var u,y=this.grid.getX(),g=this.grid.getXend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:g,yEnd:u,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)))},_buildSplitArea:function(){var e,t=this.option.data,i=this.option.splitArea,n=i.areaStyle.color;if(n instanceof Array){var a=n.length,r=this.option.data.length,s=\"function\"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,l=i.onGap,h=l?this.getGap()/2:\"undefined\"==typeof l&&this.option.boundaryGap?this.getGap()/2:0;if(this.isHorizontal())for(var m,V=this.grid.getY(),U=this.grid.getHeight(),d=this.grid.getX(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(m=r>p?this.getCoordByIndex(p)+h:this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:d,y:V,width:m-d,height:U,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),d=m);else for(var c,u=this.grid.getX(),y=this.grid.getWidth(),g=this.grid.getYend(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(c=r>p?this.getCoordByIndex(p)-h:this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:u,y:c,width:y,height:g-c,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),g=c)}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:n}},this.shapeList.push(new o(e))},refresh:function(e){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=this.getTextStyle(this.option.axisLabel.textStyle)),this.clear(),this._buildShape()},getGap:function(){var e=this.option.data.length,t=this.isHorizontal()?this.grid.getWidth():this.grid.getHeight();return this.option.boundaryGap?t/e:t/(e>1?e-1:1)},getCoord:function(e){for(var t=this.option.data,i=t.length,n=this.getGap(),a=this.option.boundaryGap?n/2:0,o=0;i>o;o++){if(this.getDataFromOption(t[o])==e)return a=this.isHorizontal()?this.grid.getX()+a:this.grid.getYend()-a;a+=n}},getCoordByIndex:function(e){if(0>e)return this.isHorizontal()?this.grid.getX():this.grid.getYend();if(e>this.option.data.length-1)return this.isHorizontal()?this.grid.getXend():this.grid.getY();var t=this.getGap(),i=this.option.boundaryGap?t/2:0;return i+=e*t,i=this.isHorizontal()?this.grid.getX()+i:this.grid.getYend()-i},getNameByIndex:function(e){return this.getDataFromOption(this.option.data[e])},getIndexByName:function(e){for(var t=this.option.data,i=t.length,n=0;i>n;n++)if(this.getDataFromOption(t[n])==e)return n;return-1},getValueFromCoord:function(){return\"\"},isMainAxis:function(e){return e%this._interval===0}},s.inherits(t,i),e(\"../component\").define(\"categoryAxis\",t),t}),i(\"echarts/component/valueAxis\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Rectangle\",\"../config\",\"../util/date\",\"zrender/tool/util\",\"../util/smartSteps\",\"../util/accMath\",\"../util/smartLogSteps\",\"../component\"],function(e){function t(e,t,n,a,o,r,s){if(!s||0===s.length)return void console.err(\"option.series.length == 0.\");i.call(this,e,t,n,a,o),this.series=s,this.grid=this.component.grid;for(var l in r)this[l]=r[l];this.refresh(a,s)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Rectangle\"),r=e(\"../config\");r.valueAxis={zlevel:0,z:0,show:!0,position:\"left\",name:\"\",nameLocation:\"end\",nameTextStyle:{},boundaryGap:[0,0],axisLine:{show:!0,onZero:!0,lineStyle:{color:\"#48b\",width:2,type:\"solid\"}},axisTick:{show:!1,inside:!1,length:5,lineStyle:{color:\"#333\",width:1}},axisLabel:{show:!0,rotate:0,margin:8,textStyle:{color:\"#333\"}},splitLine:{show:!0,lineStyle:{color:[\"#ccc\"],width:1,type:\"solid\"}},splitArea:{show:!1,areaStyle:{color:[\"rgba(250,250,250,0.3)\",\"rgba(200,200,200,0.3)\"]}}};var s=e(\"../util/date\"),l=e(\"zrender/tool/util\");return t.prototype={type:r.COMPONENT_TYPE_AXIS_VALUE,_buildShape:function(){if(this._hasData=!1,this._calculateValue(),this._hasData&&this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width;if(this.isHorizontal())for(var l,h=\"bottom\"===this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,m=0;i>m;m++)l=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:\"axisTick\",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:l,yStart:h,xEnd:l,yEnd:h+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e));else for(var V,U=\"left\"===this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,m=0;i>m;m++)V=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:\"axisTick\",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:V,xEnd:U+o,yEnd:V,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e))},_buildAxisLabel:function(){var e,t=this._valueList,i=this._valueList.length,a=this.option.axisLabel.rotate,o=this.option.axisLabel.margin,r=this.option.axisLabel.clickable,s=this.option.axisLabel.textStyle;if(this.isHorizontal()){var l,h;\"bottom\"===this.option.position?(l=this.grid.getYend()+o,h=\"top\"):(l=this.grid.getY()-o,h=\"bottom\");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoord(t[m]),y:l,color:\"function\"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||\"center\",textBaseline:s.baseline||h}},a&&(e.style.textAlign=a>0?\"bottom\"===this.option.position?\"right\":\"left\":\"bottom\"===this.option.position?\"left\":\"right\",e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}else{var V,U;\"left\"===this.option.position?(V=this.grid.getX()-o,U=\"right\"):(V=this.grid.getXend()+o,U=\"left\");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:V,y:this.getCoord(t[m]),color:\"function\"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||U,textBaseline:s.baseline||(0===m&&\"\"!==this.option.name?\"bottom\":m===i-1&&\"\"!==this.option.name?\"top\":\"middle\")}},a&&(e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}},_buildSplitLine:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length;if(this.isHorizontal())for(var h,m=this.grid.getY(),V=this.grid.getYend(),U=0;i>U;U++)h=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:h,yStart:m,xEnd:h,yEnd:V,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e));else for(var d,p=this.grid.getX(),c=this.grid.getXend(),U=0;i>U;U++)d=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:p,yStart:d,xEnd:c,yEnd:d,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e))},_buildSplitArea:function(){var e,t=this.option.splitArea.areaStyle.color;if(t instanceof Array){var i=t.length,n=this._valueList,a=this._valueList.length;if(this.isHorizontal())for(var r,s=this.grid.getY(),l=this.grid.getHeight(),h=this.grid.getX(),m=0;a>=m;m++)r=a>m?this.getCoord(n[m]):this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:h,y:s,width:r-h,height:l,color:t[m%i]}},this.shapeList.push(new o(e)),h=r;else for(var V,U=this.grid.getX(),d=this.grid.getWidth(),p=this.grid.getYend(),m=0;a>=m;m++)V=a>m?this.getCoord(n[m]):this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:U,y:V,width:d,height:p-V,color:t[m%i]}},this.shapeList.push(new o(e)),p=V}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:t}},this.shapeList.push(new o(e))},_calculateValue:function(){if(isNaN(this.option.min-0)||isNaN(this.option.max-0)){for(var e,t,i={},n=this.component.legend,a=0,o=this.series.length;o>a;a++)!(this.series[a].type!=r.CHART_TYPE_LINE&&this.series[a].type!=r.CHART_TYPE_BAR&&this.series[a].type!=r.CHART_TYPE_SCATTER&&this.series[a].type!=r.CHART_TYPE_K&&this.series[a].type!=r.CHART_TYPE_EVENTRIVER||n&&!n.isSelected(this.series[a].name)||(e=this.series[a].xAxisIndex||0,t=this.series[a].yAxisIndex||0,this.option.xAxisIndex!=e&&this.option.yAxisIndex!=t||!this._calculSum(i,a)));var s;for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)if(!isNaN(s[l])){this._hasData=!0,this._min=s[l],this._max=s[l];break}if(this._hasData)break}for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)isNaN(s[l])||(this._min=Math.min(this._min,s[l]),this._max=Math.max(this._max,s[l]))}var m=\"log\"!==this.option.type?this.option.boundaryGap:[0,0],V=Math.abs(this._max-this._min);this._min=isNaN(this.option.min-0)?this._min-Math.abs(V*m[0]):this.option.min-0,this._max=isNaN(this.option.max-0)?this._max+Math.abs(V*m[1]):this.option.max-0,this._min===this._max&&(0===this._max?this._max=1:this._max>0?this._min=this._max/this.option.splitNumber!=null?this.option.splitNumber:5:this._max=this._max/this.option.splitNumber!=null?this.option.splitNumber:5),\"time\"===this.option.type?this._reformTimeValue():\"log\"===this.option.type?this._reformLogValue():this._reformValue(this.option.scale)}else this._hasData=!0,this._min=this.option.min-0,this._max=this.option.max-0,\"time\"===this.option.type?this._reformTimeValue():\"log\"===this.option.type?this._reformLogValue():this._customerValue()},_calculSum:function(e,t){var i,n,a=this.series[t].name||\"kener\";if(this.series[t].stack){var o=\"__Magic_Key_Positive__\"+this.series[t].stack,l=\"__Magic_Key_Negative__\"+this.series[t].stack;e[o]=e[o]||[],e[l]=e[l]||[],e[a]=e[a]||[],n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),\"-\"!==i&&(i-=0,i>=0?null!=e[o][h]?e[o][h]+=i:e[o][h]=i:null!=e[l][h]?e[l][h]+=i:e[l][h]=i,this.option.scale&&e[a].push(i))}else if(e[a]=e[a]||[],this.series[t].type!=r.CHART_TYPE_EVENTRIVER){n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),this.series[t].type===r.CHART_TYPE_K?(e[a].push(i[0]),e[a].push(i[1]),e[a].push(i[2]),e[a].push(i[3])):i instanceof Array?(-1!=this.option.xAxisIndex&&e[a].push(\"time\"!=this.option.type?i[0]:s.getNewDate(i[0])),-1!=this.option.yAxisIndex&&e[a].push(\"time\"!=this.option.type?i[1]:s.getNewDate(i[1]))):e[a].push(i)}else{n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)for(var V=n[h].evolution,U=0,d=V.length;d>U;U++)e[a].push(s.getNewDate(V[U].time))}},_reformValue:function(t){var i=e(\"../util/smartSteps\"),n=this.option.splitNumber;!t&&this._min>=0&&this._max>=0&&(this._min=0),!t&&this._min<=0&&this._max<=0&&(this._max=0);var a=i(this._min,this._max,n);n=null!=n?n:a.secs,this._min=a.min,this._max=a.max,this._valueList=a.pnts,this._reformLabelData()},_reformTimeValue:function(){var e=null!=this.option.splitNumber?this.option.splitNumber:5,t=s.getAutoFormatter(this._min,this._max,e),i=t.formatter,n=t.gapValue;this._valueList=[s.getNewDate(this._min)];var a;switch(i){case\"week\":a=s.nextMonday(this._min);break;case\"month\":a=s.nextNthOnMonth(this._min,1);break;case\"quarter\":a=s.nextNthOnQuarterYear(this._min,1);break;case\"half-year\":a=s.nextNthOnHalfYear(this._min,1);break;case\"year\":a=s.nextNthOnYear(this._min,1);break;default:72e5>=n?a=(Math.floor(this._min/n)+1)*n:(a=s.getNewDate(this._min- -n),a.setHours(6*Math.round(a.getHours()/6)),a.setMinutes(0),a.setSeconds(0))}for(a-this._min<n/2&&(a-=-n),t=s.getNewDate(a),e*=1.5;e-->=0&&((\"month\"==i||\"quarter\"==i||\"half-year\"==i||\"year\"==i)&&t.setDate(1),!(this._max-t<n/2));)this._valueList.push(t),t=s.getNewDate(t- -n);this._valueList.push(s.getNewDate(this._max)),this._reformLabelData(function(e){return function(t){return s.format(e,t)}}(i))},_customerValue:function(){var t=e(\"../util/accMath\"),i=null!=this.option.splitNumber?this.option.splitNumber:5,n=(this._max-this._min)/i;this._valueList=[];for(var a=0;i>=a;a++)this._valueList.push(t.accAdd(this._min,t.accMul(n,a)));this._reformLabelData()},_reformLogValue:function(){var t=this.option,i=e(\"../util/smartLogSteps\")({dataMin:this._min,dataMax:this._max,logPositive:t.logPositive,logLabelBase:t.logLabelBase,splitNumber:t.splitNumber});this._min=i.dataMin,this._max=i.dataMax,this._valueList=i.tickList,this._dataMappingMethods=i.dataMappingMethods,this._reformLabelData(i.labelFormatter)},_reformLabelData:function(e){this._valueLabel=[];var t=this.option.axisLabel.formatter;if(t)for(var i=0,n=this._valueList.length;n>i;i++)\"function\"==typeof t?this._valueLabel.push(e?t.call(this.myChart,this._valueList[i],e):t.call(this.myChart,this._valueList[i])):\"string\"==typeof t&&this._valueLabel.push(e?s.format(t,this._valueList[i]):t.replace(\"{value}\",this._valueList[i]));else for(var i=0,n=this._valueList.length;n>i;i++)this._valueLabel.push(e?e(this._valueList[i]):this.numAddCommas(this._valueList[i]))},getExtremum:function(){this._calculateValue();var e=this._dataMappingMethods;return{min:this._min,max:this._max,dataMappingMethods:e?l.merge({},e):null}},refresh:function(e,t){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=l.merge(this.option.axisLabel.textStyle||{},this.ecTheme.textStyle),this.series=t),this.zr&&(this.clear(),this._buildShape())},getCoord:function(e){this._dataMappingMethods&&(e=this._dataMappingMethods.value2Coord(e)),e=e<this._min?this._min:e,e=e>this._max?this._max:e;var t;return t=this.isHorizontal()?this.grid.getX()+(e-this._min)/(this._max-this._min)*this.grid.getWidth():this.grid.getYend()-(e-this._min)/(this._max-this._min)*this.grid.getHeight()},getCoordSize:function(e){return Math.abs(this.isHorizontal()?e/(this._max-this._min)*this.grid.getWidth():e/(this._max-this._min)*this.grid.getHeight())},getValueFromCoord:function(e){var t;return this.isHorizontal()?(e=e<this.grid.getX()?this.grid.getX():e,e=e>this.grid.getXend()?this.grid.getXend():e,t=this._min+(e-this.grid.getX())/this.grid.getWidth()*(this._max-this._min)):(e=e<this.grid.getY()?this.grid.getY():e,e=e>this.grid.getYend()?this.grid.getYend():e,t=this._max-(e-this.grid.getY())/this.grid.getHeight()*(this._max-this._min)),this._dataMappingMethods&&(t=this._dataMappingMethods.coord2Value(t)),t.toFixed(2)-0},isMaindAxis:function(e){for(var t=0,i=this._valueList.length;i>t;t++)if(this._valueList[t]===e)return!0;return!1}},l.inherits(t,i),e(\"../component\").define(\"valueAxis\",t),t}),i(\"echarts/util/date\",[],function(){function e(e,t,i){i=i>1?i:2;for(var n,a,o,r,s=0,l=m.length;l>s;s++)if(n=m[s].value,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,Math.round(a/n)<=1.2*i){o=m[s].formatter,r=m[s].value;break}return null==o&&(o=\"year\",n=317088e5,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,r=Math.round(a/(i-1)/n)*n),{formatter:o,gapValue:r}}function t(e){return 10>e?\"0\"+e:e}function i(e,i){(\"week\"==e||\"month\"==e||\"quarter\"==e||\"half-year\"==e||\"year\"==e)&&(e=\"MM - dd\\nyyyy\");var n=h(i),a=n.getFullYear(),o=n.getMonth()+1,r=n.getDate(),s=n.getHours(),l=n.getMinutes(),m=n.getSeconds();return e=e.replace(\"MM\",t(o)),e=e.toLowerCase(),e=e.replace(\"yyyy\",a),e=e.replace(\"yy\",a%100),e=e.replace(\"dd\",t(r)),e=e.replace(\"d\",r),e=e.replace(\"hh\",t(s)),e=e.replace(\"h\",s),e=e.replace(\"mm\",t(l)),e=e.replace(\"m\",l),e=e.replace(\"ss\",t(m)),e=e.replace(\"s\",m)}function n(e){return e=h(e),e.setDate(e.getDate()+8-e.getDay()),e}function a(e,t,i){return e=h(e),e.setMonth(Math.ceil((e.getMonth()+1)/i)*i),e.setDate(t),e}function o(e,t){return a(e,t,1)}function r(e,t){return a(e,t,3)}function s(e,t){return a(e,t,6)}function l(e,t){return a(e,t,12)}function h(e){return e instanceof Date?e:new Date(\"string\"==typeof e?e.replace(/-/g,\"/\"):e)}var m=[{formatter:\"hh : mm : ss\",value:1e3},{formatter:\"hh : mm : ss\",value:5e3},{formatter:\"hh : mm : ss\",value:1e4},{formatter:\"hh : mm : ss\",value:15e3},{formatter:\"hh : mm : ss\",value:3e4},{formatter:\"hh : mm\\nMM - dd\",value:6e4},{formatter:\"hh : mm\\nMM - dd\",value:3e5},{formatter:\"hh : mm\\nMM - dd\",value:6e5},{formatter:\"hh : mm\\nMM - dd\",value:9e5},{formatter:\"hh : mm\\nMM - dd\",value:18e5},{formatter:\"hh : mm\\nMM - dd\",value:36e5},{formatter:\"hh : mm\\nMM - dd\",value:72e5},{formatter:\"hh : mm\\nMM - dd\",value:216e5},{formatter:\"hh : mm\\nMM - dd\",value:432e5},{formatter:\"MM - dd\\nyyyy\",value:864e5},{formatter:\"week\",value:6048e5},{formatter:\"month\",value:26784e5},{formatter:\"quarter\",value:8208e6},{formatter:\"half-year\",value:16416e6},{formatter:\"year\",value:32832e6}];return{getAutoFormatter:e,getNewDate:h,format:i,nextMonday:n,nextNthPerNmonth:a,nextNthOnMonth:o,nextNthOnQuarterYear:r,nextNthOnHalfYear:s,nextNthOnYear:l}}),i(\"echarts/util/smartSteps\",[],function(){function e(e){return X.log(I(e))/X.LN10}function t(e){return X.pow(10,e)}function i(e){return e===w(e)}function n(e,t,n,a){b=a||{},f=b.steps||L,k=b.secs||W,n=v(+n||0)%99,e=+e||0,t=+t||0,x=_=0,\"min\"in b&&(e=+b.min||0,x=1),\"max\"in b&&(t=+b.max||0,_=1),e>t&&(t=[e,e=t][0]);var o=t-e;if(x&&_)return g(e,t,n);if((n||5)>o){if(i(e)&&i(t))return d(e,t,n);if(0===o)return p(e,t,n)}return h(e,t,n)}function a(e,i,n,a){a=a||0;var s=o((i-e)/n,-1),l=o(e,-1,1),h=o(i,-1),m=X.min(s.e,l.e,h.e);0===l.c?m=X.min(s.e,h.e):0===h.c&&(m=X.min(s.e,l.e)),r(s,{c:0,e:m}),r(l,s,1),r(h,s),a+=m,e=l.c,i=h.c;for(var V=(i-e)/n,U=t(a),d=0,p=[],c=n+1;c--;)p[c]=(e+V*c)*U;if(0>a){d=u(U),V=+(V*U).toFixed(d),e=+(e*U).toFixed(d),i=+(i*U).toFixed(d);for(var c=p.length;c--;)p[c]=p[c].toFixed(d),0===+p[c]&&(p[c]=\"0\")}else e*=U,i*=U,V*=U;return k=0,f=0,b=0,{min:e,max:i,secs:n,step:V,fix:d,exp:a,pnts:p}}function o(n,a,o){a=v(a%10)||2,0>a&&(i(n)?a=(\"\"+I(n)).replace(/0+$/,\"\").length||1:(n=n.toFixed(15).replace(/0+$/,\"\"),a=n.replace(\".\",\"\").replace(/^[-0]+/,\"\").length,n=+n));var r=w(e(n))-a+1,s=+(n*t(-r)).toFixed(15)||0;return s=o?w(s):K(s),!s&&(r=0),(\"\"+I(s)).length>a&&(r+=1,s/=10),{c:s,e:r}}function r(e,i,n){var a=i.e-e.e;a&&(e.e+=a,e.c*=t(-a),e.c=n?w(e.c):K(e.c))}function s(e,t,i){e.e<t.e?r(t,e,i):r(e,t,i)}function l(e,t){t=t||L,e=o(e);for(var i=e.c,n=0;i>t[n];)n++;if(!t[n])for(i/=10,e.e+=1,n=0;i>t[n];)n++;return e.c=t[n],e}function h(e,t,n){var s,h=n||+k.slice(-1),p=l((t-e)/h,f),u=o(t-e),g=o(e,-1,1),b=o(t,-1);if(r(u,p),r(g,p,1),r(b,p),n?s=V(g,b,h):h=m(g,b),i(e)&&i(t)&&e*t>=0){if(h>t-e)return d(e,t,h);h=U(e,t,n,g,b,h)}var L=c(e,t,g.c,b.c);return g.c=L[0],b.c=L[1],(x||_)&&y(e,t,g,b),a(g.c,b.c,h,b.e)}function m(e,i){for(var n,a,o,r,s=[],h=k.length;h--;)n=k[h],a=l((i.c-e.c)/n,f),a=a.c*t(a.e),o=w(e.c/a)*a,r=K(i.c/a)*a,s[h]={min:o,max:r,step:a,span:r-o};return s.sort(function(e,t){var i=e.span-t.span;return 0===i&&(i=e.step-t.step),i}),s=s[0],n=s.span/s.step,e.c=s.min,i.c=s.max,3>n?2*n:n}function V(e,i,n){for(var a,o,r=i.c,s=(i.c-e.c)/n-1;r>e.c;)s=l(s+1,f),s=s.c*t(s.e),a=s*n,o=K(i.c/s)*s,r=o-a;var h=e.c-r,m=o-i.c,V=h-m;return V>1.1*s&&(V=v(V/s/2)*s,r+=V,o+=V),e.c=r,i.c=o,s}function U(e,n,a,o,r,s){var l=r.c-o.c,h=l/s*t(r.e);if(!i(h)&&(h=w(h),l=h*s,n-e>l&&(h+=1,l=h*s,!a&&h*(s-1)>=n-e&&(s-=1,l=h*s)),l>=n-e)){var m=l-(n-e);o.c=v(e-m/2),r.c=v(n+m/2),o.e=0,r.e=0}return s}function d(e,t,i){if(i=i||5,x)t=e+i;else if(_)e=t-i;else{var n=i-(t-e),o=v(e-n/2),r=v(t+n/2),s=c(e,t,o,r);e=s[0],t=s[1]}return a(e,t,i)}function p(e,t,i){i=i||5;var n=X.min(I(t/i),i)/2.1;return x?t=e+n:_?e=t-n:(e-=n,t+=n),h(e,t,i)}function c(e,t,i,n){\nreturn e>=0&&0>i?(n-=i,i=0):0>=t&&n>0&&(i-=n,n=0),[i,n]}function u(e){return e=(+e).toFixed(15).split(\".\"),e.pop().replace(/0+$/,\"\").length}function y(e,t,i,n){if(x){var a=o(e,4,1);i.e-a.e>6&&(a={c:0,e:i.e}),s(i,a),s(n,a),n.c+=a.c-i.c,i.c=a.c}else if(_){var r=o(t,4);n.e-r.e>6&&(r={c:0,e:n.e}),s(i,r),s(n,r),i.c+=r.c-n.c,n.c=r.c}}function g(e,t,i){var n=i?[i]:k,s=t-e;if(0===s)return t=o(t,3),i=n[0],t.c=v(t.c+i/2),a(t.c-i,t.c,i,t.e);I(t/s)<1e-6&&(t=0),I(e/s)<1e-6&&(e=0);var l,h,m,V=[[5,10],[10,2],[50,10],[100,2]],U=[],d=[],p=o(t-e,3),c=o(e,-1,1),u=o(t,-1);r(c,p,1),r(u,p),s=u.c-c.c,p.c=s;for(var y=n.length;y--;){i=n[y],l=K(s/i),h=l*i-s,m=3*(h+3),m+=2*(i-n[0]+2),i%5===0&&(m-=10);for(var g=V.length;g--;)l%V[g][0]===0&&(m/=V[g][1]);d[y]=[i,l,h,m].join(),U[y]={secs:i,step:l,delta:h,score:m}}return U.sort(function(e,t){return e.score-t.score}),U=U[0],c.c=v(c.c-U.delta/2),u.c=v(u.c+U.delta/2),a(c.c,u.c,U.secs,p.e)}var b,f,k,x,_,L=[10,20,25,50],W=[4,5,6],X=Math,v=X.round,w=X.floor,K=X.ceil,I=X.abs;return n}),i(\"echarts/util/smartLogSteps\",[\"require\",\"./number\"],function(e){function t(e){return i(),u=e||{},n(),a(),[o(),i()][0]}function i(){U=u=g=c=b=f=y=k=d=p=null}function n(){d=u.logLabelBase,null==d?(p=\"plain\",d=10,c=I):(d=+d,1>d&&(d=10),p=\"exponent\",c=L(d)),y=u.splitNumber,null==y&&(y=E);var e=parseFloat(u.dataMin),t=parseFloat(u.dataMax);isFinite(e)||isFinite(t)?isFinite(e)?isFinite(t)?e>t&&(t=[e,e=t][0]):t=e:e=t:e=t=1,U=u.logPositive,null==U&&(U=t>0||0===e),b=U?e:-t,f=U?t:-e,S>b&&(b=S),S>f&&(f=S)}function a(){function e(){y>m&&(y=m);var e=w(l(m/y)),t=v(l(m/e)),i=e*t,n=(i-U)/2,a=w(l(r-n));V(a-r)&&(a-=1),g=-a*c;for(var s=a;o>=s-e;s+=e)k.push(W(d,s))}function t(){for(var e=i(h,0),t=e+2;t>e&&a(e+1)+n(e+1)*C<r;)e++;for(var l=i(s,0),t=l-2;l>t&&a(l-1)+n(l-1)*C>o;)l--;g=-(a(e)*I+n(e)*J);for(var m=e;l>=m;m++){var V=a(m),U=n(m);k.push(W(10,V)*W(2,U))}}function i(e,t){return 3*e+t}function n(e){return e-3*a(e)}function a(e){return w(l(e/3))}k=[];var o=l(L(f)/c),r=l(L(b)/c),s=v(o),h=w(r),m=s-h,U=o-r;\"exponent\"===p?e():F>=m&&y>F?t():e()}function o(){for(var e=[],t=0,i=k.length;i>t;t++)e[t]=(U?1:-1)*k[t];!U&&e.reverse();var n=s(),a=n.value2Coord,o=a(e[0]),l=a(e[e.length-1]);return o===l&&(o-=1,l+=1),{dataMin:o,dataMax:l,tickList:e,logPositive:U,labelFormatter:r(),dataMappingMethods:n}}function r(){if(\"exponent\"===p){var e=d,t=c;return function(i){if(!isFinite(parseFloat(i)))return\"\";var n=\"\";return 0>i&&(i=-i,n=\"-\"),n+e+m(L(i)/t)}}return function(e){return isFinite(parseFloat(e))?x.addCommas(h(e)):\"\"}}function s(){var e=U,t=g;return{value2Coord:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)?e&&S>i?i=S:!e&&i>-S&&(i=-S):i=S,i=X(i),(e?1:-1)*(L(i)+t))},coord2Value:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)||(i=S),e?W(K,i-t):-W(K,-i+t))}}}function l(e){return+Number(+e).toFixed(14)}function h(e){return Number(e).toFixed(15).replace(/\\.?0*$/,\"\")}function m(e){e=h(Math.round(e));for(var t=[],i=0,n=e.length;n>i;i++){var a=e.charAt(i);t.push(T[a]||\"\")}return t.join(\"\")}function V(e){return e>-S&&S>e}var U,d,p,c,u,y,g,b,f,k,x=e(\"./number\"),_=Math,L=_.log,W=_.pow,X=_.abs,v=_.ceil,w=_.floor,K=_.E,I=_.LN10,J=_.LN2,C=J/I,S=1e-9,E=5,F=2,T={0:\"⁰\",1:\"¹\",2:\"²\",3:\"³\",4:\"⁴\",5:\"⁵\",6:\"⁶\",7:\"⁷\",8:\"⁸\",9:\"⁹\",\"-\":\"⁻\"};return t}),i(\"echarts/chart/line\",[\"require\",\"./base\",\"zrender/shape/Polyline\",\"../util/shape/Icon\",\"../util/shape/HalfSmoothPolygon\",\"../component/axis\",\"../component/grid\",\"../component/dataZoom\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o),this.refresh(a)}function i(e,t,i){var n=t.x,a=t.y,r=t.width,s=t.height,l=s/2;t.symbol.match(\"empty\")&&(e.fillStyle=\"#fff\"),t.brushType=\"both\";var h=t.symbol.replace(\"empty\",\"\").toLowerCase();h.match(\"star\")?(l=h.replace(\"star\",\"\")-0||5,a-=1,h=\"star\"):(\"rectangle\"===h||\"arrow\"===h)&&(n+=(r-s)/2,r=s);var m=\"\";if(h.match(\"image\")&&(m=h.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),h=\"image\",n+=Math.round((r-s)/2)-1,r=s+=2),h=o.prototype.iconLibrary[h]){var V=t.x,U=t.y;e.moveTo(V,U+l),e.lineTo(V+5,U+l),e.moveTo(V+t.width-5,U+l),e.lineTo(V+t.width,U+l);var d=this;h(e,{x:n+4,y:a+4,width:r-8,height:s-8,n:l,image:m},function(){d.modSelf(),i()})}else e.moveTo(n,a+l),e.lineTo(n+r,a+l)}var n=e(\"./base\"),a=e(\"zrender/shape/Polyline\"),o=e(\"../util/shape/Icon\"),r=e(\"../util/shape/HalfSmoothPolygon\");e(\"../component/axis\"),e(\"../component/grid\"),e(\"../component/dataZoom\");var s=e(\"../config\");s.line={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,dataFilter:\"nearest\",itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:\"solid\",shadowColor:\"rgba(0,0,0,0)\",shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0}},emphasis:{label:{show:!1}}},symbolSize:2,showAllSymbol:!1};var l=e(\"../util/ecData\"),h=e(\"zrender/tool/util\"),m=e(\"zrender/tool/color\");return t.prototype={type:s.CHART_TYPE_LINE,_buildShape:function(){this.finalPLMap={},this._buildPosition()},_buildHorizontal:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.xAxis.getAxis(c.xAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){o=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.yAxis.getAxis(d[i[f][0]].yAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,\"-\"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},\"-\"!==U?(U>=0?(s-=x>0?a.getCoordSize(U):l-a.getCoord(U),r=s):0>U&&(h+=x>0?a.getCoordSize(U):a.getCoord(U)-m,r=h),y[p].push([o,r,g,u.getNameByIndex(g),o,l]),n[p].min>U&&(n[p].min=U,n[p].minY=r,n[p].minX=o),n[p].max<U&&(n[p].max=U,n[p].maxY=r,n[p].maxX=o),n[p].sum+=U,n[p].counter++):y[p].length>0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getY();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,\"-\"),\"-\"==U&&this.deepQuery([V,c,this.option],\"calculable\")&&(L=this.deepQuery([V,c],\"symbolSize\"),s+=2*L+5,r=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,\"horizontal\")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,\"y\"),this._buildBorkenLine(e,this.finalPLMap,u,\"horizontal\")},_buildVertical:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.yAxis.getAxis(c.yAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){r=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.xAxis.getAxis(d[i[f][0]].xAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,\"-\"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},\"-\"!==U?(U>=0?(s+=x>0?a.getCoordSize(U):a.getCoord(U)-l,o=s):0>U&&(h-=x>0?a.getCoordSize(U):m-a.getCoord(U),o=h),y[p].push([o,r,g,u.getNameByIndex(g),l,r]),n[p].min>U&&(n[p].min=U,n[p].minX=o,n[p].minY=r),n[p].max<U&&(n[p].max=U,n[p].maxX=o,n[p].maxY=r),n[p].sum+=U,n[p].counter++):y[p].length>0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getXend();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,\"-\"),\"-\"==U&&this.deepQuery([V,c,this.option],\"calculable\")&&(L=this.deepQuery([V,c],\"symbolSize\"),s-=2*L+5,o=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,\"vertical\")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,\"x\"),this._buildBorkenLine(e,this.finalPLMap,u,\"vertical\")},_buildOther:function(e,t,i,n){for(var a,o=this.series,r={},s=0,l=i.length;l>s;s++)for(var h=0,m=i[s].length;m>h;h++){var V=i[s][h],U=o[V];a=this.component.xAxis.getAxis(U.xAxisIndex||0);var d=this.component.yAxis.getAxis(U.yAxisIndex||0),p=d.getCoord(0);r[V]=r[V]||[],n[V]=n[V]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var c=0,u=U.data.length;u>c;c++){var y=U.data[c],g=this.getDataFromOption(y,\"-\");if(g instanceof Array){var b=a.getCoord(g[0]),f=d.getCoord(g[1]);r[V].push([b,f,c,g[0],b,p]),n[V].min0>g[0]&&(n[V].min0=g[0],n[V].minY0=f,n[V].minX0=b),n[V].max0<g[0]&&(n[V].max0=g[0],n[V].maxY0=f,n[V].maxX0=b),n[V].sum0+=g[0],n[V].counter0++,n[V].min1>g[1]&&(n[V].min1=g[1],n[V].minY1=f,n[V].minX1=b),n[V].max1<g[1]&&(n[V].max1=g[1],n[V].maxY1=f,n[V].maxX1=b),n[V].sum1+=g[1],n[V].counter1++}}}for(var k in r)r[k].length>0&&(this.finalPLMap[k]=this.finalPLMap[k]||[],this.finalPLMap[k].push(r[k]),r[k]=[]);this._calculMarkMapXY(n,i,\"xy\"),this._buildBorkenLine(e,this.finalPLMap,a,\"other\")},_buildBorkenLine:function(e,t,i,n){for(var o,s=\"other\"==n?\"horizontal\":n,V=this.series,U=e.length-1;U>=0;U--){var d=e[U],p=V[d],c=t[d];if(p.type===this.type&&null!=c)for(var u=this._getBbox(d,s),y=this._sIndex2ColorMap[d],g=this.query(p,\"itemStyle.normal.lineStyle.width\"),b=this.query(p,\"itemStyle.normal.lineStyle.type\"),f=this.query(p,\"itemStyle.normal.lineStyle.color\"),k=this.getItemStyleColor(this.query(p,\"itemStyle.normal.color\"),d,-1),x=null!=this.query(p,\"itemStyle.normal.areaStyle\"),_=this.query(p,\"itemStyle.normal.areaStyle.color\"),L=0,W=c.length;W>L;L++){var X=c[L],v=\"other\"!=n&&this._isLarge(s,X);if(v)X=this._getLargePointList(s,X,p.dataFilter);else for(var w=0,K=X.length;K>w;w++)o=p.data[X[w][2]],(this.deepQuery([o,p,this.option],\"calculable\")||this.deepQuery([o,p],\"showAllSymbol\")||\"categoryAxis\"===i.type&&i.isMainAxis(X[w][2])&&\"none\"!=this.deepQuery([o,p],\"symbol\"))&&this.shapeList.push(this._getSymbol(d,X[w][2],X[w][3],X[w][0],X[w][1],s));var I=new a({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:X,strokeColor:f||k||y,lineWidth:g,lineType:b,smooth:this._getSmooth(p.smooth),smoothConstraint:u,shadowColor:this.query(p,\"itemStyle.normal.lineStyle.shadowColor\"),shadowBlur:this.query(p,\"itemStyle.normal.lineStyle.shadowBlur\"),shadowOffsetX:this.query(p,\"itemStyle.normal.lineStyle.shadowOffsetX\"),shadowOffsetY:this.query(p,\"itemStyle.normal.lineStyle.shadowOffsetY\")},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});if(l.pack(I,V[d],d,0,L,V[d].name),this.shapeList.push(I),x){var J=new r({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:h.clone(X).concat([[X[X.length-1][4],X[X.length-1][5]],[X[0][4],X[0][5]]]),brushType:\"fill\",smooth:this._getSmooth(p.smooth),smoothConstraint:u,color:_?_:m.alpha(y,.5)},highlightStyle:{brushType:\"fill\"},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});l.pack(J,V[d],d,0,L,V[d].name),this.shapeList.push(J)}}}},_getBbox:function(e,t){var i=this.component.grid.getBbox(),n=this.xMarkMap[e];return null!=n.minX0?[[Math.min(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.min(n.minY0,n.maxY0,n.minY1,n.maxY1)],[Math.max(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.max(n.minY0,n.maxY0,n.minY1,n.maxY1)]]:(\"horizontal\"===t?(i[0][1]=Math.min(n.minY,n.maxY),i[1][1]=Math.max(n.minY,n.maxY)):(i[0][0]=Math.min(n.minX,n.maxX),i[1][0]=Math.max(n.minX,n.maxX)),i)},_isLarge:function(e,t){return t.length<2?!1:\"horizontal\"===e?Math.abs(t[0][0]-t[1][0])<.5:Math.abs(t[0][1]-t[1][1])<.5},_getLargePointList:function(e,t,i){var n;n=\"horizontal\"===e?this.component.grid.getWidth():this.component.grid.getHeight();var a=t.length,o=[];if(\"function\"!=typeof i)switch(i){case\"min\":i=function(e){return Math.max.apply(null,e)};break;case\"max\":i=function(e){return Math.min.apply(null,e)};break;case\"average\":i=function(e){for(var t=0,i=0;i<e.length;i++)t+=e[i];return t/e.length};break;default:i=function(e){return e[0]}}for(var r=[],s=0;n>s;s++){var l=Math.floor(a/n*s),h=Math.min(Math.floor(a/n*(s+1)),a);if(!(l>=h)){for(var m=l;h>m;m++)r[m-l]=\"horizontal\"===e?t[m][1]:t[m][0];r.length=h-l;for(var V=i(r),U=-1,d=1/0,m=l;h>m;m++){var p=\"horizontal\"===e?t[m][1]:t[m][0],c=Math.abs(p-V);d>c&&(U=m,d=c)}var u=t[U].slice();\"horizontal\"===e?u[1]=V:u[0]=V,o.push(u)}}return o},_getSmooth:function(e){return e?.3:0},_getCalculableItem:function(e,t,i,n,a,o){var r=this.series,l=r[e].calculableHolderColor||this.ecTheme.calculableHolderColor||s.calculableHolderColor,h=this._getSymbol(e,t,i,n,a,o);return h.style.color=l,h.style.strokeColor=l,h.rotation=[0,0],h.hoverable=!1,h.draggable=!1,h.style.text=void 0,h},_getSymbol:function(e,t,i,n,a,o){var r=this.series,s=r[e],l=s.data[t],h=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],this._sIndex2ColorMap[e],\"#fff\",\"vertical\"===o?\"horizontal\":\"vertical\");return h.zlevel=s.zlevel,h.z=s.z+1,this.deepQuery([l,s,this.option],\"calculable\")&&(this.setCalculable(h),h.draggable=!0),h},getMarkCoord:function(e,t){var i=this.series[e],n=this.xMarkMap[e],a=this.component.xAxis.getAxis(i.xAxisIndex),o=this.component.yAxis.getAxis(i.yAxisIndex);if(t.type&&(\"max\"===t.type||\"min\"===t.type||\"average\"===t.type)){var r=null!=t.valueIndex?t.valueIndex:null!=n.maxX0?\"1\":\"\";return[n[t.type+\"X\"+r],n[t.type+\"Y\"+r],n[t.type+\"Line\"+r],n[t.type+r]]}return[\"string\"!=typeof t.xAxis&&a.getCoordByIndex?a.getCoordByIndex(t.xAxis||0):a.getCoord(t.xAxis||0),\"string\"!=typeof t.yAxis&&o.getCoordByIndex?o.getCoordByIndex(t.yAxis||0):o.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ontooltipHover:function(e,t){for(var i,n,a=e.seriesIndex,o=e.dataIndex,r=a.length;r--;)if(i=this.finalPLMap[a[r]])for(var s=0,l=i.length;l>s;s++){n=i[s];for(var h=0,m=n.length;m>h;h++)o===n[h][2]&&t.push(this._getSymbol(a[r],n[h][2],n[h][3],n[h][0],n[h][1],\"horizontal\"))}},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}function n(e){e.style.controlPointList=null}for(var a=this.series,o={},r=0,s=e.length;s>r;r++)o[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(U=this.shapeList[r]._seriesIndex,o[U]&&!o[U][3]){if(this.shapeList[r]._main&&this.shapeList[r].style.pointList.length>1){if(d=this.shapeList[r].style.pointList,h=Math.abs(d[0][0]-d[1][0]),V=Math.abs(d[0][1]-d[1][1]),p=\"horizontal\"===this.shapeList[r]._orient,o[U][2]){if(\"half-smooth-polygon\"===this.shapeList[r].type){var u=d.length;this.shapeList[r].style.pointList[u-3]=d[u-2],this.shapeList[r].style.pointList[u-3][p?0:1]=d[u-4][p?0:1],this.shapeList[r].style.pointList[u-2]=d[u-1]}this.shapeList[r].style.pointList.pop(),p?(l=h,m=0):(l=0,m=-V)}else{if(this.shapeList[r].style.pointList.shift(),\"half-smooth-polygon\"===this.shapeList[r].type){var y=this.shapeList[r].style.pointList.pop();p?y[0]=d[0][0]:y[1]=d[0][1],this.shapeList[r].style.pointList.push(y)}p?(l=-h,m=0):(l=0,m=V)}this.shapeList[r].style.controlPointList=null,this.zr.modShape(this.shapeList[r])}else{if(o[U][2]&&this.shapeList[r]._dataIndex===a[U].data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!o[U][2]&&0===this.shapeList[r]._dataIndex){this.zr.delShape(this.shapeList[r].id);continue}}this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,\"\").when(this.query(this.option,\"animationDurationUpdate\"),{position:[l,m]}).during(n).done(i).start()}c||t&&t()}},o.prototype.iconLibrary.legendLineIcon=i,h.inherits(t,n),e(\"../chart\").define(\"line\",t),t}),i(\"echarts/util/shape/HalfSmoothPolygon\",[\"require\",\"zrender/shape/Base\",\"zrender/shape/util/smoothBezier\",\"zrender/tool/util\",\"zrender/shape/Polygon\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/shape/util/smoothBezier\"),a=e(\"zrender/tool/util\");return t.prototype={type:\"half-smooth-polygon\",buildPath:function(t,i){var a=i.pointList;if(!(a.length<2))if(i.smooth){var o=n(a.slice(0,-2),i.smooth,!1,i.smoothConstraint);t.moveTo(a[0][0],a[0][1]);for(var r,s,l,h=a.length,m=0;h-3>m;m++)r=o[2*m],s=o[2*m+1],l=a[m+1],t.bezierCurveTo(r[0],r[1],s[0],s[1],l[0],l[1]);t.lineTo(a[h-2][0],a[h-2][1]),t.lineTo(a[h-1][0],a[h-1][1]),t.lineTo(a[0][0],a[0][1])}else e(\"zrender/shape/Polygon\").prototype.buildPath(t,i)}},a.inherits(t,i),t}),i(\"echarts/chart/bar\",[\"require\",\"./base\",\"zrender/shape/Rectangle\",\"../component/axis\",\"../component/grid\",\"../component/dataZoom\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Rectangle\");e(\"../component/axis\"),e(\"../component/grid\"),e(\"../component/dataZoom\");var a=e(\"../config\");a.bar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,barMinHeight:0,barGap:\"30%\",barCategoryGap:\"20%\",itemStyle:{normal:{barBorderColor:\"#fff\",barBorderRadius:0,barBorderWidth:0,label:{show:!1}},emphasis:{barBorderColor:\"#fff\",barBorderRadius:0,barBorderWidth:0,label:{show:!1}}}};var o=e(\"../util/ecData\"),r=e(\"zrender/tool/util\"),s=e(\"zrender/tool/color\");return t.prototype={type:a.CHART_TYPE_BAR,_buildShape:function(){this._buildPosition()},_buildNormal:function(e,t,i,o,r){for(var s,l,h,m,V,U,d,p,c,u,y,g,b=this.series,f=i[0][0],k=b[f],x=\"horizontal\"==r,_=this.component.xAxis,L=this.component.yAxis,W=x?_.getAxis(k.xAxisIndex):L.getAxis(k.yAxisIndex),X=this._mapSize(W,i),v=X.gap,w=X.barGap,K=X.barWidthMap,I=X.barMaxWidthMap,J=X.barWidth,C=X.barMinHeightMap,S=X.interval,E=this.deepQuery([this.ecTheme,a],\"island.r\"),F=0,T=t;T>F&&null!=W.getNameByIndex(F);F++){x?m=W.getCoordByIndex(F)-v/2:V=W.getCoordByIndex(F)+v/2;for(var z=0,A=i.length;A>z;z++){var M=b[i[z][0]].yAxisIndex||0,O=b[i[z][0]].xAxisIndex||0;s=x?L.getAxis(M):_.getAxis(O),d=U=c=p=s.getCoord(0);for(var P=0,D=i[z].length;D>P;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,\"-\"),o[f]=o[f]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),\"-\"!==g&&(g>0?(l=P>0?s.getCoordSize(g):x?d-s.getCoord(g):s.getCoord(g)-d,1===D&&C[f]>l&&(l=C[f]),x?(U-=l,V=U):(m=U,U+=l)):0>g?(l=P>0?s.getCoordSize(g):x?s.getCoord(g)-c:c-s.getCoord(g),1===D&&C[f]>l&&(l=C[f]),x?(V=p,p+=l):(p-=l,m=p)):(l=0,x?(U-=l,V=U):(m=U,U+=l)),o[f][F]=x?m+h/2:V-h/2,o[f].min>g&&(o[f].min=g,x?(o[f].minY=V,o[f].minX=o[f][F]):(o[f].minX=m+l,o[f].minY=o[f][F])),o[f].max<g&&(o[f].max=g,x?(o[f].maxY=V,o[f].maxX=o[f][F]):(o[f].maxX=m+l,o[f].maxY=o[f][F])),o[f].sum+=g,o[f].counter++,F%S===0&&(u=this._getBarItem(f,F,W.getNameByIndex(F),m,V-(x?0:h),x?h:l,x?l:h,x?\"vertical\":\"horizontal\"),this.shapeList.push(new n(u))));for(var P=0,D=i[z].length;D>P;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,\"-\"),h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),\"-\"==g&&this.deepQuery([y,k,this.option],\"calculable\")&&(x?(U-=E,V=U):(m=U,U+=E),u=this._getBarItem(f,F,W.getNameByIndex(F),m,V-(x?0:h),x?h:E,x?E:h,x?\"vertical\":\"horizontal\"),u.hoverable=!1,u.draggable=!1,u.style.lineWidth=1,u.style.brushType=\"stroke\",u.style.strokeColor=k.calculableHolderColor||this.ecTheme.calculableHolderColor||a.calculableHolderColor,this.shapeList.push(new n(u)));x?m+=h+w:V-=h+w}}this._calculMarkMapXY(o,i,x?\"y\":\"x\")},_buildHorizontal:function(e,t,i,n){return this._buildNormal(e,t,i,n,\"horizontal\")},_buildVertical:function(e,t,i,n){return this._buildNormal(e,t,i,n,\"vertical\")},_buildOther:function(e,t,i,a){for(var o=this.series,r=0,s=i.length;s>r;r++)for(var l=0,h=i[r].length;h>l;l++){var m=i[r][l],V=o[m],U=V.xAxisIndex||0,d=this.component.xAxis.getAxis(U),p=d.getCoord(0),c=V.yAxisIndex||0,u=this.component.yAxis.getAxis(c),y=u.getCoord(0);a[m]=a[m]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var g=0,b=V.data.length;b>g;g++){var f=V.data[g],k=this.getDataFromOption(f,\"-\");if(k instanceof Array){var x,_,L=d.getCoord(k[0]),W=u.getCoord(k[1]),X=[f,V],v=this.deepQuery(X,\"barWidth\")||10,w=this.deepQuery(X,\"barHeight\");null!=w?(x=\"horizontal\",k[0]>0?(v=L-p,L-=v):v=k[0]<0?p-L:0,_=this._getBarItem(m,g,k[0],L,W-w/2,v,w,x)):(x=\"vertical\",k[1]>0?w=y-W:k[1]<0?(w=W-y,W-=w):w=0,_=this._getBarItem(m,g,k[0],L-v/2,W,v,w,x)),this.shapeList.push(new n(_)),L=d.getCoord(k[0]),W=u.getCoord(k[1]),a[m].min0>k[0]&&(a[m].min0=k[0],a[m].minY0=W,a[m].minX0=L),a[m].max0<k[0]&&(a[m].max0=k[0],a[m].maxY0=W,a[m].maxX0=L),a[m].sum0+=k[0],a[m].counter0++,a[m].min1>k[1]&&(a[m].min1=k[1],a[m].minY1=W,a[m].minX1=L),a[m].max1<k[1]&&(a[m].max1=k[1],a[m].maxY1=W,a[m].maxX1=L),a[m].sum1+=k[1],a[m].counter1++}}}this._calculMarkMapXY(a,i,\"xy\")},_mapSize:function(e,t,i){var n,a,o=this._findSpecialBarSzie(t,i),r=o.barWidthMap,s=o.barMaxWidthMap,l=o.barMinHeightMap,h=o.sBarWidthCounter,m=o.sBarWidthTotal,V=o.barGap,U=o.barCategoryGap,d=1;if(t.length!=h){if(i)n=e.getGap(),V=0,a=+(n/t.length).toFixed(2),0>=a&&(d=Math.floor(t.length/n),a=1);else if(n=\"string\"==typeof U&&U.match(/%$/)?(e.getGap()*(100-parseFloat(U))/100).toFixed(2)-0:e.getGap()-U,\"string\"==typeof V&&V.match(/%$/)?(V=parseFloat(V)/100,a=+((n-m)/((t.length-1)*V+t.length-h)).toFixed(2),V=a*V):(V=parseFloat(V),a=+((n-m-V*(t.length-1))/(t.length-h)).toFixed(2)),0>=a)return this._mapSize(e,t,!0)}else if(n=h>1?\"string\"==typeof U&&U.match(/%$/)?+(e.getGap()*(100-parseFloat(U))/100).toFixed(2):e.getGap()-U:m,a=0,V=h>1?+((n-m)/(h-1)).toFixed(2):0,0>V)return this._mapSize(e,t,!0);return this._recheckBarMaxWidth(t,r,s,l,n,a,V,d)},_findSpecialBarSzie:function(e,t){for(var i,n,a,o,r=this.series,s={},l={},h={},m=0,V=0,U=0,d=e.length;d>U;U++)for(var p={barWidth:!1,barMaxWidth:!1},c=0,u=e[U].length;u>c;c++){var y=e[U][c],g=r[y];if(!t){if(p.barWidth)s[y]=i;else if(i=this.query(g,\"barWidth\"),null!=i){s[y]=i,V+=i,m++,p.barWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];s[k]=i}}if(p.barMaxWidth)l[y]=n;else if(n=this.query(g,\"barMaxWidth\"),null!=n){l[y]=n,p.barMaxWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];l[k]=n}}}h[y]=this.query(g,\"barMinHeight\"),a=null!=a?a:this.query(g,\"barGap\"),o=null!=o?o:this.query(g,\"barCategoryGap\")}return{barWidthMap:s,barMaxWidthMap:l,barMinHeightMap:h,sBarWidth:i,sBarMaxWidth:n,sBarWidthCounter:m,sBarWidthTotal:V,barGap:a,barCategoryGap:o}},_recheckBarMaxWidth:function(e,t,i,n,a,o,r,s){for(var l=0,h=e.length;h>l;l++){var m=e[l][0];i[m]&&i[m]<o&&(a-=o-i[m])}return{barWidthMap:t,barMaxWidthMap:i,barMinHeightMap:n,gap:a,barWidth:o,barGap:r,interval:s}},_getBarItem:function(e,t,i,n,a,r,l,h){var m,V=this.series,U=V[e],d=U.data[t],p=this._sIndex2ColorMap[e],c=[d,U],u=this.deepMerge(c,\"itemStyle.normal\"),y=this.deepMerge(c,\"itemStyle.emphasis\"),g=u.barBorderWidth;m={zlevel:U.zlevel,z:U.z,clickable:this.deepQuery(c,\"clickable\"),style:{x:n,y:a,width:r,height:l,brushType:\"both\",color:this.getItemStyleColor(this.deepQuery(c,\"itemStyle.normal.color\")||p,e,t,d),radius:u.barBorderRadius,lineWidth:g,strokeColor:u.barBorderColor},highlightStyle:{color:this.getItemStyleColor(this.deepQuery(c,\"itemStyle.emphasis.color\"),e,t,d),radius:y.barBorderRadius,lineWidth:y.barBorderWidth,strokeColor:y.barBorderColor},_orient:h};var b=m.style;m.highlightStyle.color=m.highlightStyle.color||(\"string\"==typeof b.color?s.lift(b.color,-.3):b.color),b.x=Math.floor(b.x),b.y=Math.floor(b.y),b.height=Math.ceil(b.height),b.width=Math.ceil(b.width),g>0&&b.height>g&&b.width>g?(b.y+=g/2,b.height-=g,b.x+=g/2,b.width-=g):b.brushType=\"fill\",m.highlightStyle.textColor=m.highlightStyle.color,m=this.addLabel(m,U,d,i,h);for(var f=[b,m.highlightStyle],k=0,x=f.length;x>k;k++){var _=f[k].textPosition;if(\"insideLeft\"===_||\"insideRight\"===_||\"insideTop\"===_||\"insideBottom\"===_){var L=5;switch(_){case\"insideLeft\":f[k].textX=b.x+L,f[k].textY=b.y+b.height/2,f[k].textAlign=\"left\",f[k].textBaseline=\"middle\";break;case\"insideRight\":f[k].textX=b.x+b.width-L,f[k].textY=b.y+b.height/2,f[k].textAlign=\"right\",f[k].textBaseline=\"middle\";break;case\"insideTop\":f[k].textX=b.x+b.width/2,f[k].textY=b.y+L/2,f[k].textAlign=\"center\",f[k].textBaseline=\"top\";break;case\"insideBottom\":f[k].textX=b.x+b.width/2,f[k].textY=b.y+b.height-L/2,f[k].textAlign=\"center\",f[k].textBaseline=\"bottom\"}f[k].textPosition=\"specific\",f[k].textColor=f[k].textColor||\"#fff\"}}return this.deepQuery([d,U,this.option],\"calculable\")&&(this.setCalculable(m),m.draggable=!0),o.pack(m,V[e],e,V[e].data[t],t,i),m},getMarkCoord:function(e,t){var i,n,a=this.series[e],o=this.xMarkMap[e],r=this.component.xAxis.getAxis(a.xAxisIndex),s=this.component.yAxis.getAxis(a.yAxisIndex);if(!t.type||\"max\"!==t.type&&\"min\"!==t.type&&\"average\"!==t.type)if(o.isHorizontal){i=\"string\"==typeof t.xAxis&&r.getIndexByName?r.getIndexByName(t.xAxis):t.xAxis||0;var l=o[i];l=null!=l?l:\"string\"!=typeof t.xAxis&&r.getCoordByIndex?r.getCoordByIndex(t.xAxis||0):r.getCoord(t.xAxis||0),n=[l,s.getCoord(t.yAxis||0)]}else{i=\"string\"==typeof t.yAxis&&s.getIndexByName?s.getIndexByName(t.yAxis):t.yAxis||0;var h=o[i];h=null!=h?h:\"string\"!=typeof t.yAxis&&s.getCoordByIndex?s.getCoordByIndex(t.yAxis||0):s.getCoord(t.yAxis||0),n=[r.getCoord(t.xAxis||0),h]}else{var m=null!=t.valueIndex?t.valueIndex:null!=o.maxX0?\"1\":\"\";n=[o[t.type+\"X\"+m],o[t.type+\"Y\"+m],o[t.type+\"Line\"+m],o[t.type+m]]}return n},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(d=o.get(this.shapeList[r],\"seriesIndex\"),a[d]&&!a[d][3]&&\"rectangle\"===this.shapeList[r].type){if(p=o.get(this.shapeList[r],\"dataIndex\"),U=n[d],a[d][2]&&p===U.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[d][2]&&0===p){this.zr.delShape(this.shapeList[r].id);continue}\"horizontal\"===this.shapeList[r]._orient?(V=this.component.yAxis.getAxis(U.yAxisIndex||0).getGap(),m=a[d][2]?-V:V,l=0):(h=this.component.xAxis.getAxis(U.xAxisIndex||0).getGap(),l=a[d][2]?h:-h,m=0),this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,\"\").when(this.query(this.option,\"animationDurationUpdate\"),{position:[l,m]}).done(i).start()}c||t&&t()}},r.inherits(t,i),e(\"../chart\").define(\"bar\",t),t}),i(\"echarts/chart/scatter\",[\"require\",\"./base\",\"../util/shape/Symbol\",\"../component/axis\",\"../component/grid\",\"../component/dataZoom\",\"../component/dataRange\",\"../config\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"../util/shape/Symbol\");e(\"../component/axis\"),e(\"../component/grid\"),e(\"../component/dataZoom\"),e(\"../component/dataRange\");var a=e(\"../config\");a.scatter={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,symbolSize:4,large:!1,largeThreshold:2e3,itemStyle:{normal:{label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e(\"zrender/tool/util\"),r=e(\"zrender/tool/color\");return t.prototype={type:a.CHART_TYPE_SCATTER,_buildShape:function(){var e=this.series;this._sIndex2ColorMap={},this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this.selectedMap={},this.xMarkMap={};for(var t,i,n,o,s=this.component.legend,l=[],h=0,m=e.length;m>h;h++)if(t=e[h],i=t.name,t.type===a.CHART_TYPE_SCATTER){if(e[h]=this.reformOption(e[h]),this.legendHoverLink=e[h].legendHoverLink||this.legendHoverLink,this._sIndex2ShapeMap[h]=this.query(t,\"symbol\")||this._symbol[h%this._symbol.length],s){if(this.selectedMap[i]=s.isSelected(i),this._sIndex2ColorMap[h]=r.alpha(s.getColor(i),.5),n=s.getItemShape(i)){var o=this._sIndex2ShapeMap[h];n.style.brushType=o.match(\"empty\")?\"stroke\":\"both\",o=o.replace(\"empty\",\"\").toLowerCase(),o.match(\"rectangle\")&&(n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height),o.match(\"star\")&&(n.style.n=o.replace(\"star\",\"\")-0||5,o=\"star\"),o.match(\"image\")&&(n.style.image=o.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height,o=\"image\"),n.style.iconType=o,s.setItemShape(i,n)}}else this.selectedMap[i]=!0,this._sIndex2ColorMap[h]=r.alpha(this.zr.getColor(h),.5);this.selectedMap[i]&&l.push(h)}this._buildSeries(l),this.addShapeList()},_buildSeries:function(e){if(0!==e.length){for(var t,i,n,a,o,r,s,l,h=this.series,m={},V=0,U=e.length;U>V;V++)if(t=e[V],i=h[t],0!==i.data.length){o=this.component.xAxis.getAxis(i.xAxisIndex||0),r=this.component.yAxis.getAxis(i.yAxisIndex||0),m[t]=[];for(var d=0,p=i.data.length;p>d;d++)n=i.data[d],a=this.getDataFromOption(n,\"-\"),\"-\"===a||a.length<2||(s=o.getCoord(a[0]),l=r.getCoord(a[1]),m[t].push([s,l,d,n.name||\"\"]));this.xMarkMap[t]=this._markMap(o,r,i.data,m[t]),this.buildMark(t)}this._buildPointList(m)}},_markMap:function(e,t,i,n){for(var a,o={min0:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,sum0:0,counter0:0,average0:0,min1:Number.POSITIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum1:0,counter1:0,average1:0},r=0,s=n.length;s>r;r++)a=i[n[r][2]].value||i[n[r][2]],o.min0>a[0]&&(o.min0=a[0],o.minY0=n[r][1],o.minX0=n[r][0]),o.max0<a[0]&&(o.max0=a[0],o.maxY0=n[r][1],o.maxX0=n[r][0]),o.sum0+=a[0],o.counter0++,o.min1>a[1]&&(o.min1=a[1],o.minY1=n[r][1],o.minX1=n[r][0]),o.max1<a[1]&&(o.max1=a[1],o.maxY1=n[r][1],o.maxX1=n[r][0]),o.sum1+=a[1],o.counter1++;var l=this.component.grid.getX(),h=this.component.grid.getXend(),m=this.component.grid.getY(),V=this.component.grid.getYend();o.average0=o.sum0/o.counter0;var U=e.getCoord(o.average0);o.averageLine0=[[U,V],[U,m]],o.minLine0=[[o.minX0,V],[o.minX0,m]],o.maxLine0=[[o.maxX0,V],[o.maxX0,m]],o.average1=o.sum1/o.counter1;var d=t.getCoord(o.average1);return o.averageLine1=[[l,d],[h,d]],o.minLine1=[[l,o.minY1],[h,o.minY1]],o.maxLine1=[[l,o.maxY1],[h,o.maxY1]],o},_buildPointList:function(e){var t,i,n,a,o=this.series;for(var r in e)if(t=o[r],i=e[r],t.large&&t.data.length>t.largeThreshold)this.shapeList.push(this._getLargeSymbol(t,i,this.getItemStyleColor(this.query(t,\"itemStyle.normal.color\"),r,-1)||this._sIndex2ColorMap[r]));else for(var s=0,l=i.length;l>s;s++)n=i[s],a=this._getSymbol(r,n[2],n[3],n[0],n[1]),a&&this.shapeList.push(a)},_getSymbol:function(e,t,i,n,a){var o,r=this.series,s=r[e],l=s.data[t],h=this.component.dataRange;if(h){if(o=isNaN(l[2])?this._sIndex2ColorMap[e]:h.getColor(l[2]),!o)return null}else o=this._sIndex2ColorMap[e];var m=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],o,\"rgba(0,0,0,0)\",\"vertical\");return m.zlevel=s.zlevel,m.z=s.z,m._main=!0,m},_getLargeSymbol:function(e,t,i){return new n({zlevel:e.zlevel,z:e.z,_main:!0,hoverable:!1,style:{pointList:t,color:i,strokeColor:i},highlightStyle:{pointList:[]}})},getMarkCoord:function(e,t){var i,n=this.series[e],a=this.xMarkMap[e],o=this.component.xAxis.getAxis(n.xAxisIndex),r=this.component.yAxis.getAxis(n.yAxisIndex);if(!t.type||\"max\"!==t.type&&\"min\"!==t.type&&\"average\"!==t.type)i=[\"string\"!=typeof t.xAxis&&o.getCoordByIndex?o.getCoordByIndex(t.xAxis||0):o.getCoord(t.xAxis||0),\"string\"!=typeof t.yAxis&&r.getCoordByIndex?r.getCoordByIndex(t.yAxis||0):r.getCoord(t.yAxis||0)];else{var s=null!=t.valueIndex?t.valueIndex:1;i=[a[t.type+\"X\"+s],a[t.type+\"Y\"+s],a[t.type+\"Line\"+s],a[t.type+s]]}return i},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)}},o.inherits(t,i),e(\"../chart\").define(\"scatter\",t),t}),i(\"echarts/component/dataRange\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Rectangle\",\"../util/shape/HandlePolygon\",\"../config\",\"zrender/tool/util\",\"zrender/tool/event\",\"zrender/tool/area\",\"zrender/tool/color\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var s=this;s._ondrift=function(e,t){return s.__ondrift(this,e,t)},s._ondragend=function(){return s.__ondragend()},s._dataRangeSelected=function(e){return s.__dataRangeSelected(e)},s._dispatchHoverLink=function(e){return s.__dispatchHoverLink(e)},s._onhoverlink=function(e){return s.__onhoverlink(e);\n\n},this._selectedMap={},this._range={},this.refresh(a),t.bind(r.EVENT.HOVER,this._onhoverlink)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Rectangle\"),o=e(\"../util/shape/HandlePolygon\"),r=e(\"../config\");r.dataRange={zlevel:0,z:4,show:!0,orient:\"vertical\",x:\"left\",y:\"bottom\",backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,precision:0,splitNumber:5,splitList:null,calculable:!1,selectedMode:!0,hoverLink:!0,realtime:!0,color:[\"#006edd\",\"#e0ffff\"],textStyle:{color:\"#333\"}};var s=e(\"zrender/tool/util\"),l=e(\"zrender/tool/event\"),h=e(\"zrender/tool/area\"),m=e(\"zrender/tool/color\");return t.prototype={type:r.COMPONENT_TYPE_DATARANGE,_textGap:10,_buildShape:function(){if(this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._isContinuity()?this._buildGradient():this._buildItem(),this.dataRangeOption.show)for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncShapeFromRange()},_buildItem:function(){var e,t,i,o,r=this._valueTextList,s=r.length,l=this.getFont(this.dataRangeOption.textStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this.dataRangeOption.itemWidth,d=this.dataRangeOption.itemHeight,p=this.dataRangeOption.itemGap,c=h.getTextHeight(\"国\",l);\"vertical\"==this.dataRangeOption.orient&&\"right\"==this.dataRangeOption.x&&(m=this._itemGroupLocation.x+this._itemGroupLocation.width-U);var u=!0;this.dataRangeOption.text&&(u=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(m,V,this.dataRangeOption.text[0]),\"horizontal\"==this.dataRangeOption.orient?m+=h.getTextWidth(this.dataRangeOption.text[0],l)+this._textGap:(V+=c+this._textGap,i.style.y+=c/2+this._textGap,i.style.textBaseline=\"bottom\"),this.shapeList.push(new n(i))));for(var y=0;s>y;y++)e=r[y],o=this.getColorByIndex(y),t=this._getItemShape(m,V,U,d,this._selectedMap[y]?o:\"#ccc\"),t._idx=y,t.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(t.clickable=!0,t.onclick=this._dataRangeSelected),this.shapeList.push(new a(t)),u&&(i={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:m+U+5,y:V,color:this._selectedMap[y]?this.dataRangeOption.textStyle.color:\"#ccc\",text:r[y],textFont:l,textBaseline:\"top\"},highlightStyle:{brushType:\"fill\"}},\"vertical\"==this.dataRangeOption.orient&&\"right\"==this.dataRangeOption.x&&(i.style.x-=U+10,i.style.textAlign=\"right\"),i._idx=y,i.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(i.clickable=!0,i.onclick=this._dataRangeSelected),this.shapeList.push(new n(i))),\"horizontal\"==this.dataRangeOption.orient?m+=U+(u?5:0)+(u?h.getTextWidth(e,l):0)+p:V+=d+p;!u&&this.dataRangeOption.text[1]&&(\"horizontal\"==this.dataRangeOption.orient?m=m-p+this._textGap:V=V-p+this._textGap,i=this._getTextShape(m,V,this.dataRangeOption.text[1]),\"horizontal\"!=this.dataRangeOption.orient&&(i.style.y-=5,i.style.textBaseline=\"top\"),this.shapeList.push(new n(i)))},_buildGradient:function(){var t,i,o=this.getFont(this.dataRangeOption.textStyle),r=this._itemGroupLocation.x,s=this._itemGroupLocation.y,l=this.dataRangeOption.itemWidth,m=this.dataRangeOption.itemHeight,V=h.getTextHeight(\"国\",o),U=10,d=!0;this.dataRangeOption.text&&(d=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[0]),\"horizontal\"==this.dataRangeOption.orient?r+=h.getTextWidth(this.dataRangeOption.text[0],o)+this._textGap:(s+=V+this._textGap,i.style.y+=V/2+this._textGap,i.style.textBaseline=\"bottom\"),this.shapeList.push(new n(i))));for(var p=e(\"zrender/tool/color\"),c=1/(this.dataRangeOption.color.length-1),u=[],y=0,g=this.dataRangeOption.color.length;g>y;y++)u.push([y*c,this.dataRangeOption.color[y]]);\"horizontal\"==this.dataRangeOption.orient?(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l*U,height:m,color:p.getLinearGradient(r,s,r+l*U,s,u)},hoverable:!1},r+=l*U+this._textGap):(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l,height:m*U,color:p.getLinearGradient(r,s,r,s+m*U,u)},hoverable:!1},s+=m*U+this._textGap),this.shapeList.push(new a(t)),this._calculableLocation=t.style,this.dataRangeOption.calculable&&(this._buildFiller(),this._bulidMask(),this._bulidHandle()),this._buildIndicator(),!d&&this.dataRangeOption.text[1]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[1]),this.shapeList.push(new n(i)))},_buildIndicator:function(){var e,t,i=this._calculableLocation.x,n=this._calculableLocation.y,a=this._calculableLocation.width,r=this._calculableLocation.height,s=5;\"horizontal\"==this.dataRangeOption.orient?\"bottom\"!=this.dataRangeOption.y?(e=[[i,n+r],[i-s,n+r+s],[i+s,n+r+s]],t=\"bottom\"):(e=[[i,n],[i-s,n-s],[i+s,n-s]],t=\"top\"):\"right\"!=this.dataRangeOption.x?(e=[[i+a,n],[i+a+s,n-s],[i+a+s,n+s]],t=\"right\"):(e=[[i,n],[i-s,n-s],[i-s,n+s]],t=\"left\"),this._indicatorShape={style:{pointList:e,color:\"#fff\",__rect:{x:Math.min(e[0][0],e[1][0]),y:Math.min(e[0][1],e[1][1]),width:s*(\"horizontal\"==this.dataRangeOption.orient?2:1),height:s*(\"horizontal\"==this.dataRangeOption.orient?1:2)}},highlightStyle:{brushType:\"fill\",textPosition:t,textColor:this.dataRangeOption.textStyle.color},hoverable:!1},this._indicatorShape=new o(this._indicatorShape)},_buildFiller:function(){this._fillerShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:this._calculableLocation.x,y:this._calculableLocation.y,width:this._calculableLocation.width,height:this._calculableLocation.height,color:\"rgba(255,255,255,0)\"},highlightStyle:{strokeColor:\"rgba(255,255,255,0.5)\",lineWidth:1},draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,onmousemove:this._dispatchHoverLink,_type:\"filler\"},this._fillerShape=new a(this._fillerShape),this.shapeList.push(this._fillerShape)},_bulidHandle:function(){var e,t,i,n,a,r,s,l,m=this._calculableLocation.x,V=this._calculableLocation.y,U=this._calculableLocation.width,d=this._calculableLocation.height,p=this.getFont(this.dataRangeOption.textStyle),c=h.getTextHeight(\"国\",p),u=Math.max(h.getTextWidth(this._textFormat(this.dataRangeOption.max),p),h.getTextWidth(this._textFormat(this.dataRangeOption.min),p))+2;\"horizontal\"==this.dataRangeOption.orient?\"bottom\"!=this.dataRangeOption.y?(e=[[m,V],[m,V+d+c],[m-c,V+d+c],[m-1,V+d],[m-1,V]],t=m-u/2-c,i=V+d+c/2+2,n={x:m-u-c,y:V+d,width:u+c,height:c},a=[[m+U,V],[m+U,V+d+c],[m+U+c,V+d+c],[m+U+1,V+d],[m+U+1,V]],r=m+U+u/2+c,s=i,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m,V+d],[m,V-c],[m-c,V-c],[m-1,V],[m-1,V+d]],t=m-u/2-c,i=V-c/2-2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m+U,V-c],[m+U+c,V-c],[m+U+1,V],[m+U+1,V+d]],r=m+U+u/2+c,s=i,l={x:m+U,y:V-c,width:u+c,height:c}):(u+=c,\"right\"!=this.dataRangeOption.x?(e=[[m,V],[m+U+c,V],[m+U+c,V-c],[m+U,V-1],[m,V-1]],t=m+U+u/2+c/2,i=V-c/2,n={x:m+U,y:V-c,width:u+c,height:c},a=[[m,V+d],[m+U+c,V+d],[m+U+c,V+c+d],[m+U,V+1+d],[m,V+d+1]],r=t,s=V+d+c/2,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m+U,V],[m-c,V],[m-c,V-c],[m,V-1],[m+U,V-1]],t=m-u/2-c/2,i=V-c/2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m-c,V+d],[m-c,V+c+d],[m,V+1+d],[m+U,V+d+1]],r=t,s=V+d+c/2,l={x:m-u-c,y:V+d,width:u+c,height:c})),this._startShape={style:{pointList:e,text:this._textFormat(this.dataRangeOption.max),textX:t,textY:i,textFont:p,color:this.getColor(this.dataRangeOption.max),rect:n,x:e[0][0],y:e[0][1],_x:e[0][0],_y:e[0][1]}},this._startShape.highlightStyle={strokeColor:this._startShape.style.color,lineWidth:1},this._endShape={style:{pointList:a,text:this._textFormat(this.dataRangeOption.min),textX:r,textY:s,textFont:p,color:this.getColor(this.dataRangeOption.min),rect:l,x:a[0][0],y:a[0][1],_x:a[0][0],_y:a[0][1]}},this._endShape.highlightStyle={strokeColor:this._endShape.style.color,lineWidth:1},this._startShape.zlevel=this._endShape.zlevel=this.getZlevelBase(),this._startShape.z=this._endShape.z=this.getZBase()+1,this._startShape.draggable=this._endShape.draggable=!0,this._startShape.ondrift=this._endShape.ondrift=this._ondrift,this._startShape.ondragend=this._endShape.ondragend=this._ondragend,this._startShape.style.textColor=this._endShape.style.textColor=this.dataRangeOption.textStyle.color,this._startShape.style.textAlign=this._endShape.style.textAlign=\"center\",this._startShape.style.textPosition=this._endShape.style.textPosition=\"specific\",this._startShape.style.textBaseline=this._endShape.style.textBaseline=\"middle\",this._startShape.style.width=this._endShape.style.width=0,this._startShape.style.height=this._endShape.style.height=0,this._startShape.style.textPosition=this._endShape.style.textPosition=\"specific\",this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_bulidMask:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;this._startMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:e,y:t,width:\"horizontal\"==this.dataRangeOption.orient?0:i,height:\"horizontal\"==this.dataRangeOption.orient?n:0,color:\"#ccc\"},hoverable:!1},this._endMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:\"horizontal\"==this.dataRangeOption.orient?e+i:e,y:\"horizontal\"==this.dataRangeOption.orient?t:t+n,width:\"horizontal\"==this.dataRangeOption.orient?0:i,height:\"horizontal\"==this.dataRangeOption.orient?n:0,color:\"#ccc\"},hoverable:!1},this._startMask=new a(this._startMask),this._endMask=new a(this._endMask),this.shapeList.push(this._startMask),this.shapeList.push(this._endMask)},_buildBackground:function(){var e=this.reformCssArray(this.dataRangeOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.dataRangeOption.borderWidth?\"fill\":\"both\",color:this.dataRangeOption.backgroundColor,strokeColor:this.dataRangeOption.borderColor,lineWidth:this.dataRangeOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this._valueTextList,t=e.length,i=this.dataRangeOption.itemGap,n=this.dataRangeOption.itemWidth,a=this.dataRangeOption.itemHeight,o=0,r=0,s=this.getFont(this.dataRangeOption.textStyle),l=h.getTextHeight(\"国\",s),m=10;if(\"horizontal\"==this.dataRangeOption.orient){if(this.dataRangeOption.text||this._isContinuity())o=(this._isContinuity()?n*m+i:t*(n+i))+(this.dataRangeOption.text&&\"undefined\"!=typeof this.dataRangeOption.text[0]?h.getTextWidth(this.dataRangeOption.text[0],s)+this._textGap:0)+(this.dataRangeOption.text&&\"undefined\"!=typeof this.dataRangeOption.text[1]?h.getTextWidth(this.dataRangeOption.text[1],s)+this._textGap:0);else{n+=5;for(var V=0;t>V;V++)o+=n+h.getTextWidth(e[V],s)+i}o-=i,r=Math.max(l,a)}else{var U;if(this.dataRangeOption.text||this._isContinuity())r=(this._isContinuity()?a*m+i:t*(a+i))+(this.dataRangeOption.text&&\"undefined\"!=typeof this.dataRangeOption.text[0]?this._textGap+l:0)+(this.dataRangeOption.text&&\"undefined\"!=typeof this.dataRangeOption.text[1]?this._textGap+l:0),U=Math.max(h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[0]||\"\",s),h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[1]||\"\",s)),o=Math.max(n,U);else{r=(a+i)*t,n+=5,U=0;for(var V=0;t>V;V++)U=Math.max(U,h.getTextWidth(e[V],s));o=n+U}r-=i}var d,p=this.reformCssArray(this.dataRangeOption.padding),c=this.zr.getWidth();switch(this.dataRangeOption.x){case\"center\":d=Math.floor((c-o)/2);break;case\"left\":d=p[3]+this.dataRangeOption.borderWidth;break;case\"right\":d=c-o-p[1]-this.dataRangeOption.borderWidth;break;default:d=this.parsePercent(this.dataRangeOption.x,c),d=isNaN(d)?0:d}var u,y=this.zr.getHeight();switch(this.dataRangeOption.y){case\"top\":u=p[0]+this.dataRangeOption.borderWidth;break;case\"bottom\":u=y-r-p[2]-this.dataRangeOption.borderWidth;break;case\"center\":u=Math.floor((y-r)/2);break;default:u=this.parsePercent(this.dataRangeOption.y,y),u=isNaN(u)?0:u}if(this.dataRangeOption.calculable){var g=Math.max(h.getTextWidth(this.dataRangeOption.max,s),h.getTextWidth(this.dataRangeOption.min,s))+l;\"horizontal\"==this.dataRangeOption.orient?(g>d&&(d=g),d+o+g>c&&(d-=g)):(l>u&&(u=l),u+r+l>y&&(u-=l))}return{x:d,y:u,width:o,height:r}},_getTextShape:function(e,t,i){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:\"horizontal\"==this.dataRangeOption.orient?e:this._itemGroupLocation.x+this._itemGroupLocation.width/2,y:\"horizontal\"==this.dataRangeOption.orient?this._itemGroupLocation.y+this._itemGroupLocation.height/2:t,color:this.dataRangeOption.textStyle.color,text:i,textFont:this.getFont(this.dataRangeOption.textStyle),textBaseline:\"horizontal\"==this.dataRangeOption.orient?\"middle\":\"top\",textAlign:\"horizontal\"==this.dataRangeOption.orient?\"left\":\"center\"},hoverable:!1}},_getItemShape:function(e,t,i,n,a){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:e,y:t+1,width:i,height:n-2,color:a},highlightStyle:{strokeColor:a,lineWidth:1}}},__ondrift:function(e,t,i){var n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;return\"horizontal\"==this.dataRangeOption.orient?e.style.x+t<=n?e.style.x=n:e.style.x+t+e.style.width>=n+o?e.style.x=n+o-e.style.width:e.style.x+=t:e.style.y+i<=a?e.style.y=a:e.style.y+i+e.style.height>=a+r?e.style.y=a+r-e.style.height:e.style.y+=i,\"filler\"==e._type?this._syncHandleShape():this._syncFillerShape(e),this.dataRangeOption.realtime&&this._dispatchDataRange(),!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,this.dataRangeOption.realtime||this._dispatchDataRange(),t.needRefresh=!1,this.isDragend=!1)},_syncShapeFromRange:function(){var e=this.dataRangeOption.range||{},t=e.start,i=e.end;if(t>i&&(t=[i,i=t][0]),this._range.end=null!=t?t:null!=this._range.end?this._range.end:0,this._range.start=null!=i?i:null!=this._range.start?this._range.start:100,100!=this._range.start||0!==this._range.end){if(\"horizontal\"==this.dataRangeOption.orient){var n=this._fillerShape.style.width;this._fillerShape.style.x+=n*(100-this._range.start)/100,this._fillerShape.style.width=n*(this._range.start-this._range.end)/100}else{var a=this._fillerShape.style.height;this._fillerShape.style.y+=a*(100-this._range.start)/100,this._fillerShape.style.height=a*(this._range.start-this._range.end)/100}this.zr.modShape(this._fillerShape.id),this._syncHandleShape()}},_syncHandleShape:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;\"horizontal\"==this.dataRangeOption.orient?(this._startShape.style.x=this._fillerShape.style.x,this._startMask.style.width=this._startShape.style.x-e,this._endShape.style.x=this._fillerShape.style.x+this._fillerShape.style.width,this._endMask.style.x=this._endShape.style.x,this._endMask.style.width=e+i-this._endShape.style.x,this._range.start=Math.ceil(100-(this._startShape.style.x-e)/i*100),this._range.end=Math.floor(100-(this._endShape.style.x-e)/i*100)):(this._startShape.style.y=this._fillerShape.style.y,this._startMask.style.height=this._startShape.style.y-t,this._endShape.style.y=this._fillerShape.style.y+this._fillerShape.style.height,this._endMask.style.y=this._endShape.style.y,this._endMask.style.height=t+n-this._endShape.style.y,this._range.start=Math.ceil(100-(this._startShape.style.y-t)/n*100),this._range.end=Math.floor(100-(this._endShape.style.y-t)/n*100)),this._syncShape()},_syncFillerShape:function(e){var t,i,n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;\"horizontal\"==this.dataRangeOption.orient?(t=this._startShape.style.x,i=this._endShape.style.x,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.x=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.x=t),this._fillerShape.style.x=t,this._fillerShape.style.width=i-t,this._startMask.style.width=t-n,this._endMask.style.x=i,this._endMask.style.width=n+o-i,this._range.start=Math.ceil(100-(t-n)/o*100),this._range.end=Math.floor(100-(i-n)/o*100)):(t=this._startShape.style.y,i=this._endShape.style.y,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.y=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.y=t),this._fillerShape.style.y=t,this._fillerShape.style.height=i-t,this._startMask.style.height=t-a,this._endMask.style.y=i,this._endMask.style.height=a+r-i,this._range.start=Math.ceil(100-(t-a)/r*100),this._range.end=Math.floor(100-(i-a)/r*100)),this._syncShape()},_syncShape:function(){this._startShape.position=[this._startShape.style.x-this._startShape.style._x,this._startShape.style.y-this._startShape.style._y],this._startShape.style.text=this._textFormat(this._gap*this._range.start+this.dataRangeOption.min),this._startShape.style.color=this._startShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.start+this.dataRangeOption.min),this._endShape.position=[this._endShape.style.x-this._endShape.style._x,this._endShape.style.y-this._endShape.style._y],this._endShape.style.text=this._textFormat(this._gap*this._range.end+this.dataRangeOption.min),this._endShape.style.color=this._endShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.end+this.dataRangeOption.min),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._startMask.id),this.zr.modShape(this._endMask.id),this.zr.modShape(this._fillerShape.id),this.zr.refreshNextFrame()},_dispatchDataRange:function(){this.messageCenter.dispatch(r.EVENT.DATA_RANGE,null,{range:{start:this._range.end,end:this._range.start}},this.myChart)},__dataRangeSelected:function(e){if(\"single\"===this.dataRangeOption.selectedMode)for(var t in this._selectedMap)this._selectedMap[t]=!1;var i=e.target._idx;this._selectedMap[i]=!this._selectedMap[i];var n,a;this._useCustomizedSplit()?(n=this._splitList[i].max,a=this._splitList[i].min):(n=(this._colorList.length-i)*this._gap+this.dataRangeOption.min,a=n-this._gap),this.messageCenter.dispatch(r.EVENT.DATA_RANGE_SELECTED,e.event,{selected:this._selectedMap,target:i,valueMax:n,valueMin:a},this.myChart),this.messageCenter.dispatch(r.EVENT.REFRESH,null,null,this.myChart)},__dispatchHoverLink:function(e){var t,i;if(this.dataRangeOption.calculable){var n,a=this.dataRangeOption.max-this.dataRangeOption.min;n=\"horizontal\"==this.dataRangeOption.orient?(1-(l.getX(e.event)-this._calculableLocation.x)/this._calculableLocation.width)*a:(1-(l.getY(e.event)-this._calculableLocation.y)/this._calculableLocation.height)*a,t=n-.05*a,i=n+.05*a}else if(this._useCustomizedSplit()){var o=e.target._idx;i=this._splitList[o].max,t=this._splitList[o].min}else{var o=e.target._idx;i=(this._colorList.length-o)*this._gap+this.dataRangeOption.min,t=i-this._gap}this.messageCenter.dispatch(r.EVENT.DATA_RANGE_HOVERLINK,e.event,{valueMin:t,valueMax:i},this.myChart)},__onhoverlink:function(e){if(this.dataRangeOption.show&&this.dataRangeOption.hoverLink&&this._indicatorShape&&e&&null!=e.seriesIndex&&null!=e.dataIndex){var t=e.value;if(\"\"===t||isNaN(t))return;t<this.dataRangeOption.min?t=this.dataRangeOption.min:t>this.dataRangeOption.max&&(t=this.dataRangeOption.max),this._indicatorShape.position=\"horizontal\"==this.dataRangeOption.orient?[(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.width,0]:[0,(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.height],this._indicatorShape.style.text=this._textFormat(e.value),this._indicatorShape.style.color=this.getColor(t),this.zr.addHoverShape(this._indicatorShape)}},_textFormat:function(e,t){var i=this.dataRangeOption;if(e!==-Number.MAX_VALUE&&(e=(+e).toFixed(i.precision)),null!=t&&t!==Number.MAX_VALUE&&(t=(+t).toFixed(i.precision)),i.formatter){if(\"string\"==typeof i.formatter)return i.formatter.replace(\"{value}\",e===-Number.MAX_VALUE?\"min\":e).replace(\"{value2}\",t===Number.MAX_VALUE?\"max\":t);if(\"function\"==typeof i.formatter)return i.formatter.call(this.myChart,e,t)}return null==t?e:e===-Number.MAX_VALUE?\"< \"+t:t===Number.MAX_VALUE?\"> \"+e:e+\" - \"+t},_isContinuity:function(){var e=this.dataRangeOption;return!(e.splitList?e.splitList.length>0:e.splitNumber>0)||e.calculable},_useCustomizedSplit:function(){var e=this.dataRangeOption;return e.splitList&&e.splitList.length>0},_buildColorList:function(e){if(this._colorList=m.getGradientColors(this.dataRangeOption.color,Math.max((e-this.dataRangeOption.color.length)/(this.dataRangeOption.color.length-1),0)+1),this._colorList.length>e){for(var t=this._colorList.length,i=[this._colorList[0]],n=t/(e-1),a=1;e-1>a;a++)i.push(this._colorList[Math.floor(a*n)]);i.push(this._colorList[t-1]),this._colorList=i}if(this._useCustomizedSplit())for(var o=this._splitList,a=0,t=o.length;t>a;a++)o[a].color&&(this._colorList[a]=o[a].color)},_buildGap:function(e){if(!this._useCustomizedSplit()){var t=this.dataRangeOption.precision;for(this._gap=(this.dataRangeOption.max-this.dataRangeOption.min)/e;this._gap.toFixed(t)-0!=this._gap&&5>t;)t++;this.dataRangeOption.precision=t,this._gap=((this.dataRangeOption.max-this.dataRangeOption.min)/e).toFixed(t)-0}},_buildDataList:function(e){for(var t=this._valueTextList=[],i=this.dataRangeOption,n=this._useCustomizedSplit(),a=0;e>a;a++){this._selectedMap[a]=!0;var o=\"\";if(n){var r=this._splitList[e-1-a];o=null!=r.label?r.label:null!=r.single?this._textFormat(r.single):this._textFormat(r.min,r.max)}else o=this._textFormat(a*this._gap+i.min,(a+1)*this._gap+i.min);t.unshift(o)}},_buildSplitList:function(){if(this._useCustomizedSplit())for(var e=this.dataRangeOption.splitList,t=this._splitList=[],i=0,n=e.length;n>i;i++){var a=e[i];if(!a||null==a.start&&null==a.end)throw new Error(\"Empty item exists in splitList!\");var o={label:a.label,color:a.color};o.min=a.start,o.max=a.end,o.min>o.max&&(o.min=[o.max,o.max=o.min][0]),o.min===o.max&&(o.single=o.max),null==o.min&&(o.min=-Number.MAX_VALUE),null==o.max&&(o.max=Number.MAX_VALUE),t.push(o)}},refresh:function(e){if(e){this.option=e,this.option.dataRange=this.reformOption(this.option.dataRange);var t=this.dataRangeOption=this.option.dataRange;if(!this._useCustomizedSplit()&&(null==t.min||null==t.max))throw new Error(\"option.dataRange.min or option.dataRange.max has not been defined.\");this.myChart.canvasSupported||(t.realtime=!1);var i=this._isContinuity()?100:this._useCustomizedSplit()?t.splitList.length:t.splitNumber;this._buildSplitList(),this._buildColorList(i),this._buildGap(i),this._buildDataList(i)}this.clear(),this._buildShape()},getColor:function(e){if(isNaN(e))return null;var t;if(this._useCustomizedSplit()){for(var i=this._splitList,n=0,a=i.length;a>n;n++)if(i[n].min<=e&&i[n].max>=e){t=n;break}}else{if(this.dataRangeOption.min==this.dataRangeOption.max)return this._colorList[0];if(e<this.dataRangeOption.min?e=this.dataRangeOption.min:e>this.dataRangeOption.max&&(e=this.dataRangeOption.max),this.dataRangeOption.calculable&&(e-(this._gap*this._range.start+this.dataRangeOption.min)>5e-5||e-(this._gap*this._range.end+this.dataRangeOption.min)<-5e-5))return null;t=this._colorList.length-Math.ceil((e-this.dataRangeOption.min)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._colorList.length),t==this._colorList.length&&t--}return this._selectedMap[t]?this._colorList[t]:null},getColorByIndex:function(e){return e>=this._colorList.length?e=this._colorList.length-1:0>e&&(e=0),this._colorList[e]},onbeforDispose:function(){this.messageCenter.unbind(r.EVENT.HOVER,this._onhoverlink)}},s.inherits(t,i),e(\"../component\").define(\"dataRange\",t),t}),i(\"echarts/util/shape/HandlePolygon\",[\"require\",\"zrender/shape/Base\",\"zrender/shape/Polygon\",\"zrender/tool/util\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/shape/Polygon\"),a=e(\"zrender/tool/util\");return t.prototype={type:\"handle-polygon\",buildPath:function(e,t){n.prototype.buildPath(e,t)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.rect;return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height?!0:!1}},a.inherits(t,i),t}),i(\"echarts/chart/k\",[\"require\",\"./base\",\"../util/shape/Candle\",\"../component/axis\",\"../component/grid\",\"../component/dataZoom\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"../util/shape/Candle\");e(\"../component/axis\"),e(\"../component/grid\"),e(\"../component/dataZoom\");var a=e(\"../config\");a.k={zlevel:0,z:2,clickable:!0,hoverable:!0,legendHoverLink:!1,xAxisIndex:0,yAxisIndex:0,itemStyle:{normal:{color:\"#fff\",color0:\"#00aa11\",lineStyle:{width:1,color:\"#ff3200\",color0:\"#00aa11\"},label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e(\"../util/ecData\"),r=e(\"zrender/tool/util\");return t.prototype={type:a.CHART_TYPE_K,_buildShape:function(){var e=this.series;this.selectedMap={};for(var t,i={top:[],bottom:[]},n=0,o=e.length;o>n;n++)e[n].type===a.CHART_TYPE_K&&(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,t=this.component.xAxis.getAxis(e[n].xAxisIndex),t.type===a.COMPONENT_TYPE_AXIS_CATEGORY&&i[t.getPosition()].push(n));for(var r in i)i[r].length>0&&this._buildSinglePosition(r,i[r]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){this._buildHorizontal(t,a,n);for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n=this.series,a=this.component.legend,o=[],r=0,s=0,l=e.length;l>s;s++)t=n[e[s]],i=t.name,this.selectedMap[i]=a?a.isSelected(i):!0,this.selectedMap[i]&&o.push(e[s]),r=Math.max(r,t.data.length);return{locationMap:o,maxDataLength:r}},_buildHorizontal:function(e,t,i){for(var n,a,o,r,s,l,h,m,V,U,d=this.series,p={},c=0,u=i.length;u>c;c++){n=i[c],a=d[n],o=a.xAxisIndex||0,r=this.component.xAxis.getAxis(o),h=a.barWidth||Math.floor(r.getGap()/2),U=a.barMaxWidth,U&&h>U&&(h=U),s=a.yAxisIndex||0,l=this.component.yAxis.getAxis(s),p[n]=[];for(var y=0,g=t;g>y&&null!=r.getNameByIndex(y);y++)m=a.data[y],V=this.getDataFromOption(m,\"-\"),\"-\"!==V&&4==V.length&&p[n].push([r.getCoordByIndex(y),h,l.getCoord(V[0]),l.getCoord(V[1]),l.getCoord(V[2]),l.getCoord(V[3]),y,r.getNameByIndex(y)])}this._buildKLine(e,p)},_buildKLine:function(e,t){for(var i,n,o,r,s,l,h,m,V,U,d,p,c,u,y,g,b,f=this.series,k=0,x=e.length;x>k;k++)if(b=e[k],d=f[b],u=t[b],this._isLarge(u)&&(u=this._getLargePointList(u)),d.type===a.CHART_TYPE_K&&null!=u){p=d,i=this.query(p,\"itemStyle.normal.lineStyle.width\"),n=this.query(p,\"itemStyle.normal.lineStyle.color\"),o=this.query(p,\"itemStyle.normal.lineStyle.color0\"),r=this.query(p,\"itemStyle.normal.color\"),s=this.query(p,\"itemStyle.normal.color0\"),l=this.query(p,\"itemStyle.emphasis.lineStyle.width\"),h=this.query(p,\"itemStyle.emphasis.lineStyle.color\"),m=this.query(p,\"itemStyle.emphasis.lineStyle.color0\"),V=this.query(p,\"itemStyle.emphasis.color\"),U=this.query(p,\"itemStyle.emphasis.color0\");for(var _=0,L=u.length;L>_;_++)y=u[_],c=d.data[y[6]],p=c,g=y[3]<y[2],this.shapeList.push(this._getCandle(b,y[6],y[7],y[0],y[1],y[2],y[3],y[4],y[5],g?this.query(p,\"itemStyle.normal.color\")||r:this.query(p,\"itemStyle.normal.color0\")||s,this.query(p,\"itemStyle.normal.lineStyle.width\")||i,g?this.query(p,\"itemStyle.normal.lineStyle.color\")||n:this.query(p,\"itemStyle.normal.lineStyle.color0\")||o,g?this.query(p,\"itemStyle.emphasis.color\")||V||r:this.query(p,\"itemStyle.emphasis.color0\")||U||s,this.query(p,\"itemStyle.emphasis.lineStyle.width\")||l||i,g?this.query(p,\"itemStyle.emphasis.lineStyle.color\")||h||n:this.query(p,\"itemStyle.emphasis.lineStyle.color0\")||m||o))}},_isLarge:function(e){return e[0][1]<.5},_getLargePointList:function(e){for(var t=this.component.grid.getWidth(),i=e.length,n=[],a=0;t>a;a++)n[a]=e[Math.floor(i/t*a)];return n},_getCandle:function(e,t,i,a,r,s,l,h,m,V,U,d,p,c,u){var y=this.series,g=y[e],b=g.data[t],f=[b,g],k={zlevel:g.zlevel,z:g.z,clickable:this.deepQuery(f,\"clickable\"),hoverable:this.deepQuery(f,\"hoverable\"),style:{x:a,y:[s,l,h,m],width:r,color:V,strokeColor:d,lineWidth:U,brushType:\"both\"},highlightStyle:{color:p,strokeColor:u,lineWidth:c},_seriesIndex:e};return k=this.addLabel(k,g,b,i),o.pack(k,g,e,b,t,i),k=new n(k)},getMarkCoord:function(e,t){var i=this.series[e],n=this.component.xAxis.getAxis(i.xAxisIndex),a=this.component.yAxis.getAxis(i.yAxisIndex);return[\"string\"!=typeof t.xAxis&&n.getCoordByIndex?n.getCoordByIndex(t.xAxis||0):n.getCoord(t.xAxis||0),\"string\"!=typeof t.yAxis&&a.getCoordByIndex?a.getCoordByIndex(t.yAxis||0):a.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){p--,0===p&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p=0,r=0,s=this.shapeList.length;s>r;r++)if(U=this.shapeList[r]._seriesIndex,a[U]&&!a[U][3]&&\"candle\"===this.shapeList[r].type){if(d=o.get(this.shapeList[r],\"dataIndex\"),V=n[U],a[U][2]&&d===V.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[U][2]&&0===d){this.zr.delShape(this.shapeList[r].id);continue}h=this.component.xAxis.getAxis(V.xAxisIndex||0).getGap(),l=a[U][2]?h:-h,m=0,p++,this.zr.animate(this.shapeList[r].id,\"\").when(this.query(this.option,\"animationDurationUpdate\"),{position:[l,m]}).done(i).start()}p||t&&t()}},r.inherits(t,i),e(\"../chart\").define(\"k\",t),t}),i(\"echarts/chart/pie\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Ring\",\"zrender/shape/Circle\",\"zrender/shape/Sector\",\"zrender/shape/Polyline\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/math\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r.shapeHandler.onmouseover=function(e){var t=e.target,i=h.get(t,\"seriesIndex\"),n=h.get(t,\"dataIndex\"),a=h.get(t,\"special\"),o=[t.style.x,t.style.y],s=t.style.startAngle,l=t.style.endAngle,m=((l+s)/2+360)%360,V=t.highlightStyle.color,U=r.getLabel(i,n,a,o,m,V,!0);U&&r.zr.addHoverShape(U);var d=r.getLabelLine(i,n,o,t.style.r0,t.style.r,m,V,!0);d&&r.zr.addHoverShape(d)},this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Ring\"),o=e(\"zrender/shape/Circle\"),r=e(\"zrender/shape/Sector\"),s=e(\"zrender/shape/Polyline\"),l=e(\"../config\");l.pie={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,center:[\"50%\",\"50%\"],radius:[0,\"75%\"],clockWise:!0,startAngle:90,minAngle:0,selectedOffset:10,itemStyle:{normal:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,label:{show:!0,position:\"outer\"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:\"solid\"}}},emphasis:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,label:{show:!1},labelLine:{show:!1,length:20,lineStyle:{width:1,type:\"solid\"}}}}};var h=e(\"../util/ecData\"),m=e(\"zrender/tool/util\"),V=e(\"zrender/tool/math\"),U=e(\"zrender/tool/color\");return t.prototype={type:l.CHART_TYPE_PIE,_buildShape:function(){var e=this.series,t=this.component.legend;this.selectedMap={},this._selected={};var i,n,r;this._selectedMode=!1;for(var s,m=0,V=e.length;V>m;m++)if(e[m].type===l.CHART_TYPE_PIE){if(e[m]=this.reformOption(e[m]),this.legendHoverLink=e[m].legendHoverLink||this.legendHoverLink,s=e[m].name||\"\",this.selectedMap[s]=t?t.isSelected(s):!0,!this.selectedMap[s])continue;i=this.parseCenter(this.zr,e[m].center),n=this.parseRadius(this.zr,e[m].radius),this._selectedMode=this._selectedMode||e[m].selectedMode,this._selected[m]=[],this.deepQuery([e[m],this.option],\"calculable\")&&(r={zlevel:e[m].zlevel,z:e[m].z,hoverable:!1,style:{x:i[0],y:i[1],r0:n[0]<=10?0:n[0]-10,r:n[1]+10,brushType:\"stroke\",lineWidth:1,strokeColor:e[m].calculableHolderColor||this.ecTheme.calculableHolderColor||l.calculableHolderColor}},h.pack(r,e[m],m,void 0,-1),this.setCalculable(r),r=n[0]<=10?new o(r):new a(r),this.shapeList.push(r)),this._buildSinglePie(m),this.buildMark(m)}this.addShapeList()},_buildSinglePie:function(e){for(var t,i=this.series,n=i[e],a=n.data,o=this.component.legend,r=0,s=0,l=0,h=Number.NEGATIVE_INFINITY,m=[],V=0,U=a.length;U>V;V++)t=a[V].name,\nthis.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t]&&!isNaN(a[V].value)&&(0!==+a[V].value?r++:s++,l+=+a[V].value,h=Math.max(h,+a[V].value));if(0!==l){for(var d,p,c,u,y,g,b=100,f=n.clockWise,k=(n.startAngle.toFixed(2)-0+360)%360,x=n.minAngle||.01,_=360-x*r-.01*s,L=n.roseType,V=0,U=a.length;U>V;V++)if(t=a[V].name,this.selectedMap[t]&&!isNaN(a[V].value)){if(p=o?o.getColor(t):this.zr.getColor(V),b=a[V].value/l,d=\"area\"!=L?f?k-b*_-(0!==b?x:.01):b*_+k+(0!==b?x:.01):f?k-360/U:360/U+k,d=d.toFixed(2)-0,b=(100*b).toFixed(2),c=this.parseCenter(this.zr,n.center),u=this.parseRadius(this.zr,n.radius),y=+u[0],g=+u[1],\"radius\"===L?g=a[V].value/h*(g-y)*.8+.2*(g-y)+y:\"area\"===L&&(g=Math.sqrt(a[V].value/h)*(g-y)+y),f){var W;W=k,k=d,d=W}this._buildItem(m,e,V,b,a[V].selected,c,y,g,k,d,p),f||(k=d)}this._autoLabelLayout(m,c,g);for(var V=0,U=m.length;U>V;V++)this.shapeList.push(m[V]);m=null}},_buildItem:function(e,t,i,n,a,o,r,s,l,m,V){var U=this.series,d=((m+l)/2+360)%360,p=this.getSector(t,i,n,a,o,r,s,l,m,V);h.pack(p,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(p);var c=this.getLabel(t,i,n,o,d,V,!1),u=this.getLabelLine(t,i,o,r,s,d,V,!1);u&&(h.pack(u,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(u)),c&&(h.pack(c,U[t],t,U[t].data[i],i,U[t].data[i].name,n),c._labelLine=u,e.push(c))},getSector:function(e,t,i,n,a,o,s,l,h,m){var d=this.series,p=d[e],c=p.data[t],u=[c,p],y=this.deepMerge(u,\"itemStyle.normal\")||{},g=this.deepMerge(u,\"itemStyle.emphasis\")||{},b=this.getItemStyleColor(y.color,e,t,c)||m,f=this.getItemStyleColor(g.color,e,t,c)||(\"string\"==typeof b?U.lift(b,-.2):b),k={zlevel:p.zlevel,z:p.z,clickable:this.deepQuery(u,\"clickable\"),style:{x:a[0],y:a[1],r0:o,r:s,startAngle:l,endAngle:h,brushType:\"both\",color:b,lineWidth:y.borderWidth,strokeColor:y.borderColor,lineJoin:\"round\"},highlightStyle:{color:f,lineWidth:g.borderWidth,strokeColor:g.borderColor,lineJoin:\"round\"},_seriesIndex:e,_dataIndex:t};if(n){var x=((k.style.startAngle+k.style.endAngle)/2).toFixed(2)-0;k.style._hasSelected=!0,k.style._x=k.style.x,k.style._y=k.style.y;var _=this.query(p,\"selectedOffset\");k.style.x+=V.cos(x,!0)*_,k.style.y-=V.sin(x,!0)*_,this._selected[e][t]=!0}else this._selected[e][t]=!1;return this._selectedMode&&(k.onclick=this.shapeHandler.onclick),this.deepQuery([c,p,this.option],\"calculable\")&&(this.setCalculable(k),k.draggable=!0),(this._needLabel(p,c,!0)||this._needLabelLine(p,c,!0))&&(k.onmouseover=this.shapeHandler.onmouseover),k=new r(k)},getLabel:function(e,t,i,a,o,r,s){var l=this.series,h=l[e],U=h.data[t];if(this._needLabel(h,U,s)){var d,p,c,u=s?\"emphasis\":\"normal\",y=m.merge(m.clone(U.itemStyle)||{},h.itemStyle),g=y[u].label,b=g.textStyle||{},f=a[0],k=a[1],x=this.parseRadius(this.zr,h.radius),_=\"middle\";g.position=g.position||y.normal.label.position,\"center\"===g.position?(d=f,p=k,c=\"center\"):\"inner\"===g.position||\"inside\"===g.position?(x=(x[0]+x[1])*(g.distance||.5),d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),r=\"#fff\",c=\"center\"):(x=x[1]- -y[u].labelLine.length,d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),c=o>=90&&270>=o?\"right\":\"left\"),\"center\"!=g.position&&\"inner\"!=g.position&&\"inside\"!=g.position&&(d+=\"left\"===c?20:-20),U.__labelX=d-(\"left\"===c?5:-5),U.__labelY=p;var L=new n({zlevel:h.zlevel,z:h.z+1,hoverable:!1,style:{x:d,y:p,color:b.color||r,text:this.getLabelText(e,t,i,u),textAlign:b.align||c,textBaseline:b.baseline||_,textFont:this.getFont(b)},highlightStyle:{brushType:\"fill\"}});return L._radius=x,L._labelPosition=g.position||\"outer\",L._rect=L.getRect(L.style),L._seriesIndex=e,L._dataIndex=t,L}},getLabelText:function(e,t,i,n){var a=this.series,o=a[e],r=o.data[t],s=this.deepQuery([r,o],\"itemStyle.\"+n+\".label.formatter\");return s?\"function\"==typeof s?s.call(this.myChart,{seriesIndex:e,seriesName:o.name||\"\",series:o,dataIndex:t,data:r,name:r.name,value:r.value,percent:i}):\"string\"==typeof s?(s=s.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\").replace(\"{d}\",\"{d0}\"),s=s.replace(\"{a0}\",o.name).replace(\"{b0}\",r.name).replace(\"{c0}\",r.value).replace(\"{d0}\",i)):void 0:r.name},getLabelLine:function(e,t,i,n,a,o,r,l){var h=this.series,U=h[e],d=U.data[t];if(this._needLabelLine(U,d,l)){var p=l?\"emphasis\":\"normal\",c=m.merge(m.clone(d.itemStyle)||{},U.itemStyle),u=c[p].labelLine,y=u.lineStyle||{},g=i[0],b=i[1],f=a,k=this.parseRadius(this.zr,U.radius)[1]- -u.length,x=V.cos(o,!0),_=V.sin(o,!0);return new s({zlevel:U.zlevel,z:U.z+1,hoverable:!1,style:{pointList:[[g+f*x,b-f*_],[g+k*x,b-k*_],[d.__labelX,d.__labelY]],strokeColor:y.color||r,lineType:y.type,lineWidth:y.width},_seriesIndex:e,_dataIndex:t})}},_needLabel:function(e,t,i){return this.deepQuery([t,e],\"itemStyle.\"+(i?\"emphasis\":\"normal\")+\".label.show\")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],\"itemStyle.\"+(i?\"emphasis\":\"normal\")+\".labelLine.show\")},_autoLabelLayout:function(e,t,i){for(var n=[],a=[],o=0,r=e.length;r>o;o++)(\"outer\"===e[o]._labelPosition||\"outside\"===e[o]._labelPosition)&&(e[o]._rect._y=e[o]._rect.y,e[o]._rect.x<t[0]?n.push(e[o]):a.push(e[o]));this._layoutCalculate(n,t,i,-1),this._layoutCalculate(a,t,i,1)},_layoutCalculate:function(e,t,i,n){function a(t,i,n){for(var a=t;i>a;a++)if(e[a]._rect.y+=n,e[a].style.y+=n,e[a]._labelLine&&(e[a]._labelLine.style.pointList[1][1]+=n,e[a]._labelLine.style.pointList[2][1]+=n),a>t&&i>a+1&&e[a+1]._rect.y>e[a]._rect.y+e[a]._rect.height)return void o(a,n/2);o(i-1,n/2)}function o(t,i){for(var n=t;n>=0&&(e[n]._rect.y-=i,e[n].style.y-=i,e[n]._labelLine&&(e[n]._labelLine.style.pointList[1][1]-=i,e[n]._labelLine.style.pointList[2][1]-=i),!(n>0&&e[n]._rect.y>e[n-1]._rect.y+e[n-1]._rect.height));n--);}function r(e,t,i,n,a){for(var o,r,s,l=i[0],h=i[1],m=a>0?t?Number.MAX_VALUE:0:t?Number.MAX_VALUE:0,V=0,U=e.length;U>V;V++)r=Math.abs(e[V]._rect.y-h),s=e[V]._radius-n,o=n+s>r?Math.sqrt((n+s+20)*(n+s+20)-Math.pow(e[V]._rect.y-h,2)):Math.abs(e[V]._rect.x+(a>0?0:e[V]._rect.width)-l),t&&o>=m&&(o=m-10),!t&&m>=o&&(o=m+10),e[V]._rect.x=e[V].style.x=l+o*a,e[V]._labelLine&&(e[V]._labelLine.style.pointList[2][0]=l+(o-5)*a,e[V]._labelLine.style.pointList[1][0]=l+(o-20)*a),m=o}e.sort(function(e,t){return e._rect.y-t._rect.y});for(var s,l=0,h=e.length,m=[],V=[],U=0;h>U;U++)s=e[U]._rect.y-l,0>s&&a(U,h,-s,n),l=e[U]._rect.y+e[U]._rect.height;this.zr.getHeight()-l<0&&o(h-1,l-this.zr.getHeight());for(var U=0;h>U;U++)e[U]._rect.y>=t[1]?V.push(e[U]):m.push(e[U]);r(V,!0,t,i,n),r(m,!1,t,i,n)},reformOption:function(e){var t=m.merge;return e=t(t(e||{},m.clone(this.ecTheme.pie||{})),m.clone(l.pie)),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),e.itemStyle.emphasis.label.textStyle=this.getTextStyle(e.itemStyle.emphasis.label.textStyle),this.z=e.z,this.zlevel=e.zlevel,e},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){s--,0===s&&t&&t()}for(var n=this.series,a={},o=0,r=e.length;r>o;o++)a[e[o][0]]=e[o];var s=0,h={},m={},V={},U=this.shapeList;this.shapeList=[];for(var d,p,c,u={},o=0,r=e.length;r>o;o++)d=e[o][0],p=e[o][2],c=e[o][3],n[d]&&n[d].type===l.CHART_TYPE_PIE&&(p?(c||(h[d+\"_\"+n[d].data.length]=\"delete\"),u[d]=1):c?u[d]=0:(h[d+\"_-1\"]=\"delete\",u[d]=-1),this._buildSinglePie(d));for(var y,g,o=0,r=this.shapeList.length;r>o;o++)switch(d=this.shapeList[o]._seriesIndex,y=this.shapeList[o]._dataIndex,g=d+\"_\"+y,this.shapeList[o].type){case\"sector\":h[g]=this.shapeList[o];break;case\"text\":m[g]=this.shapeList[o];break;case\"polyline\":V[g]=this.shapeList[o]}this.shapeList=[];for(var b,o=0,r=U.length;r>o;o++)if(d=U[o]._seriesIndex,a[d]){if(y=U[o]._dataIndex+u[d],g=d+\"_\"+y,b=h[g],!b)continue;if(\"sector\"===U[o].type)\"delete\"!=b?(s++,this.zr.animate(U[o].id,\"style\").when(400,{startAngle:b.style.startAngle,endAngle:b.style.endAngle}).done(i).start()):(s++,this.zr.animate(U[o].id,\"style\").when(400,u[d]<0?{startAngle:U[o].style.startAngle}:{endAngle:U[o].style.endAngle}).done(i).start());else if(\"text\"===U[o].type||\"polyline\"===U[o].type)if(\"delete\"===b)this.zr.delShape(U[o].id);else switch(U[o].type){case\"text\":s++,b=m[g],this.zr.animate(U[o].id,\"style\").when(400,{x:b.style.x,y:b.style.y}).done(i).start();break;case\"polyline\":s++,b=V[g],this.zr.animate(U[o].id,\"style\").when(400,{pointList:b.style.pointList}).done(i).start()}}this.shapeList=U,s||t&&t()},onclick:function(e){var t=this.series;if(this.isClick&&e.target){this.isClick=!1;for(var i,n=e.target,a=n.style,o=h.get(n,\"seriesIndex\"),r=h.get(n,\"dataIndex\"),s=0,m=this.shapeList.length;m>s;s++)if(this.shapeList[s].id===n.id){if(o=h.get(n,\"seriesIndex\"),r=h.get(n,\"dataIndex\"),a._hasSelected)n.style.x=n.style._x,n.style.y=n.style._y,n.style._hasSelected=!1,this._selected[o][r]=!1;else{var U=((a.startAngle+a.endAngle)/2).toFixed(2)-0;n.style._hasSelected=!0,this._selected[o][r]=!0,n.style._x=n.style.x,n.style._y=n.style.y,i=this.query(t[o],\"selectedOffset\"),n.style.x+=V.cos(U,!0)*i,n.style.y-=V.sin(U,!0)*i}this.zr.modShape(n.id)}else this.shapeList[s].style._hasSelected&&\"single\"===this._selectedMode&&(o=h.get(this.shapeList[s],\"seriesIndex\"),r=h.get(this.shapeList[s],\"dataIndex\"),this.shapeList[s].style.x=this.shapeList[s].style._x,this.shapeList[s].style.y=this.shapeList[s].style._y,this.shapeList[s].style._hasSelected=!1,this._selected[o][r]=!1,this.zr.modShape(this.shapeList[s].id));this.messageCenter.dispatch(l.EVENT.PIE_SELECTED,e.event,{selected:this._selected,target:h.get(n,\"name\")},this.myChart),this.zr.refreshNextFrame()}}},m.inherits(t,i),e(\"../chart\").define(\"pie\",t),t}),i(\"echarts/chart/radar\",[\"require\",\"./base\",\"zrender/shape/Polygon\",\"../component/polar\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"../util/accMath\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Polygon\");e(\"../component/polar\");var a=e(\"../config\");a.radar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,polarIndex:0,itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:\"solid\"}},emphasis:{label:{show:!1}}},symbolSize:2};var o=e(\"../util/ecData\"),r=e(\"zrender/tool/util\"),s=e(\"zrender/tool/color\");return t.prototype={type:a.CHART_TYPE_RADAR,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._radarDataCounter=0;for(var e,t=this.series,i=this.component.legend,n=0,o=t.length;o>n;n++)t[n].type===a.CHART_TYPE_RADAR&&(this.serie=this.reformOption(t[n]),this.legendHoverLink=t[n].legendHoverLink||this.legendHoverLink,e=this.serie.name||\"\",this.selectedMap[e]=i?i.isSelected(e):!0,this.selectedMap[e]&&(this._queryTarget=[this.serie,this.option],this.deepQuery(this._queryTarget,\"calculable\")&&this._addDropBox(n),this._buildSingleRadar(n),this.buildMark(n)));this.addShapeList()},_buildSingleRadar:function(e){for(var t,i,n,a,o=this.component.legend,r=this.serie.data,s=this.deepQuery(this._queryTarget,\"calculable\"),l=0;l<r.length;l++)n=r[l].name||\"\",this.selectedMap[n]=o?o.isSelected(n):!0,this.selectedMap[n]&&(o?(i=o.getColor(n),t=o.getItemShape(n),t&&(t.style.brushType=this.deepQuery([r[l],this.serie],\"itemStyle.normal.areaStyle\")?\"both\":\"stroke\",o.setItemShape(n,t))):i=this.zr.getColor(l),a=this._getPointList(this.serie.polarIndex,r[l]),this._addSymbol(a,i,l,e,this.serie.polarIndex),this._addDataShape(a,i,r[l],e,l,s),this._radarDataCounter++)},_getPointList:function(e,t){for(var i,n,a=[],o=this.component.polar,r=0,s=t.value.length;s>r;r++)n=this.getDataFromOption(t.value[r]),i=\"-\"!=n?o.getVector(e,r,n):!1,i&&a.push(i);return a},_addSymbol:function(e,t,i,n,a){for(var r,s=this.series,l=this.component.polar,h=0,m=e.length;m>h;h++)r=this.getSymbolShape(this.deepMerge([s[n].data[i],s[n]]),n,s[n].data[i].value[h],h,l.getIndicatorText(a,h),e[h][0],e[h][1],this._symbol[this._radarDataCounter%this._symbol.length],t,\"#fff\",\"vertical\"),r.zlevel=this.getZlevelBase(),r.z=this.getZBase()+1,o.set(r,\"data\",s[n].data[i]),o.set(r,\"value\",s[n].data[i].value),o.set(r,\"dataIndex\",i),o.set(r,\"special\",h),this.shapeList.push(r)},_addDataShape:function(e,t,i,a,r,l){var h=this.series,m=[i,this.serie],V=this.getItemStyleColor(this.deepQuery(m,\"itemStyle.normal.color\"),a,r,i),U=this.deepQuery(m,\"itemStyle.normal.lineStyle.width\"),d=this.deepQuery(m,\"itemStyle.normal.lineStyle.type\"),p=this.deepQuery(m,\"itemStyle.normal.areaStyle.color\"),c=this.deepQuery(m,\"itemStyle.normal.areaStyle\"),u={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:c?\"both\":\"stroke\",color:p||V||(\"string\"==typeof t?s.alpha(t,.5):t),strokeColor:V||t,lineWidth:U,lineType:d},highlightStyle:{brushType:this.deepQuery(m,\"itemStyle.emphasis.areaStyle\")||c?\"both\":\"stroke\",color:this.deepQuery(m,\"itemStyle.emphasis.areaStyle.color\")||p||V||(\"string\"==typeof t?s.alpha(t,.5):t),strokeColor:this.getItemStyleColor(this.deepQuery(m,\"itemStyle.emphasis.color\"),a,r,i)||V||t,lineWidth:this.deepQuery(m,\"itemStyle.emphasis.lineStyle.width\")||U,lineType:this.deepQuery(m,\"itemStyle.emphasis.lineStyle.type\")||d}};o.pack(u,h[a],a,i,r,i.name,this.component.polar.getIndicator(h[a].polarIndex)),l&&(u.draggable=!0,this.setCalculable(u)),u=new n(u),this.shapeList.push(u)},_addDropBox:function(e){var t=this.series,i=this.deepQuery(this._queryTarget,\"polarIndex\");if(!this._dropBoxList[i]){var n=this.component.polar.getDropBox(i);n.zlevel=this.getZlevelBase(),n.z=this.getZBase(),this.setCalculable(n),o.pack(n,t,e,void 0,-1),this.shapeList.push(n),this._dropBoxList[i]=!0}},ondragend:function(e,t){var i=this.series;if(this.isDragend&&e.target){var n=e.target,a=o.get(n,\"seriesIndex\"),r=o.get(n,\"dataIndex\");this.component.legend&&this.component.legend.del(i[a].data[r].name),i[a].data.splice(r,1),t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},ondrop:function(t,i){var n=this.series;if(this.isDrop&&t.target){var a,r,s=t.target,l=t.dragged,h=o.get(s,\"seriesIndex\"),m=o.get(s,\"dataIndex\"),V=this.component.legend;if(-1===m)a={value:o.get(l,\"value\"),name:o.get(l,\"name\")},n[h].data.push(a),V&&V.add(a.name,l.style.color||l.style.strokeColor);else{var U=e(\"../util/accMath\");a=n[h].data[m],V&&V.del(a.name),a.name+=this.option.nameConnector+o.get(l,\"name\"),r=o.get(l,\"value\");for(var d=0;d<r.length;d++)a.value[d]=U.accAdd(a.value[d],r[d]);V&&V.add(a.name,l.style.color||l.style.strokeColor)}i.dragIn=i.dragIn||!0,this.isDrop=!1}},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},r.inherits(t,i),e(\"../chart\").define(\"radar\",t),t}),i(\"echarts/component/polar\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Polygon\",\"zrender/shape/Circle\",\"zrender/shape/Ring\",\"../config\",\"zrender/tool/util\",\"../util/coordinates\",\"../util/accMath\",\"../util/smartSteps\",\"../component\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Polygon\"),r=e(\"zrender/shape/Circle\"),s=e(\"zrender/shape/Ring\"),l=e(\"../config\");l.polar={zlevel:0,z:0,center:[\"50%\",\"50%\"],radius:\"75%\",startAngle:90,boundaryGap:[0,0],splitNumber:5,name:{show:!0,textStyle:{color:\"#333\"}},axisLine:{show:!0,lineStyle:{color:\"#ccc\",width:1,type:\"solid\"}},axisLabel:{show:!1,textStyle:{color:\"#333\"}},splitArea:{show:!0,areaStyle:{color:[\"rgba(250,250,250,0.3)\",\"rgba(200,200,200,0.3)\"]}},splitLine:{show:!0,lineStyle:{width:1,color:\"#ccc\"}},type:\"polygon\"};var h=e(\"zrender/tool/util\"),m=e(\"../util/coordinates\");return t.prototype={type:l.COMPONENT_TYPE_POLAR,_buildShape:function(){for(var e=0;e<this.polar.length;e++)this._index=e,this.reformOption(this.polar[e]),this._queryTarget=[this.polar[e],this.option],this._createVector(e),this._buildSpiderWeb(e),this._buildText(e),this._adjustIndicatorValue(e),this._addAxisLabel(e);for(var e=0;e<this.shapeList.length;e++)this.zr.addShape(this.shapeList[e])},_createVector:function(e){for(var t,i=this.polar[e],n=this.deepQuery(this._queryTarget,\"indicator\"),a=n.length,o=i.startAngle,r=2*Math.PI/a,s=this._getRadius(),l=i.__ecIndicator=[],h=0;a>h;h++)t=m.polar2cartesian(s,o*Math.PI/180+r*h),l.push({vector:[t[1],-t[0]]})},_getRadius:function(){var e=this.polar[this._index];return this.parsePercent(e.radius,Math.min(this.zr.getWidth(),this.zr.getHeight())/2)},_buildSpiderWeb:function(e){var t=this.polar[e],i=t.__ecIndicator,n=t.splitArea,a=t.splitLine,o=this.getCenter(e),r=t.splitNumber,s=a.lineStyle.color,l=a.lineStyle.width,h=a.show,m=this.deepQuery(this._queryTarget,\"axisLine\");this._addArea(i,r,o,n,s,l,h),m.show&&this._addLine(i,o,m)},_addAxisLabel:function(t){for(var i,a,o,r,a,s,l,m,V,U,d=e(\"../util/accMath\"),p=this.polar[t],c=this.deepQuery(this._queryTarget,\"indicator\"),u=p.__ecIndicator,y=this.deepQuery(this._queryTarget,\"splitNumber\"),g=this.getCenter(t),b=0;b<c.length;b++)if(i=this.deepQuery([c[b],p,this.option],\"axisLabel\"),i.show){var f=this.deepQuery([i,p,this.option],\"textStyle\"),k=this.deepQuery([i,p],\"formatter\");if(o={},o.textFont=this.getFont(f),o.color=f.color,o=h.merge(o,i),o.lineWidth=o.width,a=u[b].vector,s=u[b].value,m=b/c.length*2*Math.PI,V=i.offset||10,U=i.interval||0,!s)return;for(var x=1;y>=x;x+=U+1)r=h.merge({},o),l=d.accAdd(s.min,d.accMul(s.step,x)),l=\"function\"==typeof k?k(l):\"string\"==typeof k?k.replace(\"{a}\",\"{a0}\").replace(\"{a0}\",l):this.numAddCommas(l),r.text=l,r.x=x*a[0]/y+Math.cos(m)*V+g[0],r.y=x*a[1]/y+Math.sin(m)*V+g[1],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:r,draggable:!1,hoverable:!1}))}},_buildText:function(e){for(var t,i,a,o,r,s,l,h=this.polar[e],m=h.__ecIndicator,V=this.deepQuery(this._queryTarget,\"indicator\"),U=this.getCenter(e),d=0,p=0,c=0;c<V.length;c++)o=this.deepQuery([V[c],h,this.option],\"name\"),o.show&&(l=this.deepQuery([o,h,this.option],\"textStyle\"),i={},i.textFont=this.getFont(l),i.color=l.color,i.text=\"function\"==typeof o.formatter?o.formatter.call(this.myChart,V[c].text,c):\"string\"==typeof o.formatter?o.formatter.replace(\"{value}\",V[c].text):V[c].text,m[c].text=i.text,t=m[c].vector,a=Math.round(t[0])>0?\"left\":Math.round(t[0])<0?\"right\":\"center\",null==o.margin?t=this._mapVector(t,U,1.1):(s=o.margin,d=t[0]>0?s:-s,p=t[1]>0?s:-s,d=0===t[0]?0:d,p=0===t[1]?0:p,t=this._mapVector(t,U,1)),i.textAlign=a,i.x=t[0]+d,i.y=t[1]+p,r=o.rotate?[o.rotate/180*Math.PI,t[0],t[1]]:[0,0,0],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:i,draggable:!1,hoverable:!1,rotation:r})))},getIndicatorText:function(e,t){return this.polar[e]&&this.polar[e].__ecIndicator[t]&&this.polar[e].__ecIndicator[t].text},getDropBox:function(e){var t,i,e=e||0,n=this.polar[e],a=this.getCenter(e),o=n.__ecIndicator,r=o.length,s=[],l=n.type;if(\"polygon\"==l){for(var h=0;r>h;h++)t=o[h].vector,s.push(this._mapVector(t,a,1.2));i=this._getShape(s,\"fill\",\"rgba(0,0,0,0)\",\"\",1)}else\"circle\"==l&&(i=this._getCircle(\"\",1,1.2,a,\"fill\",\"rgba(0,0,0,0)\"));return i},_addArea:function(e,t,i,n,a,o,r){for(var s,l,h,m,V=this.deepQuery(this._queryTarget,\"type\"),U=0;t>U;U++)l=(t-U)/t,r&&(\"polygon\"==V?(m=this._getPointList(e,l,i),s=this._getShape(m,\"stroke\",\"\",a,o)):\"circle\"==V&&(s=this._getCircle(a,o,l,i,\"stroke\")),this.shapeList.push(s)),n.show&&(h=(t-U-1)/t,this._addSplitArea(e,n,l,h,i,U))},_getCircle:function(e,t,i,n,a,o){var s=this._getRadius();return new r({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:s*i,brushType:a,strokeColor:e,lineWidth:t,color:o},hoverable:!1,draggable:!1})},_getRing:function(e,t,i,n){var a=this._getRadius();return new s({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:t*a,r0:i*a,color:e,brushType:\"fill\"},hoverable:!1,draggable:!1})},_getPointList:function(e,t,i){for(var n,a=[],o=e.length,r=0;o>r;r++)n=e[r].vector,a.push(this._mapVector(n,i,t));return a},_getShape:function(e,t,i,n,a){return new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:t,color:i,strokeColor:n,lineWidth:a},hoverable:!1,draggable:!1})},_addSplitArea:function(e,t,i,n,a,o){var r,s,l,h,m,V=e.length,U=t.areaStyle.color,d=[],V=e.length,p=this.deepQuery(this._queryTarget,\"type\");if(\"string\"==typeof U&&(U=[U]),s=U.length,r=U[o%s],\"polygon\"==p)for(var c=0;V>c;c++)d=[],l=e[c].vector,h=e[(c+1)%V].vector,d.push(this._mapVector(l,a,i)),d.push(this._mapVector(l,a,n)),d.push(this._mapVector(h,a,n)),d.push(this._mapVector(h,a,i)),m=this._getShape(d,\"fill\",r,\"\",1),this.shapeList.push(m);else\"circle\"==p&&(m=this._getRing(r,i,n,a),this.shapeList.push(m))},_mapVector:function(e,t,i){return[e[0]*i+t[0],e[1]*i+t[1]]},getCenter:function(e){var e=e||0;return this.parseCenter(this.zr,this.polar[e].center)},_addLine:function(e,t,i){for(var n,a,o=e.length,r=i.lineStyle,s=r.color,l=r.width,h=r.type,m=0;o>m;m++)a=e[m].vector,n=this._getLine(t[0],t[1],a[0]+t[0],a[1]+t[1],s,l,h),this.shapeList.push(n)},_getLine:function(e,t,i,n,o,r,s){return new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:e,yStart:t,xEnd:i,yEnd:n,strokeColor:o,lineWidth:r,lineType:s},hoverable:!1})},_adjustIndicatorValue:function(t){for(var i,n,a,o=this.polar[t],r=this.deepQuery(this._queryTarget,\"indicator\"),s=r.length,l=o.__ecIndicator,h=this._getSeriesData(t),m=o.boundaryGap,V=o.splitNumber,U=o.scale,d=e(\"../util/smartSteps\"),p=0;s>p;p++){if(\"number\"==typeof r[p].max)i=r[p].max,n=r[p].min||0,a={max:i,min:n};else{var c=this._findValue(h,p,V,m);n=c.min,i=c.max}!U&&n>=0&&i>=0&&(n=0),!U&&0>=n&&0>=i&&(i=0);var u=d(n,i,V,a);l[p].value={min:u.min,max:u.max,step:u.step}}},_getSeriesData:function(e){for(var t,i,n,a=[],o=this.component.legend,r=0;r<this.series.length;r++)if(t=this.series[r],t.type==l.CHART_TYPE_RADAR){i=t.data||[];for(var s=0;s<i.length;s++)n=this.deepQuery([i[s],t,this.option],\"polarIndex\")||0,n!=e||o&&!o.isSelected(i[s].name)||a.push(i[s])}return a},_findValue:function(e,t,i,n){function a(e){(e>o||void 0===o)&&(o=e),(r>e||void 0===r)&&(r=e)}var o,r,s;if(e&&0!==e.length){if(1==e.length&&(r=0),1!=e.length)for(var l=0;l<e.length;l++)a(this.getDataFromOption(e[l].value[t]));else{s=e[0];for(var l=0;l<s.value.length;l++)a(this.getDataFromOption(s.value[l]))}var h=Math.abs(o-r);return r-=Math.abs(h*n[0]),o+=Math.abs(h*n[1]),r===o&&(0===o?o=1:o>0?r=o/i:o/=i),{max:o,min:r}}},getVector:function(e,t,i){e=e||0,t=t||0;var n=this.polar[e].__ecIndicator;if(!(t>=n.length)){var a,o=this.polar[e].__ecIndicator[t],r=this.getCenter(e),s=o.vector,l=o.value.max,h=o.value.min;if(\"undefined\"==typeof i)return r;switch(i){case\"min\":i=h;break;case\"max\":i=l;break;case\"center\":i=(l+h)/2}return a=l!=h?(i-h)/(l-h):.5,this._mapVector(s,r,a)}},isInside:function(e){var t=this.getNearestIndex(e);return t?t.polarIndex:-1},getNearestIndex:function(e){for(var t,i,n,a,o,r,s,l,h,V=0;V<this.polar.length;V++){if(t=this.polar[V],i=this.getCenter(V),e[0]==i[0]&&e[1]==i[1])return{polarIndex:V,valueIndex:0};if(n=this._getRadius(),o=t.startAngle,r=t.indicator,s=r.length,l=2*Math.PI/s,a=m.cartesian2polar(e[0]-i[0],i[1]-e[1]),e[0]-i[0]<0&&(a[1]+=Math.PI),a[1]<0&&(a[1]+=2*Math.PI),h=a[1]-o/180*Math.PI+2*Math.PI,Math.abs(Math.cos(h%(l/2)))*n>a[0])return{polarIndex:V,valueIndex:Math.floor((h+l/2)/l)%s}}},getIndicator:function(e){var e=e||0;return this.polar[e].indicator},refresh:function(e){e&&(this.option=e,this.polar=this.option.polar,this.series=this.option.series),this.clear(),this._buildShape()}},h.inherits(t,i),e(\"../component\").define(\"polar\",t),t}),i(\"echarts/util/coordinates\",[\"require\",\"zrender/tool/math\"],function(e){function t(e,t){return[e*n.sin(t),e*n.cos(t)]}function i(e,t){return[Math.sqrt(e*e+t*t),Math.atan(t/e)]}var n=e(\"zrender/tool/math\");return{polar2cartesian:t,cartesian2polar:i}}),i(\"echarts/chart/chord\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Sector\",\"../util/shape/Ribbon\",\"../util/shape/Icon\",\"zrender/shape/BezierCurve\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/vector\",\"../data/Graph\",\"../layout/Chord\",\"../chart\"],function(e){\"use strict\";function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.scaleLineLength=4,this.scaleUnitAngle=4,this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Sector\"),r=e(\"../util/shape/Ribbon\"),s=e(\"../util/shape/Icon\"),l=e(\"zrender/shape/BezierCurve\"),h=e(\"../config\");h.chord={zlevel:0,z:2,clickable:!0,radius:[\"65%\",\"75%\"],center:[\"50%\",\"50%\"],padding:2,sort:\"none\",sortSub:\"none\",startAngle:90,clockWise:!0,ribbonType:!0,minRadius:10,maxRadius:20,symbol:\"circle\",showScale:!1,showScaleText:!1,itemStyle:{normal:{borderWidth:0,borderColor:\"#000\",label:{show:!0,rotate:!1,distance:5},chordStyle:{width:1,color:\"black\",borderWidth:1,borderColor:\"#999\",opacity:.5}},emphasis:{borderWidth:0,borderColor:\"#000\",chordStyle:{width:1,color:\"black\",borderWidth:1,borderColor:\"#999\"}}}};var m=e(\"../util/ecData\"),V=e(\"zrender/tool/util\"),U=e(\"zrender/tool/vector\"),d=e(\"../data/Graph\"),p=e(\"../layout/Chord\");return t.prototype={type:h.CHART_TYPE_CHORD,_init:function(){var e=this.series;this.selectedMap={};for(var t={},i={},n=0,a=e.length;a>n;n++)if(e[n].type===this.type){var o=this.isSelected(e[n].name);this.selectedMap[e[n].name]=o,o&&this.buildMark(n),this.reformOption(e[n]),t[e[n].name]=e[n]}for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type)if(e[n].insertToSerie){var r=t[e[n].insertToSerie];e[n]._referenceSerie=r}else i[e[n].name]=[e[n]];for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type&&e[n].insertToSerie){for(var s=e[n]._referenceSerie;s&&s._referenceSerie;)s=s._referenceSerie;i[s.name]&&this.selectedMap[e[n].name]&&i[s.name].push(e[n])}for(var l in i)this._buildChords(i[l]);this.addShapeList()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t){var i=this._getNodeCategory(e,t);return[t,i,e]},_getEdgeQueryTarget:function(e,t,i){return i=i||\"normal\",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].chordStyle]},_buildChords:function(e){for(var t=[],i=e[0],n=function(e){return e.layout.size>0},a=function(e){return function(t){return e.getEdge(t.node2,t.node1)}},o=0;o<e.length;o++){var r=e[o];if(this.selectedMap[r.name]){var s;r.matrix?s=this._getSerieGraphFromDataMatrix(r,i):r.links&&(s=this._getSerieGraphFromNodeLinks(r,i)),s.filterNode(n,this),r.ribbonType&&s.filterEdge(a(s)),t.push(s),s.__serie=r}}if(t.length){var l=t[0];if(!i.ribbonType){var h=i.minRadius,m=i.maxRadius,V=1/0,U=-(1/0);l.eachNode(function(e){U=Math.max(e.layout.size,U),V=Math.min(e.layout.size,V)});var d=(m-h)/(U-V);l.eachNode(function(e){var t=this._getNodeQueryTarget(i,e),n=this.query(t,\"symbolSize\");e.layout.size=U===V?n||V:n||(e.layout.size-V)*d+h},this)}var c=new p;c.clockWise=i.clockWise,c.startAngle=i.startAngle*Math.PI/180,c.clockWise||(c.startAngle=-c.startAngle),c.padding=i.padding*Math.PI/180,c.sort=i.sort,c.sortSub=i.sortSub,c.directed=i.ribbonType,c.run(t);var u=this.query(i,\"itemStyle.normal.label.show\");if(i.ribbonType){this._buildSectors(i,0,l,i,t),u&&this._buildLabels(i,0,l,i,t);for(var o=0,y=0;o<e.length;o++)this.selectedMap[e[o].name]&&this._buildRibbons(e,o,t[y++],i);i.showScale&&this._buildScales(i,0,l)}else{this._buildNodeIcons(i,0,l,i,t),u&&this._buildLabels(i,0,l,i,t);for(var o=0,y=0;o<e.length;o++)this.selectedMap[e[o].name]&&this._buildEdgeCurves(e,o,t[y++],i,l)}this._initHoverHandler(e,t)}},_getSerieGraphFromDataMatrix:function(e,t){for(var i=[],n=0,a=[],o=0;o<e.matrix.length;o++)a[o]=e.matrix[o].slice();for(var r=e.data||e.nodes,o=0;o<r.length;o++){var s={},l=r[o];l.rawIndex=o;for(var h in l)\"name\"===h?s.id=l.name:s[h]=l[h];var m=this._getNodeCategory(t,l),V=m?m.name:l.name;if(this.selectedMap[V]=this.isSelected(V),this.selectedMap[V])i.push(s),n++;else{a.splice(n,1);for(var U=0;U<a.length;U++)a[U].splice(n,1)}}var p=d.fromMatrix(i,a,!0);return p.eachNode(function(e){e.layout={size:e.data.outValue},e.rawIndex=e.data.rawIndex}),p.eachEdge(function(e){e.layout={weight:e.data.weight}}),p},_getSerieGraphFromNodeLinks:function(e,t){for(var i=new d(!0),n=e.data||e.nodes,a=0,o=n.length;o>a;a++){var r=n[a];if(r&&!r.ignore){var s=this._getNodeCategory(t,r),l=s?s.name:r.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=i.addNode(r.name,r);h.rawIndex=a}}}for(var a=0,o=e.links.length;o>a;a++){var m=e.links[a],V=m.source,U=m.target;\"number\"==typeof V&&(V=n[V],V&&(V=V.name)),\"number\"==typeof U&&(U=n[U],U&&(U=U.name));var p=i.addEdge(V,U,m);p&&(p.rawIndex=a)}return i.eachNode(function(e){var i=e.data.value;if(null==i)if(i=0,t.ribbonType)for(var n=0;n<e.outEdges.length;n++)i+=e.outEdges[n].data.weight||0;else for(var n=0;n<e.edges.length;n++)i+=e.edges[n].data.weight||0;e.layout={size:i}}),i.eachEdge(function(e){e.layout={weight:null==e.data.weight?1:e.data.weight}}),i},_initHoverHandler:function(e,t){var i=e[0],n=t[0],a=this;n.eachNode(function(e){e.shape.onmouseover=function(){n.eachNode(function(e){e.shape.style.opacity=.1,e.labelShape&&(e.labelShape.style.opacity=.1,e.labelShape.modSelf()),e.shape.modSelf()});for(var i=0;i<t.length;i++)for(var o=0;o<t[i].edges.length;o++){var r=t[i].edges[o],s=a._getEdgeQueryTarget(t[i].__serie,r.data);r.shape.style.opacity=.1*a.deepQuery(s,\"opacity\"),r.shape.modSelf()}e.shape.style.opacity=1,e.labelShape&&(e.labelShape.style.opacity=1);for(var i=0;i<t.length;i++){var l=t[i].getNodeById(e.id);if(l)for(var o=0;o<l.outEdges.length;o++){var r=l.outEdges[o],s=a._getEdgeQueryTarget(t[i].__serie,r.data);r.shape.style.opacity=a.deepQuery(s,\"opacity\");var h=t[0].getNodeById(r.node2.id);h&&(h.shape&&(h.shape.style.opacity=1),h.labelShape&&(h.labelShape.style.opacity=1))}}a.zr.refreshNextFrame()},e.shape.onmouseout=function(){n.eachNode(function(e){e.shape.style.opacity=1,e.labelShape&&(e.labelShape.style.opacity=1,e.labelShape.modSelf()),e.shape.modSelf()});for(var e=0;e<t.length;e++)for(var o=0;o<t[e].edges.length;o++){var r=t[e].edges[o],s=[r.data,i];r.shape.style.opacity=a.deepQuery(s,\"itemStyle.normal.chordStyle.opacity\"),r.shape.modSelf()}a.zr.refreshNextFrame()}})},_buildSectors:function(e,t,i,n){var a=this.parseCenter(this.zr,n.center),r=this.parseRadius(this.zr,n.radius),s=n.clockWise,l=s?1:-1;i.eachNode(function(i){var h=this._getNodeCategory(n,i.data),V=this.getColor(h?h.name:i.id),U=i.layout.startAngle/Math.PI*180*l,d=i.layout.endAngle/Math.PI*180*l,p=new o({zlevel:e.zlevel,z:e.z,style:{x:a[0],y:a[1],r0:r[0],r:r[1],startAngle:U,endAngle:d,brushType:\"fill\",opacity:1,color:V,clockWise:s},clickable:n.clickable,highlightStyle:{brushType:\"fill\"}});p.style.lineWidth=this.deepQuery([i.data,n],\"itemStyle.normal.borderWidth\"),p.highlightStyle.lineWidth=this.deepQuery([i.data,n],\"itemStyle.emphasis.borderWidth\"),p.style.strokeColor=this.deepQuery([i.data,n],\"itemStyle.normal.borderColor\"),p.highlightStyle.strokeColor=this.deepQuery([i.data,n],\"itemStyle.emphasis.borderColor\"),p.style.lineWidth>0&&(p.style.brushType=\"both\"),p.highlightStyle.lineWidth>0&&(p.highlightStyle.brushType=\"both\"),m.pack(p,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(p),i.shape=p},this)},_buildNodeIcons:function(e,t,i,n){var a=this.parseCenter(this.zr,n.center),o=this.parseRadius(this.zr,n.radius),r=o[1];i.eachNode(function(i){var o=i.layout.startAngle,l=i.layout.endAngle,h=(o+l)/2,V=r*Math.cos(h),U=r*Math.sin(h),d=this._getNodeQueryTarget(n,i.data),p=this._getNodeCategory(n,i.data),c=this.deepQuery(d,\"itemStyle.normal.color\");c||(c=this.getColor(p?p.name:i.id));var u=new s({zlevel:e.zlevel,z:e.z+1,style:{x:-i.layout.size,y:-i.layout.size,width:2*i.layout.size,height:2*i.layout.size,iconType:this.deepQuery(d,\"symbol\"),color:c,brushType:\"both\",lineWidth:this.deepQuery(d,\"itemStyle.normal.borderWidth\"),strokeColor:this.deepQuery(d,\"itemStyle.normal.borderColor\")},highlightStyle:{color:this.deepQuery(d,\"itemStyle.emphasis.color\"),lineWidth:this.deepQuery(d,\"itemStyle.emphasis.borderWidth\"),strokeColor:this.deepQuery(d,\"itemStyle.emphasis.borderColor\")},clickable:n.clickable,position:[V+a[0],U+a[1]]});m.pack(u,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(u),i.shape=u},this)},_buildLabels:function(e,t,i,a){var o=this.query(a,\"itemStyle.normal.label.rotate\"),r=this.query(a,\"itemStyle.normal.label.distance\"),s=this.parseCenter(this.zr,a.center),l=this.parseRadius(this.zr,a.radius),h=a.clockWise,m=h?1:-1;\n\ni.eachNode(function(t){var i=t.layout.startAngle/Math.PI*180*m,h=t.layout.endAngle/Math.PI*180*m,V=(i*-m+h*-m)/2;V%=360,0>V&&(V+=360);var d=90>=V||V>=270;V=V*Math.PI/180;var p=[Math.cos(V),-Math.sin(V)],c=0;c=a.ribbonType?a.showScaleText?35+r:r:r+t.layout.size;var u=U.scale([],p,l[1]+c);U.add(u,u,s);var y={zlevel:e.zlevel,z:e.z+1,hoverable:!1,style:{text:null==t.data.label?t.id:t.data.label,textAlign:d?\"left\":\"right\"}};o?(y.rotation=d?V:Math.PI+V,y.style.x=d?l[1]+c:-l[1]-c,y.style.y=0,y.position=s.slice()):(y.style.x=u[0],y.style.y=u[1]),y.style.color=this.deepQuery([t.data,a],\"itemStyle.normal.label.textStyle.color\")||\"#000000\",y.style.textFont=this.getFont(this.deepQuery([t.data,a],\"itemStyle.normal.label.textStyle\")),y=new n(y),this.shapeList.push(y),t.labelShape=y},this)},_buildRibbons:function(e,t,i,n){var a=e[t],o=this.parseCenter(this.zr,n.center),s=this.parseRadius(this.zr,n.radius);i.eachEdge(function(l,h){var V,U=i.getEdge(l.node2,l.node1);if(U&&!l.shape){if(U.shape)return void(l.shape=U.shape);var d=l.layout.startAngle/Math.PI*180,p=l.layout.endAngle/Math.PI*180,c=U.layout.startAngle/Math.PI*180,u=U.layout.endAngle/Math.PI*180;V=this.getColor(1===e.length?l.layout.weight<=U.layout.weight?l.node1.id:l.node2.id:a.name);var y,g,b=this._getEdgeQueryTarget(a,l.data),f=this._getEdgeQueryTarget(a,l.data,\"emphasis\"),k=new r({zlevel:a.zlevel,z:a.z,style:{x:o[0],y:o[1],r:s[0],source0:d,source1:p,target0:c,target1:u,brushType:\"both\",opacity:this.deepQuery(b,\"opacity\"),color:V,lineWidth:this.deepQuery(b,\"borderWidth\"),strokeColor:this.deepQuery(b,\"borderColor\"),clockWise:n.clockWise},clickable:n.clickable,highlightStyle:{brushType:\"both\",opacity:this.deepQuery(f,\"opacity\"),lineWidth:this.deepQuery(f,\"borderWidth\"),strokeColor:this.deepQuery(f,\"borderColor\")}});l.layout.weight<=U.layout.weight?(y=U.node1,g=U.node2):(y=l.node1,g=l.node2),m.pack(k,a,t,l.data,null==l.rawIndex?h:l.rawIndex,l.data.name||y.id+\"-\"+g.id,y.id,g.id),this.shapeList.push(k),l.shape=k}},this)},_buildEdgeCurves:function(e,t,i,n,a){var o=e[t],r=this.parseCenter(this.zr,n.center);i.eachEdge(function(e,i){var n=a.getNodeById(e.node1.id),s=a.getNodeById(e.node2.id),h=n.shape,V=s.shape,U=this._getEdgeQueryTarget(o,e.data),d=this._getEdgeQueryTarget(o,e.data,\"emphasis\"),p=new l({zlevel:o.zlevel,z:o.z,style:{xStart:h.position[0],yStart:h.position[1],xEnd:V.position[0],yEnd:V.position[1],cpX1:r[0],cpY1:r[1],lineWidth:this.deepQuery(U,\"width\"),strokeColor:this.deepQuery(U,\"color\"),opacity:this.deepQuery(U,\"opacity\")},highlightStyle:{lineWidth:this.deepQuery(d,\"width\"),strokeColor:this.deepQuery(d,\"color\"),opacity:this.deepQuery(d,\"opacity\")}});m.pack(p,o,t,e.data,null==e.rawIndex?i:e.rawIndex,e.data.name||e.node1.id+\"-\"+e.node2.id,e.node1.id,e.node2.id),this.shapeList.push(p),e.shape=p},this)},_buildScales:function(e,t,i){var o,r,s=e.clockWise,l=this.parseCenter(this.zr,e.center),h=this.parseRadius(this.zr,e.radius),m=s?1:-1,V=0,d=-(1/0);e.showScaleText&&(i.eachNode(function(e){var t=e.data.value;t>d&&(d=t),V+=t}),d>1e10?(o=\"b\",r=1e-9):d>1e7?(o=\"m\",r=1e-6):d>1e4?(o=\"k\",r=.001):(o=\"\",r=1));var p=V/(360-e.padding);i.eachNode(function(t){for(var i=t.layout.startAngle/Math.PI*180,V=t.layout.endAngle/Math.PI*180,d=i;;){if(s&&d>V||!s&&V>d)break;var c=d/180*Math.PI,u=[Math.cos(c),Math.sin(c)],y=U.scale([],u,h[1]+1);U.add(y,y,l);var g=U.scale([],u,h[1]+this.scaleLineLength);U.add(g,g,l);var b=new a({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{xStart:y[0],yStart:y[1],xEnd:g[0],yEnd:g[1],lineCap:\"round\",brushType:\"stroke\",strokeColor:\"#666\",lineWidth:1}});this.shapeList.push(b),d+=m*this.scaleUnitAngle}if(e.showScaleText)for(var f=i,k=5*p*this.scaleUnitAngle,x=0;;){if(s&&f>V||!s&&V>f)break;var c=f;c%=360,0>c&&(c+=360);var _=90>=c||c>=270,L=new n({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{x:_?h[1]+this.scaleLineLength+4:-h[1]-this.scaleLineLength-4,y:0,text:Math.round(10*x)/10+o,textAlign:_?\"left\":\"right\"},position:l.slice(),rotation:_?[-c/180*Math.PI,0,0]:[-(c+180)/180*Math.PI,0,0]});this.shapeList.push(L),x+=k*r,f+=m*this.scaleUnitAngle*5}},this)},refresh:function(e){if(e&&(this.option=e,this.series=e.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this.backupShapeList(),this._init()},reformOption:function(e){var t=V.merge;e=t(t(e||{},this.ecTheme.chord),h.chord),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),this.z=e.z,this.zlevel=e.zlevel}},V.inherits(t,i),e(\"../chart\").define(\"chord\",t),t}),i(\"echarts/util/shape/Ribbon\",[\"require\",\"zrender/shape/Base\",\"zrender/shape/util/PathProxy\",\"zrender/tool/util\",\"zrender/tool/area\"],function(e){function t(e){i.call(this,e),this._pathProxy=new n}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/shape/util/PathProxy\"),a=e(\"zrender/tool/util\"),o=e(\"zrender/tool/area\");return t.prototype={type:\"ribbon\",buildPath:function(e,t){var i=t.clockWise||!1,n=this._pathProxy;n.begin(e);var a=t.x,o=t.y,r=t.r,s=t.source0/180*Math.PI,l=t.source1/180*Math.PI,h=t.target0/180*Math.PI,m=t.target1/180*Math.PI,V=a+Math.cos(s)*r,U=o+Math.sin(s)*r,d=a+Math.cos(l)*r,p=o+Math.sin(l)*r,c=a+Math.cos(h)*r,u=o+Math.sin(h)*r,y=a+Math.cos(m)*r,g=o+Math.sin(m)*r;n.moveTo(V,U),n.arc(a,o,t.r,s,l,!i),n.bezierCurveTo(.7*(a-d)+d,.7*(o-p)+p,.7*(a-c)+c,.7*(o-u)+u,c,u),(t.source0!==t.target0||t.source1!==t.target1)&&(n.arc(a,o,t.r,h,m,!i),n.bezierCurveTo(.7*(a-y)+y,.7*(o-g)+g,.7*(a-V)+V,.7*(o-U)+U,V,U))},getRect:function(e){return e.__rect?e.__rect:(this._pathProxy.isEmpty()||this.buildPath(null,e),this._pathProxy.fastBoundingRect())},isCover:function(e,t){var i=this.getRect(this.style);return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?o.isInsidePath(this._pathProxy.pathCommands,0,\"fill\",e,t):void 0}},a.inherits(t,i),t}),i(\"echarts/data/Graph\",[\"require\",\"zrender/tool/util\"],function(e){var t=e(\"zrender/tool/util\"),i=function(e){this._directed=e||!1,this.nodes=[],this.edges=[],this._nodesMap={},this._edgesMap={}};i.prototype.isDirected=function(){return this._directed},i.prototype.addNode=function(e,t){if(this._nodesMap[e])return this._nodesMap[e];var n=new i.Node(e,t);return this.nodes.push(n),this._nodesMap[e]=n,n},i.prototype.getNodeById=function(e){return this._nodesMap[e]},i.prototype.addEdge=function(e,t,n){if(\"string\"==typeof e&&(e=this._nodesMap[e]),\"string\"==typeof t&&(t=this._nodesMap[t]),e&&t){var a=e.id+\"-\"+t.id;if(this._edgesMap[a])return this._edgesMap[a];var o=new i.Edge(e,t,n);return this._directed&&(e.outEdges.push(o),t.inEdges.push(o)),e.edges.push(o),e!==t&&t.edges.push(o),this.edges.push(o),this._edgesMap[a]=o,o}},i.prototype.removeEdge=function(e){var i=e.node1,n=e.node2,a=i.id+\"-\"+n.id;this._directed&&(i.outEdges.splice(t.indexOf(i.outEdges,e),1),n.inEdges.splice(t.indexOf(n.inEdges,e),1)),i.edges.splice(t.indexOf(i.edges,e),1),i!==n&&n.edges.splice(t.indexOf(n.edges,e),1),delete this._edgesMap[a],this.edges.splice(t.indexOf(this.edges,e),1)},i.prototype.getEdge=function(e,t){return\"string\"!=typeof e&&(e=e.id),\"string\"!=typeof t&&(t=t.id),this._directed?this._edgesMap[e+\"-\"+t]:this._edgesMap[e+\"-\"+t]||this._edgesMap[t+\"-\"+e]},i.prototype.removeNode=function(e){if(\"string\"!=typeof e||(e=this._nodesMap[e])){delete this._nodesMap[e.id],this.nodes.splice(t.indexOf(this.nodes,e),1);for(var i=0;i<this.edges.length;){var n=this.edges[i];n.node1===e||n.node2===e?this.removeEdge(n):i++}}},i.prototype.filterNode=function(e,t){for(var i=this.nodes.length,n=0;i>n;)e.call(t,this.nodes[n],n)?n++:(this.removeNode(this.nodes[n]),i--)},i.prototype.filterEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;)e.call(t,this.edges[n],n)?n++:(this.removeEdge(this.edges[n]),i--)},i.prototype.eachNode=function(e,t){for(var i=this.nodes.length,n=0;i>n;n++)this.nodes[n]&&e.call(t,this.nodes[n],n)},i.prototype.eachEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;n++)this.edges[n]&&e.call(t,this.edges[n],n)},i.prototype.clear=function(){this.nodes.length=0,this.edges.length=0,this._nodesMap={},this._edgesMap={}},i.prototype.breadthFirstTraverse=function(e,t,i,n){if(\"string\"==typeof t&&(t=this._nodesMap[t]),t){var a=\"edges\";\"out\"===i?a=\"outEdges\":\"in\"===i&&(a=\"inEdges\");for(var o=0;o<this.nodes.length;o++)this.nodes[o].__visited=!1;if(!e.call(n,t,null))for(var r=[t];r.length;)for(var s=r.shift(),l=s[a],o=0;o<l.length;o++){var h=l[o],m=h.node1===s?h.node2:h.node1;if(!m.__visited){if(e.call(m,m,s))return;r.push(m),m.__visited=!0}}}},i.prototype.clone=function(){for(var e=new i(this._directed),t=0;t<this.nodes.length;t++)e.addNode(this.nodes[t].id,this.nodes[t].data);for(var t=0;t<this.edges.length;t++){var n=this.edges[t];e.addEdge(n.node1.id,n.node2.id,n.data)}return e};var n=function(e,t){this.id=e,this.data=t||null,this.inEdges=[],this.outEdges=[],this.edges=[]};n.prototype.degree=function(){return this.edges.length},n.prototype.inDegree=function(){return this.inEdges.length},n.prototype.outDegree=function(){return this.outEdges.length};var a=function(e,t,i){this.node1=e,this.node2=t,this.data=i||null};return i.Node=n,i.Edge=a,i.fromMatrix=function(e,t,n){if(t&&t.length&&t[0].length===t.length&&e.length===t.length){for(var a=t.length,o=new i(n),r=0;a>r;r++){var s=o.addNode(e[r].id,e[r]);s.data.value=0,n&&(s.data.outValue=s.data.inValue=0)}for(var r=0;a>r;r++)for(var l=0;a>l;l++){var h=t[r][l];n&&(o.nodes[r].data.outValue+=h,o.nodes[l].data.inValue+=h),o.nodes[r].data.value+=h,o.nodes[l].data.value+=h}for(var r=0;a>r;r++)for(var l=r;a>l;l++){var h=t[r][l];if(0!==h){var m=o.nodes[r],V=o.nodes[l],U=o.addEdge(m,V,{});if(U.data.weight=h,r!==l&&n&&t[l][r]){var d=o.addEdge(V,m,{});d.data.weight=t[l][r]}}}return o}},i}),i(\"echarts/layout/Chord\",[\"require\"],function(){var e=function(e){e=e||{},this.sort=e.sort||null,this.sortSub=e.sortSub||null,this.padding=.05,this.startAngle=e.startAngle||0,this.clockWise=null==e.clockWise?!1:e.clockWise,this.center=e.center||[0,0],this.directed=!0};e.prototype.run=function(e){e instanceof Array||(e=[e]);var n=e.length;if(n){for(var a=e[0],o=a.nodes.length,r=[],s=0,l=0;o>l;l++){var h=a.nodes[l],m={size:0,subGroups:[],node:h};r.push(m);for(var V=0,U=0;U<e.length;U++){var d=e[U],p=d.getNodeById(h.id);if(p){m.size+=p.layout.size;for(var c=this.directed?p.outEdges:p.edges,u=0;u<c.length;u++){var y=c[u],g=y.layout.weight;m.subGroups.push({weight:g,edge:y,graph:d}),V+=g}}}s+=m.size;for(var b=m.size/V,u=0;u<m.subGroups.length;u++)m.subGroups[u].weight*=b;\"ascending\"===this.sortSub?m.subGroups.sort(t):\"descending\"===this.sort&&(m.subGroups.sort(t),m.subGroups.reverse())}\"ascending\"===this.sort?r.sort(i):\"descending\"===this.sort&&(r.sort(i),r.reverse());for(var b=(2*Math.PI-this.padding*o)/s,f=this.startAngle,k=this.clockWise?1:-1,l=0;o>l;l++){var m=r[l];m.node.layout.startAngle=f,m.node.layout.endAngle=f+k*m.size*b,m.node.layout.subGroups=[];for(var u=0;u<m.subGroups.length;u++){var x=m.subGroups[u];x.edge.layout.startAngle=f,f+=k*x.weight*b,x.edge.layout.endAngle=f}f=m.node.layout.endAngle+k*this.padding}}};var t=function(e,t){return e.weight-t.weight},i=function(e,t){return e.size-t.size};return e}),i(\"echarts/chart/force\",[\"require\",\"./base\",\"../data/Graph\",\"../layout/Force\",\"zrender/shape/Line\",\"zrender/shape/BezierCurve\",\"zrender/shape/Image\",\"../util/shape/Icon\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/config\",\"zrender/tool/vector\",\"../chart\"],function(e){\"use strict\";function t(e,t,o,h,m){var V=this;r.call(this,e,t,o,h,m),this.__nodePositionMap={},this._graph=new s(!0),this._layout=new l,this._layout.onupdate=function(){V._step()},this._steps=1,this.ondragstart=function(){i.apply(V,arguments)},this.ondragend=function(){a.apply(V,arguments)},this.ondrop=function(){},this.shapeHandler.ondragstart=function(){V.isDragstart=!0},this.onmousemove=function(){n.apply(V,arguments)},this.refresh(h)}function i(e){if(this.isDragstart&&e.target){var t=e.target;t.fixed=!0,this.isDragstart=!1,this.zr.on(u.EVENT.MOUSEMOVE,this.onmousemove)}}function n(){this._layout.temperature=.8,this._step()}function a(e,t){if(this.isDragend&&e.target){var i=e.target;i.fixed=!1,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1,this.zr.un(u.EVENT.MOUSEMOVE,this.onmousemove)}}function o(e,t,i){var n=y.create();return n[0]=(Math.random()-.5)*i+e,n[1]=(Math.random()-.5)*i+t,n}var r=e(\"./base\"),s=e(\"../data/Graph\"),l=e(\"../layout/Force\"),h=e(\"zrender/shape/Line\"),m=e(\"zrender/shape/BezierCurve\"),V=e(\"zrender/shape/Image\"),U=e(\"../util/shape/Icon\"),d=e(\"../config\");d.force={zlevel:1,z:2,center:[\"50%\",\"50%\"],size:\"100%\",preventOverlap:!1,coolDown:.99,minRadius:10,maxRadius:20,ratioScaling:!1,large:!1,useWorker:!1,steps:1,scaling:1,gravity:1,symbol:\"circle\",symbolSize:0,linkSymbol:null,linkSymbolSize:[10,15],draggable:!0,clickable:!0,roam:!1,itemStyle:{normal:{label:{show:!1,position:\"inside\"},nodeStyle:{brushType:\"both\",borderColor:\"#5182ab\",borderWidth:1},linkStyle:{color:\"#5182ab\",width:1,type:\"line\"}},emphasis:{label:{show:!1},nodeStyle:{},linkStyle:{opacity:0}}}};var p=e(\"../util/ecData\"),c=e(\"zrender/tool/util\"),u=e(\"zrender/config\"),y=e(\"zrender/tool/vector\");return t.prototype={constructor:t,type:d.CHART_TYPE_FORCE,_init:function(){this.selectedMap={};var e,t=this.component.legend,i=this.series;this.clear();for(var n=0,a=i.length;a>n;n++){var o=i[n];if(o.type===d.CHART_TYPE_FORCE){if(i[n]=this.reformOption(i[n]),e=i[n].name||\"\",this.selectedMap[e]=t?t.isSelected(e):!0,!this.selectedMap[e])continue;this.buildMark(n),this._initSerie(o,n);break}}this.animationEffect()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t,i){i=i||\"normal\";var n=this._getNodeCategory(e,t)||{};return[t.itemStyle&&t.itemStyle[i],n&&n.itemStyle&&n.itemStyle[i],e.itemStyle[i].nodeStyle]},_getEdgeQueryTarget:function(e,t,i){return i=i||\"normal\",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].linkStyle]},_initSerie:function(e,t){this._temperature=1,e.matrix?this._graph=this._getSerieGraphFromDataMatrix(e):e.links&&(this._graph=this._getSerieGraphFromNodeLinks(e)),this._buildLinkShapes(e,t),this._buildNodeShapes(e,t);var i=e.roam===!0||\"move\"===e.roam,n=e.roam===!0||\"scale\"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:i,zoomable:n}),(this.query(\"markPoint.effect.show\")||this.query(\"markLine.effect.show\"))&&this.zr.modLayer(d.EFFECT_ZLEVEL,{panable:i,zoomable:n}),this._initLayout(e),this._step()},_getSerieGraphFromDataMatrix:function(e){for(var t=[],i=0,n=[],a=0;a<e.matrix.length;a++)n[a]=e.matrix[a].slice();for(var o=e.data||e.nodes,a=0;a<o.length;a++){var r={},l=o[a];for(var h in l)\"name\"===h?r.id=l.name:r[h]=l[h];var m=this._getNodeCategory(e,l),V=m?m.name:l.name;if(this.selectedMap[V]=this.isSelected(V),this.selectedMap[V])t.push(r),i++;else{n.splice(i,1);for(var U=0;U<n.length;U++)n[U].splice(i,1)}}var d=s.fromMatrix(t,n,!0);return d.eachNode(function(e,t){e.layout={size:e.data.value,mass:0},e.rawIndex=t}),d.eachEdge(function(e){e.layout={weight:e.data.weight}}),d},_getSerieGraphFromNodeLinks:function(e){for(var t=new s(!0),i=e.data||e.nodes,n=0,a=i.length;a>n;n++){var o=i[n];if(o&&!o.ignore){var r=this._getNodeCategory(e,o),l=r?r.name:o.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=t.addNode(o.name,o);h.rawIndex=n}}}for(var n=0,a=e.links.length;a>n;n++){var m=e.links[n],V=m.source,U=m.target;\"number\"==typeof V&&(V=i[V],V&&(V=V.name)),\"number\"==typeof U&&(U=i[U],U&&(U=U.name));var d=t.addEdge(V,U,m);d&&(d.rawIndex=n)}return t.eachNode(function(e){var t=e.data.value;if(null==t){t=0;for(var i=0;i<e.edges.length;i++)t+=e.edges[i].data.weight||0}e.layout={size:t,mass:0}}),t.eachEdge(function(e){e.layout={weight:null==e.data.weight?1:e.data.weight}}),t},_initLayout:function(e){var t=this._graph,i=t.nodes.length,n=this.query(e,\"minRadius\"),a=this.query(e,\"maxRadius\");this._steps=e.steps||1;var r=this._layout;r.center=this.parseCenter(this.zr,e.center),r.width=this.parsePercent(e.size,this.zr.getWidth()),r.height=this.parsePercent(e.size,this.zr.getHeight()),r.large=e.large,r.scaling=e.scaling,r.ratioScaling=e.ratioScaling,r.gravity=e.gravity,r.temperature=1,r.coolDown=e.coolDown,r.preventNodeEdgeOverlap=e.preventOverlap,r.preventNodeOverlap=e.preventOverlap;for(var s=1/0,l=-(1/0),h=0;i>h;h++){var m=t.nodes[h];l=Math.max(m.layout.size,l),s=Math.min(m.layout.size,s)}for(var V=l-s,h=0;i>h;h++){var m=t.nodes[h];V>0?(m.layout.size=(m.layout.size-s)*(a-n)/V+n,m.layout.mass=m.layout.size/a):(m.layout.size=(a-n)/2,m.layout.mass=.5)}for(var h=0;i>h;h++){var m=t.nodes[h];if(\"undefined\"!=typeof this.__nodePositionMap[m.id])m.layout.position=y.create(),y.copy(m.layout.position,this.__nodePositionMap[m.id]);else if(\"undefined\"!=typeof m.data.initial)m.layout.position=y.create(),y.copy(m.layout.position,m.data.initial);else{var U=this._layout.center,d=Math.min(this._layout.width,this._layout.height);m.layout.position=o(U[0],U[1],.8*d)}var p=m.shape.style,c=m.layout.size;p.width=p.width||2*c,p.height=p.height||2*c,p.x=-p.width/2,p.y=-p.height/2,y.copy(m.shape.position,m.layout.position)}i=t.edges.length,l=-(1/0);for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight>l&&(l=u.layout.weight)}for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight/=l}this._layout.init(t,e.useWorker)},_buildNodeShapes:function(e,t){var i=this._graph,n=this.query(e,\"categories\");i.eachNode(function(i){var a=this._getNodeCategory(e,i.data),o=[i.data,a,e],r=this._getNodeQueryTarget(e,i.data),s=this._getNodeQueryTarget(e,i.data,\"emphasis\"),l=new U({style:{x:0,y:0,color:this.deepQuery(r,\"color\"),brushType:\"both\",strokeColor:this.deepQuery(r,\"strokeColor\")||this.deepQuery(r,\"borderColor\"),lineWidth:this.deepQuery(r,\"lineWidth\")||this.deepQuery(r,\"borderWidth\")},highlightStyle:{color:this.deepQuery(s,\"color\"),strokeColor:this.deepQuery(s,\"strokeColor\")||this.deepQuery(s,\"borderColor\"),lineWidth:this.deepQuery(s,\"lineWidth\")||this.deepQuery(s,\"borderWidth\")},clickable:e.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()});l.style.color||(l.style.color=this.getColor(a?a.name:i.id)),l.style.iconType=this.deepQuery(o,\"symbol\");var h=this.deepQuery(o,\"symbolSize\")||0;\"number\"==typeof h&&(h=[h,h]),l.style.width=2*h[0],l.style.height=2*h[1],l.style.iconType.match(\"image\")&&(l.style.image=l.style.iconType.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),l=new V({style:l.style,highlightStyle:l.highlightStyle,clickable:l.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(o,\"itemStyle.normal.label.show\")&&(l.style.text=null==i.data.label?i.id:i.data.label,l.style.textPosition=this.deepQuery(o,\"itemStyle.normal.label.position\"),l.style.textColor=this.deepQuery(o,\"itemStyle.normal.label.textStyle.color\"),l.style.textFont=this.getFont(this.deepQuery(o,\"itemStyle.normal.label.textStyle\")||{})),this.deepQuery(o,\"itemStyle.emphasis.label.show\")&&(l.highlightStyle.textPosition=this.deepQuery(o,\"itemStyle.emphasis.label.position\"),l.highlightStyle.textColor=this.deepQuery(o,\"itemStyle.emphasis.label.textStyle.color\"),l.highlightStyle.textFont=this.getFont(this.deepQuery(o,\"itemStyle.emphasis.label.textStyle\")||{})),this.deepQuery(o,\"draggable\")&&(this.setCalculable(l),l.dragEnableTime=0,l.draggable=!0,l.ondragstart=this.shapeHandler.ondragstart,l.ondragover=null);var m=\"\";if(\"undefined\"!=typeof i.category){var a=n[i.category];m=a&&a.name||\"\"}p.pack(l,e,t,i.data,i.rawIndex,i.data.name||\"\",i.category),this.shapeList.push(l),this.zr.addShape(l),i.shape=l},this)},_buildLinkShapes:function(e,t){for(var i=this._graph,n=i.edges.length,a=0;n>a;a++){var o=i.edges[a],r=o.data,s=o.node1,l=o.node2,V=i.getEdge(l,s),d=this._getEdgeQueryTarget(e,r),u=this.deepQuery(d,\"type\");e.linkSymbol&&\"none\"!==e.linkSymbol&&(u=\"line\");var y=\"line\"===u?h:m,g=new y({style:{xStart:0,yStart:0,xEnd:0,yEnd:0},clickable:this.query(e,\"clickable\"),highlightStyle:{},zlevel:this.getZlevelBase(),z:this.getZBase()});if(V&&V.shape&&(g.style.offset=4,V.shape.style.offset=4),c.merge(g.style,this.query(e,\"itemStyle.normal.linkStyle\"),!0),c.merge(g.highlightStyle,this.query(e,\"itemStyle.emphasis.linkStyle\"),!0),\"undefined\"!=typeof r.itemStyle&&(r.itemStyle.normal&&c.merge(g.style,r.itemStyle.normal,!0),r.itemStyle.emphasis&&c.merge(g.highlightStyle,r.itemStyle.emphasis,!0)),g.style.lineWidth=g.style.lineWidth||g.style.width,g.style.strokeColor=g.style.strokeColor||g.style.color,g.highlightStyle.lineWidth=g.highlightStyle.lineWidth||g.highlightStyle.width,g.highlightStyle.strokeColor=g.highlightStyle.strokeColor||g.highlightStyle.color,p.pack(g,e,t,o.data,null==o.rawIndex?a:o.rawIndex,o.data.name||s.id+\" - \"+l.id,s.id,l.id),this.shapeList.push(g),this.zr.addShape(g),o.shape=g,e.linkSymbol&&\"none\"!==e.linkSymbol){var b=new U({style:{x:-5,y:0,width:e.linkSymbolSize[0],height:e.linkSymbolSize[1],iconType:e.linkSymbol,brushType:\"fill\",color:g.style.strokeColor},highlightStyle:{brushType:\"fill\"},position:[0,0],rotation:0,zlevel:this.getZlevelBase(),z:this.getZBase()});g._symbolShape=b,this.shapeList.push(b),this.zr.addShape(b)}}},_updateLinkShapes:function(){for(var e=y.create(),t=y.create(),i=y.create(),n=y.create(),a=this._graph.edges,o=0,r=a.length;r>o;o++){var s=a[o],l=s.node1.shape,h=s.node2.shape;y.copy(i,l.position),y.copy(n,h.position);var m=s.shape.style;if(y.sub(e,i,n),y.normalize(e,e),m.offset?(t[0]=e[1],t[1]=-e[0],y.scaleAndAdd(i,i,t,m.offset),y.scaleAndAdd(n,n,t,m.offset)):\"bezier-curve\"===s.shape.type&&(m.cpX1=(i[0]+n[0])/2-(n[1]-i[1])/4,m.cpY1=(i[1]+n[1])/2-(i[0]-n[0])/4),m.xStart=i[0],m.yStart=i[1],m.xEnd=n[0],m.yEnd=n[1],s.shape.modSelf(),s.shape._symbolShape){var V=s.shape._symbolShape;y.copy(V.position,n),y.scaleAndAdd(V.position,V.position,e,h.style.width/2+2);var U=Math.atan2(e[1],e[0]);V.rotation=Math.PI/2-U,V.modSelf()}}},_syncNodePositions:function(){for(var e=this._graph,t=0;t<e.nodes.length;t++){var i=e.nodes[t],n=i.layout.position,a=i.data,o=i.shape,r=o.fixed||a.fixX,s=o.fixed||a.fixY;r===!0?r=1:isNaN(r)&&(r=0),s===!0?s=1:isNaN(s)&&(s=0),o.position[0]+=(n[0]-o.position[0])*(1-r),o.position[1]+=(n[1]-o.position[1])*(1-s),y.copy(n,o.position);var l=a.name;if(l){var h=this.__nodePositionMap[l];h||(h=this.__nodePositionMap[l]=y.create()),y.copy(h,n)}o.modSelf()}},_step:function(){this._syncNodePositions(),this._updateLinkShapes(),this.zr.refreshNextFrame(),this._layout.temperature>.01?this._layout.step(this._steps):this.messageCenter.dispatch(d.EVENT.FORCE_LAYOUT_END,{},{},this.myChart)},refresh:function(e){if(e&&(this.option=e,this.series=this.option.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this._init()},dispose:function(){this.clear(),this.shapeList=null,this.effectList=null,this._layout.dispose(),this._layout=null,this.__nodePositionMap={}},getPosition:function(){var e=[];return this._graph.eachNode(function(t){t.layout&&e.push({name:t.data.name,position:Array.prototype.slice.call(t.layout.position)})}),e}},c.inherits(t,r),e(\"../chart\").define(\"force\",t),t}),i(\"echarts/layout/Force\",[\"require\",\"./forceLayoutWorker\",\"zrender/tool/vector\"],function(e){function t(){if(\"undefined\"!=typeof Worker&&\"undefined\"!=typeof Blob)try{var e=new Blob([n.getWorkerCode()]);i=window.URL.createObjectURL(e)}catch(t){i=\"\"}return i}var i,n=e(\"./forceLayoutWorker\"),a=e(\"zrender/tool/vector\"),o=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},r=\"undefined\"==typeof Float32Array?Array:Float32Array,s=function(e){\"undefined\"==typeof i&&t(),e=e||{},this.width=e.width||500,this.height=e.height||500,this.center=e.center||[this.width/2,this.height/2],this.ratioScaling=e.ratioScaling||!1,this.scaling=e.scaling||1,this.gravity=\"undefined\"!=typeof e.gravity?e.gravity:1,this.large=e.large||!1,this.preventNodeOverlap=e.preventNodeOverlap||!1,this.preventNodeEdgeOverlap=e.preventNodeEdgeOverlap||!1,this.maxSpeedIncrease=e.maxSpeedIncrease||1,this.onupdate=e.onupdate||function(){},this.temperature=e.temperature||1,this.coolDown=e.coolDown||.99,this._layout=null,this._layoutWorker=null;var n=this,a=this._$onupdate;this._$onupdate=function(e){a.call(n,e)}};return s.prototype.updateConfig=function(){var e=this.width,t=this.height,i=Math.min(e,t),n={center:this.center,width:this.ratioScaling?e:i,height:this.ratioScaling?t:i,scaling:this.scaling||1,gravity:this.gravity||1,barnesHutOptimize:this.large,preventNodeOverlap:this.preventNodeOverlap,preventNodeEdgeOverlap:this.preventNodeEdgeOverlap,maxSpeedIncrease:this.maxSpeedIncrease};if(this._layoutWorker)this._layoutWorker.postMessage({cmd:\"updateConfig\",config:n});else for(var a in n)this._layout[a]=n[a]},s.prototype.init=function(e,t){if(this._layoutWorker&&(this._layoutWorker.terminate(),this._layoutWorker=null),i&&t)try{this._layoutWorker||(this._layoutWorker=new Worker(i),this._layoutWorker.onmessage=this._$onupdate),this._layout=null}catch(a){this._layoutWorker=null,this._layout||(this._layout=new n)}else this._layout||(this._layout=new n);this.temperature=1,this.graph=e;for(var o=e.nodes.length,s=new r(2*o),l=new r(o),h=new r(o),m=0;o>m;m++){var V=e.nodes[m];s[2*m]=V.layout.position[0],s[2*m+1]=V.layout.position[1],l[m]=\"undefined\"==typeof V.layout.mass?1:V.layout.mass,h[m]=\"undefined\"==typeof V.layout.size?1:V.layout.size,V.layout.__index=m}o=e.edges.length;for(var U=new r(2*o),d=new r(o),m=0;o>m;m++){var p=e.edges[m];U[2*m]=p.node1.layout.__index,U[2*m+1]=p.node2.layout.__index,d[m]=p.layout.weight||1}this._layoutWorker?this._layoutWorker.postMessage({cmd:\"init\",nodesPosition:s,nodesMass:l,nodesSize:h,edges:U,edgesWeight:d}):(this._layout.initNodes(s,l,h),this._layout.initEdges(U,d)),this.updateConfig()},s.prototype.step=function(e){var t=this.graph.nodes;if(this._layoutWorker){for(var i=new r(2*t.length),n=0;n<t.length;n++){var s=t[n];i[2*n]=s.layout.position[0],i[2*n+1]=s.layout.position[1]}this._layoutWorker.postMessage(i.buffer,[i.buffer]),this._layoutWorker.postMessage({cmd:\"update\",steps:e,temperature:this.temperature,coolDown:this.coolDown});for(var n=0;e>n;n++)this.temperature*=this.coolDown}else{o(this._$onupdate);for(var n=0;n<t.length;n++){var s=t[n];a.copy(this._layout.nodes[n].position,s.layout.position)}for(var n=0;e>n;n++)this._layout.temperature=this.temperature,this._layout.update(),this.temperature*=this.coolDown}},s.prototype._$onupdate=function(e){if(this._layoutWorker){for(var t=new Float32Array(e.data),i=0;i<this.graph.nodes.length;i++){var n=this.graph.nodes[i];n.layout.position[0]=t[2*i],n.layout.position[1]=t[2*i+1]}this.onupdate&&this.onupdate()}else if(this._layout){for(var i=0;i<this.graph.nodes.length;i++){var n=this.graph.nodes[i];a.copy(n.layout.position,this._layout.nodes[i].position)}this.onupdate&&this.onupdate()}},s.prototype.dispose=function(){this._layoutWorker&&this._layoutWorker.terminate(),this._layoutWorker=null,this._layout=null},s}),i(\"echarts/layout/forceLayoutWorker\",[\"require\",\"zrender/tool/vector\"],function o(e){\"use strict\";function t(){this.subRegions=[],this.nSubRegions=0,this.node=null,this.mass=0,this.centerOfMass=null,this.bbox=new l(4),this.size=0}function i(){this.position=r.create(),this.force=r.create(),this.forcePrev=r.create(),this.speed=r.create(),this.speedPrev=r.create(),this.mass=1,this.inDegree=0,this.outDegree=0}function n(e,t){this.node1=e,this.node2=t,this.weight=1}function a(){this.barnesHutOptimize=!1,this.barnesHutTheta=1.5,this.repulsionByDegree=!1,this.preventNodeOverlap=!1,this.preventNodeEdgeOverlap=!1,this.strongGravity=!0,this.gravity=1,this.scaling=1,this.edgeWeightInfluence=1,this.center=[0,0],this.width=500,this.height=500,this.maxSpeedIncrease=1,this.nodes=[],this.edges=[],this.bbox=new l(4),this._rootRegion=new t,this._rootRegion.centerOfMass=r.create(),this._massArr=null,this._k=0}var r,s=\"undefined\"==typeof window&&\"undefined\"==typeof e;r=s?{create:function(e,t){var i=new Float32Array(2);return i[0]=e||0,i[1]=t||0,i},dist:function(e,t){var i=t[0]-e[0],n=t[1]-e[1];return Math.sqrt(i*i+n*n)},len:function(e){var t=e[0],i=e[1];return Math.sqrt(t*t+i*i)},scaleAndAdd:function(e,t,i,n){return e[0]=t[0]+i[0]*n,e[1]=t[1]+i[1]*n,e},scale:function(e,t,i){return e[0]=t[0]*i,e[1]=t[1]*i,e},add:function(e,t,i){return e[0]=t[0]+i[0],e[1]=t[1]+i[1],e},sub:function(e,t,i){return e[0]=t[0]-i[0],e[1]=t[1]-i[1],e},dot:function(e,t){return e[0]*t[0]+e[1]*t[1]},normalize:function(e,t){var i=t[0],n=t[1],a=i*i+n*n;return a>0&&(a=1/Math.sqrt(a),e[0]=t[0]*a,e[1]=t[1]*a),e},negate:function(e,t){return e[0]=-t[0],e[1]=-t[1],e},copy:function(e,t){return e[0]=t[0],e[1]=t[1],e},set:function(e,t,i){return e[0]=t,e[1]=i,e}}:e(\"zrender/tool/vector\");var l=\"undefined\"==typeof Float32Array?Array:Float32Array;if(t.prototype.beforeUpdate=function(){for(var e=0;e<this.nSubRegions;e++)this.subRegions[e].beforeUpdate();this.mass=0,this.centerOfMass&&(this.centerOfMass[0]=0,this.centerOfMass[1]=0),this.nSubRegions=0,this.node=null},t.prototype.afterUpdate=function(){this.subRegions.length=this.nSubRegions;for(var e=0;e<this.nSubRegions;e++)this.subRegions[e].afterUpdate()},t.prototype.addNode=function(e){if(0===this.nSubRegions){if(null==this.node)return void(this.node=e);this._addNodeToSubRegion(this.node),this.node=null}this._addNodeToSubRegion(e),this._updateCenterOfMass(e)},t.prototype.findSubRegion=function(e,t){for(var i=0;i<this.nSubRegions;i++){var n=this.subRegions[i];if(n.contain(e,t))return n}},t.prototype.contain=function(e,t){return this.bbox[0]<=e&&this.bbox[2]>=e&&this.bbox[1]<=t&&this.bbox[3]>=t},t.prototype.setBBox=function(e,t,i,n){this.bbox[0]=e,this.bbox[1]=t,this.bbox[2]=i,this.bbox[3]=n,this.size=(i-e+n-t)/2},t.prototype._newSubRegion=function(){var e=this.subRegions[this.nSubRegions];return e||(e=new t,this.subRegions[this.nSubRegions]=e),this.nSubRegions++,e},t.prototype._addNodeToSubRegion=function(e){var t=this.findSubRegion(e.position[0],e.position[1]),i=this.bbox;if(!t){var n=(i[0]+i[2])/2,a=(i[1]+i[3])/2,o=(i[2]-i[0])/2,r=(i[3]-i[1])/2,s=e.position[0]>=n?1:0,l=e.position[1]>=a?1:0,t=this._newSubRegion();t.setBBox(s*o+i[0],l*r+i[1],(s+1)*o+i[0],(l+1)*r+i[1])}t.addNode(e)},t.prototype._updateCenterOfMass=function(e){null==this.centerOfMass&&(this.centerOfMass=r.create());var t=this.centerOfMass[0]*this.mass,i=this.centerOfMass[1]*this.mass;t+=e.position[0]*e.mass,i+=e.position[1]*e.mass,this.mass+=e.mass,this.centerOfMass[0]=t/this.mass,this.centerOfMass[1]=i/this.mass},a.prototype.nodeToNodeRepulsionFactor=function(e,t,i){return i*i*e/t},a.prototype.edgeToNodeRepulsionFactor=function(e,t,i){return i*e/t},a.prototype.attractionFactor=function(e,t,i){return e*t/i},a.prototype.initNodes=function(e,t,n){this.temperature=1;var a=e.length/2;this.nodes.length=0;for(var o=\"undefined\"!=typeof n,r=0;a>r;r++){var s=new i;s.position[0]=e[2*r],s.position[1]=e[2*r+1],s.mass=t[r],o&&(s.size=n[r]),this.nodes.push(s)}this._massArr=t,o&&(this._sizeArr=n)},a.prototype.initEdges=function(e,t){var i=e.length/2;this.edges.length=0;for(var a=\"undefined\"!=typeof t,o=0;i>o;o++){var r=e[2*o],s=e[2*o+1],l=this.nodes[r],h=this.nodes[s];if(l&&h){l.outDegree++,h.inDegree++;var m=new n(l,h);a&&(m.weight=t[o]),this.edges.push(m)}}},a.prototype.update=function(){var e=this.nodes.length;if(this.updateBBox(),this._k=.4*this.scaling*Math.sqrt(this.width*this.height/e),this.barnesHutOptimize){this._rootRegion.setBBox(this.bbox[0],this.bbox[1],this.bbox[2],this.bbox[3]),this._rootRegion.beforeUpdate();for(var t=0;e>t;t++)this._rootRegion.addNode(this.nodes[t]);this._rootRegion.afterUpdate()}else{var i=0,n=this._rootRegion.centerOfMass;r.set(n,0,0);for(var t=0;e>t;t++){var a=this.nodes[t];i+=a.mass,r.scaleAndAdd(n,n,a.position,a.mass);\n\n}i>0&&r.scale(n,n,1/i)}this.updateForce(),this.updatePosition()},a.prototype.updateForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];r.copy(i.forcePrev,i.force),r.copy(i.speedPrev,i.speed),r.set(i.force,0,0)}this.updateNodeNodeForce(),this.gravity>0&&this.updateGravityForce(),this.updateEdgeForce(),this.preventNodeEdgeOverlap&&this.updateNodeEdgeForce()},a.prototype.updatePosition=function(){for(var e=this.nodes.length,t=r.create(),i=0;e>i;i++){var n=this.nodes[i],a=n.speed;r.scale(n.force,n.force,1/30);var o=r.len(n.force)+.1,s=Math.min(o,500)/o;r.scale(n.force,n.force,s),r.add(a,a,n.force),r.scale(a,a,this.temperature),r.sub(t,a,n.speedPrev);var l=r.len(t);if(l>0){r.scale(t,t,1/l);var h=r.len(n.speedPrev);h>0&&(l=Math.min(l/h,this.maxSpeedIncrease)*h,r.scaleAndAdd(a,n.speedPrev,t,l))}var m=r.len(a),s=Math.min(m,100)/(m+.1);r.scale(a,a,s),r.add(n.position,n.position,a)}},a.prototype.updateNodeNodeForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];if(this.barnesHutOptimize)this.applyRegionToNodeRepulsion(this._rootRegion,i);else for(var n=t+1;e>n;n++){var a=this.nodes[n];this.applyNodeToNodeRepulsion(i,a,!1)}}},a.prototype.updateGravityForce=function(){for(var e=0;e<this.nodes.length;e++)this.applyNodeGravity(this.nodes[e])},a.prototype.updateEdgeForce=function(){for(var e=0;e<this.edges.length;e++)this.applyEdgeAttraction(this.edges[e])},a.prototype.updateNodeEdgeForce=function(){for(var e=0;e<this.nodes.length;e++)for(var t=0;t<this.edges.length;t++)this.applyEdgeToNodeRepulsion(this.edges[t],this.nodes[e])},a.prototype.applyRegionToNodeRepulsion=function(){var e=r.create();return function(t,i){if(t.node)this.applyNodeToNodeRepulsion(t.node,i,!0);else{if(0===t.mass&&0===i.mass)return;r.sub(e,i.position,t.centerOfMass);var n=e[0]*e[0]+e[1]*e[1];if(n>this.barnesHutTheta*t.size*t.size){var a=this._k*this._k*(i.mass+t.mass)/(n+1);r.scaleAndAdd(i.force,i.force,e,2*a)}else for(var o=0;o<t.nSubRegions;o++)this.applyRegionToNodeRepulsion(t.subRegions[o],i)}}}(),a.prototype.applyNodeToNodeRepulsion=function(){var e=r.create();return function(t,i,n){if(t!==i&&(0!==t.mass||0!==i.mass)){r.sub(e,t.position,i.position);var a=e[0]*e[0]+e[1]*e[1];if(0!==a){var o,s=t.mass+i.mass,l=Math.sqrt(a);r.scale(e,e,1/l),this.preventNodeOverlap?(l=l-t.size-i.size,l>0?o=this.nodeToNodeRepulsionFactor(s,l,this._k):0>=l&&(o=this._k*this._k*10*s)):o=this.nodeToNodeRepulsionFactor(s,l,this._k),n||r.scaleAndAdd(t.force,t.force,e,2*o),r.scaleAndAdd(i.force,i.force,e,2*-o)}}}}(),a.prototype.applyEdgeAttraction=function(){var e=r.create();return function(t){var i=t.node1,n=t.node2;r.sub(e,i.position,n.position);var a,o=r.len(e);a=0===this.edgeWeightInfluence?1:1==this.edgeWeightInfluence?t.weight:Math.pow(t.weight,this.edgeWeightInfluence);var s;if(!(this.preventOverlap&&(o=o-i.size-n.size,0>=o))){var s=this.attractionFactor(a,o,this._k);r.scaleAndAdd(i.force,i.force,e,-s),r.scaleAndAdd(n.force,n.force,e,s)}}}(),a.prototype.applyNodeGravity=function(){var e=r.create();return function(t){r.sub(e,this.center,t.position),this.width>this.height?e[1]*=this.width/this.height:e[0]*=this.height/this.width;var i=r.len(e)/100;this.strongGravity?r.scaleAndAdd(t.force,t.force,e,i*this.gravity*t.mass):r.scaleAndAdd(t.force,t.force,e,this.gravity*t.mass/(i+1))}}(),a.prototype.applyEdgeToNodeRepulsion=function(){var e=r.create(),t=r.create(),i=r.create();return function(n,a){var o=n.node1,s=n.node2;if(o!==a&&s!==a){r.sub(e,s.position,o.position),r.sub(t,a.position,o.position);var l=r.len(e);r.scale(e,e,1/l);var h=r.dot(e,t);if(!(0>h||h>l)){r.scaleAndAdd(i,o.position,e,h);var m=r.dist(i,a.position)-a.size,V=this.edgeToNodeRepulsionFactor(a.mass,Math.max(m,.1),100);r.sub(e,a.position,i),r.normalize(e,e),r.scaleAndAdd(a.force,a.force,e,V),r.scaleAndAdd(o.force,o.force,e,-V),r.scaleAndAdd(s.force,s.force,e,-V)}}}}(),a.prototype.updateBBox=function(){for(var e=1/0,t=1/0,i=-(1/0),n=-(1/0),a=0;a<this.nodes.length;a++){var o=this.nodes[a].position;e=Math.min(e,o[0]),t=Math.min(t,o[1]),i=Math.max(i,o[0]),n=Math.max(n,o[1])}this.bbox[0]=e,this.bbox[1]=t,this.bbox[2]=i,this.bbox[3]=n},a.getWorkerCode=function(){var e=o.toString();return e.slice(e.indexOf(\"{\")+1,e.lastIndexOf(\"return\"))},s){var h=null;self.onmessage=function(e){if(e.data instanceof ArrayBuffer){if(!h)return;for(var t=new Float32Array(e.data),i=t.length/2,n=0;i>n;n++){var o=h.nodes[n];o.position[0]=t[2*n],o.position[1]=t[2*n+1]}}else switch(e.data.cmd){case\"init\":h||(h=new a),h.initNodes(e.data.nodesPosition,e.data.nodesMass,e.data.nodesSize),h.initEdges(e.data.edges,e.data.edgesWeight);break;case\"updateConfig\":if(h)for(var r in e.data.config)h[r]=e.data.config[r];break;case\"update\":var s=e.data.steps;if(h){var i=h.nodes.length,t=new Float32Array(2*i);h.temperature=e.data.temperature;for(var n=0;s>n;n++)h.update(),h.temperature*=e.data.coolDown;for(var n=0;i>n;n++){var o=h.nodes[n];t[2*n]=o.position[0],t[2*n+1]=o.position[1]}self.postMessage(t.buffer,[t.buffer])}else{var l=new Float32Array;self.postMessage(l.buffer,[l.buffer])}}}}return a}),i(\"echarts/chart/map\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Path\",\"zrender/shape/Circle\",\"zrender/shape/Rectangle\",\"zrender/shape/Line\",\"zrender/shape/Polygon\",\"zrender/shape/Ellipse\",\"zrender/shape/Image\",\"../component/dataRange\",\"../component/roamController\",\"../layer/heatmap\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/config\",\"zrender/tool/event\",\"../util/mapData/params\",\"../util/mapData/textFixed\",\"../util/mapData/geoCoord\",\"../util/projection/svg\",\"../util/projection/normal\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._onmousewheel=function(e){return r.__onmousewheel(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onroamcontroller=function(e){return r.__onroamcontroller(e)},r._ondrhoverlink=function(e){return r.__ondrhoverlink(e)},this._isAlive=!0,this._selectedMode={},this._activeMapType={},this._clickable={},this._hoverable={},this._showLegendSymbol={},this._selected={},this._mapTypeMap={},this._mapDataMap={},this._nameMap={},this._specialArea={},this._refreshDelayTicket,this._mapDataRequireCounter,this._markAnimation=!1,this._hoverLinkMap={},this._roamMap={},this._scaleLimitMap={},this._mx,this._my,this._mousedown,this._justMove,this._curMapType,this.refresh(a),this.zr.on(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.on(c.EVENT.MOUSEDOWN,this._onmousedown),t.bind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),t.bind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Path\"),o=e(\"zrender/shape/Circle\"),r=e(\"zrender/shape/Rectangle\"),s=e(\"zrender/shape/Line\"),l=e(\"zrender/shape/Polygon\"),h=e(\"zrender/shape/Ellipse\"),m=e(\"zrender/shape/Image\");e(\"../component/dataRange\"),e(\"../component/roamController\");var V=e(\"../layer/heatmap\"),U=e(\"../config\");U.map={zlevel:0,z:2,mapType:\"china\",showLegendSymbol:!0,dataRangeHoverLink:!0,hoverable:!0,clickable:!0,itemStyle:{normal:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,areaStyle:{color:\"#ccc\"},label:{show:!1,textStyle:{color:\"rgb(139,69,19)\"}}},emphasis:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,areaStyle:{color:\"rgba(255,215,0,0.8)\"},label:{show:!1,textStyle:{color:\"rgb(100,0,0)\"}}}}};var d=e(\"../util/ecData\"),p=e(\"zrender/tool/util\"),c=e(\"zrender/config\"),u=e(\"zrender/tool/event\"),y=e(\"../util/mapData/params\").params,g=e(\"../util/mapData/textFixed\"),b=e(\"../util/mapData/geoCoord\");return t.prototype={type:U.CHART_TYPE_MAP,_buildShape:function(){var e=this.series;this.selectedMap={},this._activeMapType={};for(var t,i,n,a,o=this.component.legend,r={},s={},l={},h={},m=0,V=e.length;V>m;m++)if(e[m].type==U.CHART_TYPE_MAP&&(e[m]=this.reformOption(e[m]),i=e[m].mapType,s[i]=s[i]||{},s[i][m]=!0,l[i]=l[i]||e[m].mapValuePrecision,this._scaleLimitMap[i]=this._scaleLimitMap[i]||{},e[m].scaleLimit&&p.merge(this._scaleLimitMap[i],e[m].scaleLimit,!0),this._roamMap[i]=e[m].roam||this._roamMap[i],(null==this._hoverLinkMap[i]||this._hoverLinkMap[i])&&(this._hoverLinkMap[i]=e[m].dataRangeHoverLink),this._nameMap[i]=this._nameMap[i]||{},e[m].nameMap&&p.merge(this._nameMap[i],e[m].nameMap,!0),this._activeMapType[i]=!0,e[m].textFixed&&p.merge(g,e[m].textFixed,!0),e[m].geoCoord&&p.merge(b,e[m].geoCoord,!0),this._selectedMode[i]=this._selectedMode[i]||e[m].selectedMode,(null==this._hoverable[i]||this._hoverable[i])&&(this._hoverable[i]=e[m].hoverable),(null==this._clickable[i]||this._clickable[i])&&(this._clickable[i]=e[m].clickable),(null==this._showLegendSymbol[i]||this._showLegendSymbol[i])&&(this._showLegendSymbol[i]=e[m].showLegendSymbol),h[i]=h[i]||e[m].mapValueCalculation,t=e[m].name,this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t])){r[i]=r[i]||{},n=e[m].data;for(var d=0,c=n.length;c>d;d++){a=this._nameChange(i,n[d].name),r[i][a]=r[i][a]||{seriesIndex:[],valueMap:{},precision:0};for(var u in n[d])\"value\"!=u?r[i][a][u]=n[d][u]:isNaN(n[d].value)||(null==r[i][a].value&&(r[i][a].value=0),r[i][a].precision=Math.max(this.getPrecision(+n[d].value),r[i][a].precision),r[i][a].value+=+n[d].value,r[i][a].valueMap[m]=+n[d].value);r[i][a].seriesIndex.push(m)}}this._mapDataRequireCounter=0;for(var f in r)this._mapDataRequireCounter++;this._clearSelected(),0===this._mapDataRequireCounter&&(this.clear(),this.zr&&this.zr.delShape(this.lastShapeList),this.lastShapeList=[]);for(var f in r){for(var c in r[f]){\"average\"==h[f]&&(r[f][c].value/=r[f][c].seriesIndex.length);var k=r[f][c].value;null!=k&&(r[f][c].value=k.toFixed(null==l[f]?r[f][c].precision:l[f])-0)}this._mapDataMap[f]=this._mapDataMap[f]||{},this._mapDataMap[f].mapData?this._mapDataCallback(f,r[f],s[f])(this._mapDataMap[f].mapData):y[f.replace(/\\|.*/,\"\")].getGeoJson&&(this._specialArea[f]=y[f.replace(/\\|.*/,\"\")].specialArea||this._specialArea[f],y[f.replace(/\\|.*/,\"\")].getGeoJson(this._mapDataCallback(f,r[f],s[f])))}},_mapDataCallback:function(t,i,n){var a=this;return function(o){a._isAlive&&null!=a._activeMapType[t]&&(-1!=t.indexOf(\"|\")&&(o=a._getSubMapData(t,o)),a._mapDataMap[t].mapData=o,o.firstChild?(a._mapDataMap[t].rate=1,a._mapDataMap[t].projection=e(\"../util/projection/svg\")):(a._mapDataMap[t].rate=.75,a._mapDataMap[t].projection=e(\"../util/projection/normal\")),a._buildMap(t,a._getProjectionData(t,o,n),i,n),a._buildMark(t,n),--a._mapDataRequireCounter<=0&&(a.addShapeList(),a.zr.refreshNextFrame()),a._buildHeatmap(t))}},_clearSelected:function(){for(var e in this._selected)this._activeMapType[this._mapTypeMap[e]]||(delete this._selected[e],delete this._mapTypeMap[e])},_getSubMapData:function(e,t){for(var i=e.replace(/^.*\\|/,\"\"),n=t.features,a=0,o=n.length;o>a;a++)if(n[a].properties&&n[a].properties.name==i){n=n[a],\"United States of America\"==i&&n.geometry.coordinates.length>1&&(n={geometry:{coordinates:n.geometry.coordinates.slice(5,6),type:n.geometry.type},id:n.id,properties:n.properties,type:n.type});break}return{type:\"FeatureCollection\",features:[n]}},_getProjectionData:function(e,t,i){var n,a=this._mapDataMap[e].projection,o=[],r=this._mapDataMap[e].bbox||a.getBbox(t,this._specialArea[e]);n=this._mapDataMap[e].hasRoam?this._mapDataMap[e].transform:this._getTransform(r,i,this._mapDataMap[e].rate);var s,l=this._mapDataMap[e].lastTransform||{scale:{}};n.left!=l.left||n.top!=l.top||n.scale.x!=l.scale.x||n.scale.y!=l.scale.y?(s=a.geoJson2Path(t,n,this._specialArea[e]),l=p.clone(n)):(n=this._mapDataMap[e].transform,s=this._mapDataMap[e].pathArray),this._mapDataMap[e].bbox=r,this._mapDataMap[e].transform=n,this._mapDataMap[e].lastTransform=l,this._mapDataMap[e].pathArray=s;for(var h=[n.left,n.top],m=0,V=s.length;V>m;m++)o.push(this._getSingleProvince(e,s[m],h));if(this._specialArea[e])for(var U in this._specialArea[e])o.push(this._getSpecialProjectionData(e,t,U,this._specialArea[e][U],h));if(\"china\"==e){var d=this.geo2pos(e,b[\"南海诸岛\"]||y[\"南海诸岛\"].textCoord),c=n.scale.x/10.5,u=[32*c+d[0],83*c+d[1]];g[\"南海诸岛\"]&&(u[0]+=g[\"南海诸岛\"][0],u[1]+=g[\"南海诸岛\"][1]),o.push({name:this._nameChange(e,\"南海诸岛\"),path:y[\"南海诸岛\"].getPath(d,c),position:h,textX:u[0],textY:u[1]})}return o},_getSpecialProjectionData:function(t,i,n,a,o){i=this._getSubMapData(\"x|\"+n,i);var r=e(\"../util/projection/normal\"),s=r.getBbox(i),l=this.geo2pos(t,[a.left,a.top]),h=this.geo2pos(t,[a.left+a.width,a.top+a.height]),m=Math.abs(h[0]-l[0]),V=Math.abs(h[1]-l[1]),U=s.width,d=s.height,p=m/.75/U,c=V/d;p>c?(p=.75*c,m=U*p):(c=p,p=.75*c,V=d*c);var u={OffsetLeft:l[0],OffsetTop:l[1],scale:{x:p,y:c}},y=r.geoJson2Path(i,u);return this._getSingleProvince(t,y[0],o)},_getSingleProvince:function(e,t,i){var n,a=t.properties.name,o=g[a]||[0,0];if(b[a])n=this.geo2pos(e,b[a]);else if(t.cp)n=[t.cp[0]+o[0],t.cp[1]+o[1]];else{var r=this._mapDataMap[e].bbox;n=this.geo2pos(e,[r.left+r.width/2,r.top+r.height/2]),n[0]+=o[0],n[1]+=o[1]}return t.name=this._nameChange(e,a),t.position=i,t.textX=n[0],t.textY=n[1],t},_getTransform:function(e,t,i){var n,a,o,r,s,l,h,m=this.series,V=this.zr.getWidth(),U=this.zr.getHeight(),d=Math.round(.02*Math.min(V,U));for(var p in t)n=m[p].mapLocation||{},o=n.x||o,s=n.y||s,l=n.width||l,h=n.height||h;a=this.parsePercent(o,V),a=isNaN(a)?d:a,r=this.parsePercent(s,U),r=isNaN(r)?d:r,l=null==l?V-a-2*d:this.parsePercent(l,V),h=null==h?U-r-2*d:this.parsePercent(h,U);var c=e.width,u=e.height,y=l/i/c,g=h/u;if(y>g?(y=g*i,l=c*y):(g=y,y=g*i,h=u*g),isNaN(o))switch(o=o||\"center\",o+\"\"){case\"center\":a=Math.floor((V-l)/2);break;case\"right\":a=V-l}if(isNaN(s))switch(s=s||\"center\",s+\"\"){case\"center\":r=Math.floor((U-h)/2);break;case\"bottom\":r=U-h}return{left:a,top:r,width:l,height:h,baseScale:1,scale:{x:y,y:g}}},_buildMap:function(e,t,i,m){for(var V,c,u,y,g,b,f,k,x,_,L,W=this.series,X=this.component.legend,v=this.component.dataRange,w=0,K=t.length;K>w;w++){if(k=p.clone(t[w]),x={name:k.name,path:k.path,position:p.clone(k.position)},c=k.name,u=i[c]){g=[u],V=\"\";for(var I=0,J=u.seriesIndex.length;J>I;I++){var C=W[u.seriesIndex[I]];g.push(C),V+=C.name+\" \",X&&this._showLegendSymbol[e]&&X.hasColor(C.name)&&this.shapeList.push(new o({zlevel:C.zlevel,z:C.z+1,position:p.clone(k.position),_mapType:e,style:{x:k.textX+3+7*I,y:k.textY-10,r:3,color:X.getColor(C.name)},hoverable:!1}))}y=u.value}else{u={name:c,value:\"-\"},V=\"\",g=[];for(var S in m)g.push(W[S]);y=\"-\"}switch(this.ecTheme.map&&g.push(this.ecTheme.map),g.push(U.map),b=v&&!isNaN(y)?v.getColor(y):null,k.color=k.color||b||this.getItemStyleColor(this.deepQuery(g,\"itemStyle.normal.color\"),u.seriesIndex,-1,u)||this.deepQuery(g,\"itemStyle.normal.areaStyle.color\"),k.strokeColor=k.strokeColor||this.deepQuery(g,\"itemStyle.normal.borderColor\"),k.lineWidth=k.lineWidth||this.deepQuery(g,\"itemStyle.normal.borderWidth\"),x.color=this.getItemStyleColor(this.deepQuery(g,\"itemStyle.emphasis.color\"),u.seriesIndex,-1,u)||this.deepQuery(g,\"itemStyle.emphasis.areaStyle.color\")||k.color,x.strokeColor=this.deepQuery(g,\"itemStyle.emphasis.borderColor\")||k.strokeColor,x.lineWidth=this.deepQuery(g,\"itemStyle.emphasis.borderWidth\")||k.lineWidth,k.brushType=x.brushType=k.brushType||\"both\",k.lineJoin=x.lineJoin=\"round\",k._name=x._name=c,f=this.deepQuery(g,\"itemStyle.normal.label.textStyle\"),L={zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:p.clone(k.position),_mapType:e,_geo:this.pos2geo(e,[k.textX,k.textY]),style:{brushType:\"fill\",x:k.textX,y:k.textY,text:this.getLabelText(c,y,g,\"normal\"),_name:c,textAlign:\"center\",color:this.deepQuery(g,\"itemStyle.normal.label.show\")?this.deepQuery(g,\"itemStyle.normal.label.textStyle.color\"):\"rgba(0,0,0,0)\",textFont:this.getFont(f)}},L._style=p.clone(L.style),L.highlightStyle=p.clone(L.style),this.deepQuery(g,\"itemStyle.emphasis.label.show\")?(L.highlightStyle.text=this.getLabelText(c,y,g,\"emphasis\"),L.highlightStyle.color=this.deepQuery(g,\"itemStyle.emphasis.label.textStyle.color\")||L.style.color,f=this.deepQuery(g,\"itemStyle.emphasis.label.textStyle\")||f,L.highlightStyle.textFont=this.getFont(f)):L.highlightStyle.color=\"rgba(0,0,0,0)\",_={zlevel:this.getZlevelBase(),z:this.getZBase(),position:p.clone(k.position),style:k,highlightStyle:x,_style:p.clone(k),_mapType:e},null!=k.scale&&(_.scale=p.clone(k.scale)),L=new n(L),_.style.shapeType){case\"rectangle\":_=new r(_);break;case\"line\":_=new s(_);break;case\"circle\":_=new o(_);break;case\"polygon\":_=new l(_);break;case\"ellipse\":_=new h(_);break;default:_=new a(_),_.buildPathArray&&(_.style.pathArray=_.buildPathArray(_.style.path))}(this._selectedMode[e]&&this._selected[c]&&u.selected!==!1||u.selected===!0)&&(L.style=L.highlightStyle,_.style=_.highlightStyle),L.clickable=_.clickable=this._clickable[e]&&(null==u.clickable||u.clickable),this._selectedMode[e]&&(this._selected[c]=null!=this._selected[c]?this._selected[c]:u.selected,this._mapTypeMap[c]=e,(null==u.selectable||u.selectable)&&(_.clickable=L.clickable=!0,_.onclick=L.onclick=this.shapeHandler.onclick)),this._hoverable[e]&&(null==u.hoverable||u.hoverable)?(L.hoverable=_.hoverable=!0,_.hoverConnect=L.id,L.hoverConnect=_.id):L.hoverable=_.hoverable=!1,d.pack(L,{name:V,tooltip:this.deepQuery(g,\"tooltip\")},0,u,0,c),this.shapeList.push(L),d.pack(_,{name:V,tooltip:this.deepQuery(g,\"tooltip\")},0,u,0,c),this.shapeList.push(_)}},_buildMark:function(e,t){this._seriesIndexToMapType=this._seriesIndexToMapType||{},this.markAttachStyle=this.markAttachStyle||{};var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];\"none\"==e&&(i=[0,0]);for(var n in t)this._seriesIndexToMapType[n]=e,this.markAttachStyle[n]={position:i,_mapType:e},this.buildMark(n)},_buildHeatmap:function(e){for(var t=this.series,i=0,n=t.length;n>i;i++)if(t[i].heatmap){var a=t[i].heatmap.data;if(t[i].heatmap.needsTransform===!1){for(var o=[],r=0,s=a.length;s>r;++r)o.push([a[r][3],a[r][4],a[r][2]]);var l=[0,0]}else{var h=t[i].heatmap._geoData;if(void 0===h){t[i].heatmap._geoData=[];for(var r=0,s=a.length;s>r;++r)t[i].heatmap._geoData[r]=a[r];h=t[i].heatmap._geoData}for(var s=a.length,U=0;s>U;++U)a[U]=this.geo2pos(e,[h[U][0],h[U][1]]);var l=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]}var d=new V(t[i].heatmap),p=d.getCanvas(a[0][3]?o:a,this.zr.getWidth(),this.zr.getHeight()),c=new m({zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:l,scale:[1,1],hoverable:!1,style:{x:0,y:0,image:p,width:p.width,height:p.height}});c.type=\"heatmap\",c._mapType=e,this.shapeList.push(c),this.zr.addShape(c)}},getMarkCoord:function(e,t){return t.geoCoord||b[t.name]?this.geo2pos(this._seriesIndexToMapType[e],t.geoCoord||b[t.name]):[0,0]},getMarkGeo:function(e){return e.geoCoord||b[e.name]},_nameChange:function(e,t){return this._nameMap[e][t]||t},getLabelText:function(e,t,i,n){var a=this.deepQuery(i,\"itemStyle.\"+n+\".label.formatter\");return a?\"function\"==typeof a?a.call(this.myChart,e,t):\"string\"==typeof a?(a=a.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\"),a=a.replace(\"{a0}\",e).replace(\"{b0}\",t)):void 0:e},_findMapTypeByPos:function(e,t){var i,n,a,o,r;for(var s in this._mapDataMap)if(i=this._mapDataMap[s].transform,i&&this._roamMap[s]&&this._activeMapType[s]&&(n=i.left,a=i.top,o=i.width,r=i.height,e>=n&&n+o>=e&&t>=a&&a+r>=t))return s},__onmousewheel:function(e){function t(e,t){for(var i=0;i<e.pointList.length;i++){var n=e.pointList[i];n[0]*=t,n[1]*=t}var a=e.controlPointList;if(a)for(var i=0;i<a.length;i++){var n=a[i];n[0]*=t,n[1]*=t}}function i(e,t){e.xStart*=t,e.yStart*=t,e.xEnd*=t,e.yEnd*=t,null!=e.cpX1&&(e.cpX1*=t,e.cpY1*=t)}if(!(this.shapeList.length<=0)){for(var n=0,a=this.shapeList.length;a>n;n++){var o=this.shapeList[n];if(o.__animating)return}var r,s,l=e.event,h=u.getX(l),m=u.getY(l),V=u.getDelta(l),d=e.mapTypeControl;d||(d={},s=this._findMapTypeByPos(h,m),s&&this._roamMap[s]&&\"move\"!=this._roamMap[s]&&(d[s]=!0));var p=!1;for(s in d)if(d[s]){p=!0;var c=this._mapDataMap[s].transform,y=c.left,g=c.top,b=c.width,f=c.height,k=this.pos2geo(s,[h-y,m-g]);if(V>0){if(r=1.2,null!=this._scaleLimitMap[s].max&&c.baseScale>=this._scaleLimitMap[s].max)continue}else if(r=1/1.2,null!=this._scaleLimitMap[s].min&&c.baseScale<=this._scaleLimitMap[s].min)continue;c.baseScale*=r,c.scale.x*=r,c.scale.y*=r,c.width=b*r,c.height=f*r,this._mapDataMap[s].hasRoam=!0,this._mapDataMap[s].transform=c,k=this.geo2pos(s,k),c.left-=k[0]-(h-y),c.top-=k[1]-(m-g),this._mapDataMap[s].transform=c,this.clearEffectShape(!0);for(var n=0,a=this.shapeList.length;a>n;n++){var o=this.shapeList[n];if(o._mapType==s){var x=o.type,_=o.style;switch(o.position[0]=c.left,o.position[1]=c.top,x){case\"path\":case\"symbol\":case\"circle\":case\"rectangle\":case\"polygon\":case\"line\":case\"ellipse\":case\"heatmap\":o.scale[0]*=r,o.scale[1]*=r;break;case\"mark-line\":i(_,r);break;case\"polyline\":t(_,r);break;case\"shape-bundle\":for(var L=0;L<_.shapeList.length;L++){var W=_.shapeList[L];\"mark-line\"==W.type?i(W.style,r):\"polyline\"==W.type&&t(W.style,r)}break;case\"icon\":case\"image\":k=this.geo2pos(s,o._geo),_.x=_._x=k[0]-_.width/2,_.y=_._y=k[1]-_.height/2;break;default:k=this.geo2pos(s,o._geo),_.x=k[0],_.y=k[1],\"text\"==x&&(o._style.x=o.highlightStyle.x=k[0],o._style.y=o.highlightStyle.y=k[1])}this.zr.modShape(o.id)}}}if(p){u.stop(l),this.zr.refreshNextFrame();var X=this;clearTimeout(this._refreshDelayTicket),this._refreshDelayTicket=setTimeout(function(){X&&X.shapeList&&X.animationEffect()},100),this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:\"scale\"},this.myChart)}}},__onmousedown:function(e){if(!(this.shapeList.length<=0)){var t=e.target;if(!t||!t.draggable){var i=e.event,n=u.getX(i),a=u.getY(i),o=this._findMapTypeByPos(n,a);if(o&&this._roamMap[o]&&\"scale\"!=this._roamMap[o]){this._mousedown=!0,this._mx=n,this._my=a,this._curMapType=o,this.zr.on(c.EVENT.MOUSEUP,this._onmouseup);var r=this;setTimeout(function(){r.zr.on(c.EVENT.MOUSEMOVE,r._onmousemove)},100)}}}},__onmousemove:function(e){if(this._mousedown&&this._isAlive){var t=e.event,i=u.getX(t),n=u.getY(t),a=this._mapDataMap[this._curMapType].transform;a.hasRoam=!0,a.left-=this._mx-i,a.top-=this._my-n,this._mx=i,this._my=n,this._mapDataMap[this._curMapType].transform=a;for(var o=0,r=this.shapeList.length;r>o;o++)this.shapeList[o]._mapType==this._curMapType&&(this.shapeList[o].position[0]=a.left,this.shapeList[o].position[1]=a.top,this.zr.modShape(this.shapeList[o].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:\"move\"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),this._justMove=!0,u.stop(t)}},__onmouseup:function(e){var t=e.event;this._mx=u.getX(t),this._my=u.getY(t),this._mousedown=!1;var i=this;setTimeout(function(){i._justMove&&i.animationEffect(),i._justMove=!1,i.zr.un(c.EVENT.MOUSEMOVE,i._onmousemove),i.zr.un(c.EVENT.MOUSEUP,i._onmouseup)},120)},__onroamcontroller:function(e){var t=e.event;t.zrenderX=this.zr.getWidth()/2,t.zrenderY=this.zr.getHeight()/2;var i=e.mapTypeControl,n=0,a=0,o=e.step;switch(e.roamType){case\"scaleUp\":return t.zrenderDelta=1,void this.__onmousewheel({event:t,mapTypeControl:i});case\"scaleDown\":return t.zrenderDelta=-1,void this.__onmousewheel({event:t,mapTypeControl:i});case\"up\":n=-o;break;case\"down\":n=o;break;case\"left\":a=-o;break;case\"right\":a=o}var r,s;for(s in i)this._mapDataMap[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,r.hasRoam=!0,r.left-=a,r.top-=n,this._mapDataMap[s].transform=r);for(var l=0,h=this.shapeList.length;h>l;l++)s=this.shapeList[l]._mapType,i[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,this.shapeList[l].position[0]=r.left,this.shapeList[l].position[1]=r.top,this.zr.modShape(this.shapeList[l].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:\"move\"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),clearTimeout(this.dircetionTimer);var m=this;this.dircetionTimer=setTimeout(function(){m.animationEffect()},150)},__ondrhoverlink:function(e){for(var t,i,n=0,a=this.shapeList.length;a>n;n++)t=this.shapeList[n]._mapType,this._hoverLinkMap[t]&&this._activeMapType[t]&&(i=d.get(this.shapeList[n],\"value\"),null!=i&&i>=e.valueMin&&i<=e.valueMax&&this.zr.addHoverShape(this.shapeList[n]))},onclick:function(e){if(this.isClick&&e.target&&!this._justMove&&\"icon\"!=e.target.type){this.isClick=!1;var t=e.target,i=t.style._name,n=this.shapeList.length,a=t._mapType||\"\";if(\"single\"==this._selectedMode[a])for(var o in this._selected)if(this._selected[o]&&this._mapTypeMap[o]==a){for(var r=0;n>r;r++)this.shapeList[r].style._name==o&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));o!=i&&(this._selected[o]=!1)}this._selected[i]=!this._selected[i];for(var r=0;n>r;r++)this.shapeList[r].style._name==i&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this._selected[i]?this.shapeList[r].highlightStyle:this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));this.messageCenter.dispatch(U.EVENT.MAP_SELECTED,e.event,{selected:this._selected,target:i},this.myChart),this.zr.refreshNextFrame();var s=this;setTimeout(function(){s.zr.trigger(c.EVENT.MOUSEMOVE,e.event)},100)}},refresh:function(e){e&&(this.option=e,this.series=e.series),this._mapDataRequireCounter>0?this.clear():this.backupShapeList(),this._buildShape(),this.zr.refreshHover()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)},pos2geo:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.pos2geo(this._mapDataMap[e].transform,t):null},getGeoByPos:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];return t instanceof Array?(t[0]-=i[0],t[1]-=i[1]):(t.x-=i[0],t.y-=i[1]),this.pos2geo(e,t)},geo2pos:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.geo2pos(this._mapDataMap[e].transform,t):null},getPosByGeo:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=this.geo2pos(e,t);return i[0]+=this._mapDataMap[e].transform.left,i[1]+=this._mapDataMap[e].transform.top,i},getMapPosition:function(e){return this._mapDataMap[e].transform?[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]:null},onbeforDispose:function(){this._isAlive=!1,this.zr.un(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.un(c.EVENT.MOUSEDOWN,this._onmousedown),this.messageCenter.unbind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),this.messageCenter.unbind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}},p.inherits(t,i),e(\"../chart\").define(\"map\",t),t}),i(\"zrender/shape/Path\",[\"require\",\"./Base\",\"./util/PathProxy\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=e(\"./util/PathProxy\"),n=i.PathSegment,a=function(e){return Math.sqrt(e[0]*e[0]+e[1]*e[1])},o=function(e,t){return(e[0]*t[0]+e[1]*t[1])/(a(e)*a(t))},r=function(e,t){return(e[0]*t[1]<e[1]*t[0]?-1:1)*Math.acos(o(e,t))},s=function(e){t.call(this,e)};return s.prototype={type:\"path\",buildPathArray:function(e,t,i){if(!e)return[];t=t||0,i=i||0;var a=e,o=[\"m\",\"M\",\"l\",\"L\",\"v\",\"V\",\"h\",\"H\",\"z\",\"Z\",\"c\",\"C\",\"q\",\"Q\",\"t\",\"T\",\"s\",\"S\",\"a\",\"A\"];a=a.replace(/-/g,\" -\"),a=a.replace(/  /g,\" \"),a=a.replace(/ /g,\",\"),a=a.replace(/,,/g,\",\");var r;for(r=0;r<o.length;r++)a=a.replace(new RegExp(o[r],\"g\"),\"|\"+o[r]);var s=a.split(\"|\"),l=[],h=0,m=0;for(r=1;r<s.length;r++){var V=s[r],U=V.charAt(0);V=V.slice(1),V=V.replace(new RegExp(\"e,-\",\"g\"),\"e-\");var d=V.split(\",\");d.length>0&&\"\"===d[0]&&d.shift();for(var p=0;p<d.length;p++)d[p]=parseFloat(d[p]);for(;d.length>0&&!isNaN(d[0]);){var c,u,y,g,b,f,k,x,_=null,L=[],W=h,X=m;switch(U){case\"l\":h+=d.shift(),m+=d.shift(),_=\"L\",L.push(h,m);break;case\"L\":h=d.shift(),m=d.shift(),L.push(h,m);break;case\"m\":h+=d.shift(),m+=d.shift(),_=\"M\",L.push(h,m),U=\"l\";break;case\"M\":h=d.shift(),m=d.shift(),_=\"M\",L.push(h,m),U=\"L\";break;case\"h\":h+=d.shift(),_=\"L\",L.push(h,m);break;case\"H\":h=d.shift(),_=\"L\",L.push(h,m);break;case\"v\":m+=d.shift(),_=\"L\",L.push(h,m);break;case\"V\":m=d.shift(),_=\"L\",L.push(h,m);break;case\"C\":L.push(d.shift(),d.shift(),d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case\"c\":L.push(h+d.shift(),m+d.shift(),h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_=\"C\",L.push(h,m);break;case\"S\":c=h,u=m,y=l[l.length-1],\"C\"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,d.shift(),d.shift()),h=d.shift(),m=d.shift(),_=\"C\",L.push(h,m);break;case\"s\":c=h,u=m,y=l[l.length-1],\"C\"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_=\"C\",L.push(h,m);break;case\"Q\":L.push(d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case\"q\":L.push(h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_=\"Q\",L.push(h,m);break;case\"T\":c=h,u=m,y=l[l.length-1],\"Q\"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h=d.shift(),m=d.shift(),_=\"Q\",L.push(c,u,h,m);break;case\"t\":c=h,u=m,y=l[l.length-1],\"Q\"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h+=d.shift(),m+=d.shift(),_=\"Q\",L.push(c,u,h,m);break;case\"A\":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h=d.shift(),m=d.shift(),_=\"A\",L=this._convertPoint(W,X,h,m,k,x,g,b,f);break;case\"a\":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h+=d.shift(),m+=d.shift(),_=\"A\",L=this._convertPoint(W,X,h,m,k,x,g,b,f)}for(var v=0,w=L.length;w>v;v+=2)L[v]+=t,L[v+1]+=i;l.push(new n(_||U,L))}(\"z\"===U||\"Z\"===U)&&l.push(new n(\"z\",[]))}return l},_convertPoint:function(e,t,i,n,a,s,l,h,m){var V=m*(Math.PI/180),U=Math.cos(V)*(e-i)/2+Math.sin(V)*(t-n)/2,d=-1*Math.sin(V)*(e-i)/2+Math.cos(V)*(t-n)/2,p=U*U/(l*l)+d*d/(h*h);p>1&&(l*=Math.sqrt(p),h*=Math.sqrt(p));var c=Math.sqrt((l*l*h*h-l*l*d*d-h*h*U*U)/(l*l*d*d+h*h*U*U));a===s&&(c*=-1),isNaN(c)&&(c=0);var u=c*l*d/h,y=c*-h*U/l,g=(e+i)/2+Math.cos(V)*u-Math.sin(V)*y,b=(t+n)/2+Math.sin(V)*u+Math.cos(V)*y,f=r([1,0],[(U-u)/l,(d-y)/h]),k=[(U-u)/l,(d-y)/h],x=[(-1*U-u)/l,(-1*d-y)/h],_=r(k,x);return o(k,x)<=-1&&(_=Math.PI),o(k,x)>=1&&(_=0),0===s&&_>0&&(_-=2*Math.PI),1===s&&0>_&&(_+=2*Math.PI),[g,b,l,h,f,_,V,s]},buildPath:function(e,t){var i=t.path,n=t.x||0,a=t.y||0;t.pathArray=t.pathArray||this.buildPathArray(i,n,a);for(var o=t.pathArray,r=t.pointList=[],s=[],l=0,h=o.length;h>l;l++){\"M\"==o[l].command.toUpperCase()&&(s.length>0&&r.push(s),s=[]);for(var m=o[l].points,V=0,U=m.length;U>V;V+=2)s.push([m[V],m[V+1]])}s.length>0&&r.push(s);for(var l=0,h=o.length;h>l;l++){var d=o[l].command,m=o[l].points;switch(d){case\"L\":e.lineTo(m[0],m[1]);break;case\"M\":e.moveTo(m[0],m[1]);break;case\"C\":e.bezierCurveTo(m[0],m[1],m[2],m[3],m[4],m[5]);break;case\"Q\":e.quadraticCurveTo(m[0],m[1],m[2],m[3]);break;case\"A\":var p=m[0],c=m[1],u=m[2],y=m[3],g=m[4],b=m[5],f=m[6],k=m[7],x=u>y?u:y,_=u>y?1:u/y,L=u>y?y/u:1;e.translate(p,c),e.rotate(f),e.scale(_,L),e.arc(0,0,x,g,g+b,1-k),e.scale(1/_,1/L),e.rotate(-f),e.translate(-p,-c);break;case\"z\":e.closePath()}}},getRect:function(e){if(e.__rect)return e.__rect;var t;t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0;for(var i=Number.MAX_VALUE,n=Number.MIN_VALUE,a=Number.MAX_VALUE,o=Number.MIN_VALUE,r=e.x||0,s=e.y||0,l=e.pathArray||this.buildPathArray(e.path),h=0;h<l.length;h++)for(var m=l[h].points,V=0;V<m.length;V++)V%2===0?(m[V]+r<i&&(i=m[V]),m[V]+r>n&&(n=m[V])):(m[V]+s<a&&(a=m[V]),m[V]+s>o&&(o=m[V]));var U;return U=i===Number.MAX_VALUE||n===Number.MIN_VALUE||a===Number.MAX_VALUE||o===Number.MIN_VALUE?{x:0,y:0,width:0,height:0}:{x:Math.round(i-t/2),y:Math.round(a-t/2),width:n-i+t,height:o-a+t},e.__rect=U,U}},e(\"../tool/util\").inherits(s,t),s}),i(\"zrender/shape/Ellipse\",[\"require\",\"./Base\",\"../tool/util\"],function(e){var t=e(\"./Base\"),i=function(e){t.call(this,e)};return i.prototype={type:\"ellipse\",buildPath:function(e,t){var i=.5522848,n=t.x,a=t.y,o=t.a,r=t.b,s=o*i,l=r*i;e.moveTo(n-o,a),e.bezierCurveTo(n-o,a-l,n-s,a-r,n,a-r),e.bezierCurveTo(n+s,a-r,n+o,a-l,n+o,a),e.bezierCurveTo(n+o,a+l,n+s,a+r,n,a+r),e.bezierCurveTo(n-s,a+r,n-o,a+l,n-o,a),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t=\"stroke\"==e.brushType||\"fill\"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.a-t/2),\ny:Math.round(e.y-e.b-t/2),width:2*e.a+t,height:2*e.b+t},e.__rect}},e(\"../tool/util\").inherits(i,t),i}),i(\"echarts/component/roamController\",[\"require\",\"./base\",\"zrender/shape/Rectangle\",\"zrender/shape/Sector\",\"zrender/shape/Circle\",\"../config\",\"zrender/tool/util\",\"zrender/tool/color\",\"zrender/tool/event\",\"../component\"],function(e){function t(e,t,n,a,o){if(this.rcOption={},a.roamController&&a.roamController.show){if(!a.roamController.mapTypeControl)return void console.error(\"option.roamController.mapTypeControl has not been defined.\");i.call(this,e,t,n,a,o),this.rcOption=a.roamController;var r=this;this._drictionMouseDown=function(e){return r.__drictionMouseDown(e)},this._drictionMouseUp=function(e){return r.__drictionMouseUp(e)},this._drictionMouseMove=function(e){return r.__drictionMouseMove(e)},this._drictionMouseOut=function(e){return r.__drictionMouseOut(e)},this._scaleHandler=function(e){return r.__scaleHandler(e)},this.refresh(a)}}var i=e(\"./base\"),n=e(\"zrender/shape/Rectangle\"),a=e(\"zrender/shape/Sector\"),o=e(\"zrender/shape/Circle\"),r=e(\"../config\");r.roamController={zlevel:0,z:4,show:!0,x:\"left\",y:\"top\",width:80,height:120,backgroundColor:\"rgba(0,0,0,0)\",borderColor:\"#ccc\",borderWidth:0,padding:5,handleColor:\"#6495ed\",fillerColor:\"#fff\",step:15,mapTypeControl:null};var s=e(\"zrender/tool/util\"),l=e(\"zrender/tool/color\"),h=e(\"zrender/tool/event\");return t.prototype={type:r.COMPONENT_TYPE_ROAMCONTROLLER,_buildShape:function(){if(this.rcOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){this.shapeList.push(this._getDirectionShape(\"up\")),this.shapeList.push(this._getDirectionShape(\"down\")),this.shapeList.push(this._getDirectionShape(\"left\")),this.shapeList.push(this._getDirectionShape(\"right\")),this.shapeList.push(this._getScaleShape(\"scaleUp\")),this.shapeList.push(this._getScaleShape(\"scaleDown\"))},_getDirectionShape:function(e){var t=this._itemGroupLocation.r,i=this._itemGroupLocation.x+t,n=this._itemGroupLocation.y+t,o={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:i,y:n,r:t,startAngle:-45,endAngle:45,color:this.rcOption.handleColor,text:\">\",textX:i+t/2+4,textY:n-.5,textAlign:\"center\",textBaseline:\"middle\",textPosition:\"specific\",textColor:this.rcOption.fillerColor,textFont:Math.floor(t/2)+\"px arial\"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:\"fill\"},clickable:!0};switch(e){case\"up\":o.rotation=[Math.PI/2,i,n];break;case\"left\":o.rotation=[Math.PI,i,n];break;case\"down\":o.rotation=[-Math.PI/2,i,n]}return o=new a(o),o._roamType=e,o.onmousedown=this._drictionMouseDown,o.onmouseup=this._drictionMouseUp,o.onmousemove=this._drictionMouseMove,o.onmouseout=this._drictionMouseOut,o},_getScaleShape:function(e){var t=this._itemGroupLocation.width,i=this._itemGroupLocation.height-t;i=0>i?20:i;var n=Math.min(t/2-5,i)/2,a=this._itemGroupLocation.x+(\"scaleDown\"===e?t-n:n),r=this._itemGroupLocation.y+this._itemGroupLocation.height-n,s={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:a,y:r,r:n,color:this.rcOption.handleColor,text:\"scaleDown\"===e?\"-\":\"+\",textX:a,textY:r-2,textAlign:\"center\",textBaseline:\"middle\",textPosition:\"specific\",textColor:this.rcOption.fillerColor,textFont:Math.floor(n)+\"px verdana\"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:\"fill\"},clickable:!0};return s=new o(s),s._roamType=e,s.onmousedown=this._scaleHandler,s},_buildBackground:function(){var e=this.reformCssArray(this.rcOption.padding);this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.rcOption.borderWidth?\"fill\":\"both\",color:this.rcOption.backgroundColor,strokeColor:this.rcOption.borderColor,lineWidth:this.rcOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.rcOption.padding),i=this.rcOption.width,n=this.rcOption.height,a=this.zr.getWidth(),o=this.zr.getHeight();switch(this.rcOption.x){case\"center\":e=Math.floor((a-i)/2);break;case\"left\":e=t[3]+this.rcOption.borderWidth;break;case\"right\":e=a-i-t[1]-t[3]-2*this.rcOption.borderWidth;break;default:e=this.parsePercent(this.rcOption.x,a)}var r;switch(this.rcOption.y){case\"top\":r=t[0]+this.rcOption.borderWidth;break;case\"bottom\":r=o-n-t[0]-t[2]-2*this.rcOption.borderWidth;break;case\"center\":r=Math.floor((o-n)/2);break;default:r=this.parsePercent(this.rcOption.y,o)}return{x:e,y:r,r:i/2,width:i,height:n}},__drictionMouseDown:function(e){this.mousedown=!0,this._drictionHandlerOn(e)},__drictionMouseUp:function(e){this.mousedown=!1,this._drictionHandlerOff(e)},__drictionMouseMove:function(e){this.mousedown&&this._drictionHandlerOn(e)},__drictionMouseOut:function(e){this._drictionHandlerOff(e)},_drictionHandlerOn:function(e){this._dispatchEvent(e.event,e.target._roamType),clearInterval(this.dircetionTimer);var t=this;this.dircetionTimer=setInterval(function(){t._dispatchEvent(e.event,e.target._roamType)},100),h.stop(e.event)},_drictionHandlerOff:function(){clearInterval(this.dircetionTimer)},__scaleHandler:function(e){this._dispatchEvent(e.event,e.target._roamType),h.stop(e.event)},_dispatchEvent:function(e,t){this.messageCenter.dispatch(r.EVENT.ROAMCONTROLLER,e,{roamType:t,mapTypeControl:this.rcOption.mapTypeControl,step:this.rcOption.step},this.myChart)},refresh:function(e){e&&(this.option=e||this.option,this.option.roamController=this.reformOption(this.option.roamController),this.rcOption=this.option.roamController),this.clear(),this._buildShape()}},s.inherits(t,i),e(\"../component\").define(\"roamController\",t),t}),i(\"echarts/layer/heatmap\",[\"require\"],function(){function e(e){if(this.option=e,e)for(var i in t)this.option[i]=void 0!==e[i]?e[i]:t[i];else this.option=t}var t={blurSize:30,gradientColors:[\"blue\",\"cyan\",\"lime\",\"yellow\",\"red\"],minAlpha:.05,valueScale:1,opacity:1},i=20,n=256;return e.prototype={getCanvas:function(e,t,a){var o=this._getBrush(),r=this._getGradient(),s=i+this.option.blurSize,l=document.createElement(\"canvas\");l.width=t,l.height=a;for(var h=l.getContext(\"2d\"),m=e.length,V=0;m>V;++V){var U=e[V],d=U[0],p=U[1],c=U[2],u=Math.min(1,Math.max(c*this.option.valueScale||this.option.minAlpha,this.option.minAlpha));h.globalAlpha=u,h.drawImage(o,d-s,p-s)}for(var y=h.getImageData(0,0,l.width,l.height),g=y.data,m=g.length/4;m--;){var b=4*m+3,u=g[b]/256,f=Math.floor(u*(n-1));g[b-3]=r[4*f],g[b-2]=r[4*f+1],g[b-1]=r[4*f+2],g[b]*=this.option.opacity}return h.putImageData(y,0,0),l},_getBrush:function(){if(!this._brushCanvas){this._brushCanvas=document.createElement(\"canvas\");var e=i+this.option.blurSize,t=2*e;this._brushCanvas.width=t,this._brushCanvas.height=t;var n=this._brushCanvas.getContext(\"2d\");n.shadowOffsetX=t,n.shadowBlur=this.option.blurSize,n.shadowColor=\"black\",n.beginPath(),n.arc(-e,e,i,0,2*Math.PI,!0),n.closePath(),n.fill()}return this._brushCanvas},_getGradient:function(){if(!this._gradientPixels){var e=n,t=document.createElement(\"canvas\");t.width=1,t.height=e;for(var i=t.getContext(\"2d\"),a=i.createLinearGradient(0,0,0,e),o=this.option.gradientColors.length,r=0;o>r;++r)\"string\"==typeof this.option.gradientColors[r]?a.addColorStop((r+1)/o,this.option.gradientColors[r]):a.addColorStop(this.option.gradientColors[r].offset,this.option.gradientColors[r].color);i.fillStyle=a,i.fillRect(0,0,1,e),this._gradientPixels=i.getImageData(0,0,1,e).data}return this._gradientPixels}},e}),i(\"echarts/util/mapData/params\",[\"require\"],function(e){function t(e){if(!e.UTF8Encoding)return e;for(var t=e.features,n=0;n<t.length;n++)for(var a=t[n],o=a.geometry.coordinates,r=a.geometry.encodeOffsets,s=0;s<o.length;s++){var l=o[s];if(\"Polygon\"===a.geometry.type)o[s]=i(l,r[s]);else if(\"MultiPolygon\"===a.geometry.type)for(var h=0;h<l.length;h++){var m=l[h];l[h]=i(m,r[s][h])}}return e.UTF8Encoding=!1,e}function i(e,t){for(var i=[],n=t[0],a=t[1],o=0;o<e.length;o+=2){var r=e.charCodeAt(o)-64,s=e.charCodeAt(o+1)-64;r=r>>1^-(1&r),s=s>>1^-(1&s),r+=n,s+=a,n=r,a=s,i.push([r/1024,s/1024])}return i}var n={none:{getGeoJson:function(e){e({type:\"FeatureCollection\",features:[{type:\"Feature\",geometry:{coordinates:[],encodeOffsets:[],type:\"Polygon\"},properties:{}}]})}},world:{getGeoJson:function(i){e([\"./geoJson/world_geo\"],function(e){i(t(e))})}},china:{getGeoJson:function(i){e([\"./geoJson/china_geo\"],function(e){i(t(e))})}},\"南海诸岛\":{textCoord:[126,25],getPath:function(e,t){for(var i=[[[0,3.5],[7,11.2],[15,11.9],[30,7],[42,.7],[52,.7],[56,7.7],[59,.7],[64,.7],[64,0],[5,0],[0,3.5]],[[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],[[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],[[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],[[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],[[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],[[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],[[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],[[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],[[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],[[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],[[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],[1,92.4],[1,3.5],[0,3.5]]],n=\"\",a=e[0],o=e[1],r=0,s=i.length;s>r;r++){n+=\"M \"+((i[r][0][0]*t+a).toFixed(2)-0)+\" \"+((i[r][0][1]*t+o).toFixed(2)-0)+\" \";for(var l=1,h=i[r].length;h>l;l++)n+=\"L \"+((i[r][l][0]*t+a).toFixed(2)-0)+\" \"+((i[r][l][1]*t+o).toFixed(2)-0)+\" \"}return n+\" Z\"}},\"新疆\":{getGeoJson:function(i){e([\"./geoJson/xin_jiang_geo\"],function(e){i(t(e))})}},\"西藏\":{getGeoJson:function(i){e([\"./geoJson/xi_zang_geo\"],function(e){i(t(e))})}},\"内蒙古\":{getGeoJson:function(i){e([\"./geoJson/nei_meng_gu_geo\"],function(e){i(t(e))})}},\"青海\":{getGeoJson:function(i){e([\"./geoJson/qing_hai_geo\"],function(e){i(t(e))})}},\"四川\":{getGeoJson:function(i){e([\"./geoJson/si_chuan_geo\"],function(e){i(t(e))})}},\"黑龙江\":{getGeoJson:function(i){e([\"./geoJson/hei_long_jiang_geo\"],function(e){i(t(e))})}},\"甘肃\":{getGeoJson:function(i){e([\"./geoJson/gan_su_geo\"],function(e){i(t(e))})}},\"云南\":{getGeoJson:function(i){e([\"./geoJson/yun_nan_geo\"],function(e){i(t(e))})}},\"广西\":{getGeoJson:function(i){e([\"./geoJson/guang_xi_geo\"],function(e){i(t(e))})}},\"湖南\":{getGeoJson:function(i){e([\"./geoJson/hu_nan_geo\"],function(e){i(t(e))})}},\"陕西\":{getGeoJson:function(i){e([\"./geoJson/shan_xi_1_geo\"],function(e){i(t(e))})}},\"广东\":{getGeoJson:function(i){e([\"./geoJson/guang_dong_geo\"],function(e){i(t(e))})}},\"吉林\":{getGeoJson:function(i){e([\"./geoJson/ji_lin_geo\"],function(e){i(t(e))})}},\"河北\":{getGeoJson:function(i){e([\"./geoJson/he_bei_geo\"],function(e){i(t(e))})}},\"湖北\":{getGeoJson:function(i){e([\"./geoJson/hu_bei_geo\"],function(e){i(t(e))})}},\"贵州\":{getGeoJson:function(i){e([\"./geoJson/gui_zhou_geo\"],function(e){i(t(e))})}},\"山东\":{getGeoJson:function(i){e([\"./geoJson/shan_dong_geo\"],function(e){i(t(e))})}},\"江西\":{getGeoJson:function(i){e([\"./geoJson/jiang_xi_geo\"],function(e){i(t(e))})}},\"河南\":{getGeoJson:function(i){e([\"./geoJson/he_nan_geo\"],function(e){i(t(e))})}},\"辽宁\":{getGeoJson:function(i){e([\"./geoJson/liao_ning_geo\"],function(e){i(t(e))})}},\"山西\":{getGeoJson:function(i){e([\"./geoJson/shan_xi_2_geo\"],function(e){i(t(e))})}},\"安徽\":{getGeoJson:function(i){e([\"./geoJson/an_hui_geo\"],function(e){i(t(e))})}},\"福建\":{getGeoJson:function(i){e([\"./geoJson/fu_jian_geo\"],function(e){i(t(e))})}},\"浙江\":{getGeoJson:function(i){e([\"./geoJson/zhe_jiang_geo\"],function(e){i(t(e))})}},\"江苏\":{getGeoJson:function(i){e([\"./geoJson/jiang_su_geo\"],function(e){i(t(e))})}},\"重庆\":{getGeoJson:function(i){e([\"./geoJson/chong_qing_geo\"],function(e){i(t(e))})}},\"宁夏\":{getGeoJson:function(i){e([\"./geoJson/ning_xia_geo\"],function(e){i(t(e))})}},\"海南\":{getGeoJson:function(i){e([\"./geoJson/hai_nan_geo\"],function(e){i(t(e))})}},\"台湾\":{getGeoJson:function(i){e([\"./geoJson/tai_wan_geo\"],function(e){i(t(e))})}},\"北京\":{getGeoJson:function(i){e([\"./geoJson/bei_jing_geo\"],function(e){i(t(e))})}},\"天津\":{getGeoJson:function(i){e([\"./geoJson/tian_jin_geo\"],function(e){i(t(e))})}},\"上海\":{getGeoJson:function(i){e([\"./geoJson/shang_hai_geo\"],function(e){i(t(e))})}},\"香港\":{getGeoJson:function(i){e([\"./geoJson/xiang_gang_geo\"],function(e){i(t(e))})}},\"澳门\":{getGeoJson:function(i){e([\"./geoJson/ao_men_geo\"],function(e){i(t(e))})}}};return{decode:t,params:n}}),i(\"echarts/util/mapData/textFixed\",[],function(){return{\"广东\":[0,-10],\"香港\":[10,10],\"澳门\":[-10,18],\"黑龙江\":[0,20],\"天津\":[5,5],\"深圳市\":[-35,0],\"红河哈尼族彝族自治州\":[0,20],\"楚雄彝族自治州\":[-5,15],\"石河子市\":[-5,5],\"五家渠市\":[0,-10],\"昌吉回族自治州\":[10,10],\"昌江黎族自治县\":[0,20],\"陵水黎族自治县\":[0,20],\"东方市\":[0,20],\"渭南市\":[0,20]}}),i(\"echarts/util/mapData/geoCoord\",[],function(){return{Russia:[100,60],\"United States of America\":[-99,38]}}),i(\"echarts/util/projection/svg\",[\"require\",\"zrender/shape/Path\"],function(e){function t(e){return parseFloat(e||0)}function i(e){for(var i=e.firstChild;\"svg\"!=i.nodeName.toLowerCase()||1!=i.nodeType;)i=i.nextSibling;var n=t(i.getAttribute(\"x\")),a=t(i.getAttribute(\"y\")),o=t(i.getAttribute(\"width\")),r=t(i.getAttribute(\"height\"));return{left:n,top:a,width:o,height:r}}function n(e,t){function i(e){var t=e.tagName;if(m[t]){var o=m[t](e,n);o&&(o.scale=n,o.properties={name:e.getAttribute(\"name\")||\"\"},o.id=e.id,s(o,e),a.push(o))}for(var r=e.childNodes,l=0,h=r.length;h>l;l++)i(r[l])}var n=[t.scale.x,t.scale.y],a=[];return i(e),a}function a(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]/e.scale.x,i[1]/e.scale.y]}function o(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]*e.scale.x,i[1]*e.scale.y]}function r(e){return e.replace(/^\\s\\s*/,\"\").replace(/\\s\\s*$/,\"\")}function s(e,t){var i=t.getAttribute(\"fill\"),n=t.getAttribute(\"stroke\"),a=t.getAttribute(\"stroke-width\"),o=t.getAttribute(\"opacity\");i&&\"none\"!=i?(e.color=i,n?(e.brushType=\"both\",e.strokeColor=n):e.brushType=\"fill\"):n&&\"none\"!=n&&(e.strokeColor=n,e.brushType=\"stroke\"),a&&\"none\"!=a&&(e.lineWidth=parseFloat(a)),o&&\"none\"!=o&&(e.opacity=parseFloat(o))}function l(e){for(var t=r(e).replace(/,/g,\" \").split(/\\s+/),i=[],n=0;n<t.length;){var a=parseFloat(t[n++]),o=parseFloat(t[n++]);i.push([a,o])}return i}var h=e(\"zrender/shape/Path\"),m={path:function(e,t){var i=e.getAttribute(\"d\"),n=h.prototype.getRect({path:i});return{shapeType:\"path\",path:i,cp:[(n.x+n.width/2)*t[0],(n.y+n.height/2)*t[1]]}},rect:function(e,i){var n=t(e.getAttribute(\"x\")),a=t(e.getAttribute(\"y\")),o=t(e.getAttribute(\"width\")),r=t(e.getAttribute(\"height\"));return{shapeType:\"rectangle\",x:n,y:a,width:o,height:r,cp:[(n+o/2)*i[0],(a+r/2)*i[1]]}},line:function(e,i){var n=t(e.getAttribute(\"x1\")),a=t(e.getAttribute(\"y1\")),o=t(e.getAttribute(\"x2\")),r=t(e.getAttribute(\"y2\"));return{shapeType:\"line\",xStart:n,yStart:a,xEnd:o,yEnd:r,cp:[.5*(n+o)*i[0],.5*(a+r)*i[1]]}},circle:function(e,i){var n=t(e.getAttribute(\"cx\")),a=t(e.getAttribute(\"cy\")),o=t(e.getAttribute(\"r\"));return{shapeType:\"circle\",x:n,y:a,r:o,cp:[n*i[0],a*i[1]]}},ellipse:function(e,t){var i=parseFloat(e.getAttribute(\"cx\")||0),n=parseFloat(e.getAttribute(\"cy\")||0),a=parseFloat(e.getAttribute(\"rx\")||0),o=parseFloat(e.getAttribute(\"ry\")||0);return{shapeType:\"ellipse\",x:i,y:n,a:a,b:o,cp:[i*t[0],n*t[1]]}},polygon:function(e,t){var i=e.getAttribute(\"points\"),n=[1/0,1/0],a=[-(1/0),-(1/0)];if(i){i=l(i);for(var o=0;o<i.length;o++){var r=i[o];n[0]=Math.min(r[0],n[0]),n[1]=Math.min(r[1],n[1]),a[0]=Math.max(r[0],a[0]),a[1]=Math.max(r[1],a[1])}return{shapeType:\"polygon\",pointList:i,cp:[(n[0]+a[0])/2*t[0],(n[1]+a[1])/2*t[0]]}}},polyline:function(e,t){var i=m.polygon(e,t);return i}};return{getBbox:i,geoJson2Path:n,pos2geo:a,geo2pos:o}}),i(\"echarts/util/projection/normal\",[],function(){function e(e,i){return i=i||{},e.srcSize||t(e,i),e.srcSize}function t(e,t){t=t||{},r.xmin=360,r.xmax=-360,r.ymin=180,r.ymax=-180;for(var i,n,a=e.features,o=0,s=a.length;s>o;o++)if(n=a[o],!n.properties.name||!t[n.properties.name])switch(n.type){case\"Feature\":r[n.geometry.type](n.geometry.coordinates);break;case\"GeometryCollection\":i=n.geometries;for(var l=0,h=i.length;h>l;l++)r[i[l].type](i[l].coordinates)}return e.srcSize={left:1*r.xmin.toFixed(4),top:1*r.ymin.toFixed(4),width:1*(r.xmax-r.xmin).toFixed(4),height:1*(r.ymax-r.ymin).toFixed(4)},e}function i(e,i,n){function a(e,t){c=e.type,u=e.coordinates,o._bbox={xmin:360,xmax:-360,ymin:180,ymax:-180},y=o[c](u),m.push({path:y,cp:o.makePoint(t.properties.cp?t.properties.cp:[(o._bbox.xmin+o._bbox.xmax)/2,(o._bbox.ymin+o._bbox.ymax)/2]),properties:t.properties,id:t.id})}n=n||{},o.scale=null,o.offset=null,e.srcSize||t(e,n),i.offset={x:e.srcSize.left,y:e.srcSize.top,left:i.OffsetLeft||0,top:i.OffsetTop||0},o.scale=i.scale,o.offset=i.offset;for(var r,s,l,h=e.features,m=[],V=0,U=h.length;U>V;V++)if(l=h[V],!l.properties.name||!n[l.properties.name])if(\"Feature\"==l.type)a(l.geometry,l);else if(\"GeometryCollection\"==l.type){r=l.geometries;for(var d=0,p=r.length;p>d;d++)s=r[d],a(s,s)}var c,u,y;return m}function n(e,t){var i,n;return t instanceof Array?(i=1*t[0],n=1*t[1]):(i=1*t.x,n=1*t.y),i=i/e.scale.x+e.offset.x-168.5,i=i>180?i-360:i,n=90-(n/e.scale.y+e.offset.y),[i,n]}function a(e,t){return o.offset=e.offset,o.scale=e.scale,o.makePoint(t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y])}var o={formatPoint:function(e){return[(e[0]<-168.5&&e[1]>63.8?e[0]+360:e[0])+168.5,90-e[1]]},makePoint:function(e){var t=this,i=t.formatPoint(e);t._bbox.xmin>e[0]&&(t._bbox.xmin=e[0]),t._bbox.xmax<e[0]&&(t._bbox.xmax=e[0]),t._bbox.ymin>e[1]&&(t._bbox.ymin=e[1]),t._bbox.ymax<e[1]&&(t._bbox.ymax=e[1]);var n=(i[0]-o.offset.x)*o.scale.x+o.offset.left,a=(i[1]-o.offset.y)*o.scale.y+o.offset.top;return[n,a]},Point:function(e){return e=this.makePoint(e),e.join(\",\")},LineString:function(e){for(var t,i=\"\",n=0,a=e.length;a>n;n++)t=o.makePoint(e[n]),i=0===n?\"M\"+t.join(\",\"):i+\"L\"+t.join(\",\");return i},Polygon:function(e){for(var t=\"\",i=0,n=e.length;n>i;i++)t=t+o.LineString(e[i])+\"z\";return t},MultiPoint:function(e){for(var t=[],i=0,n=e.length;n>i;i++)t.push(o.Point(e[i]));return t},MultiLineString:function(e){for(var t=\"\",i=0,n=e.length;n>i;i++)t+=o.LineString(e[i]);return t},MultiPolygon:function(e){for(var t=\"\",i=0,n=e.length;n>i;i++)t+=o.Polygon(e[i]);return t}},r={formatPoint:o.formatPoint,makePoint:function(e){var t=this,i=t.formatPoint(e),n=i[0],a=i[1];t.xmin>n&&(t.xmin=n),t.xmax<n&&(t.xmax=n),t.ymin>a&&(t.ymin=a),t.ymax<a&&(t.ymax=a)},Point:function(e){this.makePoint(e)},LineString:function(e){for(var t=0,i=e.length;i>t;t++)this.makePoint(e[t])},Polygon:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPoint:function(e){for(var t=0,i=e.length;i>t;t++)this.Point(e[t])},MultiLineString:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPolygon:function(e){for(var t=0,i=e.length;i>t;t++)this.Polygon(e[t])}};return{getBbox:e,geoJson2Path:i,pos2geo:n,geo2pos:a}}),i(\"echarts/util/mapData/geoJson/an_hui_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3415\",properties:{name:\"六安市\",cp:[116.3123,31.8329],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@nJUXUV°UÑnU@mlLVaVln@@bn@VU@xlb@lLnKlVIJUVxnI@lVL@b°VX@bxnVVUnVVnU@kX@VwV@al¥UUnUWa@@wĸULU¥lKUa@aUI@alLVaU¯anWkUKm@XV@VaXlW@aU_UWVUI¯@ma¯W¯I@UU@WWU@U@@UU@VkV@@WUUm@UaU@lK@IUKL@KWmXUWaXI@@a@a@U@U@KV¥lwk°b²JVIVKlV@UXlaUl`UVLVVVUJU@Lnm@_VK@KUIW@J@Xk@WW@UmmXmWk@kK@aUUVmmkUwUmWL@WmU@UJmUULkKWakLWVkIlwULW@X°lUJ@°ULWVwmJ@bmb¯Vkm@@WkWm¯wL@lkXWmXym¯UImJUbkV@Vn¯@V@lUb@mk@maUxmlUbULWn@JLmKUkWKkwUKbmXWxkVUKmLkVV@JUUWL@xkJUUV@X@VVlUbVX@xk¤x¼xWxnnn@Þ¼JVb°aVn@mlnXUJlbVlkz@lUlXJmxVxXnWxXÈWlU@UxU@VX@xUL@UÆmLnV@lWXk@@JlbXblnlJ\"],encodeOffsets:[[118710,33351]]}},{type:\"Feature\",id:\"3408\",properties:{name:\"安庆市\",cp:[116.7517,30.5255],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@n°znWXlW@kK°xXnl@Xn@l°Una@anIxXUVK@¯VIkW¯X@VKxklJXUlKXblLVKnVVIV@Xn@XKVnVxlnnUlmV@²óUkVlWbln@VVVIn@lw@WVIXblV@ÈxaUaVIVVnKVLKln@b²K@»U£ÑķġÝÅbKa@Im@Û@kWÓkkmKÅnóJUÅ£W@wĕ@wĉţ¯¯UkK±l¯U¥UÑkÝUķ»Ý¥¯JIUVbUl¯ÈV¼VJU¼Vb@bkLUl@VJ@bUXÇ@lkVmXmKkLVxVL@VkVVVlzWkbmLUUUbVbUVlÒnJlUnLllUL@bUVxlLXVÆ¦ÈVU¦WJ\"],encodeOffsets:[[118834,31759]]}},{type:\"Feature\",id:\"3411\",properties:{name:\"滁州市\",cp:[118.1909,32.536],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@@`nnl@xK@X°KXVIXVlbXVWnXlL@È»LVan@VJêVVn@X@laÞbVayn@_xnWVXnWl@VnUVkI@lnXKVLVV@V@kW@LlVô@J@bVnnKnkVa@»lç@nwKmaUUUVÑ@nmWXalI@alVn@VwUaVU@nlaôJnUVVXlJaXXVK@UV@VWx@nXVWXVUlLUbVULVVnUVbUbVb@@aKÆnnKVK@U@UU@@a@V°¯ÈJVIlķ@aaUaVKU_@mkxUI@aUlyU@@wkKWmUbUnUVWbkJW_J@bn@Vm@@KULk@V@@bVbÅm@LW@UVVbkK@UkKWL@VULUKWIUJUbkK@_WVXUJka@XVa@ky@aVIUUW@@mUlLKWÑUKVan@UkVmmIXKaVaUwVU@UmykU¯@±UUL@WUIVUU@KkIWaaU@kUUaÇUó»mKk¯@y@kWK@bkI¯`mnl¯XWlkVUzUJlbUbVJl@nnm@VULV`XnWÆbmUUnJmUknJ¯km@yk@kUxL@VUbmnn¤lX@`z@JmaULUVl@Xn@xllkXWaaW@UVmUb@mVXWxXbWbUÒnVVnVVUL\"],encodeOffsets:[[120004,33520]]}},{type:\"Feature\",id:\"3418\",properties:{name:\"宣城市\",cp:[118.8062,30.6244],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@Vb@XLJXxlIXxlVlV@I²¤nlUnVU@VULWVUJ@Lnb@lV@UnV@@VVVlLnbnJUVkUUVWn@@anUVnVJVIV@@nUJVbUb@VUbVK@bn@VbnIlxkllXVlXKWUXUlL°¤UVVb@bUlkXWxXz@IlaUlnUlJVInVÆJULVUnVK°@VnlVnxV@XLlK@wVL@KnUlJXUbnKVLXlUw@VWlLXKm@@a@VLnmlIVVnKn@kVaVlwk@@a@k@VIUa@maUa@wna@kmWUUmVUIVÇ@aKmakUJ@InmUUaVaklX@Vk@m@VU@wnK@alKVUkUkKbmUkm@U£WVk@@UÝbbaÇx@b@WVUa¯@wVwUUV@VwnK@KWaÅ@KIUyUI@WmXóUbWaKm@km@IUyIUaWKx@zUKUL@llVUnkLVVkJWX@VUKUVIkVWakb@VWb@n@JkXUlmL@xkL@`VxLUÈUJ@Vm@@bmIUlUL@VUVVbknm@mKUwKVÈ@J@LV±kkJUIl\"],encodeOffsets:[[120803,31247]]}},{type:\"Feature\",id:\"3412\",properties:{name:\"阜阳市\",cp:[115.7629,32.9919],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@Vn@ak°a±@¥@UUI@aUmlwUUxb@¥XU@mmI@a@Kn@@_W@@WI@mUVVXUl@XaV@K@I@aLX@aVI°K@KVLUUwyXkK@kKÆbXnlK@k@aJlU@w@U@»@aXKWn_JXkVKn@°LlKXW@¯U@aUK@kmJUwVIUJkmLK@kka@wUVm@@am@UkUbkK@nmVÒ¯VUWVVmIULk@ma@kkK@nUbUamU`UUVUkKVkkW@@bkmnmUXVKXVL@VbUmbVXJ@nmKÅI@KWKUXVJUL@VUKUX@KUKWL@LUJmaXXm@kVVV@L@VUL@VlK@L@V@LUK@VUb@UUU@°@nVxU`Lkn@`@XVJ@XVmk@UKmV¯LVVn±Wm@Ub@JlLUl@VLk@lmVVn@bnV@V°IVaVJXI°K°V@XXVlVVUnKVlUbWXnV@bV`U@@m@@@nxmn@bXVlL@¤nbUl¦VVUnJVUVl@@bÞL\"],encodeOffsets:[[118418,34392]]}},{type:\"Feature\",id:\"3413\",properties:{name:\"宿州市\",cp:[117.5208,33.6841],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@@UWU@bkW@aWU@aUIkWVlLXblVIUVV@mn@V_n@VaUK@I@UaanJVU@lVUVnnKVVlaUaI@wnKLnll@nVlk@wVKXkl@@bbUJ@VU@UUUyVk@aVUXwlWXXWU¹@aU@WUI@mlUnJ@Il@aXbV@VKl@XxVL@WIJlb@al@IUUm@@aVK@¥¯@mUķ¯bWk£Vm@akm@VaÅ@UVWa@UJWkJUbWbU@UlXk@amV@K¯nk@lU@Uxmz@bU`ÇbUbÅVm£U@Wwx@akLUK@UlakwUJWVkLmaUal@n_mVUnKVUUmÅXWa@kJmx@XUJ@bVLXxl@VVUVVUbkLWbU@@lUVVVVXK@XkJ@nU@@bV@VxUVlbU@xXLWn@UxVbVĊV@b@XV`mnkJ@kUKmbaU@VbnbÆx@XU@@`k@@bl@@bkL@WakXWaU@Vmkx@XWW@@wUUUbJU¯V@¯ÞU@WxXlL@bkb@lVlnbJW@kkU@mbkaWJIVlmz¯`UnU@mb@@`@bkVlnV@b@V@aVxn@VxKXnl@nbVKbVK@a_V@Vw@WLlwnK@UmIU@VW@UÈ@lKnalw@@V°@aUmlUUw@V@@UXK\"],encodeOffsets:[[119836,35061]]}},{type:\"Feature\",id:\"3410\",properties:{name:\"黄山市\",cp:[118.0481,29.9542],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lXnlWX@VUJVnUJVzXJVxkVJlI²lU@K@IUÇLVxnLn@lmUaVU@UVKVknJ@an@@UVIVÇKUw@_lK@wnKVklW@I@mXa@UlaXblUJVUVL@UXWlIUUlKVmkU@kVKVL@ywXLVbJVz@Jln@nLXbVaônW@la@UVWUa@@a@mk@WIk@VwUa¯¥m@UUVK@ImK@aX£kKÅVa_@±akXWWLnU@@a@¯mK@LJUWwUVVmbXX@lWLn`mzUJUbLk@makVWmkXambkKkna@ab@U@Unm@WV@VbUbUJWIk@@lmL@°UVUVmn@@kmWkb@x_m@@aU@b@JlUzlWxXn@b²@l`IVlUlL@VKnVbUl@VlIn@@bbVWUk@@bX@Valb@bnb°Vn@xVKlbVnV@VxL@ln@UXVVL\"],encodeOffsets:[[120747,31095]]}},{type:\"Feature\",id:\"3414\",properties:{name:\"巢湖市\",cp:[117.7734,31.4978],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@VV@blL@XlWnnn@VXXl@@WIX@VJ@LxŎxln@bXJVblX@VVbUVn@VbUVlb@LnJVbVLVXLÒVLÒVbVIVylUXk°Wknm°_lJ@aXL@lz°@lnLô¼VÈVUUaVKU@WW@@UUa@knmVLlaV@a@kak±@UmwkKmkǉÝUUkL@mlIVmnÝWkkUÝ@KƑĉa@»mma@mX¤¯Uw@@UU@bU±±L@akmLUKmLUUUJVbbÇw@kUWaUJ@Xkxm@UJUUm@kakXUVl±ôU@kn\"],encodeOffsets:[[119847,32007]]}},{type:\"Feature\",id:\"3416\",properties:{name:\"亳州市\",cp:[116.1914,33.4698],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@lU@Un@@anUlw@KVmUwlaX_lKna@KU@@kWKUU@ankWXK@@V²VVIÈU@al@VaÈamK@wU@klaUV@XVUU»WUUbkmUkVmk@aÈw@mWU@VkIkVWKUÑķXȭºU¯l@kkLWmÅaL@lLWlzVxVUK@L¯LUJ@bWK@b@JLU@Wbk@WVUUV@nJ@XX@@`m@@L@bnJ@nWV@¦awVVkxVn@bVJ@V¦@²¯blb@mUU@¼¦XbUV`@nnxUxWLkUkVWKkV@XV@@VVL@VX@lVV@L@blL@`L@xXKVL@VnU@lwnU@ml@XnV@@UVW°LnalUI@aUK@aa@UkXW@I@mWL@UXK@UVW@U@@kWn@@V@XblaVxL@bVKXbIlJ\"],encodeOffsets:[[119183,34594]]}},{type:\"Feature\",id:\"3417\",properties:{name:\"池州市\",cp:[117.3889,30.2014],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@V°°ĊŤ@xĖ@xXÆ¤VôIÆmnLllXÔ@lÜn@@JbLÆaĢÞĸ°VVUUKVanK@UV@VLVVnln@xnklxXamk@WV@Xa@naVkKlk@mkUWwkJWwIWK@UaUwWIUyVIUmVI@UXWmkkWKUUVWm@@kKw@UUUmkaULwm@¯Uma@akaUbW@@a@VlUXa@am@kJ@UVkUamL@UkKVUkJk_±@a@WmXwÇkkaVaUa±wV@VkwnyUaW@UU¯amLk@m@kmmU¯K@L@lUX¯WlkXVbbVUL@J@LVKnlJXnlb@`nXlalV@bnL@Vnb¼@lXbWlkLK@zUJmIUxUVUVmX\",\"@@llUL@VlxL@a@UwXa¯@\"],encodeOffsets:[[119543,30781],[120061,31152]]}},{type:\"Feature\",id:\"3401\",properties:{name:\"合肥市\",cp:[117.29,32.0581],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@LxVĊLÞkVlVVXaWaXwWnU@anVVUX@bXblWkk@wWmk@VUVKnb@Iy@_kWm£nmVa@UKwlVl@zn@°lIlmnVIVmnVaXÅWmU_VK@Unmmk@UIVakaaUÑUKÑWKUUKUamI@KkaVUUam@VUUa@UkWUaWI@akmōwwUL@`mn@KVIUVUUUKVk_VkbW@VkUULUJ±I¯alkxU¦@L@V@V@b@b@WJXbWVXn@LKVL@JkLV@Vbn@VV@XU@UlV@@VV@V@XXV@@VJ°°Xnb°@JUVVXV`@bkXWUbU@Wn@VLXlm°bVUbkK@bVJ@bVbkLV¦KķV@x@XbmVVVk¦\"],encodeOffsets:[[119678,33323]]}},{type:\"Feature\",id:\"3403\",properties:{name:\"蚌埠市\",cp:[117.4109,33.1073],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@VÒXLlUlJ@UXV@nÇx@bnlUVllnVaXVV¼UVWU@V²wVV@Vl@VnwlI@XbÆWVnUVmLUVnm`k@VbnblKXUVIlxkb@VVLlK@bwXxV@n¤ÆUVaÈaV_@anyVwV@kl@°m@LnUbl@WVkV@XaaVIXlIV@XbVUÆ@XKWwUkmW@_UmnIlJXkWKXmV@w@_XV@Kl@kU@KlX@@UUUUKWLm@klJVUUmk@mXUWmXw`m@zUbÝakbW@m@UUéUIm@UbKÇ¼@kKWXmWUkaWUJWU¯L@WLwk@mm@_ÅlUVkmWUnV@VWLUbbƑĬ¯l\"],encodeOffsets:[[119543,33722]]}},{type:\"Feature\",id:\"3402\",properties:{name:\"芜湖市\",cp:[118.3557,31.0858],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@bVaV@XllLXU°lL@V@VUnVl¯IkVUVU@@b@lUXUWmbn@¼bƒĊLÞ@lVXlmÞUnkJ@nlKVVÞXklWVaVI@aUKn»lL@Kn@XXwlm@mn°@V@WywXlWVk@aUaVU¯£kKWVXVWLUkkWlkkwmJUam@@aULVa@UVaUaVI@m@UUJUIUmmV@bm@UXVVUlVmImakKUU@UU@VmU@@kma@KVIXUVK@UVmUkVm±£@JkU@nlkLUlmb@WbU@@XnlWb\"],encodeOffsets:[[120814,31585]]}},{type:\"Feature\",id:\"3406\",properties:{name:\"淮北市\",cp:[116.6968,33.6896],childNum:3},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@lnnK@¦n@@VV@@VV@nIVV@VW²a@b@bVnUVVV@Vz@l@°UVIVaVV@x@XX@WlwUnV@XblWb@XlK@a@k@al@@_V@@WÅwmaUaV@bnaVL@llInmU_@W@aUUĉUaVwm@XWK@wVkaVUUwU@@aV@@mlI@WLWUUUVU@kV@XalKVaUVUUUk@WwUK@aVI@WUk@@UUU±xkb@lV@xnLÇbUbk@@bÇVUJ±U@U@WLXml@bVVXL@lV@@LmbkLW`kbVxUn@LkxmV@bm@@VkV\"],[\"@@VVVkV@¥@UV@U@VUUJkWakKUlXVJ@bXV@blX@aXV@V\"]],encodeOffsets:[[[119183,34594]],[[119836,35061]]]}},{type:\"Feature\",id:\"3404\",properties:{name:\"淮南市\",cp:[116.7847,32.7722],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@°kƒīaVaXK@UUVmnXUlVÆkVKUUUmmUÑkUUÝlĉKUwKbU@UxW@@lmVUUVmUUmwaWkL¯K@mULWlIm`XWL@b@¼@V@xkVI@b@l@lkV°Ȯ¹ĸW\"],encodeOffsets:[[119543,33722]]}},{type:\"Feature\",id:\"3405\",properties:{name:\"马鞍山市\",cp:[118.6304,31.5363],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@ǊnllLnxV@laXLVKmaaXbVIbVKVVVIVyn@n_W@@UnJlUVVXlLnaUWlV@VVIXW@_W@XK@K@UVUUwVamÑXmmwwKUnUKçU@JU¯@m@nknWxWm@@LkKm¼VL@bUJUbkXWl\"],encodeOffsets:[[121219,32288]]}},{type:\"Feature\",id:\"3407\",properties:{name:\"铜陵市\",cp:[117.9382,30.9375],childNum:3},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ÒV¤@¼V²@aVV@@x°V£nW@nbnaVXVW@k@aV@VUUl°JUkVm@U@UkK¯WVkKWkU@Ubakwmlwm@kUmUUKU@@VmLUbVLUV¯U\"],[\"@@LllUL@VlxL@a@UwXamK\"]],encodeOffsets:[[[120522,31529]],[[120094,31146]]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/ao_men_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"8200\",properties:{name:\"澳门\",cp:[113.5715,22.1583],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@HQFMDIDGBI@E@EEKEGCEIGGEKEMGSEU@CBEDAJAP@F@LBT@JCHMPOdADCFADAB@LFLDFFP@DAB@@AF@D@B@@FBD@FADHBBHAD@FAJ@JEDCJI`gFIJW\"],encodeOffsets:[[116325,22699]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/bei_jing_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"110228\",properties:{name:\"密云县\",cp:[117.0923,40.5121],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@vIHZDZQtDLNMXIbHRCXXITbJ@H`LGPRDDJNCLHTOCWFGvGBUJMKGFO^IHWXITQCIY^AXGfRDXF`DJOLB~G\\\\DZIHHpErUVMhHb]\\\\MBVF@FTP`@zTbD\\\\@~M\\\\K`H^EVODWICAakAQXoIcCOCIgGYNWFWNGGKKGaJEGMEIKYJUT_J_Go@_SyQaSFMEGTcYOQLIIi@EKAUPCV[EEXQCW|aMUMAaYCYNIDGGACIMGGSKDQGaF_C[GaB@GOIiOKAYLmI@CN]F[SWWAcKKI@HMUimEKbeYQYISNUOcBKPIFBNgvDPGZYFSf]CMSIWGEUFgDIQ[MeDMJS@RR@LphFPCHaBAJKF@J]IBJO@HlO@@RKAMPJHCNDJTHFP@ZGNANBRFH@J_fM^ONJNF\\\\VTDJHDON@XRND\\\\XRCPVETCLBVKDFJINHRGPRV@\\\\CLJN@VbXbLVT\"],encodeOffsets:[[119561,41684]]}},{type:\"Feature\",id:\"110116\",properties:{name:\"怀柔区\",cp:[116.6377,40.6219],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@JHTVHXCHPfnDJGHNDJSB[JSBGVSAOH@PMPuDEHHXZN@PHF@ZLJ@LHVYJA\\\\OFWP]BMtMBSRGV[JeVAPQVIFENMD¡@^NV\\\\JH@NNL@NM\\\\kTQ\\\\I^FNIpBHGTBFFAZQfKDIXQTLXFXNNVMVHRGpCFLlRLEVBBH`IVO\\\\G`RDPAXLXBXORHZEHTDLLN@VGTMrQNFPeASKG@GMOAKBYMK@GTUHUXSHMVDNMOUEOZMJML@^KRACMZEZMRQLUHE@OFENPR@DI\\\\ChMHIDG\\\\GJMDWHCKGMDCIQCHO_K@GaIJSWWQDaGWJMNCKRsCYGYuJUSaKaW@UIMDK@[QUHOGQJMEILCAUDKFSOUQD[WMCQ@WPMGCCIUSE[IMPMN]`e@IEGAQBMHM@YEOSGCIDMIGNOLB@QP@GkP@AI^J@ILEBIbADGEOog@KQQWSekWQQUOFKZLF@PUNmIaHIUeBCTSHENcJa@_IWSaGu`GLSBKJQFOXGDXVQVOBIHcDSJWBEFGTMH[^mLaXcHiKElTRKtFXZ`MHMPCNRDxZB\\\\ICIHK@KHbIVFZ@BPnGTGbDXRDJaZKRiGEFSFEJhjFNZFjn\"],encodeOffsets:[[119314,41552]]}},{type:\"Feature\",id:\"110111\",properties:{name:\"房山区\",cp:[115.8453,39.7163],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@h@bl@HRJDZ``TA\\\\VVD^H`\\\\pF\\\\J`JGv@ZO\\\\GPSTEjPTR`FnEbDTDHEhLFMTK@ETSPULKEI@OVISKSJACEQNQbVIXGDIN@dMB[IIBcN]ZHNLP@XOWCFWCNRHTpATD@^NVNLED@Rh@jCEF}E[OOHUEW]W@QGGDIQSH_MmFmCUT_K]i@MHCMWFCFE{BMHMPOHKS]CFNGBELDH_@BcAKOACESAOBELaXAROB@FODMEDWJAG[aE@UM@DImEWJMC@OeCA{aE[@{L@MINUCQXKfUJORCHqJBF@TCXWNQX]M[EAJO@@KMBQJIC]EWMCCUBEBFHKDOTMBGNGF]MWDBRDdMDQVyE@LPVHDCP@JVVMTG~HNSH[CmRUvHPHBbA\\\\PTNRC\\\\YNJPRARPJDDR\"],encodeOffsets:[[118343,40770]]}},{type:\"Feature\",id:\"110229\",properties:{name:\"延庆县\",cp:[116.1543,40.5286],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@^AXOPEB[ZIGU@KKI@YGE@OYMGWFGvCNO@OPGTBHUTA\\\\ITACIGMIHmCOeDGGWSUIGimYEEMgiFITEFEjHLQbYCIWQaCSHmHAOY@UEaJG@LGLDJ[JAwYQCDMNONGY_EWLsSQFkMO[NWAIGaIYL@HMBOKiOQDWEUDMQSF_QIUBWdg@[NaAKQ@M]OQ@WhgLUMMFYQDIRCEUZOOCIOJ[KIUMKL@HIDKVEBM`HJAJSJUdBLGNEdMBMO[BYEWJSNKNaD]PE\\\\SjOT_RQVEZPpNQXfNA~lNG`@PNLp¼RFLfbdKbATUh@FSNWjGFZVLFHVA~X¨PPROfFJbNJPLFbENJPrEFNPFRHDDJdENJLVEPBJTVTHGHFRFH@PXP\\\\ORQHW\\\\BjWFDERLPPBbB\\\\E`B\\\\D\\\\L`@F]FCnJ^AZL\"],encodeOffsets:[[119262,41751]]}},{type:\"Feature\",id:\"110109\",properties:{name:\"门头沟区\",cp:[115.8,39.9957],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@V@XMnGPY²JQNEhH\\\\AZMPDVTTDZCPiJkHSHCjIdFtEHITCNITQEKUAMCEIKCECABYESKFWAKBEIIHABGDCKCAIHMHALKEI\\\\CFIBILIJQZS]BBEECS@E@@C]COKI@CABAAEEDMGCH]A[M@CJWHJaUMRFRBDTITLUJ@PFJKLOVST@FSLENgKGFSCaCmF_ESQiOSFOT[HYPu@IH_[IoE_[]GUC[USB__CYQI@Gakg@qZeHQNMNV\\\\FVLPgJAFJPRLCH[XcPELUT[JiV_EELFTADBXRTRLJC@fHXHHbPd`fR@NfT`@TLplHMpCEJHJBVLF@JTVnG^KXDXHNVGRLRXFJVdDHSNWLGfEzA\"],encodeOffsets:[[118635,41113]]}},{type:\"Feature\",id:\"110114\",properties:{name:\"昌平区\",cp:[116.1777,40.2134],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VNLJI\\\\JPPDYPFVQDCJZRNEVNhKXgR@^P@NLRbB\\\\Mh@XcVARJE`RTCNFVXRCjPPLNA@GZKbJJHXB\\\\MNPjLdGbWnK\\\\]NGHSFEXATIdCJGPARUWUHCPWRELITAHKv_E@iYCaW_BQ\\\\Y@QIO@QDCIGZCEMWGFMFAFgHEDOCSqKCCFGAMKEAC@ODGCGs@WH@KQA@EE@CE@GEA@EH@GGUEEJEAYD@JM@@DAA@FHD@FTJEHUC@JUBKCKG@G[CIIQReAYhO@OXGDO@@FF@IHJFCPEBACBIAAKDOABXARHPNEHGbQAAKQFGIAM[C@WHKaGiCEGOAHUKCIokSCUSOCYN[BgGMFIR±OZmHWNU@ShbbXDHVXXGJ^lZ@PZ\\\\Nb@\\\\FHJAD\"],\nencodeOffsets:[[118750,41232]]}},{type:\"Feature\",id:\"110115\",properties:{name:\"大兴区\",cp:[116.4716,39.6352],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@F\\\\E~DFN@BDFEpHFCHBBEGCDCJBHUDSBB@ELCPbF@B\\\\J@BJVAFJ\\\\ADKTCBGECFMT@BMN@@FH@DaNBEnvB@FPBATK@FHEFIAKFBFL@@PKBFJHC@FXBRAFCDMPDTOL@JIVFDHH@DDH@BGRFCDLD@N^@@CNA@KNOAEBCECFEGCFGMGFIPMOEJOLBADBBHGG@GCHIECY@INC@DMGS\\\\AIOZAAEYA@GT@KKMBEETCGMVINFxA@MJADB@FlA@HJA@NND@DFA@DVAZBBOFKH_JA@K^GBC@EFEG@gAENMXKJigC@IbSJMqGOP£RGSMGE@kbQFDPEFiBSGGSBK]I{CDWCIDOic[C_G@SuSO@EWKCO@MNY@\\\\uZOPENQD[LKESSKGBKEG@EJGAGHoH¥CqhifeJkX_XFFGHFNEDFPENKHM^IFIVL^S`DVEnNnG`RTCJHH@R^XFXGVPP\"],encodeOffsets:[[119042,40704]]}},{type:\"Feature\",id:\"110113\",properties:{name:\"顺义区\",cp:[116.7242,40.1619],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@EhEBENXHFNYDJHCD@RJP@R[ZARX`DbjZF@bHXT`Jb@dIFMTGDSfAJVbGnJVM@OKELYPERVXRflXTT@NIfC\\\\NJRhCVEHFJXNT^DTeZEHYCOhuAMJELOdAVPTMOWBWNMNEJgl]@WGUFIC[T{EEDEHGCIGMI@SECUQI[D{A{GQESPUH]CsiMCmHUeoHENcAaDGCMDGMQCACCBaCGLMAHB@DIEQLOAAEEJ@CW@CDINGAAGKQOCgV@LG@BEGDKNeREFBNCFIDOPKD[@YRW@GFWDAFE@EHDDrLDTCPGF\",\"@@KrJEH[\\\\B@FF@CHFBHUNAJKADGECBCMAG^E@EbI@BEGP\"],encodeOffsets:[[119283,41084],[119377,41046]]}},{type:\"Feature\",id:\"110117\",properties:{name:\"平谷区\",cp:[117.1706,40.2052],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ZJZRafFLjnVGNJ@LLBdXX\\\\T^EDMJ@nZKLBjPPJ@HbA\\\\H`DbERHLCFK^BZaFWXQLAGMHa\\\\OLO@SBIpBdCLVQfElO@GSAKEDQTC@GEBKG@ORIJBDAPDFA@CaOq@GGQAAEJK@KMUGAAGEAa@MGMBGCGSIIW@WSUCMDOJeWOM@IUF{WMWaDIMgIoRoCOKeEOEAG_I[cg@wLIFENQFDVTFJ@HNDJGHCFFFS|D\\\\EJHV@Xk^IhMFMNAXPX\"],encodeOffsets:[[119748,41190]]}},{type:\"Feature\",id:\"110112\",properties:{name:\"通州区\",cp:[116.7297,39.8131],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@FDAJTGDNDCTDDEDBBE@DT@@EHCDGJ@EIZ@@FDBR@ATFBBVFFE@@HNA\\\\VE@CLIFNJFNJBCP]A@LJFA@HJEDD\\\\C@DBCHLAEPF@@DH@APHAERDF\\\\GIxDTM@CFLBBFJ@CNUPMHECGDBF]BMFPDLRBHHBJMDCX@@DFIBFPBRKJF@CGANBHKbDDABDRDHNNCHDbCdBFMpGHiOYMefKJMC}HWAUNW\\\\NNBNAkNU|]HMTMN@MZBLFFF@RIRUTBMFIEGaAGGAOIIUGTSFcYKS@MSLYPKRUBU]EWDOI]CKGASgW@MTWKIMCS@uMAKKADMECGAKVUTSDy@IjWLMNBF@hHEF@FAD]H@LIBG`ELAPYAUB@CEB@CMC@MIB@GkB@ECAIB@NwBMEUJHNSDFFNALLS@@HZBBFYBJP[BHTCND@JMZ@FDGJHDH@GHAABCKAIPPFONEJNHEHHDEFFDADBFMP@L\"],encodeOffsets:[[119329,40782]]}},{type:\"Feature\",id:\"110105\",properties:{name:\"朝阳区\",cp:[116.4977,39.949],childNum:2},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@bFGHBHFBFIVFHHG@@FFB@HDFF@@FRB@LXGt@DHCH@PBDLFBNF@BEXCHEX@ZQ\\\\@LCPOJCDEAMFEfQLMHCAFH@@KhUNE^AAEHCFDNGVODMI@AEKADEN@CSJw[HCEFQGBBOG@@CE@FOKBDGCAD@C[FCGIB@IE@K^BDOIAEMMIJEDKF@[UMB@GF@EEAUEABSQ@CA@EY@FJI@CHGD@FS@@CAFCACFSCCDCMSHBIECMB@D]@@MKCDCQEAHG@CCG@CGUEIJK@SPOCCNEDQBDNDB@DJCDLFCBBALJB@BVGPBKVO@KHCCCD@FE@BNA@FNCTDDJA@FGB@NBDW@CL@hT@@ZHHQDDDAFSAANBC@HG@EFS@@DE@@PCB@Ue@CADNJB@FCBWA@LI^ix@FIHrH\"],[\"@@HUNAJKADGECBCMAG^E@EbI@BEGPKrJEH[\\\\B@FF@CHFB\"]],encodeOffsets:[[[119169,40992]],[[119398,41063]]]}},{type:\"Feature\",id:\"110108\",properties:{name:\"海淀区\",cp:[116.2202,40.0239],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@plDJVLGPBFHjDbHGL@X\\\\DBNHJREBLRBHaFGMGOBQAWPBLCBBAJBDFADOIEJGE@@EP@HCPWP@ZgfBRQJJ\\\\D@HLHLDVA@IVDFGSI@EGC@EBB@CN@@IZCAGHGaEqGJG@EjwJ]@K@GSA@e_I@NE@CA@Kg@KC@ENCFAKQAW@WIMK@V@I@@F@^EDFB@HcIaDYCBRRDCHD@EFLN@FE@CJUPEJOJMTBPEDIFCMIAKNOGMRFJNDVBFLSRMJSDGJsFcEiJGDGTIlOjYD\"],encodeOffsets:[[118834,41050]]}},{type:\"Feature\",id:\"110106\",properties:{name:\"丰台区\",cp:[116.2683,39.8309],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@hMN@NFTQCFRCBJFA@HJ@@HJ@HJ\\\\FTACD@@UNLXJX@@MA@@IECAQlDFEHBDI~D@GXCFMVDFCH@@NF@ANJC@FnAB@AMF@@EDCDDLGP@LUOAUH@AIABKAAEDCKID@CCACMWA@EGDEILA@OK@AELEJBFEEGL@BSOA@EuAFmMACbG@@EM@ANS@ENFDAHSDCL[BEIUBAII@A[E@OaKD@FAACTGVIACDHDAFGAEDoGEFACM@ig@@QFCMKMU@]SCoBGSMQDEXXDWPO@MKYGM^AdJJA\\\\cNB\\\\G^DNHFCBFABDBJ@PL^D@DF@T@FDAF^A\"],encodeOffsets:[[118958,40846]]}},{type:\"Feature\",id:\"110107\",properties:{name:\"石景山区\",cp:[116.1887,39.9346],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@NQPHLMJBDNJEFCAONSPIFIVODIF@@EKMFEC@DGQCAQZDbCdJ@GEAFC@]@EJ@DCSB[EGII@@GI@@GEBAIQDDESRMEM@gNYTIRKJAJEJ[DFJKLGBGNBJLDCDAHGBJJAFBLEXTLZFBAFDLD\"],encodeOffsets:[[118940,40953]]}},{type:\"Feature\",id:\"110102\",properties:{name:\"西城区\",cp:[116.3631,39.9353],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XBDA@EIACM@IJAD]BC@SFABISAD]H@@OAEDQEW@BLEMD@FLDh@@LDBF@@M`J@fTB@H\"],encodeOffsets:[[119175,40932]]}},{type:\"Feature\",id:\"110101\",properties:{name:\"东城区\",cp:[116.418,39.9367],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@DBf@@VDA@OF@@CT@FEH@@GADBMTBBECCRCGG@YS@@gDK@AC@PG@C^TBAJEB@TADC^IB@J\"],encodeOffsets:[[119182,40921]]}},{type:\"Feature\",id:\"110104\",properties:{name:\"宣武区\",cp:[116.3603,39.8852],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@RBX@RFFCBFU@aK@WA}CCJGAEFkCBRFD@JB@@N\"],encodeOffsets:[[119118,40855]]}},{type:\"Feature\",id:\"110103\",properties:{name:\"崇文区\",cp:[116.4166,39.8811],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XBL@@bEVD@BX@AC@MHA@EIBCCDSEMmB@EIDBME@@MG@EDUCENWD@H\"],encodeOffsets:[[119175,40829]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/china_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"xin_jiang\",properties:{name:\"新疆\",cp:[84.9023,41.748],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@@ρȁôƧƦóəʵסʵóƪԫʵѵͩƧͩړυࡓɛʵ@ȃ@óᇑѵƨɝɚôóНѺͩɜ̏ԭʵôƧɞñ@υƩ݇ȂóƩƧ@ѵȂυƥŌਗ॥ɛóʵѵƧѹ݇̍ࢯəɞυρͩ̏óਙƨƧŋôōó̍ͩóʵןóŋړͪƧѶ@ɜԭԫƦɛȄ̍ɝȄöςƩȂ̏ñȀ̏ƩóóŎə@Ő̎@ɞȀɝŎôƨóנѵȄƧ@óŏɝóɜôŎ̍ͨςŎ@ƨóôƨɞ݈ʶóƨφó̎Ȁƨ̍ԮòѸԮמ@ѺȀ@ƪၬֆòȂñ̐òȂɜóƨ̒Ŏ̑߼@φρȀ@Ő๐ς̎Ƨφ@ɝφڔ೦Ԯǿࢰ@ƦŏԮƨƨȄƧ۬ɜʶڔŐɚɚóŐôƨ߼ôƧƧó̐ƥóŏѺǿƦȁφƧςƨƧ̒@ɜƥƦυ̐ɛƪͩƩəƪʷ̑ə@ȃƨʵנŋྸōਚԭԪ@ɝƨŋ̒օςʵôƧ\"],encodeOffsets:[[98730,43786]]}},{type:\"Feature\",id:\"xi_zang\",properties:{name:\"西藏\",cp:[88.7695,31.6846],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ôŌנôʶ̎ͪôóŎƨŌਚƧ̐ôςͪφɚɝࢰ݈̎ѺѶƨôʶ०ɜਘƦŋφѶȁ̍ôŏɚŋ@̑ə@ŏò̍ɜóƥôʷƧ̍φѹԪ̍ע@Ѹʷɜ@ôñנ@Ѷɛɞô̐ŏѶƨѸƧƥōƦôŏô@ƧôƩ̒ŋƨŌƦǿô̎ɜȁ̒óʶѶôôО̒ςƥɜНφσɛȁ̎υƨఱƧŏ@ʵƥ@ŌóóóͩƨƧóŋ̑õóɞóɝԩͪɝρôƧ̍ƧѹͨڑŎ̑ōóƧࢭͩ̏ѵɝóఱóóԪυô@̒ƥŌ̏Ƨ̑Ȅ݇ŎƧѵӏ@ɛõŏɛȄôӒƧŌѵǿɝƧŋԫ@̏ʴƥ@óǿ̑Ȁóǿ̍ςóóυô@ʶɛñρƦƩŐó̎óѵó̑ͪࢯОóɜןƧ̏ƥȄ߻̎̏̐ןŎɝɜöɞƩȀôöɛȀóͪ̐ƨƪ̍̎ȂƥԪυО@φɞôƪ\"],encodeOffsets:[[80911,35146]]}},{type:\"Feature\",id:\"nei_meng_gu\",properties:{name:\"内蒙古\",cp:[117.5977,44.3408],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@ኊȁ૊ö߼ƩɜɛנñԮɛѶóԮô@ȁѸóמ̎ගѺၬ@߼ʶԮӒ߼̎@ŐѹӒ̒Ԫƨöග̑ѶȄ̒ς।ѶɚöɞɜʴڔôôȂ̎ѺȀςƨƪóԪɜôɛОਕڔԭѵ̍ѹȂԫɛƥ̍Ȃóɜ̎ô@ʶ݊ੲࢮʵږͪנƨôȂƧ̐ͪ@ŐƦƨφԬѶɜôƦ@ŐƧôôƦəŐ̏@ŐڒѶԬô̐ʳԩНςōôŏɞ@ƨȂѶəóƧ̒ػ̎ó̐Őנóƨô̒@ƨɚɚ@עԫɛɛ@ȁυͩƥʳòևρ̑ࡗƧͪ༃ॣԮփ̎Ʀ@ôô@ôō@@ȁѵóƨ̍υȃóʵɛƨƥóυȂóəƪ̐ρƧͩɜԭڔȄ̎عƧȁ̐ŏó̍ɛƥƧ̑óρŐ@Ƨ̏ɝəɛ߻ͩ̍ͩɝО̍ƪƧóóӓƨóƧʳ݇@ɝςƪ@ʴƩƧƦôƨɛȄəƧŋυóͩѵ@ɝǿóŌן̍ɛóО̍̑̏ôȁ̍ŏòȁñóƦͩ@ǿə@ɛƧ̑ρȁυô̍օѹóȃə@ȂσʵѷƪòƩ̍ôó߻ۯôʳƧóõʵѵóѹɜ̍ȂѹôɛŌφֈƩͨρóυӑóޟఱ̑݇ͪóƪƨŌóȄڔԬƩςםñ̑ȃѵŐԭŏƨȁɛǿρôõɚɛóƧОə@ѹ̐ѵöԪͨôͪɛ̒ןŏƧƥóôƥƧɛŌôóɝó@̒݇Ӓ̒Ō@Ŏԭࢰ\"],encodeOffsets:[[99540,43830]]}},{type:\"Feature\",id:\"qing_hai\",properties:{name:\"青海\",cp:[96.2402,35.4199],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ƨ@ôƪ݈ȁƪ@φɝòóƨԮʶɛ̐ѹͪôОəóƧɞᇒѶ@ôږô@ǿѶƪȁςɜͩφςŋɞôѶɛƨŌɞ@ɚςŐñԪॢͩƨȂɞóƨŐ̎ŏעӏ̎óƧƦô̒ȁɜςͩ̒ɚɛƨôƨɝφɛóȁƨŋóóɚͩƨóóƩ@ƧəŋƦƩ̍@ƧƧôǿυ̑@ȁɞǿõŏρƥסɚƧóτԫɞôƧƦ@ñȃòñƥóυôôѹѵ@ŏ̏Ȅɝó@ȂəŌóəѹƦ@Ő̍Ōυ݈ԩŐƧóôƧ̑ôʵɞƧ̑ѵôƩɞƧ̑óНѵóôʵ̑ɛȂó̍ƥȀƧŋ̑Ōóƪ@ƨóóŐƥƦŎѷƨѵƧ̏Őɝóѵɜן@óòɛ@ѷʸס@ԩ̎υѺƨ̎óʸôƦɛñ̎@Őɚ@̒əŌóŐ̎\"],encodeOffsets:[[91890,36945]]}},{type:\"Feature\",id:\"si_chuan\",properties:{name:\"四川\",cp:[102.9199,30.1904],childNum:21},geometry:{type:\"Polygon\",coordinates:[\"@@ôôŋó̑Ԯ̒ɛОמͪƨōöͫ߼ƥôȃƨóóñôƧóƧôōڔŏƨŐ@ŎôòƥѺŎ@ōɜóנôǿôƦôԮ̍ɜôɚƧñɛɚȁ̍Ƨɛևυ@óóôŋρԭɝ@Ƨʸ̍ŏυɜƧƧóƧƨȁρ̍ƨȃɚôʵφóô̑̏Ȃ̑ʵɜʵɞ@ƨʳסƩóŎəóɜƧôƩƧρóôôô@ŎƧƨƨƪѹó̍̍Ʃ@̏ѹНôޟ̍ƩóƪυɝɛəƨôŎɛȀ@Ȃ@ñɝʶ@Ōρנ̏õóɛͨƨȂѵОɛʵ@̏ƩŐó߼Ƨల̍φɜȂυτɛОρƦɝƨóƪ̒Ѷɝƨóʶ̒óƨƨôԪŏφ݇̎ŋ@ŏѺƥôɚɚŋ@ȁɞô̐ȃ@ŐѶóѺφóƦôñòòȄ\"],encodeOffsets:[[104220,34336]]}},{type:\"Feature\",id:\"hei_long_jiang\",properties:{name:\"黑龙江\",cp:[128.1445,48.5156],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@ᇔȂਚНƨŐѶŏöƥςŏñƧƦóƨȁ@óƨóȁφӑóóƨóǿ̎̑ôНɞó̑ɜə߼̎ǿ̒ôڒӑφ@Ƨȁ̎̏ƥƩ̎ρశôȂςƨφ@נɞ݈̑ƥƧɛƨʵƧȃƥ@Ƨƥ@ŏ̑ԩôɝρρóɛƧƩͩƧó߻ʸ̍ʷѹƥɞڕõ̍öɝυ̍ȂƧ̐̑ŏóƨñŋѹóóȁ̍̏Ԭõʸ̏ŏ@ǿ̍@ƧОυ@ñƨòȀƥŎ̑ŐѵóɛŌóȂԫōƧŎѹñ̍ʶóОן@Ƨ̎Ѷô@Ȃ@óŎó@@ó̍ƥԭք༄।ƨͩ̒ࡘςñֈƦʴφͪ@ȂɜɜסԬə@Ƨə̑@Ƨóןô̏ŏ̍ô̑ؼôƨѵɚƧȁɝ@óŐρŎԪО̏ʴ\"],encodeOffsets:[[124380,54630]]}},{type:\"Feature\",id:\"gan_su\",properties:{name:\"甘肃\",cp:[95.7129,40.166],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@ڔôԮࢯ@ō̑ŋ݈ӑ@̑ɞôóôɜŋƦƨôóƨƦנŐɜ̑óͩԩͧѶõѺ̏ɚ@ƨНɜôöəςóɜȀƧȂԮŐѶŏ̒ȄמòƪρړԫôȃƧŋôƩ݈ͩɚ@@ǿɜ@φͩóŏɜӑƧōôǿ̎ôƥƪóõö@ôƨôƧƦôó̒ɜ@ɞŌõʶ̏Ő@ȀóôƨȂ@ʶע@@ƥ୾ӑó̑óŋôʵóɛړ@@ƩöóƩóρɛƨ̑@óʷƥƥ̎ɛƧôōƧǿôͩѵôɝȃɞȁõƧρóó@ōƧŏړŐóŎôƨóƨôòƧôóȄ߻ƦõͬƧŎםͩɜНԭ̑ô̒óŌóƥ@óƨɝσԬƨôעəςƦöŐɝȀ@Ȃφ̒óȀƨƨ̎@ƥƪɚŌ@ƨôƪƧôəͪôôƧŌôȂυɜƧɞƧóəɜ̑ρͪɛ̑Ȃóƨƥ̍ôסӐ̍ŐƧŏɝôƧȁॡͪòԩρŏ@əɝƧŋѵɜɝóρŌυɛͪρƩȂѵ@Ȁڕó@ȄɜʶφࡔڔƨͪѶͪԬʶôƩעʶɚʶƥôóƨςȂ\"],encodeOffsets:[[98730,43740]]}},{type:\"Feature\",id:\"yun_nan\",properties:{name:\"云南\",cp:[101.8652,25.1807],childNum:16},geometry:{type:\"Polygon\",coordinates:[\"@@ôɞôɝ̒öôŌƧƨôͪôô@ŋƦ@ʶƨŐô߻ƪŏ@̐ɜʶѶНƧȁɜͧöô̐ςן@ŋɞʵ@ò@ȁɜǿóōɚƧɜφɞôƩ̎ƪóޠѺО@̐̎ƪô̎ѺƧƩƨƧ@ōóóôóςƪƨƨóôɛó̑ԭƥŌɛǿɝƨɛͩô@ǿƨȁѺŌɚɛ̍ןѶНɛƧôóƥȁƦͩôŎɞƨ̑ɜòôφ@ƨʵ@ɛѹōóȃəƨυǿóʵρƧƧŌƩɛ̏ȄñƧƧȀɝ̍ԩʶƧ̑υóŌƥʳɚӑóНƥô̑óӒѵʵѹƧӐןôƪφõŌƪ̒ԫŌƧؼƨƨסρȁƧƨȂóʶó@@ʴƨôôφ̎Ŏ@ȀƨƪɚƨóƨôôôςóޤƧŌƩŋƧԪ\"],encodeOffsets:[[100530,28800]]}},{type:\"Feature\",id:\"guang_xi\",properties:{name:\"广西\",cp:[108.2813,23.6426],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@ƦŋѺ̎ڔʵƨŐ@ƦמȄƪôóȂɜŌɚͩɜ@öóɜôôȂƦôɜȁ@ɞφóȄ̎ƨʶɞŋƨʴɚǿ̐̎Ԭ@ôñ@̏ƨρ۫ôɚƨƨНƪŐ̎ƥóƦʵƥŋ@ȃóƥƧ@@ŏɝǿôυƧȁѵɛ@əóŏ̑@@ə̍óƧó@ȁƩρóòНƥô@Ӓ̑@óŎ̍ƥσŎυ@̍ƨ@Ō̑ôóͪƨ̒óŌړ̏Ŏ@ŌôȄѺŎ@ɜƧʶυ@ñóɛƧ̒ɝóōƥͪ\"],encodeOffsets:[[107011,25335]]}},{type:\"Feature\",id:\"hu_nan\",properties:{name:\"湖南\",cp:[111.5332,27.3779],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@@քɜОƨ@öŐמóƪôƩɚ̒Ő߼ȁςͩɜòƪɜȀòñɝòѺͪ@ŏƨŋóɝôǿƨɚȃóəƨȃѵͩó̍@ȃƨóóƥƨƧ@ʵƦóͩɜɛóñԭɛōυȂ̍ƧƦō@ɛƥɛȀ̑óʷóō̍ƩŏƧОəƧóς۬Ƨ@̐óòԫ@̏̍əȀƧʳɝŌóɞƧƨɜóŐƨò@ȄƧŌρŋóôԪОóʶ@̎óȄ\"],encodeOffsets:[[111870,29161]]}},{type:\"Feature\",id:\"shan_xi_1\",properties:{name:\"陕西\",cp:[109.5996,35.6396],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@ςôöƨɝȂɞȄѶóóͪƨȀóŎƨ̍ɜƦƦôʸ̒@ɜƧςƪôõô@ƪڔ@ôɜóʶôŌô̒୽Ӓ@Ʀ@Ѻ̎ɜѺɛѶôöʶôƨóʴ߼۰óô̎ñƪѸƩτʶ@ȁòŋəѹóǿ̑ʵ@ȁ̒ʷυփô݉ôН̏ط@ȁƨóô̏ƪõ@ʳ̐ʵ@ɝɛŋƩŌɛóןôƧŋ̒ó@ŏ̐ƥ@ŏυ@ƧƧôן̏@ƥȂѹɜəɛóԭ̎ƥóóóȀןɛô@ŎѹōñƦ\"],encodeOffsets:[[108001,33705]]}},{type:\"Feature\",id:\"guang_dong\",properties:{name:\"广东\",cp:[113.4668,22.8076],childNum:21},geometry:{type:\"Polygon\",coordinates:[\"@@@Ȃôôƨ̎@ɚ̒@ôŐ@ɚѶɜƨȂóφɞȀ@Őƨ@ôƦ@ȄƦŌƥʶƦôôŎôʸ̒ɜǿƦ@ɜƥŎ̎ƨφȁɜŎòƥԮŎƨōóŏɛƧɝəɞƧ߼ɜςȃñȄƦŎ̒ōôòƨəƨɚН@əƨ̏ƪʵυŌəɛóəԭŏəóŏѹρʵɝƦ̏ƥʳѶöō̑óóŋρȀυƧƥɛѹōƧôןɛŏѵ@óŋôʵɝƪԩõ@Ƨō̍@Ƨ@@ƦɝԮƪО@@\",\"@@X¯aWĀ@l\"],encodeOffsets:[[112411,21916],[116325,22697]]}},{type:\"Feature\",id:\"ji_lin\",properties:{name:\"吉林\",cp:[126.4746,43.5938],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@נ@ôН̎ʵѺòƨōԬŎôȁɜŋѶô̒ŏƦōñǿòƧφ@ƨН̎@@Ȁ̐Őöʷ̐ԫ̎ôȂѺôòŌôƧ̒Őƨ̏̎ȁφ@ŋƩͩםȃƨ@ȁ̑ʶ@Ōóôɛƥѹ̑συ݇@ɜρƧȃࢯƨôəȂɛōƩɛ̏υρóõƪʴυφ@ʶôŌóρք@ɜƧ@ɝǿƧͪρȀƩó̏ŐƨȂ̍غړȃɛԮƨͪ̏ςƩôɚφȁƦôɜƧôʶφȄ\"],encodeOffsets:[[126181,47341]]}},{type:\"Feature\",id:\"he_bei\",properties:{name:\"河北\",cp:[115.4004,37.9688],childNum:11},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Ʃ̒̏ŌѺ̒ƩóȄƧŌƥͪòôñȂ̎ŐóȂ̒̐̎ôНɜנ̎ôŋɞȀѶ@ôͪφƨŌɚɜȃóƧƨƥƪ@ʳƩɞρ݈@υНφʵɜƦρƨƧ̍ɝóɛѹ̍ρŏ̑ôóƨ@ƧƦôƨɛ@ƥƨ@ȂƦ@@ôəŐƧʶƨŌυ̍̎ɛŋôōɝ@óƧ̍ƦʵѵʳôʵɜŏςôƪŋƨŌɚ@ôНƥƧ@ōѸɛ̐ô̎ʵѵНԭ@̍̍Ƨò@ȁɝ@əρυͩƪ̏ƩõƧŎƧōóॡȄɛʶɜȀ@ɞςѶƧƥςɛŐ@ɚɜɜ@Ŏôôςƪς\"],[\"@@õə@Ƨɛ@ŐóƦφô\"]],encodeOffsets:[[[117271,40455]],[[120061,41040]]]}},{type:\"Feature\",id:\"hu_bei\",properties:{name:\"湖北\",cp:[112.2363,31.1572],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@ñȄυƦöŐƩóנƨƨφ@@Ő̏Ʀ@Ő̑ôƨŌנóɜôƪŋɜŌѶօڔə݈òɞōɜŎôӏƦóƨô̒óôȃƨó̎ŐôƧƪ@ƨȁςƧə̑̎Н@̍Ƨŏρôԭͩԫ̍ʵƧóȀôɞƧŌ@ŐѹͩñòɞñɛǿƩɛñρͪ߻Ȃ̑ŏƪəƩóםôõŏƧ@ɛНƥȄó̑ѺƧôφóƨƨƦƪóɜŐôóòôƨóφ̐ƨóƦ̎\"],encodeOffsets:[[112860,31905]]}},{type:\"Feature\",id:\"gui_zhou\",properties:{name:\"贵州\",cp:[106.6113,26.9385],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ɜȀƦŋԮô̒ɚôōעƪƧʴɝ@ɛʶ̒ʶ̐ȁƦóȂô@ôŏ@ōôƨʶѸô@ʶƨɞó@ōτöòυƨ@@əƨô@ɛ̒@Ʀɜôȃ@̍ôʵԩНôóςŌƨŋ@ȃƧñôŏƧɛƨôɝƧʵ̍ôȃυ@ɝɛȂƥóóȁɛóõôɛ@əͪɛŋôȁƩóםȃ@ƥƧŏړʶѹ̍ƥŌƦȂóôɜƨѵО̎נəɜѹŋƧȂ@ȀóɜͪɞƧ\"],encodeOffsets:[[106651,27901]]}},{type:\"Feature\",id:\"shan_dong\",properties:{name:\"山东\",cp:[118.7402,36.4307],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@Ʃ̐φͪɚςɞ@@Ȃƨñ̎̎Ԯ@ѶОƨƧڔ@φН̑ŋ@Ʃ̒ǿ̎@ƨɜԬςôʶ̐ʶöԫƨƧנƥɜŎôō̎@ôŏóρƧŏԫôóƧԩó@ƥɜƧԭóƨʵɛƨ߻ӑɜНԩóô̑óƧʳəóɛƧ@õȀƧ̍ȃɛŐóŏυО̍óɝƩԩ@ƧɚԫȄɚʶƨɞʶԪ̐ړɛƪ̒\"],encodeOffsets:[[118261,37036]]}},{type:\"Feature\",id:\"jiang_xi\",properties:{name:\"江西\",cp:[116.0156,27.29],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@ƧȄôɚəȄ̎ʶԬԮͪςóƨŐƪτɞƦōƥƧ@ŏςôóŐôô̒ʷѶƪƩƩǿ@ō̒ɛôυ@Ƨȁѹɛəƨѹ̑ƨ̏óƥѵʷô̍ɛȁôŏɝǿƧԫƧôʳƥōòȃρȄ߻ɛɝƨɞɚɜƨôŐƧŎԭōñƦòԮɜôɛôͪƥ@ʶƧƨôƦƧô@Ȅô̎Ѷͪ\"],encodeOffsets:[[117e3,29025]]}},{type:\"Feature\",id:\"he_nan\",properties:{name:\"河南\",cp:[113.4668,33.8818],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@φ̎ƪ̐ɞȄɚ@@Ȃעó̎ŌѺ̒ôֆॢȃôƨŎƨōƪöƩ̑ڔɜԩ̏ɝʵƧəʵԬȃƨəԪ@@Ƨ̒ŏô̍υȁƧɚ̍ôóŋ@ɝƧŋõ̑σ@ŏɜŋôɝ̒ƧɚôôطρóóɛƩ@óƨ̍ŏƧôóȄ̑ôƧóƥôóӐɛōɝŎ݇ñړɚѵֆ@ɞ̏ʶ@ʴƩöó̐\"],encodeOffsets:[[113040,35416]]}},{type:\"Feature\",id:\"liao_ning\",properties:{name:\"辽宁\",cp:[122.3438,41.0889],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@ƨʴƧôôӔƨô̎ƩɞН̎ͪ߼ͪɜɞɚ̐@ƨςŏ̒ôƦƨɜô̎ƪôςǿƨͩɞȀƨ@@ɛςփôóŋ@ʵφυƩʳö॥փρѹס@əɛ@ͩࢯ@ѹʵρƩʶφȀƧ݈̒۬óʸɝŎѵ@ԭԫןɛƧƨƥςɛυʶφО\"],encodeOffsets:[[122131,42301]]}},{type:\"Feature\",id:\"shan_xi_2\",properties:{name:\"山西\",cp:[112.4121,37.6611],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@ɚѺñŌɚôȄѺ̎ֆφóςȂ̒ɜƨɚ@@Ȁƨŋôȃƪѹ̑̐ŋƪ̑Ʃρρóó@ōɛɛ@əɜŏƦρƨρѵ@ɝɛǿɜʵóօѹ̑̍ŋסô@ȁə@ɝȃ̏̍ƩυƧô@Ȃ̐ظóОó݊φք̑ʸ@Ȃ̒ʶôȀ\"],encodeOffsets:[[113581,39645]]}},{type:\"Feature\",id:\"an_hui\",properties:{name:\"安徽\",cp:[117.2461,32.0361],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@ó̎̑Ő@ƨƪѶǿɜ̑φƦʵ̐ƧѵôóƪôôυςƨȂɞŏ@̍ԫôò̑ƥóȃѶͩƧƥôŏѺôŏƦ@ƥͩƧôȁυó@̑ƧɛѵʵƩƪѵ̑ʸóóôŏρó@ŐƦƨƥŎσɝƩ@̎̍Оɚ̒ρƨƧȂôɜςôóظəó̑ƨóɞɛŌ@Őτö̒ƨŌ@ɞôŌ̎óƨəφȂ\"],encodeOffsets:[[119431,34741]]}},{type:\"Feature\",id:\"fu_jian\",properties:{name:\"福建\",cp:[118.3008,25.9277],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@̎óȁƨӑ̒̎ɚƨͩφŐƨɝ̎ŋóŏρ@ōƨòʳəóƨō̏õɛƧ@ƨѵƧōəŏóŋƧô̑ɝɛʳƥ@@óɛõ@Ƨ̑ƧóȁəƧ̑Ƨ̐@ɚəОƧƧɚóñ̑ŎóʴƨƨԬɞȀóŐɜȂó̎ѶʸôƦƧ̐Ѻ̒ɚƧѺɜƨȂ\"],encodeOffsets:[[121321,28981]]}},{type:\"Feature\",id:\"zhe_jiang\",properties:{name:\"浙江\",cp:[120.498,29.0918],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@Ѷʶƨɜ@̒φôóȂƨƦͪ@̐Ѹ̍τȂ̒̑נŐמôƪƧôӑ̑@ƥρͩƨօ̏@@υɝó@ŋɛ@ôƩəóƧѵυó@ƩɜŋƧ@̍ŌƧɞυŏƧͪ̍ə̑ƧӒôȂ̍@óφ̑ɜ@ŎƪȀ\"],encodeOffsets:[[121051,30105]]}},{type:\"Feature\",id:\"jiang_su\",properties:{name:\"江苏\",cp:[120.0586,32.915],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@ôɞ̎φНôŐɜŏ̎Ȅƨöǿƨ@ôɜɚƨʴ̒ôôó@Ƨ̎əԮȃԪૉöͩ̐ƧòʵφƧôʵ@óړɜóŏɜǿƧɝρσȁѷ̎̏ƥóŐѹóŐƨƦѵͪôȄƦñ̒Ԭó@̎ɝŐƧȁρóφƩóóôƨѶ̏ƥʶυɛ̒ѵȀ\"],encodeOffsets:[[119161,35460]]}},{type:\"Feature\",id:\"chong_qing\",properties:{name:\"重庆\",cp:[107.7539,30.1904],childNum:40},geometry:{type:\"Polygon\",coordinates:[\"@@əȂòɜƨѺɛƦȁ̐@ƪõŏφƥòȃƥ̍Ƨôυ̏ƧôñóóôɛŏƩôƧƥôƧóυƨ̒ѹôƦȃ@փƥɛ̑@@ɜƧó@ɚƧ@ñφσõ@ŎɝôƧ@ʵѷóƧʵó@ŎóŐó@ôȁƥó̒υôóʶəƧȄς̎ƧȂôƨƨƨφɛ̎Őƨʷɞ@ςԮóŌôôφ@ɜֈ̎ƨ\"],encodeOffsets:[[111150,32446]]}},{type:\"Feature\",id:\"ning_xia\",properties:{name:\"宁夏\",cp:[105.9961,37.3096],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@ల̒ôޠφӒςôƪͧυևɜŋѺó̎ȁ̍ɛ@ѹס@@ʵƧȁôó@ǿ̐ŏöʵɝŋɛ@ô̑ƥóóƨƧóôó@ƩôóƦ̍óȀƨŎɛӒôŐυͪɛ@@Ȁə@\"],encodeOffsets:[[106831,38340]]}},{type:\"Feature\",id:\"hai_nan\",properties:{name:\"海南\",cp:[109.9512,19.2041],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@φɜƦʶ̐ôφô̎@ƨŎö@τʵƦԩ۫õН̏óƥȃƧ@Ʃəםƨ̑Ʀ@ޤ\"],encodeOffsets:[[111240,19846]]}},{type:\"Feature\",id:\"tai_wan\",properties:{name:\"台湾\",cp:[121.0254,23.5986],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ôƩɝöƧɝѵəޣ̏ρƩԭóōóͪρɞƧОôԪ݈ଦѶɜ̒ɛ\"],encodeOffsets:[[124831,25650]]}},{type:\"Feature\",id:\"bei_jing\",properties:{name:\"北京\",cp:[116.4551,40.2539],childNum:19},geometry:{type:\"Polygon\",coordinates:[\"@@óóóυóôƥ@ŏóóə@ƧŋƩŌρóɛŐóʶѶʴƥʶ̎ôƨɞ@óŎɜŌ̎̍φƧŋƨʵ\"],encodeOffsets:[[120241,41176]]}},{type:\"Feature\",id:\"tian_jin\",properties:{name:\"天津\",cp:[117.4219,39.4189],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@ôôɜ@ƨöɚôôôɚŏ@óƥ@@ȁƦƧɜ@óƧƨƥ@ƧóəН̏óѷɜ@ŎƦƨóО\"],encodeOffsets:[[119610,40545]]}},{type:\"Feature\",id:\"shang_hai\",properties:{name:\"上海\",cp:[121.4648,31.2891],childNum:19},geometry:{type:\"Polygon\",coordinates:[\"@@ɞςƨɛȀôŐڔɛóυô̍ןŏ̑̒\"],encodeOffsets:[[123840,31771]]}},{type:\"Feature\",id:\"xiang_gang\",properties:{name:\"香港\",cp:[114.2578,22.3242],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@óɛƩ@ρ@óôȀɚŎƨ@ö@@ōƨ@\"],encodeOffsets:[[117361,22950]]}},{type:\"Feature\",id:\"ao_men\",properties:{name:\"澳门\",cp:[113.5547,22.1484],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@X¯aWĀ@l\"],encodeOffsets:[[116325,22697]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/chong_qing_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"500242\",properties:{name:\"酉阳土家族苗族自治县\",cp:[108.8196,28.8666],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XJ°lJX@lbl@XbV@VLnJlxnbUU@IVK@lVIVwnJlU@n@J@L@Jn@l_nWVLVln@@blLmV@@xÔ`nxVÈLlxLVxVVV_U»VWn_m¥XwVmnX°lmUUVwÞaVk@a@mmIUa@mwk@m@@U¯a@UV@@K@ykkmwkV@kU@ÑVkKWLÅamaUm@kyU@WkU@UaIUaVaUUmUUa@aVLXKWa¯UUbmJXnWnX`l@@xkzWÆ@VLU¦x@b@JkIkJ@LmbUamJwm@óxnk@V@xVnUVmVUVUbVlUbkXW\"],encodeOffsets:[[110914,29695]]}},{type:\"Feature\",id:\"500236\",properties:{name:\"奉节县\",cp:[109.3909,30.9265],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@WVXbUnK@x@b²kxmKkl¯_VV°VU@bnKVVV@@nk@nbn@°@VLČU@°WV@VnU@InKVl@nUbKnXWlknLlKUwnalLaVlUXmWk@UU@UWWIUyķ¹XaWW@XKUIVmU@W@UVU@KV@n»VkUkÇmUmVIUmULUbm@wUaKkkm¯ÑUL@bWVnx@VmxUI@klmkkK@aK@IlJ@I¯k@mak@mnkJVL@bV@UbW`UUUVI@VU@VVbUJVLUVVbUXVVxk¦VJUnVxnVVUJV@Ubl@@bXV@L\"],encodeOffsets:[[111781,31658]]}},{type:\"Feature\",id:\"500238\",properties:{name:\"巫溪县\",cp:[109.3359,31.4813],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nLWbXVLVUV@KIVl@b@lbUVnU@JÆU@V@n°KĢUl@VbÞKV@_VKXUU@KX@wlkkU@mWKUU@UôJ@XV@aVmÞIVaVL@»km@UkLU@aU@WWLUUUKkbwWa@KU@kaXmWLamVk@UmL@JmVUU@¯X@ċVUK¯@ÅnWKLkKULWK@UXK@wW@LkV@bVLlXn`¯xU°LnlV@n°Lnl\"],encodeOffsets:[[111488,32361]]}},{type:\"Feature\",id:\"500234\",properties:{name:\"开县\",cp:[108.4131,31.2561],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@n@naIw@@VVKLVbVxnVÆUnanKWXamKmk¯K@mkUm¯KV°w@Wm@UIUUlKUU@a¯KWanwmUXamKkUWUnU@KkUwWKXaWLUWkImaUUUKka±k@l¯wwmbUkXm@UJkIWXXbmUJXUV@°KllVXV@xmbnV@blV@VU`UL@Va@bULlb°VXbÜ@V@bL@JxnLVb@lVb@V@@zbXWXKVLV@@bUVVL@blVna@ll@zl@@J\"],encodeOffsets:[[111150,32434]]}},{type:\"Feature\",id:\"500243\",properties:{name:\"彭水苗族土家族自治县\",cp:[108.2043,29.3994],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@Jlb@nVV@bXb@ÆlLUl`nVKU¼VxkbWnlUxlXX@°°WnnJ@VUn@Jk°L@VlV@nUJx@bVVVz@VnLlaKnalVlIU¼@nV@@anKUwVal@UlJlI@akU@UWXKVI¯Uak@@KmkXWÜkXWykIWwXw@laXamkVUUym_XmlkkmmakwmIUKU@Wak@kaW@kI¯WIk¦VUUmaUV@XkVUV±aUb¯b¯¥m@@ImJ@mmL@kUKUkkJbV¦\"],encodeOffsets:[[110408,29729]]}},{type:\"Feature\",id:\"500235\",properties:{name:\"云阳县\",cp:[108.8306,31.0089],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@lbLVVVnblJVXXKWbXLVxl@LmVXVVlnLWbnVmxXb°L@bVVkLVVVJn@@X_WmkUK@alUKX@@xWL@VXLVKlLKXLÆm@ma@ml@mU@UUmL@aVUU¯U°`lknLlw±@a@wmLVWaXU@KWU@ak@VaU@IUVmUUwVmUIl¥UwUVWUaVUUKVIUa@UUUUJUUmknl@@VWV@L¯aUbUlx@@b@VULUx@VUxVVU@bU@mxUU@mUVklkk@WxknlxK@amLKUK\"],encodeOffsets:[[111016,31742]]}},{type:\"Feature\",id:\"500101\",properties:{name:\"万州区\",cp:[108.3911,30.6958],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ĸĊVInaWWXlJVIn@lWVnax°xkl@²LVLnK@bLkwlmXw@lllkUnVV@VnwV@@aVUUVw@UVwVK@U@a@kwVVa°b@KXU@U@mkÇÑamlkUVmn@VULUm@kUVkUawUWm@Uw¯mKUUmVUUULUKUW@XbWVkaWwkUUk@maUbmbVlk¦xUVUIWVUkJVVkL@UmJUUVU@lLUVUlx@@VbJUL¯¤@V\"],encodeOffsets:[[110464,31551]]}},{type:\"Feature\",id:\"500229\",properties:{name:\"城口县\",cp:[108.7756,31.9098],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VK@w¯L@m@UÅV@ImVUVka@@aUkJ@LUUVUKmLmbÅVmUUwUaKUL@U@xJmbm@nVJ@X@VkVnlLXx@b@bUVLU`UnbU@@mVVX@JX@VLVVklV`@bUL@VLVKn@U@UJkn@lmLmK@X@Jn@mbnÞWVXnJkKČÑÆ@VK@knaÜmXlUČW°kôÇÆ@a@yÞ_VmUnU@K\"],encodeOffsets:[[111893,32513]]}},{type:\"Feature\",id:\"500116\",properties:{name:\"江津区\",cp:[106.2158,28.9874],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@InWUUlU@LValX@°²lÒXxlK@Ul@@Un@UaVJ@I@W@UUUVUwVIUKUaUUVwn@Üx@XUlnnbJ@¥VklKUUlk@ynU@kVUUVWnI@¥V£VWVIUKU@UVa@n@Vm@@nlUaVkUwJ@blLkLW@XWmXkmmLn@m@U@UVm@UVUUlakUVaVkV@@wnaWUk@VwklmVIkUUxmJ@U@KIkx±V@IUm@K@IUKkbWKUbnm@bmVnbmb@xkxUJ@ULW`@bX@WVXL@V¯mk¯@UJ@VmLUaWnX@WJ@nkKkxW@UIV@@KkImmkK@UW@XaWIU@UIkbWbxXlLVbnV@bWlX@VxVLnl@nÆÞVÜ\"],encodeOffsets:[[108585,30032]]}},{type:\"Feature\",id:\"500240\",properties:{name:\"石柱土家族自治县\",cp:[108.2813,30.1025],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@kl@¼UbmVXJ@bV@nxVIVJULVVk@@LWbnJVU@bVbUJ@blLXnWV@mbnV@Vbn@VJVLnaVanbl@VlVXxlbXUWaX@VUUVwUUVm@I@WmI@amlLlK@alwnUV@kóVaÝk@UlbVK@VU»VUUVWU@U`ULkwm@@KmU@knK»VkJkUmbLkbmK@UUyUU@awm@@XXJ@VVLVVUbVnUJVX@Kk`WXXJWXUbmW@bkLUm`Xnb@JVL@LU@°VVXKVnUxVLUbmJ\"],encodeOffsets:[[110588,30769]]}},{type:\"Feature\",id:\"500237\",properties:{name:\"巫山县\",cp:[109.8853,31.1188],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@kVUbkKmbVxkLmKkllbV@@LXbxlaLVVVKXXV@@bVlKV@ln@¼°KXaU@Ulw°JXalIUaÝWXW@kVU@VUVWUUUamUw@aVamwn@VUUlLXWm£@wÇĉkKklmLUÒ¯Wn@ğ±kwmaWm¼U@@LUV@V@XVUnVJLW@XXWbĸºVzXJVXV@@VXlWn\"],encodeOffsets:[[112399,31917]]}},{type:\"Feature\",id:\"500102\",properties:{name:\"涪陵区\",cp:[107.3364,29.6796],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nèVblĖVVnL@xVn@nJ@LUVVX@lbUJV@@nn@VVVK@zV@nzVJVUlmX@@_VVVbnaVal@@knW@wnaVK@aVIJ@£kUVW@wXUVJam@Ik_X¥@WwkKkwmkUxnÅmm¥WV@Um@UlVL@JU@@X@UVkKVkKVkKkb@bmJVXUVVUbU@@`W_UV¯b\"],encodeOffsets:[[109508,30207]]}},{type:\"Feature\",id:\"500230\",properties:{name:\"丰都县\",cp:[107.8418,29.9048],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@Þè@XUK@LlV@blbUJ@V@bnV@VVVXU@lbXal@VXnKV@maXUÞ@amk@aVKXVanb£°mnIVaUKVwUmWLUU¯V@@KUK@IaWmn_VlK@anXVaXWWIXWl_@LUWVIUmVaUUUK@UWI@Wn@VI@mkU@U¯Kl@ImVÅLwU¤óbUU@wWXkmm@LU@@VUIWVUL@JUnax@JnbUIWVx@UXlV@¤IUJ@bULmb@xmX@lk@UbmbUaUU@`W@kn\"],encodeOffsets:[[110048,30713]]}},{type:\"Feature\",id:\"500232\",properties:{name:\"武隆县\",cp:[107.655,29.35],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@lwbVm@IVKXUVJ@UV@@KnnWlX@xVVôaV£xÆKnUVm@UmIXm¯¯@WkWVwmkXlaUwV»ULmk_VkK@ÅWa@aUU@mkaIb@n¼nm_@mmK@ULUVVmI@aUJ@XWJ@U`UIkm±kk@@lULmUmKUnVnlUVmI@VkVlxbkIVmLUxkKUXn¦ÆnmVwlnlxlLXx@W¦`\"],encodeOffsets:[[110262,30291]]}},{type:\"Feature\",id:\"500119\",properties:{name:\"南川区\",cp:[107.1716,29.1302],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VUbVJVUn@VLX@WVXVVI@VUVWxU@m@ĊX@@¼V°aVUX`@_V@VaUUVUWnI@alaLUlLUllLVU@@WV@@IUKVkn@@VlLVwnKUlJakwlU@UnJVUmkUVmXa@wVK@UUw@VVI@ak@alInwlKXUmaUW@wWLkKVak_ÇaUV@XbLVxUlWIk@UK@V@kU@VbUVUlVnLUV@lVXmxkV@L@V@Vk@WbUwmL@JUI@xVxkx\"],encodeOffsets:[[109463,29830]]}},{type:\"Feature\",id:\"500241\",properties:{name:\"秀山土家族苗族自治县\",cp:[109.0173,28.5205],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XlV@lzn@VnbÆbXKlLUÒV@@llUnxll@z@LU@@V°b@Vn@l@VÑUnK@UU@aUakVm@K¯wklmnnUl`nI@almkIUwmWVkUakkJmUUa@K@aU@@_m@@wUyVUUa@Um@awl@Wka±UkUykIWVb@bUVk@aU@UXUUIWakUWmUxUV@nUVWb@XXVVmXX@VbVLkVWx\"],encodeOffsets:[[111330,29183]]}},{type:\"Feature\",id:\"500114\",properties:{name:\"黔江区\",cp:[108.7207,29.4708],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VX@V@LV@VJUL@lVnnxlb@VXVXV@@W@UIVK@kUKna@£VWUaVUUalIVJVIUW_lm@bXKV@mn@JUUw@KnIVll@VanLVmUkVKXLVKUIVamw@UaU_lwKlwUWV_Ua@aUa@KUwm_Ó@wU@nkK@am@UkUKmXk`m@@I@K@I@mkVmIUxUJ@kUL@JVVlnklWnn`VzUVnlWbkb@WxXxlJXzWÛlWXnl@Ll@Vb°UJWLX@VlV@bkJ\"],encodeOffsets:[[111106,30420]]}},{type:\"Feature\",id:\"500117\",properties:{name:\"合川区\",cp:[106.3257,30.108],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XKVXlKVL@UnV@aValXXKU@WVwUaVU@IV@@aVWL@U@anVV@@bVK@UVL@bnJWL@VnUnb@@JnIlVl@@bXIWbn@UKVLVKXLlaV@VVnK@bVLmIV@KmknUUWVI@aVJ@_WU_VmUwU@KVak@am¯mJU_UJUkU@WkIV`UI@JV@LmmU@@mbUzÅ@VK@nUKbakb@UWK@bkVVbVÛ@@`Xk@W@n@lXL@bmb@VVJUn@JnUlnUlmX@`XLlbkJW@kzlb@`@b@b\"],encodeOffsets:[[108529,31101]]}},{type:\"Feature\",id:\"500222\",properties:{name:\"綦江县\",cp:[106.6553,28.8171],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@¦@XlVX@@UVKlVUX@lanVlUVbXWVXVVVUnKVUlwUwU@UJ@nmVkUVlwXam@VaUUUw@W@kk»mV@UmKkwVKVUU@@LUKVI@mV@XVWxnXVKUUUK@wWU@UUWnUlLXamUIam@wI@K@amImUUkI@makUkKWUUan@wamLVxk@UVmUUL@Vm@kV@I@ak@@bWVXJlLVbVL@@bn@@`Un@WbUKULWVXb@UVmbXWVb@bVmxUKUV@Un@V@V@nmnKlnnWWXX@lKkK@aIVxUlVbk@mn@@U@mbVUV@VLUJUXU¤\"],encodeOffsets:[[109137,29779]]}},{type:\"Feature\",id:\"500233\",properties:{name:\"忠县\",cp:[107.8967,30.3223],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VLÞĊU@W@¼V@lk@w²mlVUllVnI@VlKUUlIVXUVJVUwl¥UkUKUIm@aU@mUna@XUWmkK@aVIUa@aUVmIXa@Kl@UUVKUIUJmwU@@aWInUVa»k@@l¯n¤mabWUUL@bnl@bÝWVnbU@mLUWk@Wbka@WVUU@UmUmVkUULVlVUxl@L@VbÈÒlb\"],encodeOffsets:[[110239,31146]]}},{type:\"Feature\",id:\"500228\",properties:{name:\"梁平县\",cp:[107.7429,30.6519],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XLV@VV@b°°nnkb@bnJWVXblIUVxWnUJnVVLVUJlUnLVK@UnUVJ²nKVbVKla@aXlJkKlb@U°£KVIUa@@kwVVUkKV@VUkkUVk±n@xkl@U@»@XVÝĉUJnxWb@UXKkVUbUKWUkVmkkLU`b\"],encodeOffsets:[[109980,31247]]}},{type:\"Feature\",id:\"500113\",properties:{name:\"巴南区\",cp:[106.7322,29.4214],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nxnVlJlUXL¦@x@Vl@nKVVX@V_V@@KlVXU@lKlxXIl@ÈĊ@Vl@n_VJlnVlnb²VVVJVVmUUkĕUamçU@»W@@ĉnV@XwVU@UUJWUXUW@UKm@UVUIVaUUVmLUVUUUWWXUakVmUkbW@UVkUL@VW@kUW@mJUXVVU@lmV@zklVVkLUl@¦I\"],encodeOffsets:[[108990,30061]]}},{type:\"Feature\",id:\"500223\",properties:{name:\"潼南县\",cp:[105.7764,30.1135],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@a@a@_kalyX@lIkaWK@_nWVkkmmV@IVmUI@Una@aWK@k@mkbWaknmJUk@mk@@kUal@Ua@Wa@aXLlwUKlkk@KmI@VUJ@Lk@@VUUmL@amJU£kKUaWakLmU@bVVUbnbWV@xkL@bUbxUxVbXJVbUVWIUVU@kLWxkKWV@n¯VUbU@@VVX@VmaUL@VUK@VVbn@lVnI@@lnLULm@Ub@l@na@lK@XVVkJ@b@zl@@VnV@bVb@J@bnXV`lXXmVI@W@InbV@@aVKUblKVLUanLlmnLlK\"],encodeOffsets:[[108529,31101]]}},{type:\"Feature\",id:\"500118\",properties:{name:\"永川区\",cp:[105.8643,29.2566],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@bÜnWVLXlxVVxXxlVn@@bVblK@a@UnLVJV@@UnLVU@VXaVKVX@n`WUÿ@IUKlaUUUkWyUÛÅÝ@mmkUKUwW@Xk@amUUakKWwXaK@VVLklXVlkxVUL@bm@Vxn`IVxUVkLVUl@@lkXmmVUn@VV@Xb\"],encodeOffsets:[[108192,30038]]}},{type:\"Feature\",id:\"500231\",properties:{name:\"垫江县\",cp:[107.4573,30.2454],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@Ċ°¤nÒ¼aV_lKnllUXVVLValULVW@XamwVIUKkaÇÑa@U@KkVwkUUVKlVnU@aU@VIka@akU@KVL@WÝçUV@VmbÅ¯@LKnnJWVkxlL@VX@VxmnXVWxUb@bkn\"],encodeOffsets:[[109812,30961]]}},{type:\"Feature\",id:\"500112\",properties:{name:\"渝北区\",cp:[106.7212,29.8499],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@bVVXLa@lnbWn@L@XVlK@VVLUVlbkLUKVVVL@VnXVL@VV@UbVb@x@¦UxVb@bUJL@LVVxlK@nk@U@WUVLlKXV@VblU@UUKVU@wn@VJVanLlkX@VaVK¯@a@U@U@VaUKkUU±maUkm@UUkbm@@Vk@@JwU@Ub@I@JmwUL@a@@KkVÇLkWk@kUU@@xUVmKUnllUb\"],encodeOffsets:[[109013,30381]]}},{type:\"Feature\",id:\"500115\",properties:{name:\"长寿区\",cp:[107.1606,29.9762],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VVUbXlX¥l@XnVmlxUx@@blVnnôĀlm@aVaXwWUnmUwW@@UkKlwUXmImL@KÆ°na@UUImyU@@yULUUm@@mU@VIkaW@UUV@KI@mmUw@mKUnUUIlVLUb@@V@V@b°ULUbW@klmKUbUIm@@xUVVL\"],encodeOffsets:[[109429,30747]]}},{type:\"Feature\",id:\"500225\",properties:{name:\"大足县\",cp:[105.7544,29.6136],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XUmaVaUU@anVlKXbValU@aV@@IXK@@bV@VxVK@UXLlUJXa@_@@aVKÅWVkwWawUa@am@kUWLU@kWmX@ykI@W@UV@na@LlLV@UkwWUKmXX`mIVl@bXLWVkbkkx@`VXm@@J@U@UUKUxk@WbUIVl@VXLWJUkUlUImxXlmb@X@VUJUnVbW@UV@@VVX@bnW@LVxUnlJUV@n@VxVIn@l`UVVVL\"],encodeOffsets:[[108270,30578]]}},{type:\"Feature\",id:\"500224\",properties:{name:\"铜梁县\",cp:[106.0291,29.8059],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VblLV¤nI@bnKVV@Ul@@KVI@UnJ@LlklVLkxWK@bXb@Vbk@Vb@ll@@nVlnIlmXblaXl@W@_Ü@UUalU@aXL@VlabaVL@mUL@UUÇXUWX_WaU»m_@UWULWb@UUVmK@VU@UImK@V@bkLxXblxXUÆUL@b@@`WbIkVWK@VULUwU@@a@WL@JU@@bkVUb\"],encodeOffsets:[[108316,30527]]}},{type:\"Feature\",id:\"500226\",properties:{name:\"荣昌县\",cp:[105.5127,29.4708],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VI@U@WnaWknwVJVkVlIXWK@UUkVJXal@VwVL@V@V@In@UW@_wlllaXUWK@aUknJW_Û@aWaU@@UVmUUaUImJVnÅUmVUm`kUUVWLnVU@VVmXK@nxmULkxImJ@nU`@X@Vkn@`@nlV@nVJVaXVLnK@bVV@nV@lbXW@\"],encodeOffsets:[[108012,30392]]}},{type:\"Feature\",id:\"500227\",properties:{name:\"璧山县\",cp:[106.2048,29.5807],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XzVlVVkbVL@JVĀX¼VXbW`XWVÈVVVkV@@UXa@alK@IU@UKWUyUI@wVUUWVak@VUkW¹@WXI@yVIUK@kWwkÑ¯±W@kUb@KkVVVmXJ\"],encodeOffsets:[[108585,30032]]}},{type:\"Feature\",id:\"500109\",properties:{name:\"北碚区\",cp:[106.5674,29.8883],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XVLV@@JkL@bWb@VU@UlÆVya@nV@nn@KU@IVJU_lJXV@VlVIV`nIn°@blUbKVI@aUaVw@¥@wUaVaU@@UUKWm@UUKUUVLlKkaVUUK@UkLWU@@KXmma@kbWKUU@aUamLnÞ@VWLk@@Wm@ULU@@UKUVWI\"],encodeOffsets:[[108855,30449]]}},{type:\"Feature\",id:\"500110\",properties:{name:\"万盛区\",cp:[106.908,28.9325],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VIV@@wVJ@InKVxXal@@U@U@KlUnwUW@kVUKUmVkUa@I@KW@@bk@@mU@m@k@a@aIUxmJk@wULwkKmVVX@VXV@xVLVVULmWXwWUU@@nUJVL@KV@UVULlxnL@VnUl¼@l@XVxVVUbn@WbkxUlVnU@m\"],encodeOffsets:[[109452,29779]]}},{type:\"Feature\",id:\"500107\",properties:{name:\"九龙坡区\",cp:[106.3586,29.4049],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XKL@V@XbV@lW@UV@@VXIV@UVKlL@KnnJ@VV@VU@I@@mVUVWUUmL@V¯LUK@UV@UU@a@U@yU@WLUK@X@KUVmL@@aXI@w@ammVk@WÛwm@UxVVVbVLUJVxVUV@V@X@JUIVbm@@Vk@@VkL@lVLUJ@zWJ@X\"],encodeOffsets:[[108799,30241]]}},{type:\"Feature\",id:\"500106\",properties:{name:\"沙坪坝区\",cp:[106.3696,29.6191],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XºlUVl@UbVXUV@xVJVzXJVUL@VV@VKn@@Xl@XK@UmÝnKVbVakkVm@kUK@UmIm@LkKULVU@WJ@UU@@VkXU@Wa@@UKWL\"],encodeOffsets:[[108799,30241]]}},{type:\"Feature\",id:\"500108\",properties:{name:\"南岸区\",cp:[106.6663,29.5367],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VVJVL@bUVVnl`XIlwXJlw°nnlIXW@UÇĉk@WJkwkL@WVkU@LU@U`W@UXUV@n\"],encodeOffsets:[[109092,30241]]}},{type:\"Feature\",id:\"500105\",properties:{name:\"江北区\",cp:[106.8311,29.6191],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nLVU@wV@lV@XllÈKlU@L@@bVKnx@I@JVaV@x@Il@@Un@laVVn@mkUIm`k@WXJmk¯mkxWIkxWJk_UmVUUK@UU@@l\"],encodeOffsets:[[109013,30319]]}},{type:\"Feature\",id:\"500104\",properties:{name:\"大渡口区\",cp:[106.4905,29.4214],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@k@@U@w¥WKkVkImUmwa@b@xWJ@b@nKVU@L@WVLXKV@@z@V@bVVU@@VVL°K@U\"],encodeOffsets:[[109080,30190]]}},{type:\"Feature\",id:\"500111\",properties:{name:\"双桥区\",cp:[105.7874,29.4928],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@WwUwU@kK@KmbU@@V@XlJ@znWlXV@XK\"],encodeOffsets:[[108372,30235]]}},{type:\"Feature\",id:\"500103\",properties:{name:\"渝中区\",cp:[106.5344,29.5477],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VL@VV@VL@aUKIUU@@JUVU@\"],encodeOffsets:[[109036,30257]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/fu_jian_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3507\",properties:{name:\"南平市\",cp:[118.136,27.2845],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@@knyk@KU¥wV@nkWzUmk@@lKUa@aVI@UKUamKUUVaUI@X@UV@K±IUVVlUbUbUL@KWUXmWk@KkXmmkÅKUa@amUbkUkKWUnwUÇwVUUÝUKV£U@nKWwXLVKm¥@wUXkmWk@@wX@lU@yVImaXwV@knU@mbk@mlUXmU@mV@n@bnW@bUIWJImVUKWbUK@nkKaU@W_VUUmWmL@UU@bUWUL@V@bmVUz@`mUUVVbXL@VL@lmLUxmVamXkW@xWbUVbUxkU±@ÅUmmkLUbW@@`kLknVlV@lbXxlVUXVVUU@UbWkIWVUUUJkI@llbUxVL@VVUU°ULUmWXUV@VULWb@xm@UaVLVKUa@w@VbkmVambUUm@@VkK@@bxlxX@n¤@X@@lkLWV@nVkb@bWJXLWx@nkxmmbXn@VWVUn@VnJ@bVXl@VJXnWbX`lLUlJVI@@VXV@Vl@bn@@Æmn@VxXU@mVIlxVnIl@nVJaXI@mlU@aXkVm°klmnVV_na°@V@xÜ¦XKVnnUlVXbVKLXKV@naV@@VVl@@lXblXWnLlbVK²n@@VLUnlV@lXxô°V@UnaUUlKXLVUVVUbVVlUnJVX@VW@an@lb@nl@VU@anUVW@kaUm@InVVKVU@kUW@Uam@km@kVa@a@nwU@WlI@mVI@WXaW_n@nlkkW@U¥@kV@Uw@wU@@IXK¥VIn@nU@`@Xl@VVLnaWbVaUwnU@VIKlV\"],encodeOffsets:[[122119,28086]]}},{type:\"Feature\",id:\"3504\",properties:{name:\"三明市\",cp:[117.5317,26.3013],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@lL@Un@VVnabnUla@Ux@VbULUKVbn@w@XaVK@UVUXWVnVKV¯VU@UUKVwka@klJVIVVXUlJXVaV@VUUVWkUWwkaU@UklmlK@_X@ValKnnÆV²@lVVwUaVXa@wlXnWbnUVwnK@kK@UWKUaVUnV@_VynU@a@UVKVXaV@@VnKnXVVUX`V@blL@mVLXaVLnUJXIVJ@amX@a@mnUV@nVWnkl@naV@ml@@KmKUam@UU@@UlKUVkUK@aVaUwVU¥UIkJ@wmI@mbkwkVW@UXKULU`IVKUa@LkkVmUU@WlULUWÅU@I@WWnU@@w@a@Uam_XyVIVWkk@mwVKXUV@nwVXkWÅU@aU¯KUnK@¯mULXVLnWVbVbUVm@Ub¯¼W@am`kbamLUUUaUXV`@x@XmJ@n@L@xkJUU@kU@mWm@kUUwUUVWl@VUkIy@kkaVUUmIWVXbWxU@kmVkK@nWVX¦WxU@@bkx@VU@Wk@kUbmJUUmkUW@_kKWK@knV¤kIUKWLUbV@Wbk@@VWL@VkI@lUXVxUVU@@mWIV@a¯nUaaUV@Jb@bÞ°VbU@XaUVmL@VXblnV°n@Vnx@VUUUlK@InJVb@Vlnn@VL@VWJUx@XlJUVVVl@LUUUJ@L@lUL°¦kVVnV@xVl@blLnlLVaXll@nVUn@xn@nml°X@lb\"],\nencodeOffsets:[[119858,27754]]}},{type:\"Feature\",id:\"3508\",properties:{name:\"龙岩市\",cp:[116.8066,25.2026],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@aI@VUbVb°m@bUXJ@nV@VUUwVW@klJ@UXK@Ul@Xa@UVaXKVLlJU£lm@XLlL@`VXnlVVnIVall@XV@@Ulw@aV@XwW¥XU@mlLnUlV@XwWaXUJVnUVlb@lzlJUVk@UXVVVxlVn@nXV@@lVVlI@w@K@mnI@W@wU_VWbVVVnKbla_nbX@°»Van@VUUaUamXUKWK@a@Uk@wWkXWW@wUUKw@_lywUkU@@U@kamVmXaUVUka@Wk@»UUUVKkbWUVUbk@mkxkKnIVUmW@kUKmXUmVaU@kU@m@KUWVkIWJ@U@UI@wUUUa@KW»nU@mVkUmm@XwWU@UUmL@w@mnVUU@aWak@@amxU@UxULWVXbVLU`mbUImVUbnV@@bVn@bnVWxLmyUbIUK@aVmakbVUXWUlKWbkV@WLUlk@@nbb@lkKmU@UIWJkw¯UUVVxm@@XkbWxXKlUzWJkUUL@bmKkV@@VUIUlWV@XK@VkbWx°xUb@LUbk@@VWb@LXJ@VWXU@@bUVVVVn@VVlLn@l@xk¦Vx@bVJXbn@JlnXxV@@nJ@X@V@lmxbUn@xVL@VVKlL@lnLVaVL@xkl@LxVl°XWVXVlJWnxlJ\"],encodeOffsets:[[119194,26657]]}},{type:\"Feature\",id:\"3509\",properties:{name:\"宁德市\",cp:[119.6521,26.9824],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@@LVKVaVaUkVU²J@LVU@@WVJUbVVnLVbL@VUJ@bVbkL@l@VnyXmlU@xV¦L@lmz@lnL@bVVbVb@lnKVkVl¤@zXV@l@XJVLVKnXVKVnU@wUm@KU@UlVlw@U@U@UaUKlU@kXKlmXIWKXaVIVUVK@KU@@kJVUnLVJUL@VIVa@VnLKUnl`VbVV@Vbn@Vzn@lKnVlIVVKUalkXJl@XXVWVLVUUmVU@Unm£lK@Uk@WUXK@U@WVwVkĠkĢÇ°aUÅUwmaţɱUÇaw±V¹XalKôx@UVaÜʓͿVóbÅLJm¯Vk¦k@mamXkKUULakbk@mV@LkJWb@VkmXk@UVmaUV@amLUKUamI@KUaU@WbU@UUUUIWJUkm@wKkVJm@kxÇVUK@mUVUkmlkkVm@amwLVWU@UbVLkUb@VmK@XaVWU_VJnwV@@kUmWakx@kwWakIWxnbUJz@kVW@@x@XllnVW@xn¦ULWKXxmL@VU¤VLÞVVUÈxVmxXVlLlVanV@bbVLlÆnnlW@LXlWnXV\"],encodeOffsets:[[121816,27816]]}},{type:\"Feature\",id:\"3501\",properties:{name:\"福州市\",cp:[119.4543,25.9222],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@lxna@nJ@xlIVJV¦UVxUb@bLVUlVkL@V@VVn@VbLn@LUlJXblx@lwXbVn@lU@mxUIV`UXWb@nLU@ValUKVaV@UXKnxbn@lUkllnUVnV@VLUÈlwn@UIlLxn@VlXIVJVVVV@XaV@Vb@LnJVbVLnK@bVUnbVUl@nWl@UXalI@KnUl@labVKVlLnWnbl@l¥°UnIÆKôa΀Ua@UUwÇWǓIUWUÅVkƨm@@£@KmLU¤ULˣJkUVǟUUķ@ĉVKUk@Ñ°wôÇç@īé@Åţ¥mīÛkm¼Å@VķVó°ō¦U°n@bVJXVVL@bUakLmx@xmxXzW`XbWnXV@bWLÛ@a@aXbWVkaÝwU@mlWKkLWWkLUKULW@kVmVUUÝUamV¤n@xUVUzkJV¦lJU\"],encodeOffsets:[[121253,26511]]}},{type:\"Feature\",id:\"3506\",properties:{name:\"漳州市\",cp:[117.5757,24.3732],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@@bl@Xb@bVVUm@nx@nKVV@XVWxn@VnUl@nmVX¼@LVbVV@xVJV@@XIlJXUV@Ln@lVV@UbVnnWVL@lnXUVmJLlwnll@VaUXVlaLVUVV@¼Xl@lbUVVWbnnUlb@@VV@aVUmlUaUny@kU@Wkk@WaUVk@@ammk@@U@UlU@aUa@wl@mXLllnLU@anVnU@L@VVV@KlXnWVnVanUw@w@wmnÅ@waUam@UkmUl@@aa@U@¥kôKwÈ¯°w@ŻkwǕaKÑÛk@ĕōřċ£ĵUKW»kÅŻLU@Ulġw@¤VzVUbkKUbmLmlULU¼UxmbXl@bWVb@bUnVUVbULU@@VkbVL@`U@WX@XV@b°@b¯@¤@Xm@@b@`UVVUL\"],encodeOffsets:[[119712,24953]]}},{type:\"Feature\",id:\"3505\",properties:{name:\"泉州市\",cp:[118.3228,25.1147],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@Vlxkz@`xLVV@xXXWXl@xl@V@bnV°@LVm°LVbV@ÆXWlUmxU@WVULnx@llUXUJWzn`Vb@@b@xV@mXX@@JÆVVXVKXkV@nVlUl@KVbULJV_VKLVWX@lUVkIU¥lIVyVU@wm£nUVWU@am@UmWw@UX@@amVUn@@aUUlUVanaWUXWmUnkK@VUlVVUUw@XLWWXma@knmbVbVXbVL@XJlInlLwmXów@çV»ÇçŋaķƧóƅóKġ°nÅUķƑUÇW@¯xÇ°öÆlVn@lla@Lb`@VXVVx@V@bULVJUkÇ@¼XUKk@mmULkaWbk@x@UkL@a@K@U@UmKmbU@kV@UmVUbUmmXkW@LUU@U@KmVmU@bVmKkkWKnk@@xVb@bkV@V@Vl@nn@bl@VUXbl@XlV@@lmzVVbknUVb\"],encodeOffsets:[[120398,25797]]}},{type:\"Feature\",id:\"3503\",properties:{name:\"莆田市\",cp:[119.0918,25.3455],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@VbÞVVnUlUX@VKVLlKXXlKXLnkV@ÞxlbXUWab@bÜ@XK@aWUXmWaX_Wynw@wnwlKbV@aUKWUUI@amV¯Ŏ¥ô¯ĸUUÆ@n»¯aƿé@ţ¯nĉĬÝKóó@ÑU¼@èxWônxKmkkJWI@UKWaUUaamn@lnbWXXWK@VxUVkUV@ULmlnVWXXVmbUbkVVV@bm@UVn@bW@@VXxn@Vn@bVUX\"],encodeOffsets:[[121388,26264]]}},{type:\"Feature\",id:\"3502\",properties:{name:\"厦门市\",cp:[118.1689,24.6478],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@VlUV@nanL@V@V@L@blK@Vwl@XalbVKnnl@VLW»È@lVUIVK@a@UUwWUU@_aK@bkkm@UkõÅxóLl@¦@Vb@bk@VnVln@Vbb@xmÆn@x@xx\"],encodeOffsets:[[120747,25465]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/gan_su_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"6209\",properties:{name:\"酒泉市\",cp:[96.2622,40.4517],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ÇnÅaĉ@U¯¥UŹ£WUýUU±JkkUwyÞIČxĊĕĊ¯¥ÆUkţUÅÓ±¼IUx¯UÒƑÝÅ°KÝnğ°ÅU@@Vn@þ¼¯WnŎ°XLWlnVnbWnVXxmbabóUlǕUUaIUmlU¥k¥ĉwkkÝɛa@¯U¯°mVkVnKlōÑÇÑU@klUġkUŻnUW@¯k»mWV£UKnUmUww@UIVaXwm»Èmmwn¯ċ¯LĉUJUalka±Va@Uk@ÛÑ¯WmnUaɝ¤Ûmn¯m±x@wóxÛLġÒUx¯VÈJUbózÝÇKĉ¯ōlÝUÅWl¯nťbÝ@¯ǩLġmV@Æ¯ĢkÆmĊkVťLɃmÝXó°@ĢbVóVÝ¦ɱ@ƧaġUVĠÇÈV¼UVţwmbJÇwˋaXmÇ¯KkkmbXm¼V¼ǬŚ²¤ôŰÆƴô̐ŤǪnɆӨ¼ɆLÆłUĊxŎƞȘǔˎǬǪnƨŮǬö°»ġÞÜÆĸÒĊǀbƾèôÈ@¼¯þŤĸƧ°VĀ¯b@lÈĊʠń̐ȘKǀֲॗţÿǕý@ʊǓƨóÆÑǖŃôw@΋ʈƆÅÈVVĊVóĊÅ@ÞƒĬV@Þī@°V@ĸĢ°XτƜĠ@ÈaÜ¥ŐƅnğóĕVġUůƿŋĕa±VUťÇğÑ\"],encodeOffsets:[[101892,40821]]}},{type:\"Feature\",id:\"6207\",properties:{name:\"张掖市\",cp:[99.7998,38.7433],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ÈÒŎÒkmLUlU¯nV°@°ɜbÞĠaÈ»ĸlLVUÈ@Ċ@ýUm@@ÆVĠ¯ÞmLÆ¯ÞƒÑ°VVwJ²»ÆÔVlŤÅV¦ĉ°ĉĖċwÝJzVxll²IVVVþX¤źV°¦VĊ@ÆbÈmǔLĸĠ¯Ģaô¯ĸmÆÛUlÇĸk°XyĊUǔVǩnmV»a@ýnK°n@l¥@»żĊ¤mç@£ČU@mmVkÞUƐ±²¹°ĠwÅƑŃU¯V¯aÈŁÇ»ġn_°xŎKlxklx@Þw@Æm²bÇ²LlkWXať¯ĊaÑK±w@wUÅçV±Uk@@¯¯xU±±UU°ōxVxÅÔō°ó¯UÝ¦óbÝþ@ĉÈóUVUx@VUVÝwÅÈÇóVkk¯JÇkmmL@KÇx@bk@U°ķ²ó`mn¯°UwlÅkU`¦ɛôķz@ÅnÇ°U¼¯KmVk²J¼ƏÞķô¤UL@mnğ`ÇnUxÇ@ÛÿU@kŻ@x@móJkÅ¥VŹĉóÒĉlċ°ķUƽÜ@x\"],encodeOffsets:[[99720,40090]]}},{type:\"Feature\",id:\"6230\",properties:{name:\"甘南藏族自治州\",cp:[102.9199,34.6893],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ÞnKlnwX¥WÝXkxÞUn°aĊVnUUKlÞĶWXnĠ¥ô»@nmVL@¤°VzJanU@aÆwna@kU¯yX_aĉbwéXkWwÅa¯V¥m¯UI@@mb°aÈçU¥@»knwɜƇ°I°ÑÈmVU¯Xa@wW@wV¯Č¥l¯Uwnm@kaUaóKkk@Çab@ÒWa¯IÇxÛam¼VUxÒl@zÝÒ¯bÝaĉVĉwÇWzJmJn²mÜ¯U¯ĉ@ġ¤Åb@²nml@@ULVxVU¼Ålmab@°l@WIU¯@m@ó@UzţyXÇUÇVUUVLkbWakVWmUbkkKUÆ»n°Knk@aUVmnk»l¯Ģlw@_kKVU@na@lUk@¯¥mV@kmbWb¯Åõa@mkU@kÇkU@`@óóbl¼Uxn¼lVÈx@blVkVVn`XÈġÈ@ÇK£ÝJmUUnUĖmlUmKUnVÅaUwUĉ`¯n¯wW¼nxV@bĉnkIċŘkXU±ÒxÈ@X°`lVIÈ¯ĊVVVan@VaUVażVmblkÈWWIXaalL@wVbV¦lL@lĠnÒUnkL@ÆÞkÞKbñþW¦ÛċVULUºkÈlŎUxÆxÞUUxÒx@XbL@lÆ@ÒlXVln@bm¼J@Ånx@bnĠmxVXmbÈè@Ċ£ČWw\"],encodeOffsets:[[105210,36349]]}},{type:\"Feature\",id:\"6206\",properties:{name:\"武威市\",cp:[103.0188,38.1061],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@±¯¥@klwU»ÞÝmwKm¯ç@kVÇUL¯lVUKġġm@a@U@X£°l°LŎÇ@aōVÝwÔKUÅWJ¯lm@ÛVWa@klĉUmaLUanak¯J±KkXóÜÅx²Ç@nUÒĊb°@ÆkLXÇÆ@xÝnxWxţ¯¤I@ÆnVVVlU²ÆèV@x²xLÒĉbŦ°WbXklÞ@l¤XĊ`wl@ĢÈŎm@bnVUb@ÈÆÛLèÇUÒÅ¦lĸ`°ĮʟÆǓbĉôϚĊÆĢnŤé΀ÑĸĀĊ¦@@l°l¦Ȯ¦ɆÞĊKŤĵĸů»mŁyġķŭ@Çɱȭ¯mƧUĊķnŁŻ»UaUƛɞÝƨů\"],encodeOffsets:[[106336,38543]]}},{type:\"Feature\",id:\"6212\",properties:{name:\"陇南市\",cp:[105.304,33.5632],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ÈÞ@l`UmV¼@nnÆwVlnVVaLVÈ_ÿÞ@naxÆ@l_@VxnK@llLnxmÈŎJnbUxI°l@n¦lÈIlmX¥k°@kJk²é@klaUaVaU@@ÝnIWnmnxkºÞaV°V@nwKxôbÞ£VUbþLn»mVwIJ°@nb@°°IġUkÇKV@Å¯»lLnm£@anK@ÑÜn@»mL@£ykUUmbUÞÝ@kyÇbó»XUxWVzb±mÝbXawUamL¯»@wUKVwm¯ĵJ°ÅUWVkKVk°wÈVVÑlU¥kmVamknUw¯¯bċ¥ÅKkKkVċVk£kKVwÑa@kóyÛ¯ÇVkówXō¥Ç¼ów¯U±k@xIĉÒÅVmÈnÜ@n°bUbÝVUnnJ¯Į@m¦nVÜ@L°JXbÑ@aÈb@llôLVbb@lmnVxk°ċ¦U°@xX@xWb°UVÇn¯Ò¯Jɛƈmxl@¼\"],encodeOffsets:[[106527,34943]]}},{type:\"Feature\",id:\"6210\",properties:{name:\"庆阳市\",cp:[107.5342,36.2],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@kwĉ»VamV¯wIóVkl¯KmVō¯ÝWkL@bÝKō¦@@Lx@b@la@km@@l¯nm@UaÅ@óWUXm¥nw`@UUxķôÇ°ğ¦@VJ_nIVnalxkXJWn¯nVLxl¤nnVbklVX@xnxmV@bUK@nm@@xV°±aÅnkUWnUax@mn@¯LmUĀlU@lV@blLUblxklkIÇx¯°UXbaVUnV@°LUlnbX@`°nVmbnÆmVkLmK¦U@Xy@kl@U°K@¼XbW@bWnLVaVVz@xlVČ¥lbUxÞlVU@nÆWôn²VJlUƧLnmÜLXan@mw@wlUlV²mblwVÈlLÞ±@lVnUlxnkma@mkJ@kXVU@mn@¼VXUVlLnmVbôaVnWV»ÈUl°È¯ÆInÆU@kk»mKkÆġk¯@»mk¯@óÇlÇ@VykklUml¯Þ@w\"],encodeOffsets:[[111229,36383]]}},{type:\"Feature\",id:\"6204\",properties:{name:\"白银市\",cp:[104.8645,36.5076],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@VKUÈl@è°nLnxÝÞV¼kx@l¦²°ĊóĠĊ»@ÈxaĊxlwÈVŤa@¯²aÇ£Jk£lnUÞ@°ô@ywl»lIX¥Ǫnw@ÑÞWlaÅlL@Uwĉakl@¯mwna°JV¯nUVÓÞÑm£²óWaUÇ@óÝUçV»ÈkkW@¯xV@XlK@wX@Vmm_@wÈÝKU¯ÇwVwÅK¯VkJXkWVaIm¯UkÇlVĀV°mxók@¼óWxĉÜU@UbzÛJÇk@ÆnVlÔ@kxô@ĬWL¯K@aÛImm@IUa@UÇêU¤VÒÇx¯ÒVlk@Wbĉ¦UbkWV_y¯Laók@b@nmbkx°\"],encodeOffsets:[[106077,37885]]}},{type:\"Feature\",id:\"6211\",properties:{name:\"定西市\",cp:[104.5569,35.0848],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@aV²wVJV_@LlanÅllŦçÜÓ_lnWaôkxUbmV@È°lènk°l¦`@nnL@ÈlÜIyVaV@ĊÛXwô@»lônwU¯ÿUÈkl°VnJUblXWIl°UV@aVVVmnL@lUUwmk£bV¥VUVwÛlaÇÝÞmk£LUy¯L@WlkKW_XaWmġU@akakXkmVwmŹVUbWónmwnWW£KÈnV¥¥Æ_klWbU¯V°aôbnaVwmaōInÇmwkK@kmLUw@`kÅ@wb@mÝĀÇ`UKUbmUUkÅxmm@»nUVk_Ý@Ç¦VÇè¯ban@@JV°nU¦°ÆbXxWlêxĊabW`zV°@lmbÅx@bmVbI`¦@ÒUVUI@ÆL@b¼@@lmxnL°ULÞğÞ°kLUL°xVnKVl@zX@\"],encodeOffsets:[[106122,36794]]}},{type:\"Feature\",id:\"6205\",properties:{name:\"天水市\",cp:[105.6445,34.6289],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@UyÈVVUnn@VU`UblzJnk@VbKU°lwW°nkVUÈl£°V@n¥VklkU±Unlw¯UkwmKUlmkUmnkym@Å@UmWÈU°l°anlJkUKlU¯Èm@kmWV»kkÝLUWUx±b@¯ma@¯IJUxnm¼KýaVUÝ¤óawLmxU@¯UbÝ¹lmwmnXmJ@ÞV@UbVbkbl@±êlIl¯@lW¦knÇJkm¥k@¯Jmbóa¯bUV°akXlÅ`¦U¦ÇmLX¤mXnxmôXaVźUnUxlnlWbl@bĢVnXWbX`lLXk@°KVzKl¤nÞÝÈkbÜ\"],encodeOffsets:[[108180,35984]]}},{type:\"Feature\",id:\"6201\",properties:{name:\"兰州市\",cp:[103.5901,36.3043],childNum:5},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@lW²L°IlmbVbKnbĊVlk@XbÜU@kn°XIÆVLÓÞxŎUlôb°KzU`lXVaĊ¥Xal@kU°ÑÈwUÑV£ÈéV@VbJ@nnÜJ@bL°XK@īówl@kÓmUÅmK@m_k¥l¯mkçÇ¯@nUaVwólXbmk`ÛÔťèkkmÆkbK@U`UI±xUbWlXmbVbÅÒólkIWJk@zKŻ¼@xUxó¯LWb@ÅÒ±¦U`nbťĀUVbLU\"],[\"@@¯lwna@mōÈ¯K¯kW¤@@V@bĢnĢVLU°k\"]],encodeOffsets:[[[105188,37649]],[[106077,37885]]]}},{type:\"Feature\",id:\"6208\",properties:{name:\"平凉市\",cp:[107.0728,35.321],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ÆLUxÈxV°LÇÞ@xn`Ü@X@nĊÆwnJmwUxaUkw@V@waVmlLXÝl@XVĢmV°@nl@UUUWK@wÿVI²Òlm@nÝĊýVV@nJ°Ułm@kV¼nKĢÈ¤ôKblnKllVk²aĠ¥È¯ĸóVw@V_xmn¦VWôXÆ@Vbn@°m@kn@@lb@ka@wK@@UlKVaWXW²¹lÓw@_°n@@_lKÅķW@mLUWn»Û@l_Ç`Ûmm°ÅbWb@VWbUUKÇÅaġlmkUġl»LlUm¦@¯U¤ÇkVUml¯Xx¯kVLUa@mlIkyVa_UV@mmUVUÇVzUxUVU¦a¤lnVxVk@mKUnUU@bU\",\"@@@ż@mlkġk\"],encodeOffsets:[[107877,36338],[108439,36265]]}},{type:\"Feature\",id:\"6229\",properties:{name:\"临夏回族自治州\",cp:[103.2715,35.5737],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@@ż»Ly@lXIJlôkÆÑUanaWXkW@yk@ULmUw¯KVlK¯ĠÝÝVK¯mKnwk@@»@aK@ÅVJVU@Ñ¥_Uy¯@£UKmn@ó¼ğ¦WmĵXÝkVLmVĉU¯bmÝVwWlXÞW¦xkmmLÝ±U@VÞ@ÅÈW°XÜ¼ƨyUĮnWnXÝxUx°lVXJlôV\"],encodeOffsets:[[105548,37075]]}},{type:\"Feature\",id:\"6203\",properties:{name:\"金昌市\",cp:[102.074,38.5126],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@ĢÈ¼Çł°bU°VƒńÆǖŰnÆōĬǔaʠÅ¯ĭ_kķÆ¥VÑÈçÜKÅ@ÇVaUm@aōnġÇk@xĉ_Wk£@Ý±KÈ±aÅn@Ýx@kwlkwōL¯wm`\"],encodeOffsets:[[103849,38970]]}},{type:\"Feature\",id:\"6202\",properties:{name:\"嘉峪关市\",cp:[98.1738,39.8035],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@llĊx¦l¦kVVnJVbǖVkôVabnaWwUXmmamUXkWKō¯Xm°»ĉÇ@UVKķkÇ¼ğb\"],encodeOffsets:[[100182,40664]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/guang_dong_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"4418\",properties:{name:\"清远市\",cp:[112.9175,24.3292],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@lÇ¯kÿaV¯VaÈU¥ÆÇIlxmnbUxlUôl°kWl@ôVwUanUl@xVkaX¥kU»a¯±@kka@UwmUkwJk±k@L@ÝWUwVÝxÇU¯ÇX@mÅ@@yĉ£VmUwȗ»ÇUnlUnWU¯`Uk@@x@bÇxX¼VV¯LĀkÝL¯@VĀ¯lnĊW¦kVÇôkUÇUK@ţU@aóÜUU»@¦k@VxKVbn@Æl@xbWnlUlxÈlVÈ°Æ@¼@xWxŎVK°¥nÆkŎ@ÈÑmK@¥k@ô@nôV\"],encodeOffsets:[[115707,25527]]}},{type:\"Feature\",id:\"4402\",properties:{name:\"韶关市\",cp:[113.7964,24.7028],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@WXk±Ñ@UwmUwĉwlmn@Æwn£mkI¥ÇÅ@¥aón£nWWw£V`Þ@nVml@xô¼IV¥kUmkamUkVWwÛ»mó£UVÅKmn@x@kbmm¯aXkaVĉaUbÝ²lIlxnVVx@lb@l²°bV¼lW¦bUlwk@mVVbUxó@kX¯lókVkwVmankwJÅÈ¦ÇVUbU°blĀ°kÈ@x¦ÆÜ°@°¦óaVUôlUlbXl@nÜVnKlnIVÞ°W°U@bnm@¥IV²Ul°VnalzXyl_Vyƒ¦lLlx@ÞbKmknVWanwÑVwČº@n_ÞVaVÜIl@KÈVJ@a£È@@kmaV¯W@_a¯KmbkÇkLmw@Å¥\"],encodeOffsets:[[117147,25549]]}},{type:\"Feature\",id:\"4408\",properties:{name:\"湛江市\",cp:[110.3577,20.9894],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@@kX@aUUċlkJk@wVJXUWk°W@nKnwlUl²blU@lIl@XbWxnm@lW@wwUJX¯VU°`ŎóˋkÝÝkÅ@ÇmğÈřmwaĵVxUÛ»°ĠǷnýmóX¥ɅĵҏÇ@°²ĊUĖ±ĮU¤Ç°Ā¯ɐnżUĊĊĬV@è@ÔÒU¼l¤nĠbêVĠ°ÈyzVaVnUÆLabVlwÆ@\"],encodeOffsets:[[113040,22416]]}},{type:\"Feature\",id:\"4414\",properties:{name:\"梅州市\",cp:[116.1255,24.1534],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@nÔlW¼x¦@lVllLkèa@z¤Ė¼UxlnUKUbÝlU¼lb@VxVklJÈwV¯@ĠlÛĖnbkÆźÞUÈôklmL¥LWnKUkVa°Vx@IVV@x°bUkaa@mV@@ywLÑUwVUVUbÞVVann@XwÇÿ¯²aVamkXaÆ»@»nw@¥UXakbWa¯KUw@¥m@kwmLU»UUJ@kmU@UUWU@yanwmçÛl¯¯UmKUmwVkmÝXbW@XWÝbk¯@±w@»U@W¯Å@Ç¥UU@IUakJĀê°þXkam@_J°m@X\"],encodeOffsets:[[118125,24419]]}},{type:\"Feature\",id:\"4416\",properties:{name:\"河源市\",cp:[114.917,23.9722],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@°VlmX¹laĢÒlm@V£@¦Ģklynn¼lW°zW°VbÈV@lÆbnnJkXVÆaÅW@UUw@kaV»ÞkVaVLkmVw»ĕ£@yblçkKkU@k¥wX»kmÓ@Wn¯I`@nlbWý¯éÿlI@XUmWUw@@UJUÇmKUV@xţk¯¯LWnUxK@Å±»Vwa¯@¤WX@Û¦@¤ÇIÈ¼WxX@WxwUnVbÅèmVa±²UWl@klÈ¤nôÜ¼XxlUnVlbVnlU¦Jó»@wnkmUÝ@U_¤XxmXm¤ôb@¦ÈÆ¦lJn\"],encodeOffsets:[[117057,25167]]}},{type:\"Feature\",id:\"4412\",properties:{name:\"肇庆市\",cp:[112.1265,23.5822],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@l@¥@V¼VôÛ@bV@ŤVLÈlVÈólUX¥mĉ°kÿU°@ÞKlÿ°KUUW»Èw@aw@@nm@w£kÓVUVnKk¥£Vam@nkKkbÆǫmakmLU¥UmÛwmVUmUJÇaUxÇIn`mb@Þ¯b@nJ@nlUVlVULW¯Û`Ç_¯`m¯IbĉWċzx±Jx¯ÆU_k@J@UmbXôlLn¦@¼ĊxlUXxUbLĠUnVĊwlUb@lWXm²@ÞWxXUnb\"],encodeOffsets:[[114627,24818]]}},{type:\"Feature\",id:\"4413\",properties:{name:\"惠州市\",cp:[114.6204,23.1647],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@lbW°bnnla@@wnmÆLVUkÇl@XkV²±bnUÆçUaVmxXw@WXwÇ»ÈJ@£Ü¥@XW@£°bUx²¼@ÆLVwmX°K°Ťl@wVUnLÈVVIky±wkKU¯ÅkXġÑÛlwUwlm@mnKWaÅm¯óÇmğb¯alĉUwķbmb@lÞÒVnmĀŹ@VbVUnmakLm`@xĉkklVÔVJVnlVUnmJmaLUblzmkLaō@@zV¦UV²kJnÜU@VXUL@lJL@bÝ¤UnVb@xVnlK²Vx°VxlIlkVl²k¤@n\"],encodeOffsets:[[116776,24492]]}},{type:\"Feature\",id:\"4409\",properties:{name:\"茂名市\",cp:[111.0059,22.0221],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@LnÇlkKnkÆLUmÈxlUJló°n@ana@@X_@mÝóóU@aaU¯mL¯kV¯ÇVwkw@V±Ŏ£@@alw±Vk@mÅm¯ÿÅƧIÇ`ōô¯_UVW°IVx@xkX@mnwXWa@kkJ@kVa±kkVmxmL@¯XXlWVUI@xlIklVČV@blW@@nUxVblVxkôlxnynIÆ»Æ°aXwlKbVnXbL¤kLèVV¼²IlĠVXynz°KVx°@VlLlblK\"],encodeOffsets:[[113761,23237]]}},{type:\"Feature\",id:\"4407\",properties:{name:\"江门市\",cp:[112.6318,22.1484],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lUXx°JWnnÆXVWX@ºVLV¯nUVnbôxaXmWXIUb°xlKl¯KxXÞ°XÈ¥Ü@ĉÞUç»nóVmax¯UÅU¥Ý¯@ç@ș@çĉÅUmUç±ĉKÝxÝ_ÅJk¯»ó¯nmèkǀWx¼mnUÜġ°@¦@xLkÇaVnUxVVlnIlbnÆÆKX¦\"],encodeOffsets:[[114852,22928]]}},{type:\"Feature\",id:\"4417\",properties:{name:\"阳江市\",cp:[111.8298,22.0715],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@°nKV°b@bôVÞô@nVlÒôÆUnlnn@lmkmVkaÈkÆÆk¥ÅÞ»ÆKXkW¥ÅLmÅkamJUkUVwUmÈblKw@@¥Ģ¯VÛnm»Xwlƿ@kbWaʵ@óLl¯ƽ@Ln°Æ@nUl²kxb@@ō¤U²@lxUxÈU°l\"],encodeOffsets:[[114053,22782]]}},{type:\"Feature\",id:\"4453\",properties:{name:\"云浮市\",cp:[111.7859,22.8516],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@@VIl@`V°Åw²IwČyĊXa°Jn°_È`Ü_°XKVkUUVk@mmI@°a@Ýnam_ÈJVwlĉX@lUómaUmVU°UK¹@WXUWmÅXm¯IWwkVWlÅLÝ¼Æl¦ÅÅÇlbUllnknm@kmVmóÅkÑUW`@@bmb@¯mkôIkVÇwnVÅKmlLklmÈKVĊK°²`n¤nUbWlxVxLUx@°nXm`VklVxmnnx\"],encodeOffsets:[[114053,23873]]}},{type:\"Feature\",id:\"4401\",properties:{name:\"广州市\",cp:[113.5107,23.2196],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@Ș¼VxUnĊ¤@z@Æ@nÈW°ÈVwUÞVxÞX@Kl@ÞVaĊbU@ml£k±lUkkJw¯UUw±kLUm@waUVmÞ£@aKkI@KVUW@ÛVmlIU±VU¥@yğzƧÇƽĠřÅnī±m@²¯l°@nÝÆóUll@XnÝVU¦mVV°V¼Jnb@°mbn@²¯¯wVw@@nmxX¤¯L@VLUm@@l\"],encodeOffsets:[[115673,24019]]}},{type:\"Feature\",id:\"4415\",properties:{name:\"汕尾市\",cp:[115.5762,23.0438],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@@@VxnXWV@bVJV@ÞÅU¥Ċx£UWUwÅUU¥WVUkĊÇnkV`°LVwnU@lbĊ¯Vnal@@çkUÝ¥ġaó¯ÅaÅLŻÆUýmy¯ó@ĉÆóȯwÆXbmL@nknVxkxÜĢÒWÆlV°Ll²xlz\"],encodeOffsets:[[118193,23806]]}},{type:\"Feature\",id:\"4452\",properties:{name:\"揭阳市\",cp:[116.1255,23.313],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@VÈ¦Æ@X°V@@¼x²°@lÞaWXX@aÞWlnUxVnnL°V@kmĢl@ak@mlk°aX±nwm±²¯JV²@wW_maV»U@m¯ĉUÑJlabVnlĸLlƅÛÇ±wÝ@ĉxó@è@kmbUĉ°ka@mVxU¯KU_mlĉÈVlXUV¦ÆVxVVX¤ĉwV¦ÝÆ\"],encodeOffsets:[[118384,24036]]}},{type:\"Feature\",id:\"4404\",properties:{name:\"珠海市\",cp:[113.7305,22.1155],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@è@Þ°V¦VÆ°wnbUÆ»nçÆ@nxÜ¤²llU°VnÈJÞ°UôéķUklô£VVˌKÞV°£n¥£ȗÝy¯¯mÅkw¯bÇĔğ@Ýn¯ĊVğōŁŻķJ@Ț\",\"@@X¯kmèVbnJ\"],encodeOffsets:[[115774,22602],[116325,22697]]}},{type:\"Feature\",id:\"4406\",properties:{name:\"佛山市\",cp:[112.8955,23.1097],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ÈbInVVnUÜxnVV¦nKlnbÅǬlalL@mnUb¤l¦LUmUVlÔ¤@xmnVl°_XVVmkVmÈ@kn@VUK@°KW£nw@m@Ux°x°@±mna@¯amIU»U¯nUV¥ÞUWmk@Vk¯UknÑWÝĊÛ@Ç¦W¯WÝwLk°kL¯wVaWJXWnbwkVW@kĊ\"],encodeOffsets:[[115088,23316]]}},{type:\"Feature\",id:\"4451\",properties:{name:\"潮州市\",cp:[116.7847,23.8293],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@°Üknèmxbz@VVX@VnV@lIVVV¼nKlxn@@¦Vx°LXblaWbV°£¯W@nW@aUñVwW»@¥ŤÅUÝǓÝóV@ńÇkUVmIUwÅVWÇX¹@W¯bkl@nlb@kġn@l\"],encodeOffsets:[[119161,24306]]}},{type:\"Feature\",id:\"4405\",properties:{name:\"汕头市\",cp:[117.1692,23.3405],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@@U±°I±n²mx²@WºXÈÆUVxJUnlVÈ@ŃôUǔÞVçn»VyĢÛVm@»kaÝUÇ¼óÛÈķKċ¥X¥Wwğk¯@wķKkUmabkIVÒ°Ċ@nVU¼bn`Xx\"],encodeOffsets:[[119251,24059]]}},{type:\"Feature\",id:\"4403\",properties:{name:\"深圳市\",cp:[114.5435,22.5439],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ÞL@xbVVK°X°Kô¥Vw@anUèlkĊl@wn_lKnbVmUaUź@nÿUmÝÑ¯Ubk@ÆkxŻ@aÇXwJ¯LķÝUĕóĸóêWº@b²nmĬÆ\"],encodeOffsets:[[116404,23265]]}},{type:\"Feature\",id:\"4419\",properties:{name:\"东莞市\",cp:[113.8953,22.901],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@Ŏ@blKnykVaKnbnIVmUkUmUIUÓçmV@bUxó¦¯LW¯LUUa@wÝKğŚƾƨÈĠy\"],encodeOffsets:[[116573,23670]]}},{type:\"Feature\",id:\"4420\",properties:{name:\"中山市\",cp:[113.4229,22.478],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@XÒlmV°ôÞÅ@m¯°k±@@aX¹¯VÝÇIUmV¯kk±Û£mw@ÅmèÅ¼mô¼èV\"],encodeOffsets:[[115887,23209]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/guang_xi_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"4510\",properties:{name:\"百色市\",cp:[106.6003,23.9227],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@lklWXL@VIl@XnJn@VUUalk@mK@kny@UlU@a°UU@VmaU@Ua@UWw@n@KmLm@alkmnIm@an@VIUamWÅImwU@@a@KX@JVLUVmUaVkUa@m@@Ulmkk°UaVUlKXbVwVIkaVmUk@KVk@aaW¯m@w¥laX@KmakVmnUl@nxVKInU@yVaVIV@na°KlxX@@_lmXUV`VIVV@n@lbn@@WUkValK@²yl@VUV@@K°L@KU@@UVaXIVVV@naVkVa@K@UUK@UUaLWaw@m@K@UVV@mVUUVKnLmVLKbVK@UUIkmI@mUIVK@IUK@VkL@WU@mU@WmUk@I@VJk@WwX_@amK@UUWkIK@LVb@mVmakL@J@bU@Ux@xbmI@`Iwm@UbmKUaUWa¯UkJWV@XJUU¯LUmV@ma@kkamKwLUUmWVkkm@aVUUkVKnVVUmXK@UW@km@Ukkm@@W@UkUy@I@aUUmb¤U@kUmL@bmJU@Ua@wkLWWkL@U@VaU@LUakKWbkUWVkKkLVLUV@JVbz@V@VmUU@kVmK¯@VU_VWakVmIUKUaU@@bml@XU@@V@LmKUVmVUKKbkaUXKUL@x@V@l@mxU¦V@lL@V@Ln@@VV@nlKUaV@nLUbmJnL@VWLkbmV@@LWXLlxVVIVV@x@V²blUVmLVUK@kWWXUlV@Xl`LXl@@Vn@VnbV@lVUVUÈVb@@`UXU`l@@XUVm@k@xmVknUJVXUbmKULmbx@VlJ@LVbkKUbVLÇUUVUVmU@VaUkUKVUwmLkUUVVlbkaXmwKUVVU@@V±Uk@VWUUm»XamUbKk`U@UnWW_kKmbUVUVmnUV@nJVUlUbU@UV@n@JmI@VmbnVUXlx¯kKmnVV@L@VbkVUmm@Ub¯LmlUL@VWLkmkLmmn£WmnKU_mWbnbmx@U¦UJU@Xmlk¦@mnUUm@@Jn@lVÔVJnIVWI@aÆK@I@aVKIlÞnnl@nl`nbÆX²l@xV@llbVn²VVl@nnV@IlW@Un@@kVa°KnÈmVaVXUlaVÈUVlwôUlynIVaan@lVXbI@n¥la@K_n@bÆx@XnJVnKVz@`VXVU`@b¦UV@VIlxUnVKXÈbVllbVbnVn@\"],encodeOffsets:[[109126,25684]]}},{type:\"Feature\",id:\"4512\",properties:{name:\"河池市\",cp:[107.8638,24.5819],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@lLVlbVV@nXVlI@JVXmnW°bIVV@ln@nalVUbnW@kVkÒlbVKn²°bUlV²@X@`nbaUI@°wlU@aXJVI@aVK@wUamIXm@XUV@@bV@VmImnUUwVaVKXUnVK@akVwV@nL@UV`n@@XlnIUJl@X¦V@aUIVm@anV@UwnL@VlbVL@KVVXUWwUUVUka@UVJnUlbnalbVVn@°LV`Þ@XVxV@@bVlUVVbXnWlXnml@XXWVXJmbUI@VllUVkn@@VWV@Vnb@VXUJVnn`lLVka»lVLnw@WV@lInw@WnU@U@mknUVóKwUmUXUU@@wVJVIl@XKVVVbVIJ@Un@lVLnmb@U@Ul@nU°VUVJnnVJV@@mVU@@wkUVwkKWkyUUkU@alkÈ@lJ@xIl@UUWVkUw@Kn@@kmaVUlUULÇUUKl@UUmL@aXU@mlUUwmKkUUVKVUaKUnK@U@Vl@XUWUKlwX@b@K@XkV@UwWJka@aUwmV@U@@U@wUm@»kLWVkIWXnmV@VkbmKLUbkVa@aa@@aVU@aVak£@±UkVU¯VUUJVUI@kxmUmWUbLw@K@aU@@aVU@Kma@aka@_VWkk@UWVUKULWKULU@KUnwVaUKxU@UmaLm@kVmVa@UkmI@@KmIkxU@@KU@mmakI@VLkmWkkJ_U@V@L@nxXbKVb@VVL@V@LUbUlmbU@UUWJUb@VV@@L¯K@LU@UVk@±z@kLUbVl@Xm@akm@U@UUJU_VWkn@`W@kw¯LmbU@UJUb@zmVJULmwk@mVUnlnb@LWkb¦@x°nXb@bUl@LVlUnlbUJUxWakLUVVb¯llkn@V@@nVbUlVbUnVUK@IW@L@bV@nxÆJnXVbUJm@@bnmJnkl@bnnK@Lm@Xx@VVbV@nb@UVV¯@bkV@Vmz@lnLl@kVbUVm@mI@WkJ@UWKkXkl\"],encodeOffsets:[[109126,25684]]}},{type:\"Feature\",id:\"4503\",properties:{name:\"桂林市\",cp:[110.5554,25.318],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@nU@JX@`XLm¦Vb`lVXXW@VblČnVlanLnmVLK@_Va¥@kUa@VmVbaV@XVVzlVVK@knKVmX£VKLlbn@b@llL@xĊôXaV@°È@¤bnV@@Wl_VU@WnVamwwVbn@KVLX@VmVUxlV@nVV_nK@mI@Wn@@IUĊ@@wVWX@@I°VVm@wmU@m@IUVklkUmmkÅV@@aV@@Wn_UKla@kaVlVanb@k@@KlVn@@aV@nIWWUUaVU@kKmwU@UImKk@UU@w@W@k@UkW@mk_W@Ua@a@¯mV£@mUUam@kWakVama@UUm@nw@alaUmnUlVlIVLVyk£Vm@k@UUJkK@kmKUwKkWK@UXImyVwnI@mkUlkUKkUVmw@kkJWUÈm@_k@@aaW@UUJUwU@@IWKkmUUV@nVl@bVb@bUUXakw@WUkbkKbm@xUlkLm@@wmKUX@UaVWXVmU@@UUUxkmWXkKkUWaUaUbL@`UL@LV`UXmK@VmakLVbkLxUJUIVbUVVb¯KV@Xnl@lVXbmÒnV@L@VWKkVUIWJkIUamUUbm@UkU@JUbW@XWxUam@kbVVUnUJmUUV@bU@UUV@Vk@bmULV¦U@VU`VLUL@xVbn@UJ@nWJXXVVV@bkxVbUxL@x¦@UlXUVVlULV@@nUb@xlnJVnlVknUlVUbmU@bVx\"],encodeOffsets:[[112399,26500]]}},{type:\"Feature\",id:\"4501\",properties:{name:\"南宁市\",cp:[108.479,23.1152],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@lKnbnU@Ua@KLlJVX@VnL@bW`Xxl@I@UJl@nV@XV@nXV@lK@UVL@JULVJ@nnJlVJ@VULaLUKnmKULVVU@nU`lIXllnK@UlJnb@nV@LV@lwnJ@L@nJl@VUbUn@lnKnbVV@wVLUbxVm@LVVKXLVKVLXU@VllUX@`lb@bnbL@UV@bV@@b@LxKVanXVUUmVUUUaVUkyUUaImK@mUUVUkKU_@W@UVVVIUWUVaVU@UUKn@k@al@ll@bnL@bVUVX@V@@bKnblmn@V_@aUalL@a@akK@kVKUKlwUUnV¥VmU_VWVIVaX@VaalÅK@LVJnalL@LnKwlVUwmX@VXlLUVnblaUmVUVwXU@Wm¯Va@ÞKnw@wmk»UVW²a@_mW@U@IyLVUUKW@@LX@VUV@@yVU@UV@nwUUmJka@IU@mVkaW@UwUX@`@kLWUk@mkUUm@kUUWkUkWxk@@VK@nV@UVaUUJmIkV@UamLUbkVmamLka@kmL¯WI@wJmwx@akU@aUKmbkaW_nW@_U@Wm@a@wkwUKmk@bkbw@mKUkkU@J@bW@kVWz@bVUaVUx@ULkJWbXVVX`@mJUVU@@Lk@WbU@UJlnXlmVx@Ln@b@KLXWJUUW@kaUVUbmV@nnV@n@lVLVmLXmXkV±@kxÅLUbJWIÅJ@ImXalkUamKkkL±aVwKUU@mÞnbWJXm@lbmKULWUUVkabnn@Vl@VVV@VbVbnLWLXJWxXLV@@VV\"],encodeOffsets:[[109958,23806]]}},{type:\"Feature\",id:\"4502\",properties:{name:\"柳州市\",cp:[109.3799,24.9774],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@wUaV@nVaUVklmkUUmmIk@waVm@U@VKUkVUkWV@¥@wKVwUalw@aUUUWWXI@mVIm@Ua@wVKUKV_UV@U¥VKnal@U@VU@VV@aVUnVVIVmUUlan@VbXwWX@Va@IlVVn@VanVVblJXIVJlUXL@U@KmUnÑWakU@mkJUI@mk@wUmmUV@JXaWIXWmaUIJkk@WnJ@aUak@kkJ@kUKU_@myUóWUkm¥kUmL@KUKm@k_UmVa@k@@UmU@mm_JWIUVUWLUlbVUJÇVUIVwKUVk@mU@n@lUL@Km@@l@LVzJmUU¤m@UbV²U`U@@¼Vn@x@V@@VnUVx@blbXIVxU@Wl@@LaW@kxLXVWVk@@U@VmLVLbUVULVVlnLVxkV@nWV@bnKVVk@VLVÈVKVVkUnb@lm@@LVxUlVX@VkJ@wkIÇ@kl@blVVVzXllLUxlV@x@UV@nU@UImmUIUV¯mVk@@V@VamnUKkm@@VIUJUaUUWLk@UJUI@xV@VVWVnxLUômVV@VkVVVUnV@UVkL@VVV@bVxla@bkXVJVn`nU@bb@bVL@VnJ@l@VaU@@_lW@UUU@Unlll@XLl@@UX@°bVWVanLlknVV@VVX@VVnUVLmbXJ@nllXX@`VXlmaXVWk@WkwJ@VL@JbnU@bn@@bVKUnVJVIVVVL²a@bV@@Vl@nUVakalmUL@VUL@Va@mXl@nK@UlKL@Vl@@nkllb@Vnn@nVV°lVInwlKXxlU°n@@I@UnVlakUJWkUK@anUWK@_ÞJ@U\"],encodeOffsets:[[112399,26500]]}},{type:\"Feature\",id:\"4514\",properties:{name:\"崇左市\",cp:[107.3364,22.4725],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@@JVzl@V@Xn@ll@VlnX@@VWLnUVmUULVlUV@blnUlnXVVKxnLlb@lnbU@Vn°KVVI@WXUlI°VXbVVbnLVan@xJ@_nJa@wVwV@@a@IU@UU@WKXwWIXKmKUaa@UUUUk@@UmmalbVUXVVKnLa@knWXImanÝV@VLUx²blKlnLVbklWbn@JÆIXJIVaÆKlw²@lUnWWnKUUK@k@mmU@mnUVaVUb@lVXVXIWK@Lam@@KUwnWkkmVIV@Xal@@KV@VUnI@_UWWUkam@kkm@ka@mk@wkJWIUU@WXkWXkWWLUU@UakLWXV±VIVWUU@anUWaUK@IU@Vak@@UUKWa@m@ak@@wUkla@mUaUklakwV¯¯@WWUkLkKmakLUnV`UxWX@Jkn@bmlakkk@b@l¯bmbJb@VXnbVV@bJUkkKWVU@mÛVUUW@UVUJWXkVkKmUL@WW@UVl@XXKWXJ@XVlmbUxnnm@UlVnV@XVm¦VJb@mLkKÇbXblVkn@l@bWnX`V@@IVV@VV°n@@_naÆVVbUVVbUJnzlVUlXkV@Vlx@XVnxbKUK@b¯VVUVL\"],encodeOffsets:[[109227,23440]]}},{type:\"Feature\",id:\"4513\",properties:{name:\"来宾市\",cp:[109.7095,23.8403],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@nVlw@VJUIVVUV°lU²V@l¤Ub@bUV@b@b@bUblVaKnLla@UnUWmXlJXUlKV@V_U±Van@V£nVIyU@K@kn@@LVK@k@mnVl@VULUxVJÈUVIUaVkXKVVUXJIn`@nnV@Vl@@UbVnl`n@VL@LnKlVn¦VlôXVnz@V`VL@llIll@Vbb@mIXl@lIVJnbWXXJWb@IUnVVn@xl@nVJI@WU°LUaVUUaVJVIwlKUalKnb@UnLVWU_@KVK@_KVa@VKU¯VLVKn@laaUkU@maVUJ@k@Um@XmbkyVaUIUU@KV@laVn@KXKWUkUk@aWUUVw@aXKmVaUUkmIlUU@wUaxUmmU¯U@WLUmVIUym@UVmUa@wmw@çm@aWLUJUIUamKmL@ax¯¥kU¥U@±kUVmKU_mJUbkKmLÅÇ_@WWUXUmaVUkKUWW@nVxkUxmL@KkKmbUI@KLkÆbUbW@UbUJUXV`UnU¦mVVkxVLUL@llL@b@bkKVb@bU`m@knmaL@a@@UWVUU@amK@akkk@@b@lmVL@VUVUbVVXUJUU@V@XV`lLUVVV@nnLJVbVlzUVVbVVnUVVU\"],encodeOffsets:[[111083,24599]]}},{type:\"Feature\",id:\"4509\",properties:{name:\"玉林市\",cp:[110.2148,22.3792],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@VJUXVVXlWX@VxVnX@@`ULWUXÅbWK@mULUUmJ@n¯b@l@VULVxxXU`VXXJVIV@nm`@nUVXn@lWVn@b@Jn@nU@Lm`@Xn@WJ¦U@@VnLlV@@Xl`nIlJnkVLw@KVK@UaVL@bVKXlUUKVK@IVLa@U@WLUlVL@bU@@blb@VlbUxVbXUVJ@xVLUlV@VUbVLnKlXJ@Lb@an@VanL@`VLKV_UWl@U_a@WVInlVUUUVm@I@W@wVakIWm@U@XwlaVbnI@m»Va@aXaVLU»@aVa@kKkL@KmU@WzUK@wU@VWUUVUUKUa@mKmbUK@_nWVaUkVaUaVUVLXKVVUVmVI@UkKkLm`UkW@UwWW_UaU@WakXmK@xUXJkUUWUk@WlmJ@km@@aUKzmyVka@kkWVUU¯lmU@@wkkmV@Vk@mÅIUka@Ub@m@UUU`mUbWaWmbXXKWIXUWm@Å@y@UkIUJUUWLUWL@UkVUxW@kaWbKWnXxW¦nm`XLVlUbVbUxI@JmLUKUb@VW@@bkL@b@VlU@xk@L@lxXxWXX°V@VVVbUVV@UVVbULVnVJUb²baUb@VVVVInlV@VnXaVUlIVUb\"],encodeOffsets:[[112478,22872]]}},{type:\"Feature\",id:\"4504\",properties:{name:\"梧州市\",cp:[110.9949,23.5052],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@VbXblVlLXWlnwVV@VV@UnWUXVb@VWXa@kVKUaVaVkUlyX@VaVmUwUaVU@UÈymI@aU°@nWV@VaVaw@IV@VmnLVK@kmmna@VbVI@aV@XbW`ULUVVx@VbUV@bl@VLXblJn¦lL°°@n@K@UlLnKa°LWbnJ¦UÒVUllLlVnKnbWnnV`w@@Xa±nl@XKV_WVkVa@kVyUa@wU£UW@UIVW@@awWaX_WKkVmUULmak@UJUI@±m»k@m»VyUImnmmwnkUmVaVIUn_mW@»Vk@VwkmmUXa@IaVmm@Wm_U@mIUWóLmUk@laXmmkUK@UmKULUUmWUL@VakU@Ub@b¼VUKWb@bUbn¼@mJUakbWx@@VXnlJUb@x@X@JUnVVUVmkUJ@XbV`k@VXU`LUK@_mKUbm@@b@U`@nlV@bUnbVbn@@`VbUbVV¯bm@@mJXb@bVnUllVXUlbUl@LU¦VVmkLVb@bl@V@XlK@V@nUJUz°mwmLmlXbWVU@UUUlIU@VVmV@@¦bXbWxXWlXVWL@LUmkbU@@LVVVJUblzna@WVn@@lIUVnbV@Vlbkbm@ULUKV°UL@\"],encodeOffsets:[[112973,24863]]}},{type:\"Feature\",id:\"4511\",properties:{name:\"贺州市\",cp:[111.3135,24.4006],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@nL@xn@lKVkwn@alLlaXV@lxbVWV@aUa@aUk@mVUnVlXL@JV@VxVIVX@b@bl@@`ÇnXVlI@lxUnlVVLkllV@nmJUxnzWJ@VXLlLVxnL@lLlVI@V@lUnl¤UzK@Vl@LlLnb@VnVVU@kaKnxn@VkVJ@ÅUlakmWIUaVanm@_UK@UVWUa@klXamU@VmVIXW@lUVknVlKVLXVXW@b@VlnnVL@KXLKn@lb@UnW°@VaXWVb°aVa@I¯aUkUaVKVwaXk@aa@wkm@alanUVw@alK@Umkw@UaUmU@WXUaUK@UW@UaVWI@¥Xa@w@WWVXwU@mKUXUWVU@a¯kl@akU@UULmK¯VUVW@U_m`U@@xVbUz@lUbUlXU`WLk@m²Wb@@xU_mXmmamLkUkKVkUVÑ¥mIXa¯KbmLkK@V@Lm¯@¯kKm¥kIWaUKk@@aVUUa@UwVUKVX_WaU@@bUJUa@mbnn@lULmKUnU@@JxUbUbU@mX¯@V@bnJÇz@VUVVbVxUnUbW@kzVUlUbVbUL@lWb\"],encodeOffsets:[[113220,24947]]}},{type:\"Feature\",id:\"4507\",properties:{name:\"钦州市\",cp:[109.0283,22.0935],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@@IlVVlnL@xlaal@nVLlx@x@bXnV@@`mXX`lbnaVL@blV@bwnxI@xXJ°nKl@lbnKnblUVanKVb@lUnJVIVUb@VU@mL@Ul@XwllVVXV@lVnlVnl@XVlK@@_VWVxX@lbUnV@@JlbnIlmnVV@UwVK@U@k°a@mnIVVVK@nXLÆaVWXVK@_W@Umw@UXWWkUUVWUIVaUkJUVWbUmU@mkUJUU@UVab±aVaUIUmVKUaVUU@VUUaUUU@W¯XWWww@k@Kl@wkV@U@alK@aX@@UmIUWUI@mmkXU`U_WJUnUJmUk@@amLU@UVW@UkU@@VbUWVUk@@wmKkUWLUWX@JmIlUkkKWKkLWU@UKWa@bU@@a@_UKWUUUmJmw@nV_@ġğKóLmbU¼VÆ@xUX@Um@wklVnUnlkaUV@lV²WVklWXXbWlkVkIm`UULUU@UWx@XU@@lWLU@kbUbV`UXllUV@bmb@LnKVbULmnVVIV`X@\"],encodeOffsets:[[110881,22742]]}},{type:\"Feature\",id:\"4508\",properties:{name:\"贵港市\",cp:[109.9402,23.3459],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@n@VzUJnVK@XV°nVVnwVb@xVVknJlVVUbnWL@bUxVVXbl@lVXkWXwWaa@¥@nUUUV@JVkVVV@XUWanknKxn¯VyVI@m@UkL@W@Uk@aUalKnUUV¥@KVkkaWVkUVkUm@aWanI@n@°aUUVaUa@_m@UamaV@akU@mV_@a@KWIkmLUKaUVU@kVUK@wUIWVUaVwka@Uka@aV@@aUKVkK@X@VbKU@JULVLkVWUL@aUKb@VUL@LxUKmlkImJk_@WU@kmK@UV@¥XIm@@Wn_@KmVm@@I@aUmkXm@UWV@mn_@mUUJWIUWV_WwU@mUknVVmxU@@VUV@zU@UVW@K@X@VLUVKz@J@VnX@`±bUXV¼ln@xmxÝL@Ubn°@XWVUxUVVnkbWVXV@X`ÆÈKnlLVanIV`nLVUl²V@V¦l°¦wb@nKnLVbVJIVXK@bn@ènx@xVbUnV\"],encodeOffsets:[[112568,24255]]}},{type:\"Feature\",id:\"4506\",properties:{name:\"防城港市\",cp:[108.0505,21.9287],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@XV@X°°UlxkbVlVb@nkbVl@xl@@b@nXbVL@Vl@UbV@@JVLXbmV@bVVUXUJU²WXlKVb@VVXKlXWlXXWV@VXJlI@xl@nlbn@lln@lbXalIVK@VwUVbU@aXylUX@@aW@U_UJmUnVKUamL@Kna@aVUkkVWU_ValaV@XK@kV@@WwVXV@VKVVn_lJlUXkWaXWlkXU±kU@VUlbkVmUmlk¯ÝW@mb@¦VxULmkJUU@ma¯wmkX@VóJ±bUVUXÝWklWXXlxUabIğÇ@U@mVUKkkm@UJm@XnWV@x\"],encodeOffsets:[[110070,22174]]}},{type:\"Feature\",id:\"4505\",properties:{name:\"北海市\",cp:[109.314,21.6211],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@VaVLnK@IJVwUaVaUkWKn_mX¥WwXmLXalbU£UyVÅ@Ýwm@°lLÅUmkmwÛaƑLÝUUm@ȣÆV_Ó@£UUV¼U°W̄ÞVbXbôx@b@bmV@ÇUÝ@@ĢU`m@nxnIVVVXVL@`@bV@@aXbVL@XVlKXLlLVlknJ@IWVXXKlVnL@xl@UVVXa@UV@VlX@VUV@nK@bl@nVVIVmXIV`V_lWnn@VJVXnJ\"],encodeOffsets:[[112242,22444]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/gui_zhou_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"5203\",properties:{name:\"遵义市\",cp:[106.908,28.1744],childNum:14},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@@UnUlJnwJU°VL@bnVUwlJ@XXVlU@klVUJknlUllL@bUJ@xULUlUblVkblbnwUXmla@wV@VK@L@UXaVKVLXWUVa@U@Im@@W@£UKUakKWIXU@al@@llUnL@W@Un@@VlUV@VIUanKl@Xb@lmxVb@b°bb@nlJVVnnJ@b@LV@ln@LmV@Vx@blnVKnlJXIlwJ@Òb@nlK@Un@UL@VVVVUUUVKl@VUVLJ@UVUUw@Wm@UVÈVlbUb@JLlX@@xLmk@@nlx@bUJUzVJ@@LVxUV@bWxnLnVVK@_K²xVbV@n¥@aVI@b@l@VaKnb@n`nmmýW@U_wV@VlVV@Vn@n@nI@Jn@°¦VaUU@mVVWVaUÅU@aVKnVbVUmmU@a@kUwm@aUUmUUJ¯lakUaXaWUUaVkkamkmUnVlULVlJ@XU@UJWUUwk@aU@WbkWL@U@WU@@XUKmV@aUVwUĕUJUamUUVUÑmnIVJ@kl@XalJVn@KVL¥@UWIXWmU@mVUKnUWLUKUaWUUKVU@U@anUny@UlUkK@w@a@aVU»UkVw@WmkJÅmUUVmwXalLXWWUnam@XkJ@UVU@U@W@@U@I@Wl@Ènlw@KXLWblVUkalKUUVVaV@@wnIlaUmkUKWU@KkUkLWaKUUWUn@VK@LnnWJUIVkUWVnV@V@@XK@VUIUJ@IWJkX@VVJIVkK@I@UVaUWk@m@wnUWKk@mxk@@lV@bxmb@x@VUmLkUJ@nVV@b@VkLVbU`¯Il@U_UW@UU@K¯wm@xL¯¥kI@bkb@Ua@m@kkW@XVbmV@kV@bWbUbV@¦xXlmVk@¦bkaWL@KUImK@wUK@VUIb@bmK@LÅy@akXW@kbWlXblL@ULUb`@UkUymX¯@mUJUUJL@Lm@@WX@lUVlXll@l@Èk°V°X@VU@UVll@XUJVXUVm@@VXLWlnV@Xk@mVULnxV@@bmkL@VWLUbU@UVm@b@ķ¥UnmJ@UUVkkJUlÔU`UIW@°kLUlUI@WVIU@mWKkXk@WU@bXW@J@xX@l@LVl@xLVxXX@xKnxVknbKVV@ULWlXU`@nUlX@llVXVUKlkUKlI@anKVLXKVaUIVWV_VK@VnLlU»VKVLm\"],[\"@@@KlKkUUVVX\"]],\nencodeOffsets:[[[108799,29239]],[[110532,27822]]]}},{type:\"Feature\",id:\"5226\",properties:{name:\"黔东南苗族侗族自治州\",cp:[108.4241,26.4166],childNum:17},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@VV@XkV@bUbWJU¼Vb@Vnb@b@J@bL@LV@UVlUI@aKULVb@bkJmxlLVxknVJkxnKmnnL@bn`WIXlWLU@UxVbUVmKVXI@JVIVJ@UL@W@@UmUXUlVUVJXImm@KL@UVmVXVLXblKlV@LXVLlVVnkbmJ@xnXl@bXa@VanaÒLmVnIlÞ¦°k@b@@lVnJlUnVX_@lVlKVUUxVLVWVIXJUlnnWlI@KUaUUVKn@VaVXV@na@mw¯@mUkJUamI@lk@@am@@IUmVImUUw@anUVaUU@LU@WaWUXWWwV@VwnU@L@ynbl@@X@aJ@nW@@Vn@lVLlxnIl@@UWKUnIlJXIVllIVV¼XK@aVIV@@bn@VKXLVKVVVInwJ@UWI@mX@WKnI@KmUUVJUL@VKW@@k@aU@@W@InJWUXwWI@W@¯wkaVaUIl@nValIXWWI@UUm@anwWkXWWIUbk@UJmIUamKVUUUVVama¯VkIVVUlKnXVwX@@WVaUUVa@IlaVmknawkUU@U@mUVUVwl°LVbnJVU¯la@mX@@UWKXU@aV_V@@JlkU¯@VnK@km¯kU@WUW@mmU@kmlU@wkL@WUkL@VmLJ@b@V@bknUUVK@UVKUK@Uk@Wa@LUVVnUbmVk@@UU@@aV¯K@U@UU@WmUL@aU@WVw@IxXll@UXK@KXXVJna@wWa£naUKVm@UU@mUmalm@@XkVm@U@VLmWU@kkWxU@@bVV@VkXVlV@UUk@@mI@KUwm@UmVUUwU@lwkV@IUa@mUaVIVKVa@w@U@UJkb@n@bmJ@XmlVUxWXkJmUkUUVWxUlU@aULUmbU@@WXkmL@xUV@nUxÇm@XLWbnlnVnnUVUnVVz@lbUVVlULVb@V@nUJkwm@Ux@bWbUK@UULkaJbUU@U@lUK@XUJmnJ@bU@UwWax@zkJWnUJUUVVV@bXn@xVb@JLm@Xw@`@bkb@VmXUV¯L@mW@@n@V@L@KIW@@aaUx¯@Um@XbW@@LV@bnVWVkKUzlV@bÆa@lnI@VV@@LnVVKUaV_VJVbnU@bn@nX@yVIVxXKVLlUVaXU°J\",\"@@@KlKkUUVVX\"],[\"@@UUVUkUmV@ln@VXVK@K\"]],encodeOffsets:[[[110318,27214],[110532,27822]],[[112219,27394]]]}},{type:\"Feature\",id:\"5224\",properties:{name:\"毕节地区\",cp:[105.1611,27.0648],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@UkV@kW@Xn@@KKVIVVIn°@nWVzl@V_VaVK@kKWaXklaX@lW@bÆz@KnL@aaVJ@UVL@xnLVJ@LXKlba¥l@nUWkw¥U@VaXa@amLkUKm¯kmkIUaKUIWkKm@anw@mlwXImUk¯@a@amU`kkKWVkxmUUak_mJmw@wmXUW¯X_@WnI@aVwkWWýÅU@WLkUaUbVV@lUVVnm@kUmV¯kKLwmVUUaWVaaWw¯wÈ@VULUVUUK@nWJkIl@Umxnbm@kbUJa¯bUbVxmLUVaU@VUUWxkVVV@bUV@XWbnlUbbUJlbUV¯b@z`WbXnmbawUwVWUbUxmbU@Uam@VkVawVaUWI@mUKóz@lUlÅ@WIb@xXxml@XklULWKUmwUa¯KUXWJkaULmKkLWbkKUVImWa@kUaULW¯LK¯@kbL@bx@J@bmnnlUlzU`U@@Ub@mn¦°bUVx@bkVm¼mx@mkmVV@bkxVnaVV@bU@mL@b²`lIVV@lXLlbVxn@@bl@XllIVnbVn°°wlbXw@mVa°lVnU@mVLVbn@@b@@WVnUV@Xlxn`VznJVb@L@bV`V@UnwU@WUXKV@UUlmUUlaXalLmbIVbnJVIlVVaUUnWVXnVLk@nWnblnlb²xxVKVXlVXLVWLlUVJna@wVL¼@JVX@`@nnx@nWJU@Vx@XXKUblxU°LVKVVlL@KnbVUnJIlUnKl£VWxIlJ@nVÞUVVnbVX@V_°lnK\",\"@@@UmWUwkU@Um@@VkL@V@VVkV@nbVa@\"],encodeOffsets:[[108552,28412],[107213,27445]]}},{type:\"Feature\",id:\"5227\",properties:{name:\"黔南布依族苗族自治州\",cp:[107.2485,25.8398],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@V@IöalK@UV@@KUaVIVVLlaVbVWnX@@LnUlxl@naVLXVVaVUJ@lUUanWWI@VlV@Xbb@Vn@VmVVbk@kU@VV@XJ@zn`ULW@kK@_WVUK@LUb@Jlxn@nnWlU@@bx@XVVU@UbVb@n`VI@VVLUlUIUV@KmL@VV@XIV@@lVLVmXV@WLXLW@U`nkb@Vl@UL@VVVLllX@`lIXbJIXWLaVL@XXWĢb@bmK@L@°@VnxmxnK@xVn@VkL@VLakbl`VnnxVnUlV@@VVXV`@k°JV_UalK@U@aUU@mIlVnKV@U@wnaw@akU@l@nwl@XLmV@xnl@VXUb@V@JlLUJUI@UlWUnLVUUaVwV@XKWkXJm_@amKnmmLwlUIlmUwkKnwlI@aUaVKL@bVJkVUU@@KK@a@I@ama@UUaV»XIVa@alU@WUU¯IWVUbkVUKWLUwUJ@zmWm@@amVUaUIU`VbULmU@KU@@UmJ@kÅb@akUVylLXUmU@aU@KX@Wan@V°@Vwb@bX@J@LK@@U@mX@@n°KVUnW@Ula@a@_x@WnK@IUa@wWm@aUUUVVVIXmlI@ywXbVxV@@aInmVI@WVL@k@VVVaIlbVK@VVLXa@aVwn@lxVI@m@UUaVKUkVUka@UymUVVUmmUmmkXaWK@ÈnVw@mVU@wKlnXW@V@naVVKUk@KVIUW@mk@KXU@Um@@lVk@UVJna@UWaL@a@Xa@kmmVUUk@mkkamJImJUUmIm±aUUkambkamVUU@VlbUbVVxXWVUU@VUakU@UmUVU@mnUVVnUbVJ@bUW¥kLVamVkUaWJU_UVWKk@@nlUVVJUXm@Vm@UnVlmbnmJUbULU@@UUKWVIWxnJVb@xUL@bUJWIkxbkb@xVJbmU@kW±LkKUkVa@a¯am¥ULkalÑlKXUWXaVakImV@ka@UUJ¯aXmmbKWU@wUUaUaKmU@UXlWb¼WLUKUb°UlVbkbVL@VJ@nVlUbUXmJ@VX@lbUbU@@bWb@VnLVJ@bVVUzVL@lnL@bVVVULmKUkJkbm@xVb@VkKVnnV@b@WXUnVlVVXVJUXlVXbWV@VU@Ubk@@KWbUUmL@JnXV°XJ@_`UbkXVVlÆkb@VLXVV@V@kKXX@`V@@n\"],encodeOffsets:[[108912,26905]]}},{type:\"Feature\",id:\"5222\",properties:{name:\"铜仁地区\",cp:[108.6218,28.0096],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@°a@aÈbVUlU@aVKnVVVUlyX¹lWVa@UVnUVU@m@mUl@mÞw@xnIVbna@KVIJ@kwV¥UXÇVkVW@kkKWU@aXUWmnIVa°VXbmL@VVbnVVVUbVbJVbVKXkVKVanU@aWnWUWa@Unk@mVIVK@wXxlLXbVJVlKbl@VI@maXalVVVbX@@aalnkx@b@Vb@Vnx@bVVUXn¤WXn@Vl@Vlzn@`@I@KUU@V£namVkXa@aVKnnU@anVlKa@UUU@amk@»kU¯@aVWnkWmkImU@akaVm@»VUV@UKnkW¯XWlkUKnIWa@nmlIXmWUnwUwWm@wULmaUJkIUaaWaklwkwmJmU@bkJ@XUJ¯W@XbWbUKUkWJUUVKnn@UmmXUWa@mU@@UI@WmXVykwm@kaULWwU@¯lKUUVU@mU@UkmaUbmV@bxVnVUJVn@Jn@@bl@@knJVblInV°@nx@mbU@UWUbm@ULVVVb@LkJmXkmVWIUJUXUKVwVUkLkU@W`UmkVmIU@k@@a¯lÝ¥kmJUnKÑmbUb@Wbak@mWU@UbUVVkLlbUVkXaWK@LkxÇmk@@X@J@V@@X@VUV@VIWln@mbXVWXkKWbnxVUnVÆInl@XUxVl¼UV@b@b@xlLkV@VmzmV@b@VUVVLXVVbVLXKmVVLU@nnVWXXJ@V¦UK@LUmkIWbk@@lUImJnVÒVUnVVbVIVĖUxV@bnUVL@WV@@X@VKlXXaV@@blVxXVVIV@@WkIUVKUkVmlnnbllUVbXVWbblVkb°VInVVV@bnVx@l@bnVVnUUamUL@bVVÆUbUXUn@VVUb\"],encodeOffsets:[[110667,29785]]}},{type:\"Feature\",id:\"5223\",properties:{name:\"黔西南布依族苗族自治州\",cp:[105.5347,25.3949],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@VL@Vl@@IXW@kVUVbnW@XlKVVnUVlL@baVbb@xX°ÔUxV@kbm@VxkxWJV¦@ÈnVKxWXJmV@nÒ@xVbn@@blLk`VX@bla²JVUlnn@U±lw@wnw@mlwVIX@@m@klKnkaKnwmmXkÆVmU¥l@nb°n@aVwVmVIVnI@a¯@mU°l@@VnI@JV@UV@b@IUbVJmXöºzllUbVa@aXUl@U@llLnKVaUa@UmK@UwVbnKV@VwVK@UXV@Vbn@w@UWnX@a@mI@UUKlaUaVk¯VaVLXK»XaWk¯mkğwmW@mIVkwJUIÇVwUUkVKkm@UkmU@WÅwm£Vm¤¯IkJWa_lUbmJzÝJkUÇVU@bUÝnm¯LUb@`mL@VkL@VUmmk@UU±Umka@kU@ķymUkk@mmkÝmUaUakImV@V@VÅL¦JUXmJXWb@n°Æx¼nV@LlbUUbmL¯@ÞbV¤nbVx@bUVlblI@KVVUnVJUn@VlLUlmLUUUxmK@I@@VW@@bU@UJmUkLVVUl@b@V\"],encodeOffsets:[[107157,25965]]}},{type:\"Feature\",id:\"5202\",properties:{name:\"六盘水市\",cp:[104.7546,26.0925],childNum:5},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ôyVL@nXJVUbxbUlU@nVbV@naVwaVUXVxxbnaWmXa_@y°aVUkaVIaVamkXa@WVU@aUUlUXwVV@UVbVUnKUwVa°abVIlan@manw@VklJXI@mLVVVUVK@UÇk@KUa@UkaVU@UVWV_XWVXVWlLXKlLXaÆKwVL@akKm@Uw@@XUVk@VUI@wWK@aUVI@UkK@mLW@kImJUÅVmkXUW@UJkx@nmx@xkxV²m@kmUV±Ikb@aUWl_kK@am@Ua@wÑ@mnUWIXwULm@ÇU¥XIlwUwn@laU@Vw¯ÓW@waUab@akKUmVUUkL@WmXUaUV@lWX@Jk@@UUKULmLUJmzkKmVX°VUnWKULL@mU@UnVJ@b@UV@X`m_@l@@bmbXJmnn@°wnn@VLX@V@nVl@nk@@bl@nn°WlXzW`XXVKnUlxVbUb@VXb@VxÈbVlnbmn@kVUL@mLUVVL\"],[\"@@@@UmWUwkU@Um@@VkL@V@@V@VkV@nbVa\"]],encodeOffsets:[[[107089,27181]],[[107213,27479]]]}},{type:\"Feature\",id:\"5204\",properties:{name:\"安顺市\",cp:[105.9082,25.9882],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@lL@bUKxÅLWbkKWLkKUXUWWXU`UX@VUVlb@VVb@Ll°xXxbbXUVbVnUxKlL°nUlVn@UmVU@kUUVablVXKV@ÆXþlXUxnU@mVK@_@ml@UU@blU@KnLVyUw@@UmkWVw@UVK@VXzVK@nVVUUW@kVJnla@nKWkaWL@Uõb@JU@mU@@_WWL@lUU@WUUK@lakÅUUlWVa_@`WIU¯mW@InKVVXa@Ll@VaV@@UXUWakUVWUIUWUkUmVXW@@amUUmLl@UUawn@laIVlnLVKUUU@amK@kUKVyUU@aUImK@UXa@aV@VakaW@@UnIVWVaUkb@mWX@Vxm@UaU@W@VULUxU@mLaUx@VnL@VVbUbmLkK@kVk@WV@bUbVakkyõ¹nWUIVa@J@aVUU@@ImJ@Uk@¯V@n°@bmJUUJUnUxbm@¯mak@¦VUnÅWlnnmxLbmlkL@l@nWVnlÆUVnIlJ@XnK@lL@VJVU@bXL@xVJUl@VU@W@Vxn@\"],encodeOffsets:[[108237,26792]]}},{type:\"Feature\",id:\"5201\",properties:{name:\"贵阳市\",cp:[106.6992,26.7682],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@nlLXVJLVblJn°lnLlVnKlU@nUUa@WlX@ln@Vb@la@alJ°¦Kwn@°xLVkUmmwUmk_labK@UlK@UUm@wLmnwmw@U@¯@KnL@aaġXWW@UKbKWXJIWakJ@_kWkKUU@UVKk@@UlamV_X@WKXK@WUUnUK@kU@WJU@@UnK@LVUVJVkUK@UUJm_@UaVaV@UU@Ww@aV@Xkmmm@kw@IVa@KVLXU@`lLX@VKm_@yI@WU@UlVl@UanU@Um@UaWaU@Uk@XJmXVbkV@IUVUbWUUKmbk@kwmV@K@mWUXUakbKUUUJVb@LU@@VkL@VXKlbXmL@kbmUI@lVXUVU@mULWy@UUL@VUxXnl@V@VxUzmK@LkVa@VVk@@n@`UL@nmV@bmJ@X`WX°WVn@xnxnIl`VbnVlwXUlLl_nV@b@bl°VnWJkx@nmx@b\"],encodeOffsets:[[108945,27760]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/hai_nan_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"469003\",properties:{name:\"儋州市\",cp:[109.3291,19.5653],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@à®¼jpnr``pRVHÊÌ¤Zt^JÖA[CâlTébQhRPOhMBcRSQiROE[FYdGNOEIH]MgEAMLLIAG_WMCSL@ED]PCLYC[ZIHgjSxJTMbHNEFCMEE_HSDFHSLECRNSFDRICHNADGPI\\\\RZGIJTIAHLDQOHG`GTNCOIC@eIGDWHIS[kiE[FMbECZS@KKS[FDWsCeRuU_DUQNOE[LKGUBM¨EDQP@HWHGDImXCog_~I_fGDG|QDUWKBC\\\\ore|}[KLsISBHVXHCN`lNdQLOnFJSXcUEJMCKSHOUMDIm_DI`kNDIGEYFM\\\\YPEEIPMSGLIKOVAU_EBGQ@CIk`WGGDUM_XcIOLCJphHT_NCISG_R@V]\\\\OjSGAQSAKF]@q^mGFKSW^cQUC[]T}SGD@^_aRUTO@OHAT\"],encodeOffsets:[[111506,20018]]}},{type:\"Feature\",id:\"469005\",properties:{name:\"文昌市\",cp:[110.8905,19.7823],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@hĲ¤Ī¯LQDaFßL[VQìwGF~Z^Ab[¹ZYöpFº lN®D´INQQk]U[GSU©S_­c}aoSiA£cÅ¡©EiQeU­qWoESKSSOmwćõWkàmJMAAMMCWHGoM]gA[FGZLZCTURFNBncVOXCdGB@TSbk\\\\gDOKMNKWQHIvXDJ\\\\VDTXPERHJMFNj@OwX@LOTGzL^GHN^@RPHPE^KTDhhtBjZL[Pg@MNGLEdHV[HbRb@JHEV_NKLBRTPZhERHJcH^HDRlZJOPGdDJPOpXTETaV[GOZXTARQTRLBLWDa^QAF`ENUPBP\\\\Eji`yºEvåà\"],encodeOffsets:[[113115,20665]]}},{type:\"Feature\",id:\"469033\",properties:{name:\"乐东黎族自治县\",cp:[109.0283,18.6301],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ªVLP`@PEdNRAHOPEAKHEVL`GZBJfvdTAXNNTZJFPrHHNpKTD\\\\ILHbEVd^JOHLh@NNBnHP`\\\\xH@NBRLJTlNv_^CTLd@bNDVFbxdFVUPBTKOGEOUO@OEBXQP[H_EI\\\\EbeYa@UO_JMEJ_IEDKJUGMDcNUd_FMTEJSGoZ]EIYGO[YWgEQ]a@WHEDQKUSDUGAbYBUpSCYNiWqOSQEoF[UcQISWWNMSDe_cLQ_UBiKQOOASQAWgS­ā]ZaSPÝZ]XMXS[^oVËNgNKlE RôEø\"],encodeOffsets:[[111263,19164]]}},{type:\"Feature\",id:\"4602\",properties:{name:\"三亚市\",cp:[109.3716,18.3698],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@®ĂhTBXTRPBRPjLVAR`dKf`TCNXMTXRJVdE\\\\FpTRrPjXZMTDVoZABaVHTCLVCRGF@X^bFRhZXP\\\\ZHHMA[^wBWXJlW¤EJ[bCTOFWWMm@ILMGWQ@DQ^QNWFSHEbF`OXNbOVNKTEPDTLTCCVTREfvfEHNbRAENH^RJXCFHNFRpVGHWISDOTMVCZeGamaLoLÛD¹¹ėgsia{OųETtlÉwr}jR±E{L}j]HąKÃT[P\"],encodeOffsets:[[111547,18737]]}},{type:\"Feature\",id:\"469036\",properties:{name:\"琼中黎族苗族自治县\",cp:[109.8413,19.0736],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@bRFnHNbHgN@NPEnbXP@bND`NT\\\\@\\\\QZb@`@J]V@XhDpWnCJGHGXO@CR§FANHVKLF\\\\MPVR`CvVfQtDPKpGHG@S`WJP~^dSTHWX\\\\RHTFACQTIAUPOU@MG__IaYSFQKNSbORHXCZeTFJgB`YBMNMFi~IVDV[tGJWXGDQRGF]JrALgESLSAYDGIaFeXQLS\\\\MKSLSQYJY}eKO[EHiGSaK[Yw[bmdURgEK^_kcSGEOHKIAS]aFSU@Y]IWFUTYlkP_CUOUEkmYbSQK@EMWUuAU\\\\M@EpK^_ZMDQ^OXwC_ZODBrERURGVVZ\\\\DTXcFWNIAWJWAYUUFYEWLQQaCIZeDM`cLKRGpanJZQd\"],encodeOffsets:[[112153,19488]]}},{type:\"Feature\",id:\"469007\",properties:{name:\"东方市\",cp:[108.8498,19.0414],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ºxJYZQIYXLl@dR\\\\WZEn]bA\\\\S~F`KXaDeTiNO^EEKWEDQXITBXaWaDQMUJOIaTWf@NJV@dSxGZFu_@WMKAU}AQ@MwG_[GOAmMMg@GKP]IUcaFKG[JSCoLGMqGEOYIMSWMSBucIeYA_HUKGFBLOFGPQBcMOF_@KO©UAtERadwZQ\\\\@ÊJÒgòUĪRlR°KĮVLJ\"],encodeOffsets:[[111208,19833]]}},{type:\"Feature\",id:\"4601\",properties:{name:\"海口市\",cp:[110.3893,19.8516],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ńZƂtĢ¬æßFuz¹j_Fi[AOVOFME_RBb]XCAKQKRSBQWSPY\\\\HbUFSWSPoIOcCOHIPkYCQ]GdGGIFQYgSOAQLK`MFUIGa@aQ\\\\GGUFcHKNMh@\\\\OYKAigsCgLSF]GOQO]@GM]HyKSHKPW@Pxi@EMINYREXWRQ@MQcFGWIAwXGRH\\\\yDI`KJIdOCGRNPNtd\\\\UTMbQYi@]JeYOWaL[EcICMUJqWGDNZEXGJWFEXNbZRELFV]XQbAZFrYVUBCLNFCHmJaMIDDHXHEhQNXZ_TARFHVB@DTQIRR@YHAJVnAbKFUEMLd\\\\c^ÍÞ\"],encodeOffsets:[[112711,20572]]}},{type:\"Feature\",id:\"469006\",properties:{name:\"万宁市\",cp:[110.3137,18.8388],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@^J@ZTVbET^JBGLFPTHld]`FLQhcVanx\\\\\\\\ZbLHTGj\\\\FLP~fIZRZPVTQFSVAFJE^NDLEE[~LjsxVTG\\\\NZZNGlLRRGLJTV@hPZANN^@T\\\\NEPPbDZXO`d^HSvcJDIV\\\\XZAJUFCLNP@PQ¤@[ïKLÑIÏ]ÇE±I{u­YśUćFcYUmsVeBSVgB[RO@aYYPO^]@UVaNeDShMLG\\\\EfFVE\\\\F`\"],encodeOffsets:[[112657,19182]]}},{type:\"Feature\",id:\"469027\",properties:{name:\"澄迈县\",cp:[109.9937,19.7314],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@T\\\\GJCXJH@fJDDPNCNJENN^NLHBNSx@DDYbBLLDRbjZTj@`XXTlG^Xr@PJLW\\\\WLTlWR@HDJTD@X_PO@STMDNTMVV@NLDM`M\\\\XM\\\\JNBH[PYZúYzŸ`Ċ\\\\ÎÝd]c[NKVFLEBaUmBIZGQ@JQSR@CUAEGBQ`SWYRMFgWGCGJCbNnIDGMEDKVAZUEqBYRa^WEUFKYQMaFWXEHIFWMYHCrXVIIiaK@aMCUYNSIISTwXALKH@XWXIEIJQCG[IEQDE_XSBaa[AIPW@]RS[FWS[CD]PEBYNGFSaSyJG]@ugEUDQlGHiBKHUIoNSKqHFaPMICK]UUHIPDJMuCA[SCPIDIOILGAEmU[POPBVSJDREBGS[QXWSGcT}]IO_X@TGHoHOLCX\\\\ELT@LYTDaFENF\\\\lj\"],encodeOffsets:[[112385,19987]]}},{type:\"Feature\",id:\"469030\",properties:{name:\"白沙黎族自治县\",cp:[109.3703,19.211],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@D\\\\RV]dTXELnHr]^@LETBBRTHPi^[@U`QTHDJ`MGSogDIPKdJ`WVNHCXHl_DJR@AH`FBVPUJLHKNTJOFFZON[ZEHFCJlMJ_Cn`CJVNGPLTNDFIdVTWEIPmRKMc_kDMWGGUTAtJLK~\\\\f{pqD[LAVXRCH{HC`eJ`}@W^U@I@_Ya[R[@MSC_aMO@aWFmMOM@haGGMEmaQ[@MESHaIQJQMckBIw[AOSKKAMPSDSLOAV_@@`KJRbKRDfMdHZERgAWVsDMTUHqOUr@VQXTT@TfgL^NH\\\\@heTCZaESNObHPHeZF\\\\X^ElM^F^\"],encodeOffsets:[[111665,19890]]}},{type:\"Feature\",id:\"469002\",properties:{name:\"琼海市\",cp:[110.4208,19.224],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@TP\\\\pATHTGlZDJGAQjE\\\\Rb@jVBDCN`JZ[NCNHNXbULPrP\\\\KNbMTLjJJRFP`pNLZz^FLRHjVPZ@hxVKbHBHMNNJFRlLzGPnNHhIrHHADcPWdUAmEMVQDSKYHY\\\\EhBN^HpXGNDBNNBnIßÅ_g{³So]Ã£@ORO@KMEDIVYB[WJUICudGTc]P_YWaCOOMFS[]@MMYBgOU@ISHKQQkKMHYY[MSHwUit}KF\\\\KFMCF]EIUBETSROUKTLT[NKTWREfJbCHBZKTFTKh\"],encodeOffsets:[[112763,19595]]}},{type:\"Feature\",id:\"469031\",properties:{name:\"昌江黎族自治县\",cp:[109.0407,19.2137],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@`ZĤd`òü BSPGP@VSbQ`@]HC~T^SE]N]FkW]E[fYGGOPaTMbFDYfS@g[MGK]he@SSSRW@UVqrPVGNStCXUhBFQGYNcCeLQQaLI@_`@EUwcEaCUaMc@SK]Du`MSkKI~BVNL@X`EvYwHcTU@MIe@SXJbIPNVCRXbWbSAWJCRXFFL]FMPSjCfWb_L}E[TaBm^YF[XcQk@WKZJYRIZw¹ \"],encodeOffsets:[[111208,19833]]}},{type:\"Feature\",id:\"469028\",properties:{name:\"临高县\",cp:[109.6957,19.8063],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@jD`hNd\\\\^dZädĒH´Op@ùZY\\\\OAGIMN[[W_NCNMKU@NUMSNCTSP@`O@WSCCI@GXQSkXKX[IK@OWqH]SkWW@_SiiYQaKCAKZaCCw@MTGAMKM]FMMIMDSM_HGHRPKCBGSJJIYH[QOJCHMBDGQJECMTDQKFGTCEGTF`NFEDMFaGSNwIiTGhYJD\\\\KZODC^@FTKND`XBHKJNKFBNhG^FJMPcHEZF\\\\QPRjQTAdgNOPgQaRSê\"],encodeOffsets:[[112122,20431]]}},{type:\"Feature\",id:\"469034\",properties:{name:\"陵水黎族自治县\",cp:[109.9924,18.5415],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@R]NC`YL]FoN@V[vBXVFNL@TRZalnVFVP`DlOZkVSXEE_F[EUFeH[NKTgfCbMVU^@P]ZObZP@\\\\QhATUfAtUasñiāEoI]eYǯ@aKmaeWuCºKÜKpnbHbYfUDSNCPJTRAHJTDJSfDNLHXC``VBNGTYCQDIXMDSP@xLNEFRNXBIpVNLXah@RgF@`qOML@LJNSPLbaHAh@Jdj\"],encodeOffsets:[[112409,19261]]}},{type:\"Feature\",id:\"469026\",properties:{name:\"屯昌县\",cp:[110.0377,19.362],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@\\\\OnVBFKHPJCJOJTDB\\\\vDINOCGJVVL^JDONEbrGTLpMVJLGjAHGRkVChF@vH^zIbTETMHAZOFC^\\\\DXT\\\\EffAP\\\\PdAV@UIYfS|S@YPICMeM@sC[_A]VQEwyHSMuNcAUlQJMVGMS@mVBZPFO\\\\CSFQK[LqDMACiUa@[QiFBRIHYCHkGSBS[oSOqBIE^QHCRWHIXsHU\\\\UC}JEjMNAN_ZAIhSEYfWDQGaPMTLERZTJb``NHV@\"],encodeOffsets:[[112513,19852]]}},{type:\"Feature\",id:\"469025\",properties:{name:\"定安县\",cp:[110.3384,19.4698],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@JjDNdJ\\\\FbKPXfZ^Ij@RZNaVSc[MsMOHQPDJcLIJ_zCG[HQxWJBHXdENRR@XQFWZQQGOFSWUCI[WCJuRGLXNMPLhCl[Ta@SqGgJMGOmyHkKEQMINMAGaGULgwY@UOGiKQ]EYyMKoO_QEIIKiNSMa[LqOKOaVMWMGMDY\\\\_IKrL\\\\ERT[DEPYOUA@nNTUHINkRBVMdNvGTxzRF^U`BD\\\\@tfNDNOJ@Z{TeTJZ@VUcB[OBOeeQT@^OXBJb\\\\AbWTF`RCJFH\\\\RDJIJFXW@WLGBKxWTSJJMTVZND@bbL\"],encodeOffsets:[[112903,20139]]}},{type:\"Feature\",id:\"469035\",properties:{name:\"保亭黎族苗族自治县\",cp:[109.6284,18.6108],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@FJp@fxpQ\\\\ApN\\\\GNPNBM`HLMrXLXj\\\\PEHnI@WUCEM\\\\GTc\\\\GZYHTPBHRCPTdH\\\\K\\\\@HXiBJILJJAVNTOZJNtFPC`YxDPWci@IBgbGKaTOIM@KNKrP@_hE@QbgKWUMJoWAQMFEKM@wTONCJWRCZDHSAM_UD_GWMKeCITSCGIQBGXUHQoMEEGWDQIG]FMQBMaFGueFeSQDUSDSKOCSFMLUaPWM_PaEGFETMX]RCRR@HXKN@JNnXXESPaDI\\\\£FkXWIAX]xB\\\\GN\"],encodeOffsets:[[112031,19071]]}},{type:\"Feature\",id:\"469001\",properties:{name:\"五指山市\",cp:[109.5282,18.8299],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@TCNOLBTLBPx\\\\AJdlNRRIbJTGNF\\\\@RcIYbmHoLQdKN_fCJYbDRRXKZFVEZVXBXIJBXMdESW[CUYHUVQFQAqsEIMPYMSBUIIJKAIjGW[@[LGScDOGQOAGSYZ[HSd[HFNVD@XmJFG[OWiWKNqGKN_MAMO[HoM[BoRewo@Y^HpITSFENc`MVCdHNIVCLJFI`NFIP`@VZbaf[FFJG`O\\\\WRFA@PVPFPPH\"],encodeOffsets:[[111973,19401]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/hei_long_jiang_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"2311\",properties:{name:\"黑河市\",cp:[127.1448,49.2957],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@VÈÞ@kxnX°VÈa°V@kôwbJVkXlVUx@lL@xkVV°VbxlVUnVxk@KkVbIl@°kVl@lÆnkll@@VVX@V²bUlVlVUVÇn@nkJlkVb@x²V@n°VUnlKUn`@n°bWLnVUblVUVVbknV`°kkl@@V°@nzJ@XxlWXb°n@bĠlbXbbVbJ@Vba@@lbUbVmn@lVmnIW@WbÞ@n@x°@ĢaƐéϚnlČ¯ĠŻÈwm@ôçUmm£Xy°UV@wÈ£Ǫ¯kõÝçUÑUķĢkVÑÆÞU°nŎ¥ČUĊx°m°¦żVƐx°Ç£@yUônÞÆ@Èĉ°Kô¦WkWUbÇ»@ÈĕWÇÈ£ŤU@n£ÆUUKVamanwÅmÝJ¯k@JIkaVaUUÇbkaÆÑkWmÝUÛÝ@wnU±@kkV¯KUkJ¼U¦Å@ówķaķůV¥Uaó@Åwm_kVwĉĉmmn_V»a@UVwķóU¦LǫéóXÇmōLǓÇķxÝkĉkmakbUĶ°@W¼@bÈÆ@ĖLl@°J¯mkl¯LÝ±LamJ@¼VƧUóUXċb¯ńVbkÆÝI@llxk°V²V@UxÞL@b@b`ÇzkókÝ¤@ğ¯WLĉÇLmmnċVkbUaL@¯bU°ğLÝÝ@\"],encodeOffsets:[[127744,50102]]}},{type:\"Feature\",id:\"2327\",properties:{name:\"大兴安岭地区\",cp:[124.1016,52.2345],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@kϙmƏêġb¯@@wmÝ@XV@Ill@bUxl¯VlVbV@ULVlUV_kxVVVÈÝJ@¯Ulm¯x@xóÒĉ¼m¯Wxţ@Uz¯WwnUwť@knW£óVUUwğyó¦WIVmmI@±kwÇ@@b@ĉ¼ó@¯wó@¯aó¼KÅaUwmWUwÅI@aKó@UaLaVÅwō¼UUÝl±I¤VxÇx@zkJmnnmbnzxll¯ČkJl°@kbmx@x@kêmVnWxôXxU°bWLóJnÇWĵV¦UUbbÆġKk¯VU±aXmċÑUwĉKġkVxkÇKkbIÛXWl¯bX¯KbĊÞVÆnĸ²lxU°n°òÈb¦xVb@¯Vx@¯VķÞČlĊ°KĸȘI°¤ČIôò»ƨnȰKǬ¦ôWŎÈƨwlnKVXmbX`lbwkVWXXL°aƾaĊ£n°@°¥ŎzÞ¥»alwôkƒJa@ĶK£bU°ĊxźVÈUĠ¥ƨVI@XU°x°Ln¥w°UmwXmÝV¥Ģ°@nU@mÆ£¯lKÜw@aÅU¥UaÝIkmV²nn@Ķ»@Uk¥VKÞ@ÞÛ@kVmĢa@_Jómǖ¯ÆwóÇa@alUwwĢřk@wÆWXUWXWam@_ƒ»ÇéXaĸwVa@ÝKkUWkXkKXxn@lĊV@¯m¯nřÆw¥\"],encodeOffsets:[[130084,52206]]}},{type:\"Feature\",id:\"2301\",properties:{name:\"哈尔滨市\",cp:[127.9688,45.368],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@°`_JlU@@V¦°JUnLôlnŤ@@ÈaUÒVbkbl¤zk°ÇVÛô°IlVUVôUxÆU@bźĀº@¦b@l²UVl@°ÒĠxnXxÆVô¼Þ@Üx²KÞlVÑ°UȰôlwô@²ĸ°lanV@VŎUll@bÈnÜmwĢ@la@ÝÞb°UXblŎ²ÆkVI@nJnĠ°knÜbĢwna@akÞKƒĀaIVbU¥wĠwkôxnLċVçkaU±IUmnġW°WôĉalÞÅĵ¯@W¹XÝab¯a±X¯ºLaVmkLóbkaVUKVkkKV_@aÝykk±L@ÅU@yV_aU¥ówÇx@UkVn@lkÅlwWVwUkĉmkklW@abVwnWWwWL@UUÇLÇm@wJĉL¥@Ý_@a¯yUWw¯¯Uġx¯aÝXVmaU£ó±¯nwa¯óÅVXmanUlUXkWa@mkIğamIklÇUkĊzkKlUōĬl@nX°@llUxŹ²mKĉVWwk@UbUK@bmVmIVmwaWxXlWČmºÞÆbUxV@ĵńWÆĉLkWUbaWzkbĉ`U±LklōwUVÝ£UW`Uwk@mk¯VkaõVX@WbLK@XƧºWzxK@lmX@bkVVÆk¼Vbk@Vn\"],encodeOffsets:[[128712,46604]]}},{type:\"Feature\",id:\"2302\",properties:{name:\"齐齐哈尔市\",cp:[124.541,47.5818],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@Þ@ÞĠKV¯a°@KVblaČUmnnKĊÈKX°Ġ@Þ£ôllÈy_@a@aKÝVwU@±¯Ulkw@kÞJlÅUa°ŃČaWVôƨVU@»nIb²KÞ°Klkn°¯I@kK@ĕÇÅ@aX»¯@VĵlaÿVamI@aÅÝउýĊȗJôȁÅkmƑÛ@kxġ@@laVk¯»īŹak¥Å¯JUaWU@@wa»KUkÆkUmUmwÛ±±UUbUUXwWwÆÝklkUanaWwnKlkal¯kaƽakÅxa¯@amb¯VlÇwÛĀV@xmêVÆVVaôVwÈx@ˌx¦VÞ¯VlmX@L@¯Ua¯LmV@°XċKV@UÈ@¥@wġIUkm¥Źw¦¯lmn@°kxVV@¦óamn¦l@nxlĉVómxnÒĉĀĊ¼þǔêÞ°ˌĠÞÒ°ĀɲĀƨźˤȤƨĊ°w@£nymwnkUUV¥ôÑVmkÆmUUVamVIkmôlxkXÞþbll@kVƆVxV@¼VÒ@UnnÞJ\"],encodeOffsets:[[127744,50102]]}},{type:\"Feature\",id:\"2310\",properties:{name:\"牡丹江市\",cp:[129.7815,44.7089],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@U`lLUlVLUlbaôlKnUbK°¹²W°baÞbknyUlUkamř²L@m°@lm²n`ôÅlKxÜKnxV@l@ÅXyW_k@wmŹĕmX»Ûl°ôÈ»ôô_WW@Ual»wU@@wUV@VXI@wĢ͑ÞȻaU_@mUkly@¯óV»XmWUXUWmnm¥nUUaWLk»Æ²IÇawÅaÝ°¯nUa±a@¦õÆğ@@ÅbxUÜnÇłlb¯¦ôó»m@±Uk@Wwa¯xUV°xXbÇÅUVK@¹KUaȯ@ōÝXallÛkalÇUǫÇÅÇakbÝƆ¯nl¯@¼VUx@x¯W¼Æ¯mĖĬ¯ČVkķÅmx°ô²V¤bUnÞW°bĢw°V°XxV°z@bÞ`@¦KĊI@xnÈÈKV@VXKxXmXUxab@kXllĊnVlUxXkxlÆkm@UVl@ÈwôxV¦bU`@zÆV@²KllÞz@b\"],encodeOffsets:[[132672,46936]]}},{type:\"Feature\",id:\"2312\",properties:{name:\"绥化市\",cp:[126.7163,46.8018],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@ऊþÆÞ@bnJUbĀnblĊÞlĸwǔÈŎKÈnôWǬêKV¥ĸôUx@VbU¼m`nnĊĊxlUmkaVÿLw@°»UmbKmÝUwUmVknKUUl¯KUUÈnK@ĠkX±lX°L@¯¥@wV_mĵ¯WwL¯UkōÇVUlwVó±¯aVka°wVk°mÞ¯ŦřÆl²ŎkU@mUkb¯ķ±ó@kxȯó¯VUÒkÝ±LÛwÝ@ó»ÅUWwmğw¯Ñ@UkV±@ka@¥¹Źÿ@aÅVwóVVUkU¯JÜóÈUl¯yk£laUaVÑÇb@ţ@kmómKV¯IU¥@@kVI`@ô¼blUlbÈb@xÇKkĢɳaÅɆō@VK@z@@¥ÆKnÜ@@aÛUwwnUķ@_V°@klVnULVVÞbVl@°@nxn°LÅÆlVÈmU²@VmĠLxn¯xkWzJwnLmbXbW°Æ²@x@JVxLĀ²Æ°I¯ºÈ@ÒnÈ\"],encodeOffsets:[[128352,48421]]}},{type:\"Feature\",id:\"2307\",properties:{name:\"伊春市\",cp:[129.1992,47.9608],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@K¯kWW²ğl@mLÇVVLk°VVmLUlVnxVnÞLnaV¯¼@xKUĀlbn`nÆxô@VbU¦ĸŰĸbôxÆ@V¥»IVl°LUll@²mVx@ÞÜÞVnlXÅÒlbÈaVVUblbJ@I°lÞInÆmxnbUbVLÅVm¤@ţVÇ¤XÈÇĖ@È¼aXVÜaXbWnzŎařKôbUlw@¯naÆKnUU¯Üa@mkkVUĊmżÝǖK°L²lÆI@¯¥ĉƛVaÞk@ÝVaĠlnUVwóma@wĉ@aVxamX@a@UaÅLaVW_nWm£nWm_ÅV¯m@mó¤Ý¦¯ÅalmX£VWUÅwmÇ@@IVWUw@aI@k@wŎ»WÅVaKIka@¥lUkUlwÅwVyÈwWU@a¯U°mÇ@UçaVa¯mV»ÅwÝUlUkV@kmUkX£w°@@ÇaÝIamÛam¯lğmmI@JUl±ÅōkWa¯VÝa@Þkbġ@xÛnÇm@akkōVōl±kÅťŚÝ°¯nUl¯xlbU°b²ôUxkVÈUŎVl°KXxĶ°nU`@x°¦@\"],encodeOffsets:[[131637,48556]]}},{type:\"Feature\",id:\"2308\",properties:{name:\"佳木斯市\",cp:[133.0005,47.5763],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@nbÞJb@È¯@xW¤Vln@lUVlkÞVÆxU¼°nUbbVèÈ@nIn@ĢmlUw°żVUn@lnL@VôbwĊlJķĸĢlwôwƨxVVUŦxLźÈ°`nnĠwŎJÞĶwôJ@¤XnÜĸln°¼È°lUbx@l@ÞÞÈm°lôwL°¼ĸ°Þ²nĠ@ôwÞ`ŤIVÒĠU@VJĸbÆ²@°ĊKJĶaĢȰ@ô¥°n¤bČU@VxmUw@aÝţÇķ@ĕķīU¯²@ÆmVÑô¯X¥ċç@ĉ»U¥ÝţKWVÅkUVÝŎUmÇÝx¯aķxÛUóL¯a±óōb¯ÑÅVÿ_Åķa@UK@wm@Van@UmmLVa@VImmXUWÝUÅKUwÝUUkVk@l¯XÅ_J¯kJmÅLa@¥U@¯Vz¯@`@¼mxƥŏKÛk@±laÛ@@Xm@@xƽ@WŎnˣĕÅ@@aÅ@@nÝbÇ¯@_UkUWkbwÝU@çWlw@anI¯lyX°m°VaÛm@mVwÞK°XlaXmm_@UkwÝK@VIXmV»I@a¯ğWbġaU_¯JU¯ġĉkō`±nÝÆkbóĊ¯XĢXmVn²JVlbUèČmKwlóğxxV¦UaJbƑÿÝLl@bmbġx\"],encodeOffsets:[[132615,47740]]}},{type:\"Feature\",id:\"2303\",properties:{name:\"鸡西市\",cp:[132.7917,45.7361],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@LKVVnkbVÈb²U°VnklVlaÈL@anU°ÜmXV`nôLèxlLXL²aVVmÈX@ķlnUÈl`È¹@Ť°U@xKnnVmlnnUllVnnaŎwlVÞÒ@n¦LV°lwVkLaÞlnÒ@xmLÞ¤Wn¼WÈLVVUxlÈôWVaU_VKKXUÆbnnôKbÞw°bÆWXamVwKUw¯WUkUlJUwVUa@@kmyzmĉw@kVwkW¯ÅKU_VmxU@aW@@kK@wa@K@@kVUaky°_Vmkna¯K@Lwġk@@IÇóXwVakmV@mwXUWanlĉ@ÇUwKóܛǊÛm°@wÅ@±b¯W¹WVwŹĕ¯kVmōb¯w@awmVUUbVIkaVwķxk¼b@VXXó`ó¼Çó¯kÜ¼WnźĖnxl@X`WzÆ\"],encodeOffsets:[[133921,46716]]}},{type:\"Feature\",id:\"2305\",properties:{name:\"双鸭山市\",cp:[133.5938,46.7523],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@UUwómÑÞÑUÝÝUkmmÅyV¯ī¥Uÿĉ¯mÇkaWbÅX¯aÝxaóLmmÅaWVLULV`UbXókÇVwUUÇKX»XmÝ£nK@wmÑkÝbKUlx¯kUKm¥@ÝÑkUōxmbUmkVkmmnkUmmL@w¯Vţ@Çºk_ÇmVk@ĸVxVÈ°lLkllUbōwnVW¼nlUx¯XmWUnÝ@xÝUó¼¯J@LVbkJWnkbW¯ÝLUxn@nÜb¯U¯nWkz°mJ@bkxX@èÞVxlaXlVV`°@ÈÞa@mÆ@@bÆ@ˤĖmXōƾ@@wn@@WÜ@kb@²ÜlŐLƦnw@»_°@y°UV@@¦bÆKnI°lIÆ`°W@kllUVÞVVxLÆÞVXWVnnUJ@UbnKVnm@Ubn@@xL@VbÆĸ`UĀÆÒ°Ŏa²ô°bôKÜVĸw°bÞwÈVnÞōVUÆlXU\"],encodeOffsets:[[137577,48578]]}},{type:\"Feature\",id:\"2306\",properties:{name:\"大庆市\",cp:[124.7717,46.4282],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@mÇ@ÑÇ°¹¯J±ÅÿKUwI@w@±ÅX¯WanamKxIylX°wmwğKUn±@nVÇUÅkÆ¯Kmmw@@¯UkÝaUUVKmUlk@¯U`ĸ@VmxVxÜ@bÛ@mÅL@¦@@yLUŎ@ÆɅɴblġÈL@wÇaakkVa»@ó¯_ÝJwÇaÅXnyU¯¥Å@wbÝaLmm@@VUlbğVm¯Xm_`¯_UxmLa¯b@maó¦Çk¤V@bóJknVxVXx±aLUbVxkLVlLWl@nX@VÅbWlÈnxbWÅbm@xbml°bXbWXVmnn`Lmnbmb@k@mwU@@¯Jlbk°lbkmLXxmbVbkllÅÞxXxVWVVa²VÜ²nxVVnÅlVlL¼b@xV@XVbIÆ°¦lźbĬ°¼Ulb@kĢ@lw@ƒÜlnȂÆóȘIĉ\"],encodeOffsets:[[128352,48421]]}},{type:\"Feature\",id:\"2304\",properties:{name:\"鹤岗市\",cp:[130.4407,47.7081],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@Þ¥ô£nn@°ÆUn`mXn¤mX`UXbÆKVb@@bnWbwUbĊ@x@nbWVm_mm@ó»UmÅWXkĠ»²¯¯nķwŎ@ĊŎK°bĸUnÑKČ¦ĠÈbÆknJÆUĢV°IVƾwaVkÇ¯¯»mķkÛWm@£óIĵxÝōIğxmm¯_ÇŹKwťUVUƧwóxxġkĸķIkĉxóa@UmK@kVmUŻ¯Vxkġn@mmJ¯n°V@bXVÇxUzÆxkxlVkV@¦lbJLUbÆXō¼@xl@J@bVxXU@JÈ@nxVÆUXW¤knÆb°\"],encodeOffsets:[[132998,49478]]}},{type:\"Feature\",id:\"2309\",properties:{name:\"七台河市\",cp:[131.2756,45.9558],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@²mŎ_lĊĢV°°IV`ĢbaĠX°@bJU¼WnUJ@ÞLlxV@n`lIUa@K°Iô»ÞVwÞ@VmnX°WVwmkX»UmŎxVaklkkKÇ¯UUwÇWUnU±bKWKkwçóKmU_nW¯ÛmV@bÇKkbkUml¯U±VÇaUamlUULKk@U@mwÛLwkLóÆm_±nk¯@@n±KnŚlbkVVmzlWXº@Ķ°\"],encodeOffsets:[[133369,47228]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/he_bei_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"1308\",properties:{name:\"承德市\",cp:[117.5757,41.4075],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@lLnlmxnIVVlUnb@VVxXJWL@LÞVnnVJ_@wkmKbxwXkWXXKlb²K@nVVVbL@WlU²lKVnUJVz@VVb@lÅ¼mVUVnbôaVX@°Ub@lWbX@b@bVb°x@VxÈLVlaÆ@Þb²k°@lVU@Xn@VWLXb@¤VXKVVVLnm°_ƨ¤@aUIVaalkX°kV@alwUVyU@kó°na°UVUUmUÆw@mkLVUWVIWLnn@xlVnKmyU@U°UXaV@U¥U@UÆ@aVUkWU¯aU@WLUV@bkbmKULmKkUVUkmVIUwlWV²Uml°U@WLUwVm@UUK@_KUUÜaXw@VKUU@mVIUUlmnIVVVbÈVlKnbVK@nI@nVnwVLVKKVnb@aUIVW@In°@lVnI@lWĢ@°UVL@b@VyUUa@w@WUnU@WÇ¯K@UkkJWaÛbmk@mVaÞU@amkW@mXUKkÿ£@akl@Um°UXwlaal@nmlXnW°znW@awV@akbĉ¥VmU@IVUJkUmWUKbmkUaKkUVU@KV@@klwWaU@kmXVènbmlUUKX¯JkbI@JmIUWU@Lml@XkJ@UkK@aVKwWaIWwmU@mU@J@UaċUaUUVkI±k@UU@UbVVm@UVKLlkIWaULUWXUJU@WbUb@lkXUxm@@JVn@J@bnb@Vkx@bLUÆnJaVXnKVVmzX°V@_lJXxWXK¯bÅamU@lUIbñJ@LÇKkIÇ`kxWL@@@bUVUb¯xWKkÅVlULW@n¦Ul@IlmUUUVm@kWnkKma¯XUKWmnwVwÝLmVUbUVWb@LnxmxVmbXx¦@nb@`V@kbLUmVUlkbVXkºmnm@@xk¦bĢÜl\"],encodeOffsets:[[118868,42784]]}},{type:\"Feature\",id:\"1307\",properties:{name:\"张家口市\",cp:[115.1477,40.8527],childNum:15},geometry:{type:\"Polygon\",coordinates:[\"@@kġÛal¥@wn@nml¹UWlaVknUVKla@U@_ma@¥WwnaUwnmw@KXaVUVaUnmWUk°lnUVUXWVwIWVóKUI@WXxUU@mma@kUKWLkw@yk@aVkUUċaUU@Wk@Unm@UVmLm±IUkJkW@aI@m@UVUla@VXVXmVwnkWKKU_k@m¥mX_JmnU@km@U@KmUVU@U@Umk@@LmW@Û£Wka@wk@aI@mmk@mUa@UmUIwW@aWUbU@kbÇ@kw@makVUkU@am@aU@mxkUbKUXU±KXVWLUK@wkU@V@WXUa@WbUxJI@¦VèVVX@±ê¯KUI`¯UULVx@V@UKIVkLmVkKm@nUJÝbkIUJVXVVxVbUVJUn°bVmlU°XnK@Ul@lVÈVUXx@W@VXVKÞbn@VnbVm`UxkW@UVkLKm¼@lUnUJVnVXV@Vm@@LVklIkl@VWlULWKUL@mJ@blbUVUlmzUJUxm@UUbċÜk@Ub@VLVV¦ôbVmUKUkU@m@VlVn¼WbUJ¯@@°nIllÈl@nXWlLkJ@bkxlxkxlXUlklJXL@bWn`@nÆXxlL@xl@XbLKlVlIXblVUbUJW@lX@VL@VVXJwn@WnL°KbVbl@VI@K@U@nmVmV@XUWI@aXm@VUUkWmn@lmUUk@mUmK@UnwVĉ@mU_V@XJôVVULVUn@llUnJl_n@ml@XlLlw²LVJUL@VmbVblVXmVnl@Ť¦nn@Ü@bl@@XV`Unb@VlLVb²JXn¥ÆÑ@¥Þ@\"],encodeOffsets:[[118868,42784]]}},{type:\"Feature\",id:\"1306\",properties:{name:\"保定市\",cp:[115.0488,39.0948],childNum:23},geometry:{type:\"Polygon\",coordinates:[\"@@VbXW@@UlV@xVLXKWU²LVVWLalVnwV@@bn@bVVllUnb@lxÈ@laV@aXV@bXxJnV@VVb@nnl@nJ@bll@aU_VWUwVUkUmUkb±mVwU@VIUW@UWk@VU@ynLm@IV@bnKLVaVmnIlaXwV@@WVL°@@xnX@V`V@VbUVVLVKnwnL@ll@@_V@VVnaÆ@KVXÆ@n@wKmUWm@km@kÜKXU@ÑW±nIUwVKla@I°wU±kkmm¯m_JnawW@IVaUama@wUmU@mVw@aXk@mWa@£km@a_kVmUnWW@¯bkUmk@VÇm@@kUUKUU@UVUamVUaWIkb@xU@@amUkKVkam@@kVUkUWmKmUkLUb@xmJU@UImVÛVmnUwJU@VX@UWm@Ub°¦UmxklmX@`ULU@@UW@@xkn¯@makVUmxUb°lUbUbnUJUUVaLkbUUJUU@mUUUJka@xUIWJUnJ@Vz@kb@`@bln@lb@X@@@XlbnbVb@VJlInlbVw@UKl@lbnan@VbJôLnUzlV@lÈLVbVK@LVxVWXX`WxXzbV`UXV¤nx@bVlVnVlUL\"],encodeOffsets:[[117304,40512]]}},{type:\"Feature\",id:\"1302\",properties:{name:\"唐山市\",cp:[118.4766,39.6826],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@@VVl@²lJUVVbČVVb@@InV@VnXxJXbxUL@bLl@VlI@WnkKV@VXnJ@IJla°IWLVVnkmaUçWVkôaÜ¯@nV°wnJlaV@VUnUUaW¯wXWWwna@£UaWKU¯¯@aVUkKUamUUn»anIVwUWlk@LlWVakU@K_lbÞU°@y°n@KÈkWWţ¥ĉōkġWUw¯£¯Çwţw@kK@k¥ÝwÅbÇ¤ÛťVlW°@ĸx@VVVULVLkl@V@X`Ub@Xm@UWbk@ÆVbnLWV@lnXUbl@X¯lmUVkKWLkK@_UK@U@UmmUxmVXLWVULkU@`W@ULUK@XlJXzV@@xml@VU@UX@Kk@WbUK@Xn`XmJnmkxUVbUVlVVxUbV@nKlLkVKÞbVKXI°KVmVUIUKULVxVJVLkV@V@UbU@WUU@UbUK@b@nV@VkLmb@b\"],encodeOffsets:[[120398,41159]]}},{type:\"Feature\",id:\"1309\",properties:{name:\"沧州市\",cp:[116.8286,38.2104],childNum:15},geometry:{type:\"Polygon\",coordinates:[\"@@@ln@UÈl@Vnl°aX@mXnVlU`@bln@¤Xb@nWl@bUx@nnVV@xnbVbUb@JXxbmXa@kUVwlWkKôVm@wkkK@kl»ÈmVKXkla°@XVV@VI@ml@@Vn@VX@V@J@VxUzVV²blVk¦@Ġ@@»@VK@VÈLlK@XnJ@alIUlaVVb@n@aU@WUIV@mUn@mKXml@lL@LnWb@XV@@aVVbV@VVIVWÈbIÈ»ƒǟlWaVUÅUUm@kVUWVkaUwmaóUJUU¯ÑU¥mk¯UaKÅnÇyóXmWÛX¯aċbÛaJWÝU¯»aóóUm@IVVl@bLUJWLX@@xXUxl¤V@VnVUVXVbV@@@VVn°V@ţU¯VUmUWV@mUXabUKUwUaÇKnVk¦Wb@VnLmV@bkV@nxW`Å_UVV@bUklVX@VmlUx@VVL@xVWVL@VW@UUm@\"],encodeOffsets:[[118485,39280]]}},{type:\"Feature\",id:\"1301\",properties:{name:\"石家庄市\",cp:[114.4995,38.1006],childNum:19},geometry:{type:\"Polygon\",coordinates:[\"@@la@y@UImVXIVJw@lbIVVnV@VVIVVlaKbVUVVImVaaVk¯VanwVlUnb°@lm@wX@@VV@VK@_nWlknwV¯¥Van@VX@W@UVIVxnmÜUnUVJV@nI@wValKnV@kmU£na@mVk°KLVa@UU@UmknWWkXU@aWW@@km@UaU@@klK@UkaWaUnamm@Ua¯wWU@UkL@Un@xVlUXVJUbLmU@aUWUkmKkLUUm@mWXammkkWUm@@U¯JUUmkU¯@mKĉxÝwÝ¥LUómwkUUUWVkKmkKmLXlxVLVxXJ@nVJnz@VWL@`nX@x@kVUUmJmIXxJVnUV@UVV@LU`UXVVlXL@l@b@VmX@bxn°UbkKWLXlW@@bKmKULmakLUlmb@Xb@xmXU`Vb@`lLx@nWVXL@°WlXnlbKVKXVb@X@l_lJ@V@XnI\"],encodeOffsets:[[116562,39691]]}},{type:\"Feature\",id:\"1305\",properties:{name:\"邢台市\",cp:[114.8071,37.2821],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@nKlLnlLXUVVlVnxôVKÞ¦ÞxĊwnL°@lVnVV°I@Vn@VlXnlnbWnXn@VVlKnLVlVX@bnVKVaUIVWkU@wVm@¯@U¥VmU_°lKkw@LXVaU@wUUUKlUóW@UVUUl°KwlKU_naKVnlKkkWWa@IJVa@IlJnU@KVUUmVlaXUl@lm@kXWÝÑnk±k@wğ@@U@mKĉLmVJ@zmlnWLUÝJU_@@mJkXUVlbklÝ@Ýab¯@¯±JÅwġaUU@kU@mVI±bUKLWUXJkaLóKULWbUVkKmnk@@bmLUl@b@mnmJkUULabnmn@lVV@¦n@l@bznx@`Vz@bxnV@xllbnKVx\"],encodeOffsets:[[116764,38346]]}},{type:\"Feature\",id:\"1304\",properties:{name:\"邯郸市\",cp:[114.4775,36.535],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@bVKlVnInm@@akVnK@al@nmlLVUXaVKôLKlbIVWXKVL²aJnU@lV@VVĢbÆx²I°°@aÞbÞ@lkkaVUlWnI@@V`ÞIVXKmnk@yInUĊKÇkUUamUUk@aU@Uk@WUwVkVJVkkw°a@mK@UX@VVLVW@wwVa@¯Xm@@lUIWaU@UWkXWmU@UwmUkKmn@lkV²VaULUVmJUUUwLma@UmkIUmLmVmx@bLUamKÅL@VmbkU¯KÝamzkJUb±VkbL@lU@WIkJzkKmKnUalWkkKW@@nkbk@WW¯XUVUJ@XlJ@X@XlWLkU`VUnaWaUV@UVIaUxUUmVK@I@W@ÇU@@U@b@nmKXmx@UxkVWUX@`VLlL@`zXÝb@b@VUVkIUJVz°KVlnLlKnLxlLVVUVlXUJ@nnI@mVUlbn@@m@bVnV\"],encodeOffsets:[[116528,37885]]}},{type:\"Feature\",id:\"1303\",properties:{name:\"秦皇岛市\",cp:[119.2126,40.0232],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lnV@Xbkx@lU@@LUVlVLVbnlaLXVVnlIVUJV@UnĊ¦lab@nJ°UmV@wn@VUJVI°bnWlXnWVLVK²bakklI@aUaVUwVUUalaVwnUVak¥X@WkLVÓmmUK@_lW@n_UK@alÅ@ğÅƑŃÝm@ÑţÇlL@¯mz¯@ÝVak`@LlVUbkXK@klVXUxJmbm¼VnVVblLUV@b°V°XLVb@¤mbXxWX°xXVbmVUVU@kbmI¯xmU@Û°óbUl\"],encodeOffsets:[[121411,41254]]}},{type:\"Feature\",id:\"1311\",properties:{name:\"衡水市\",cp:[115.8838,37.7161],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@KVlV@X°xb@VnnmbVXblb@VkL@lV@Vbn@@l@XX@bWVXlmXnlVV@@VUbK¯LUl@nmbV¤n@lLXnlVUV@ln@lbUlLnV@bV@@wlaXJVbnUVbVU@VVLVVn@VVX@@UKXUU@wUK@UwVnk@UUWlkV@aUVUÆ`X_w@mlU@anUmK@UXal¥UmÈLVbVxVLabVW@nXUVnV°UŤV@U¯Um@U@@UUaWVUmUUU@k£VwW@wW@XKIUa@wU@@al@UK@_mKXKbUU@aVKm@Xm±@kbÇakLğVaUw@a@mkUJk@ykw@£WX@lknk@WVkbUVnUVL@mVkI@JUbI@JXbXllkLUmLmbV`kLx¯LkVUV@VôXkVVLVV@xVUbW@KxlL¯kV`UnV¦°@\"],encodeOffsets:[[118024,38549]]}},{type:\"Feature\",id:\"1310\",properties:{name:\"廊坊市\",cp:[116.521,39.0509],childNum:9},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@laU@UnL@VWbklWxnIVVV@XJlbUlXVbn@@KmV@@X°WVInJmn²@lmVbnL@amKV_kwlmX@@LVamaXaaVU@UnJVanLlUkaW@UaVakK@IlKUU@an@ln@alKUkIVa@a@klaUKUV@UkUV¯KVV@kUmU@@a¯ImJUU@VV@UL@U@@WXUWa@Ukwm@X@@w@al@@aVIUmVUUUVWUknK@I@l¥kU±aUUVyUw@@I@UUWm@@Uk@@nUJU@WU¯@kbWlULnÇk¼@llLl@xUnóLlkXUxV@lWbI`°nnnllV²¯x@JkbLUVxmJX²@ÒWVÛL@lln@XnnVL\"],[\"@@@kX@Valaa@KWI@UXW@WanaUIW@UaUKķk_W@UVUKU@b@UamxVXnJUbWVXLVbn@W°kb@U@Wó¼mIU¼k`V@bVbl@lX@lUôVlUIV`lXVn@lUlVn@l@UVaIUWl£UmVWU@@UUKlUUUnVL@KUnLVWUa@U\"]],encodeOffsets:[[[119037,40467]],[[119970,40776]]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/he_nan_geo\",[],function(){\nreturn{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"4113\",properties:{name:\"南阳市\",cp:[112.4011,33.0359],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@lKl@nVV@bn@VVnmnLLXx@VLlKVUIXWÜ@Člbl@XUĊUlwnWLÞwm@ÞUVmnVl@nXJXLm@VnnJlaI@VkxVb@VlnJ@knKVn@°aVanal@XK°b@¯VJXIVK@al@nVk@nKab@XL@blVVKVLXK@VaVI°mVaX@V_@a@yUkVwVIVaJ°@anIlaV@nKnXÆm@wUUV±UUWUKnaWwXUWmÅ¯Vam@kakImUK»lan@VXXaW@@UlUUa@a@UlwUV@Xal@@anIVaUK@VXmwVmUmVLXl@nalLnal@nKlkV@@UnJUXnl@nVl¦V@@VnJ@nUVVVVIn@VaJÆn@@K@mka@kmWVaUI@a@k@@aUL@mmaVIUKUV@@IU@mUmmL@K@UUUU@mW@@nU@ğ»mVmbk@klW@UXnV@LJmlUnUJUUUW@UnkKxmLa@@@lUUbmUVWk@@nkUmam@UakJU_Vm@ÅlÇLUVmVUwULKU@k@UVUlU@@U@UaUUWaÅzJaWLklb@bmL@kKabWUV_@mV@b¯JmXUbUK¤ÇLUU@b@JkLWmkUWIkJ@VmX@JUbVXU`¯VV¯blK@LXKlUV@Um@@Uk@kxWkbL@KkbmL@UXmaU@@l@x@blX@xUJ@bULUlULÇ@@VnU`W@@nÛ¼U@@VmKUkm@VVX@@xÇ@bUbVb@VX@@xLUb@l¼XLlbUlVVUUb@n\"],encodeOffsets:[[113671,34364]]}},{type:\"Feature\",id:\"4115\",properties:{name:\"信阳市\",cp:[114.8291,32.0197],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@VllInJlknJVkVU@mXlUÞ`VnVVU@U@y@nXlKVnJVkXKWaXIb@yVkVUkVwn@K@nW@kKlUXVVUlbnUV`n@V_V@llX@@Vb@bV@@nlVUb¯WLnbmb@nLnKbUbVWnLlaX@VVUX@Vln@`kL@ll@VXVJÈIVl@XÞJ°UnaLlylU@UXKlnn@lanLWWnbVI@KXKVL@LVWVL@UVKUIVWX@@XÆJ@In`@lJVI@aWÛnK@UlK@UU@VKnlmnXalUllLUbVVknJ@nV@Vm@al@@xnVlJVUU@w@ak@XW@_mWnUlŁUmVKV@VXwW»XWaUwnkWUkVUU@@@WlaUkkaIWVkm¯xmIUmLUVaUIó»m@mmwXk@amk¯¯l@wmkLmmU@UbkUWJ@XUbJ@b@l@znÆmK@Xk@Ub@lm@I@akmVKUUVUkU@U±JUbk@IWmkxa@UUVUWVkIUaW@UlLWn@VkJI@VkK@L@bmKkJmUUaUKWXk¼VxnJ@V@@VULV¼@@UkaUlWL@U@W@IkKmL@KULUWULWKUXUJmIbK²UWnWKUUkLUmUUam@UU@mUL@xkV@VV@bmV@Vk@mwkUVUx@mbXÇnVbUL¯WnUVLVb@xnlWnU@UVUVVUbVVlVkn@llVUXUWUXVbUJ@bmLUJnb@nVK@bl@@@bVJUbnX@lb\"],encodeOffsets:[[116551,33385]]}},{type:\"Feature\",id:\"4103\",properties:{name:\"洛阳市\",cp:[112.0605,34.3158],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@VVUllLXl@LWn@J@bKUVmnL@`VblLnbV@b@JmL@LnV@VV@¯VJVnXL@nm@aÞ@ak@mImVbXLynLk°@°aVJnUV@UVVXk@WJ@VXLlUnJVnn°U@»°Uwl@bWmUXÆ@VLXU@m@Ua@Imkba@naWW@_@WXUV@@U²@K@I±U@¥kKWLóLla@£Um@kWKXU@mlLXUVKUU±J¯_@`UL¯Wmk@WakklUnVUVaU@KUU@mmK@_a@KX@VaUIm±kaVKVUkw@kaW@kbkL±UUaK@UUKVak£@UmmL@lIkmU@Ualw@UJkbmIUmn@WKImWk@mUUnÝV@nÝxKmXkxĉVWVk@kaċÛ@WXJUV@zmVWnbUbVbLlUnlUÒnWVVWnk@@Vm@kxm@Unl@Ll@@V@XnkJVV@nlVXxU@ln@a@VLnWĊ¦nx@lbVKXLl@ÞVLXJl@XXl`lIXVl@XlXUVKwV@lanxzUbVJ@VVX@b\"],encodeOffsets:[[114683,35551]]}},{type:\"Feature\",id:\"4117\",properties:{name:\"驻马店市\",cp:[114.1589,32.9041],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@n@b°UÆXnVlnLÜ@VLm@n@na@Jm@k@lVVxXX@V`lLVXVV@VVÞLVV°²@labnxV@@bLmlm_VWnIWUna@lLbnV°VL@KVLVUVaVLXK@mÆXna@wVma@Xw@KlL@a@Va@wUkaWnIVla@Kn@Vn@VUl@nKVnJ@LnK@aVkVUUW@VakUVanI²XW@UUU°KnUVLl@XaVK@aU@KUI@W@_lm@KkLUKV_U@»@UVJ@XV@@mVL@K@U@Kk@VwUUm@kmWL@VkVkzKmb¯VÝI@WUkÇJUIUWk@@klK@_km@UVWUUW@kbmKUXaVamLmK@namaXK°VakU@mU@@aa@UW@kkU@U`m@U_mVkaUVWUkVL@lmX@Lm@UxVlUUl@zaWJXbWLUlmIUkLmW@@z@VUVUUmÝ_kVW@nUVUlmIklmIkJUkl@n@Lm@ÅIUbm@UJUUVU@mmI@UU@k¥mUk@WmVmI@VU@klmLk@mbkKmb@WkKUVnUnnxW@UVLUbmJ@bk@WbU@Vkx@V@bVbkV@V@XWbUWm@kb¼VLnlJlb\"],encodeOffsets:[[115920,33863]]}},{type:\"Feature\",id:\"4116\",properties:{name:\"周口市\",cp:[114.873,33.6951],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@lnb@xlJ@UnLlKXUlJl_KnV@xVL@bkbVVUè@Wb@UbmkVmbXVJnUl@a°@@bLVblXxInmnLVwanJÆw²IlmnXVl°VVbÈaVb@lkn@VWnLlUVmÞUUklkVkUaVaVaUwK@kkaVWmw_l@nUVVb@baV@VV@zXJl@@kl@lk°WVnÆbnbUVJI@VKVm@kK@_kK@a@aU@@wW@@k@aUW@IUWVUnLlUlVXKVwmk@W@VWa¥@k@lnUIÇKUaU@UUVmIUVUk¥Vma@¯k@Wanwm@@n@@m@UIVkUVamUXWaVU_@mUVUImW@aUIĉK@VmIb@lU@@nJkU@KIUmmLk@UVm@Um@@LkbUmJXlbV@xUb@@bkK@LWx@bUn@xmbÅW@nWLUKUbUVKU@LUK¯mU@VV@xULUVL@bU`WUz¯aUamKUa@@xkX@x\"],encodeOffsets:[[116832,34527]]}},{type:\"Feature\",id:\"4114\",properties:{name:\"商丘市\",cp:[115.741,34.2828],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@XVl@lLÈ@VkV@V»UanWX@VaÆÇô@ÈaVX@xVJXUÞUaVLĸbXKlV@m°Vn_nyXX»mUk¥lK@a_@yInaVKVa°_@WXI@@KVnIlbnaV@l@a@_w@lwUKmXa@UV@»Vw@kUKVUUm@w±VUXUKUwmJUU@km@@±mXkmUI@mmKUwkbWakLWaUIkJmX@l@@VUX@JWbX@VbULWblUVULknlV@bVJkmb¯KknWmk@@nmVkx@VmU¯KUnUL@JUIVmaÅaUm¯Xlkk@@lk@WI@yUUU@b@aUaUmVk@`nxUXlb@lLVxUbUbVbUllkVlÝVUnkVmKUXm@kl@nUx@xnxn@`VX@V²x@V@b@Wl@zU`VUVVbL@VbW@bkXllkLWV@V@VVÈwlV@@XK²LlbWnnÆL@VnJWn\"],encodeOffsets:[[118024,35680]]}},{type:\"Feature\",id:\"4112\",properties:{name:\"三门峡市\",cp:[110.8301,34.3158],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@WKUmUI°U@@UmU@KnK@IaU@makKUa@_KnmVUL@a@IXm@KWkkKVkUU@aUW@UUIVaymwkbU@xLVUWWkk@WUkJk_WWk@WIUKÝk@WKULka@mwĉ¥mXUK@@bm@kVWwkU@mUUlIWm@@Uk@@KkVmn@lwn@@Ul@XmUXUmVÑkmkVKUaVamaUXn@ykLUK@WwKmKnUm@UmaU@mUk@kL@lxċxUnkVmnXxWb@`kzWJ@VLmVUnlmUL@lW@Ub@VXUb`VLUbUJ@nmnUlUUm@@bUJlnUU@lxkb@@XJUn@kb¯VVVmlXXlJlzn@VlkVW@bkKbmkUbVblXVxKÈnwÞlĊKlVnKlwX@lL@xlUnVn@l@lmX@ÆÈb°¼ÈwVJlx_°xalUÈxlUnbVxnL@lllbmn@nb@@VL@V@@VLJnIVVlKnV_\"],encodeOffsets:[[114661,35911]]}},{type:\"Feature\",id:\"4107\",properties:{name:\"新乡市\",cp:[114.2029,35.3595],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@XVlLK°bUblbUbl@nX@WXVVKVk@@mb@UbnW`kLLV@VVLnKlVXIlV@@a@l£nWlkVa@°bnUlLVlnabnUVUXKlU@@lk@aI°y@ôkUU@wmônkWakmlUkVmkUlmUUm@nkUKWanamULXW@UVnUln`lblL°KXV@ĠJ@L°JUVwanK@UUImmkK@¯±Um@IVmUmmÅnWaUK¯aUkw@W±kVxUVwnÅJUIWaÝJóIbm`ÝbÅImJUI¯¥¯@mU¯UJmnUVóUkl±V@zXlbWVXL@bmmº@@XmJUXU°llk@nWJk@U@¦U`m¯Wx\"],encodeOffsets:[[116100,36349]]}},{type:\"Feature\",id:\"4104\",properties:{name:\"平顶山市\",cp:[112.9724,33.739],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@l¤UbVL@VLVb²VlKlaX@lb@lxUVULbln²VJUbW@@Lb@`nL@nVV@LVUbUVmkVllXbl@Xn°VK@_°`²IVVV@VUVJnInaWK@U@KLÆ@nmlXXWVUUw@klKVa@knyVkVanIJXUl@XbVUl@@aa@mXkbnK@UlK@UUUVaXaWmkUm¥nWmXaWakl@VmÞbKVL@aVI@mUwVm@KÅméULKVaUk@kUK@UWXI@VlKXU@VVnInVV@VLlK@UUkKU_@WWUwU@kln@@Imb@@mnUKÛ@mKUkWVXxmbVLXVVU²VV@xÅnmWmLU@kbmJ@b¯IUbJUUxVl@z@bU`W@Ub¯nUJUb@WLUKULkU@aWK@abmL@lmUk@@bULWJUI°@¯aWLk@mbUb¯b\"],encodeOffsets:[[114942,34527]]}},{type:\"Feature\",id:\"4101\",properties:{name:\"郑州市\",cp:[113.4668,34.6234],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@@nWVUKÅ@WnVnIV@kÆwV@nn@lxÞlnôJzXJl@nalUČVll@²UlkôVVUnmI°VnV°@°¦VJnIÆJÞan_VmU@ama@kU¥kaUklw@UIV¥kVUI@mmUÅmUlwVU@amUJWbUakVVé¯Im`k@wVWmLkU¯XkWmLmx@UUbm@@xJ@LbW@UUVWUkVK@kaIUamKUkkmmLUkJUVWXkWmnÅ@KL@@VXLmbmJUIUVU@ULWVkK@nWVXL@lVn@¤bkôKXKlL@¦²V@JL±@@VU@WV@X@`XXmb@blan@Jb@V\"],encodeOffsets:[[115617,35584]]}},{type:\"Feature\",id:\"4105\",properties:{name:\"安阳市\",cp:[114.5325,36.0022],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@°kVaV¥kVmUkWkWVkVKUwkkmKUU@awWWXWakKWkXmlaIVmX¥U@a@WnK@kVI¯@KğI@WU¯LkKak_kmmVU@VWXKnVmbXbVLmln@VVknlVUnVlklnXbmlmlXblnÈlWbn@@nK@VLbVV°VVzln@VxIbU@WLUa¯VUkWõ@¯kkmxk¼lXUlVbVLnlULmU@lLkVUlX@xW@¯mU@UmIUWL@aXakU¯anWk°@kkKmmUIWaambUkkKmV¯a@UblkmXk¤@@b@UbULWVnb@lUVVnmnVVUJ@bWXX@WJkL@blVU°UV@XlWnXUbW@UVkVVWbnLUJWLUK@Lnn@blVUnUblxVUVJXUa@UbLnUVV@mVIVVn@UbV@XbmbUV_lVXUWanJVI@WkI@WVIVU°WXXl@la@mX@lLXlkVbmXylIXJV@@kKla²UVaIVyÞb°LlVna@UÆKnLVbK@anwU\"],encodeOffsets:[[117676,36917]]}},{type:\"Feature\",id:\"4102\",properties:{name:\"开封市\",cp:[114.5764,34.6124],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@lUVbXaInV@bUVxknVVÆnn@VJlUU¦VJ@kxVllb¦lV@nb@bVUnaôJÞIXbVJÆImxUVwU²l@XxVl°bVLXb`XklUnmVblL@lmx°LVK@UXIVaWlL@Uk°KkVaVUXmmI@UÅKmmXka±KL@W@kUÇxUU@@UXUlKkklW@aXa@UKUaVUUV_@yXk@@a@U±w@UUW@_mmw@wVwmUaÇbUa¯UUkmWkn±JÅxmIbUxmKmnJWwkUaK@a¯@bk@mVUIWLmwm@Ua@WJUb@LUl@UUmLUbWJ@VL@VmXWWzUJUê\"],encodeOffsets:[[116641,35280]]}},{type:\"Feature\",id:\"4108\",properties:{name:\"焦作市\",cp:[112.8406,35.1508],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@V@VL@x@bXWV@XklUWX@J@nI@KlLKUVaV@JlL@KUk@KÞLl²_@nWlLUVV@nLWVUJVn@anV@awÞUVLVxb@lW@lbXnVn@@¼L°mKVn@bnl@nVK@blbLWU@VWLXV@nlKn@lVVbXw°nV_@¥Vl@XI@mlkkV¯VWnI@W@n¹n@aWKXUaWk@yk@kċUkVmbk@WIyóImÝkkwm@mU@xÅlU@mJXak@x¯V@¼¯VmUmmIkVWK@UXIl@UWVUU@mVUI¯b¯@lmKzWKUanJ@nlbÝ@@b\"],encodeOffsets:[[114728,35888]]}},{type:\"Feature\",id:\"4110\",properties:{name:\"许昌市\",cp:[113.6975,34.0466],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@lIVnKlnVlnLVbJlb@ULVlUXVVX@a@KI@wn@aVV@nwnKlXW°lVnKUXx@ln_°JVIXyXnW@UK@UXIVanKVV@Vk@KVaXI@Vbn@nxKnaUlnVa@Xa@VçUUla@aUK@wmULk`kIWVkLmK@V@XUln@JXV@nmbUóImUa±@@ÑóVUUk@UlKVU@akWVUUlUUaUK@UUKWbUkÅJ@XWa@XbmJ@nUJ@bUKLÝaUnk@lXbWbXnmn¦lVXnWbUbVV@VkL@VmLaWl@nb@bk@UVWak@WVImJUbUlmz@lUbkL@lVx\"],encodeOffsets:[[115797,35089]]}},{type:\"Feature\",id:\"4109\",properties:{name:\"濮阳市\",cp:[115.1917,35.799],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@lLXbWXXx@bVVnLllVxULUlXXlVlUnlU¦Ub¯lnK@VbVb@XbVLKVxVVnIlaba¥lU@wnalLnVVlVLXnlWVXn@@lVI@WnU@mÅW¥aW_k@WwXy@km@wUm¦lUxVLV@UwJ°x@VX@Vb@`VX@VX@llIVbnJlIbVlJ@mÑ¯Lóa@KUakX@UK@wU@lWUUÝ¯ImW¯aLUKU@k»k@mwa@UnKWI@UU@akVWKk@a±bóUWKXUmkKUmLbUx@lmLX@@bVW¦UnJkbWnXl\"],encodeOffsets:[[117642,36501]]}},{type:\"Feature\",id:\"4111\",properties:{name:\"漯河市\",cp:[113.8733,33.6951],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@@LUnVxnIWa@Xb@WÆIVlXaVL@VVLVbkVVUVlX@bUVkLVl@VVôU@Ò²@VbnôJVan@mWU@ImVk@WkI@wmak@wlW@w@VbnLVb°bVyXV_@aUKVVK@wUU@aK@kmbXVmJUX`knnK@aU@mwakb±@¯UUÝKUUU@WU@VkLUKU@mUmJUU@WVkL@UWJX@VVL@lVlUbLVKnêÆ\"],encodeOffsets:[[116348,34431]]}},{type:\"Feature\",id:\"4106\",properties:{name:\"鹤壁市\",cp:[114.3787,35.744],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@ón@xVVól@¯zJ@bkl@@kVWLUVmVXbVJnnlLl¯@Xlm°bVlWb@bKVXnJ@VV°nX@@wWVklUK@knVVKmkUKUaVkWkl»nwl°lö@lXV°UVbXKV@aJw@UmkUy¯UUUaK@UL@mm@XaÇkkmWank\"],encodeOffsets:[[117158,36338]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/hu_bei_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"4228\",properties:{name:\"恩施土家族苗族自治州\",cp:[109.5007,30.2563],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@VKbX@lbUVnL°@VlVnUl@VUX@aVmaXlaUUU@wmaVUn@Vnmmk@mU@knaaU¥VamX_@WUmW@_kVaVKnLl@VVal@k¥@kUW@kUKVUlUVÑW@kÇaU»ValmkUVUVak@aV¯_@WUkmVUlU@aalI@akkVWUaWXUWwWVbÆ@lalIVK@Um@UUW@al²a¯UağÇm@bkk@w@@WaULmxIUb¯@U`UXJmL¯aKXWUL@aknmK@aWUXaWm@I@UÅmVU@aUV@bVI@WkUbXkm@VakwUKULWKXmJ@XUK@mL@KUwVaUI@KU@mmnmXka@»V@@UUaw¯yVk@UUVmmkÛÈU@mWUnmxmlUbV¦UlbWVUL@UUIUmÇKVVbUVVxknLUxV`VX@kJVVUXWaUVVlUnmKUbkI@WULmK@L@LVlLnmUIWV@akn`VXUJIVlUVVbUX@¤mbnLmm@UXk@mm@Uka¥@kV@@KkU@aUKWbkLWVkIVk@UbVlmX@bU@@mmL@bn`@Ln@llVLVk@XVVU@`VXU¼k`VULka@VllVIn¤VU@@blÜbkx@bkLkKn@bn@@b@JUnV`UnVbVKlVXUlbn@°Vx@@bnVbUllVn@VVK@UnW@UVUlnkVÈÞxVbVVIxVaÆ@@aka@UVaU@@ak@Wl@nbVIÆ@Jk@L@VlXnlla@VJnw@UmwXU@aVK°ÒnllnLlbxnKVaV@l¦²nVl@llLx@XVVĶ@nax@U@alXUVaLÈþV°XxWXkK@mLnlUb@bxnLVlVVkb@UJ@xWXX\"],encodeOffsets:[[112816,32052]]}},{type:\"Feature\",id:\"4203\",properties:{name:\"十堰市\",cp:[110.5115,32.3877],childNum:9},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@@a@w@kV@nbVK@nUla@laÅl@nlVakwWX@WkLaVmwV@anK@UlIXmWkk@@mmLkWlwk@U_mKXwWK@U¯K@UU@VUakmkIyUUVUmanU@mlwk@_mWXaUWU@Ç@U@aUaVwUKUIVkK@UWIXmaV@k@Vm@UnwlUamk@V@ULUamxUJkU@I`WkkK¯XWak@@W@IUVLWJkXkaÇVUK@kUmbmUUUKbkKWUkI@kKÝ@@aUm»nI@mU@UnWV_@aUmWbkLUl¯b@akkk@WkkJm_k@UV±@J@bnU@@WÝIUJVbXL@nlJkx@Wn@VkJmbLmU`VbUL@xVn@XV@mVVnnJVbUx@VnVUbVVx@nbUK@b@bJm²VUlbXzVJVJVbn@@Xmb@V@bVJÈ@Vnkn@°aVVV@XKnalLVmUnnVKVlnLWlXXKlk°XWkLUVVV@nU@ml¯nmbk@W`Å@mbLWm¯UxnêVèk@mbVnUK@kKmXk@@JUIlÛLllnbVnlJ@LULnlÆaVLnV@nkVJ@lkô@²bÆm°wLWV@VXKVXI@W°ÆVKb°UJVIVV¦XKVL@lInaVÝnUl@@bX@nmVL@lVLlVLVUnbVW@xXnbU°¤V@a@kWKUUn@VlnL@UV@Ü»@mX@V_akaÞ@VK¯@kkW\"],[\"@@mUkUUm@nllVKXXVK\"]],encodeOffsets:[[[113918,33739]],[[113817,32811]]]}},{type:\"Feature\",id:\"4205\",properties:{name:\"宜昌市\",cp:[111.1707,30.7617],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@°`U@blUbUVlVknUbV¼Èb@lXUÒkVUVVL@lVX@ll¦k@UbU@kmKULUbl@`nXV@XW`nUbV¦bmb@lV@nnlmnUm@UVnb@xVVVkbWnbVnVa@an@UaVUJXnWlXX@l¦@lKÆXbXV@VV@°¯°xXxXV@nV°UVWU_VWXkmaVnWVkn@lln@lb@UVLXWlnX@aXUmaVK@UXUU@WVIWXXVU@¥VK@UÞa²LlV@kV@UanKma@UVUnK@UVLXyVLknJ@UV@@UXKWUXaV@Vb@mVLnKWm@aUUm@@UkK@UlaLXKWaXI@alKlmUk@wVKXL@m@WWn@UVa@K@wna@aW_XWWkXbVW@k@U¯WWwka@UUaVIVkU@m±@U@@wVKka_@VV@XUVwU¥yUkm@V±ÈUKk»ÇLmmLk@ó£kmWwm@UIkWKXwWU@kLwkbmabkK@VLkmWIUKkUUÇIǫJXÅJULVÇLUV@UK@kI@WVI@UaWmXVVUL`±kÅLmKkkÅ@UaXXxWVXVbUXll@bkJb@bkVUVlnV@X\"],encodeOffsets:[[112906,30961]]}},{type:\"Feature\",id:\"4206\",properties:{name:\"襄樊市\",cp:[111.9397,31.9263],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@@Xl@Xb°WlLXl_@JlVVInwVbVK@@UnlVbkmx@VUnl@U@nbWXJ@VlLUVJVLUxVb@b@VÈ@XVVWbnX@`lkx@nmVnbUVVVzlJnlVbUV@@V°L@VXLWxnLV`l@kxlXnK@nl@XlWn`Xnl@@UVa@VÈK£VLVanW°U@UVU@`VInmV@nV@Xa@aVW@UalkXKblIyÆXnlJXbl@@VV@nklU@`nVKLVKVb@VU@UÈKUVKIlUX@V`lIVbn@nblVVmV@@XXJUVV@knKVn@`@XVnKwlLVmUUU@U@aXL@WlU@UUW@UmU@KkLWaXkWmXUWm@U@nk@UmK@U@UaUVUUKV_@al@namWUI@KUK@aV@WUIb¥ULUJkImK@U@KV@U@a@UkU@K@wVaUwlU@mUULmKUkV@@anIWmUK@I¯mKkl@LUb±lUakLmk@WwUKÝVUIm`¯n@Uk@makJU_@Jma¯ImwUVkKbaUÅ@wWaU@VU@mXIVmmUkJkwm@mIlUKWzUK@VmLUV@VnbmLVbU@@lkU±KbÝV@UL@¦VWUWXUJ@XVWV@VULnbWVbW@kmWXUK@Vkam@kkm@UlmXUnbWlUXV`UX¯VmUU@Ul@Lll@nnJ@LnWmbm@b`\",\"@@kUUm@nllVKXXVKmU\"],encodeOffsets:[[113423,32597],[113794,32800]]}},{type:\"Feature\",id:\"4211\",properties:{name:\"黄冈市\",cp:[115.2686,30.6628],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@VVUnWVXnVJ@U@V@VXV@@IVJUn@V@L@KlIVlVanLVbnVlIn@@a@Kl@@IJlI@aXU@KlKkVblJXUVlU@VbVkVKXn@VlxVa²I@VlVUxln@bJXklaVWnLmÅ@y@k@aI@W@aXIlVVaV@nnlKnLVW@IUa@a@KUVVlI@wXKVV@IUla@lUXwWnnalLlxXLll°@XwVKVaXIlnb@nln@Va@U@k°UmÆUVaXIJV¯ÇUmmkU@WaKmakVm@U@aVKkkmKkVmIkÇ°£@aUUVaVVnKlkXmk@lUVaX@@Um@UmlUXVUVU@wK²¥Ua@I@UVl@UV±UIUÇ°»VkUmVI@a@Umĉ¯V±bŹĖğaÇL¯lmkX@óĀ@mÝêb±WkLn@xXx@@b@V@LW@UblţX`kxWnXô¯¦ÆV@L@JVLxkK@V@bkz°llXz@JUlVla@XUVbVKXnW`XXV@laVV@VX@V¯xx@xULVbUJ@n@LU@VmmakbUK@bIWWUUVkUmkLm@VJkb@nUJ@`V@kXaUaVmmLkUmJ@Uk@U±lkzmJUb@bVUxVXU¤L@JX@VlL@JkLUVU@mnUl¦@V\"],encodeOffsets:[[117181,32063]]}},{type:\"Feature\",id:\"4210\",properties:{name:\"荆州市\",cp:[113.291,30.0092],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ÈJVlVVLXJlnK@UlLanblaxlK@XVWxXLlJ@VnXxlnô¤l@nKnÈKl¼VL²ÇUn@VlzV¦UxWVU@@U`lbUL@xV@²@@nlVUUJVb@VlbXx°XVWX_VKUwVKVa@UVKUUVk@KnblaUU@wnWl@UX@lÆ@@aIVmUkxVJUbÜ@Uk@WWnk@VVm@I@m@Un@mXUlVlUnJ@knJVU°@@aÆLX@llL@¦nJV@XblLVa²U@UlW@VX@`@LV@@bXJlIXml_lJU°bKÆLnVVl@öVmXaVIĢllUlVnLVlX@@bannxVLbn@°ÆXmmkĉ¯w±Uċ@KÝÅƧŃÝçUw¯m¯k@WkV@¯UIUJW¼kbUwk@W`@¦Uônb@VÆlÈ@VU@£UWWnUÆUnmJkUÇ£VWUI@aUU@WkI@Ua@JW@k£kaWVUKmnkKbkkVWbVmUUmwU@kk@UakUUa@V@nlx@lUb±lUbnnWLUyk@UamUK@mlk@Wb@VXL@x@xWI@a¯¯V@bVn@LkKmL@`XmKmVU@@bkL@V±bk@UaaLKUVIWXamVVbUK@b@Lm@UWkxULWVUnm@UlUX\"],encodeOffsets:[[113918,30764]]}},{type:\"Feature\",id:\"4208\",properties:{name:\"荆门市\",cp:[112.6758,30.9979],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@n@lxlInVUnWJ@nUVV@Xb@xVÆbalLVUnx°JnbI@V`lInbl@@V°mn_VJÞUVLXx@nllKVb²kVa@KlknL°@JVLXnmJ@bU@VlnLVKV@nX@lUKVaXal@VKn@¥°L@UnwbnaV@KV@VUX@lVXI@KW@@IXWV@laVLKlaXUVVnkVWV@lwXblIXWVkVmaU£VaUmVIkU@y@WakKUamU@UUK@kmK@w@@mK@LV¯U@WwkmULamVVUU@IbUKUakmm@UakLmxU@UÒWlULţÿmwkIUm@akÈblW@UVUUk@JW@XkWWUkUKUIlw@aUWknWUUmnIWaUwVaÛaVUIwVlUnJ@bÅ@@kVWk@mX@xVVkbma@LUlVVUL@VUbULVxULW`UX@V@lUXWaXlWXX`@bmb@x@LUb@VmXX@@nWKUL@xVlknkL@bWJXbWLKkb@VlL@Vn@VV@bnXmLUK@nUaU@WbXVWL@VU@@V\"],encodeOffsets:[[114548,31984]]}},{type:\"Feature\",id:\"4212\",properties:{name:\"咸宁市\",cp:[114.2578,29.6631],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ÞÆLČ@V²°xĊnlWnÅ¯m@aK@°nJwnVIUaÆJÅ@wwVXW@aV_l@²V°lĊwlaXLwlUkalVVaX@lVXI@aUXJ@U°UU¥VIVKVklanLVa@VÈIVV@nk@aVa@mV_@aK@klKUa@UnKWk@@lU@@UW@@nUWUwmaVIXlV@mLXblJ@kV@kk@KU@WkUWVÅwkLmW@UmL@lULKULak@maUUÝwUJIbKUU@aWK@kUWVkUwVw@mÝ@I@wkW@aww@LU¥kJ@nVJIkVVnkVUkyUIUl@xWUkaW@@°kzWxkLUWmzk@@bVVVb@@XlV@Vl@bVbUn`Wn@WbVVI@`LVbXLV`mnU@@lL@LUak@Lk@WbUJn¦@lVb@xVb@n\"],encodeOffsets:[[116303,30567]]}},{type:\"Feature\",id:\"4213\",properties:{name:\"随州市\",cp:[113.4338,31.8768],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@@n`lwkUmUVWX@lk@VanUĠ¼V@@mX@@nVVVXLmJVLnK@bV@@J@VUn@VaVUUUVWVLV@@Kk_@almaVkUU@WVVUVLXmmk@wUaUKUV@°@kmaUaÈmWmUVklaX@lVnxl@@UnaUk@VUVwVKn@VVn@VbVJUknUmmVmk_VwKUUmVak¥@UVKVIkW@UmIVWkIVkmmLkwmVU@LUU@VVXL@JmLUbmK@UUKmkKUUmVUaUnÇlk¯mJUnmLUaUJUaWL@UkJU@aklkU@¯@KWLUmUUWVkbLUKkbU@WX@JX@@LWJkUW@UVU@@LUmbamx@V¯K@¦mULk@WbUbLkVW@kVVxUb@x@LlV@V@b@VU@L@VLnlJVIVK¦aVJ@XU@bLV@LVJnXmbk@@bU`VLUVVb@V@VnL@Vml@@VXnWVXnWlXblK@LnV@VVX@VkV@XWK@bVV@VV\"],encodeOffsets:[[115830,33154]]}},{type:\"Feature\",id:\"4209\",properties:{name:\"孝感市\",cp:[113.9502,31.1188],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@VnXK@L@°lVlkb@VlI@VXKVbVIVbnKVmnI°lÈkVmVbnUVVlLnVL@VnLVanK@IWKUUV@V@KVnUlxnKlnUlJUXnJ@VlXUJUL@Vl¦UbnVVLUxl`UnnnmVVlnVKbmVX@a°Ý°LaXJV@VUnKVXVK@LnKlLUbVVX@VwVJVn@@UU¥V@@UUK@maUVUkkJ@L@K@UmVUI@JU@W@U@UV@UIWmXUVmUUÇ@UVmIlmnmakK@akaW@UwVUkKVnUlKVwkVU_WKUkVW@UXaWkUa@w@VU@XaW±@IkbKb¯L@WXkW@UakL@UV@UmVUmL@UXWVL@aUVUUUVU@yUUIUa@wUKWVU@kWk¯UkwVKLUxK@nVxUlUUWVUmw@wUUyXWlX¦WbUV@U@blbUVVbXXl@lVL@bk@lxkVVnVx¦`UnkL@V@L@@@xnL@lVL@VnVVblLXb@@zlVUJVnUbV¤bUnUlWXkJWakxU@UXml\"],encodeOffsets:[[116033,32091]]}},{type:\"Feature\",id:\"4201\",properties:{name:\"武汉市\",cp:[114.3896,30.6628],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nbnmknJVUÈ@@U¥VknmV@VUlK@IkK@UW@IKV£UWVwU@aVanIly²kVl@@VnIlVnKUnVbblWU@@_VI@mlaUIn@lKVnUlVVXXJ@aVLlanbUnV@@K@mVIUaVK@ww°w@UW@UUUkbU@WWX_WmULaVU@WkbkUV@IWyk¯kly@a@UlLwUK@I@KÅUW@Å±Um@wl¥ka@@_Vw@ķa@akw@kKW£XVUVwVwUaU@VUUxWKkbĉx¯k±Uk@U`@bWXUx@xÆÅIVbUJmxIm¯@UmxnUVVbnJV@L@@kV@bVn@UVULlx°VXllV@XUVL@xVbJVV@zUVVVUVV@bUKWX@VnKUVVnU@@VlKVb@lXW@X°KaLla@JX²Wb@UV@@xVbXlWb@VUXVlXLV`UlUxkLmVUlLUVVxX@lb@blL\"],encodeOffsets:[[117e3,32097]]}},{type:\"Feature\",id:\"4202\",properties:{name:\"黄石市\",cp:[115.0159,29.9213],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@VUVV@VbUxaWUblUVmnKlX@bXJVIlVUxVVVIUzlx¯@VbnL@xx@UVaXKb@XkWU_Vm²klWXVKl@nXV@@wmlK²XaÞén@ôÿ@lWn°kUKmmUÑUmm@wkImWU@UakL@bVLUVċ@bUK@alIXKWK@nXnKmkUVw@¯b@LlUL±Wn@KULUaW@kL@lL@bU`@nUb@bmlU@UÇJ@UUbmKkblUULUJV¦¯V@VWIV@bWJkUW@UbkUlbkV\"],encodeOffsets:[[117282,30685]]}},{type:\"Feature\",id:\"429021\",properties:{name:\"神农架林区\",cp:[110.4565,31.5802],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@n`lIXll@ll@b°aVklKXaVn@bU`mX@VV@nmJn¼V@bÞ@lL@lJXVlLaVLVnVnalV@VLÈUlblWXIKVU@J_@annaXm@KmI@mkk@KVkWWw¯w¯°@UUU@WaÅWkL@¥@kWWXkWmIUVVbm@@bUbmUUbW@UVk@mVkU@U¯mKVUkaW@aULÆVbb@VÅ@Un@VLWl¯L\"],encodeOffsets:[[112624,32266]]}},{type:\"Feature\",id:\"429006\",properties:{name:\"天门市\",cp:[113.0273,30.6409],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@K@UlKVm_¥UwUmlUkwl@@aUK@kkWWUaVUka@aV@VUXaW¥Xk@WWIklm@ÅxmIVÝUkxka@bWJaUL@W@l¯UULUbkVUa¯bm¤UnÇUkmUUxb@VkXÇal@bVnlJnxŤĀVKXkVÑV@nwlKVbn@nlVbVLaJ@VVUnUbVKlnXxV@°U@KnL\"],encodeOffsets:[[116056,31636]]}},{type:\"Feature\",id:\"429004\",properties:{name:\"仙桃市\",cp:[113.3789,30.3003],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VK°VkX@@VKbXI@alblwÞVUnJÆwn@lkXJ@XWVzV@xnxVXUVVVkUw@mLVwKVU@Um@alU@@@KUmIUaVUmnwmwmb@aW@UkmKkUkVġkUJWbnUõ@UkmUÅKL¯aVkIk`WnkJ@xVLUVVbUbk@WlXbmVxnxUblbUV@@VUV@nVL\"],encodeOffsets:[[115662,31259]]}},{type:\"Feature\",id:\"429005\",properties:{name:\"潜江市\",cp:[112.7637,30.3607],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@UbVxbXmJVnXVlmVX@bkxVJVLVlXXWlX@@IVlVUaVwVlnÈVVmn£°aVbUlaVUK@mVU@U@VUkaVamwUwnWaXkl@VaUaVUUK@wWI@aU@@K@_UW@kX@V±VUbkKWaU@mI@¥kKkW@ÅK@b¯@UVmI@lmIkVkUWVnm@@V@n@JUnU@mlXXl@@V\"],encodeOffsets:[[115234,31118]]}},{type:\"Feature\",id:\"4207\",properties:{name:\"鄂州市\",cp:[114.7302,30.4102],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@°¥WóXmlw_ŤWkVaX@@K@U@a@WwU@mWk@ULWkX±lUnV`XWl@aWLUb@Vw@wmKUa@°kwyVUJUUVwkUUJWI@akWmLUnkVaXVbUxUVWX¤lL@lx@bb@ĸUx@`@lbk¦@xn²VÆX@\"],encodeOffsets:[[117541,31349]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/hu_nan_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"4312\",properties:{name:\"怀化市\",cp:[109.9512,27.4438],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@@n@b@XnJ@k°x@aVUnlUXnV@@VnJWUJVnIVV°UbVVVL@²LUVa°V@aV@nmUXblLXWVXVmVLVK@an_`@X@l°VlXXW`nX@Jmn@b@nV@Lm`bUbn@VUVl@nIVbUlV@LkJUnVV@xVblVUbU@zUKU@mx@xUnn@@WV@lbUb@nVWXXV@VIV@VUnJ@VUz@JWbXllI@VXVVL@Vn@Wlb@lXVlLaV@VJ@XX`kVwVl@bkbUlVXIlnLVamVwV@@nV@XaVJVbX@lwV@n@nV@VWnIVVUÆ@Xxa@IUUKmk@mVIXmWUVJnUVU@anaVwkU@UXa@W@m_@a¯@@K@UVbnK@blIlbXa@WW_n@VU@¯bmyUkUJÇÅ@WU@kWKÅwnm°KVkmankVWnXVWV@UwXkV@mUlLnaVaX@VUn@VnVK@xlnXWU@a@@klakVwmUaV@wmIÛ`m@mVUXmlIXVI@K@aU@UaV_UK@wkUmmUKWXmVkUL@mU_nK@aVU@Ukak»@U@ymU¯UUVKkam@nka@mwkLWb¯mka_VaVKUIUw@kKmU@WK@UnmaULkU@wUalWV¹U@@WUI@WU@_@W@U@mU@WbbUK@Um@@UmbUwWWkk@WUa@anUUwlWUwUU@wlJVUnnV@@mnI@mK@U@wa@wUm@_mVUUaVUk_kċUkVWL@mlU@kn¥W@UwUWV@VÝU@lXLWVUbVLXlVIlknmU@VUJk@@@kVmwmVkxU@@XmVUb@xnKVLl@VxUxkIU`@bWVXX@JWL@bkb¤@bmUUU¯Kkmb@VVUVVn@@Vb@`lnxmblUnbk@xUmV@bmWbUV@VJIl@nVUbK@nn@VbnJVIlJVkXJ@X@lmx@bnnWVXJWXU@UlU@mk@@llb°xIUbnJ@VWbXVmI@JVX@bk@bWL@JUXUK@U@U`n@@Xm@XVW@@nX@@`ImxU@@JUI@KLmK@UÅUUV@VW@¯kUU@UamVUUmJ@nxmLKkmJkwkKm_mKXU@aU@b@Wk@ma@zUJVUmbUlU@xnXlWlXXblK¤V@@nUVVLkVl@Xb@VVKnXKVx@znW@X@@lVK@X@JXbWbnn@JUamLVVXIVxnK@aWUX@x@VnI@WlI@anVIVxkl@lbXXxVVVJVInbV@@ln¦ml@XXVWbkJWb\",\"@@XLVKVXVKUa@UUUmV@l\"],encodeOffsets:[[112050,28384],[112174,27394]]}},{type:\"Feature\",id:\"4311\",properties:{name:\"永州市\",cp:[111.709,25.752],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@lxUXVlXUVnlVĢJVbUXVJV@XUW¯VIUK@klW@Un@nl@V`XUVL@l@Vx@XXW`UnUbxUlVnUVlb@VnJUVVVInJlUVnwVklKnwLVJVV@nIV@nbVa@KVVVUUaKV_nVVJ@_VWnV@n¥lI@anl¥X_VKlwVlULUVVV@U@VXL@IUmn@VU@wmKXUWU@m²l@VIXWWkWUkWlkIVamUXamUnmWUU@@UnlK@XJl@kVUk@mWKXkl@@aVU@UVWUUVaIn`VUVLnw@U@K@U@w@UVmUU°K@UnV@bV@Xk@KVm@amkaU£VWUUmUUwm`UbULkaKXU@kVmU@aV_UWVIn@yXXK@klmVV_kWVUn@WUU@UmaU@wnwWanUmmXkam@UakLmK@bxUUUU@Km¥Va¯@kUaVUlmUU@mUUÇmUkUybbUaXUWWbÅLmL@VaL@WWXUKmmk@a@UUKXW¥kU@VUkxmVkUWbUJnVJ@nVJXzWxk@lVbUX@VVL@`mbUnUnVV¼k@Ulm@mwLb@lmLUK@UamWkK@£Ua@UkJkUmbVlkX@bWbUVnnUVl@bbVK@VX@lbV@nU¤x²Knblb@xVô@l@b@l@XWxnVl@VV@XLVlLUUXV`bXXmJU@@bm@UUkLW@UlUKWUUbwUmL@nklVVmVXXm@@bUKlÆnXkllVUVVL@nUbV@V@nnV@xUn¯U@JW@UX@xĉ@`m@@LV@b\"],encodeOffsets:[[113671,26989]]}},{type:\"Feature\",id:\"4305\",properties:{name:\"邵阳市\",cp:[110.9619,26.8121],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@XIlJIVVK@n@VVVKnLVwVmnLVK@U@wJ@wVIÆ°X@ÜÈUÈxll@kn@VwVaXJWXn@@WVL@UUKVKV_U@@aVKx@UaV@lk@XylbUaV_Vnal@WU@aI@aV@@aVUl@XmUXWaXml@@kk@ma@V_UnUVUUWJUa@kkaWLUmk@@LUVWUkJWkK@¼UnWJIkV@b@JUIm@UlVm@Uw@a@kWXWKUknW@WUU@kmxUkVmIUJUUVmI@UkaUVUmVkwVaVmX_WW@Uw@@kUKWVU_k@mm@@VkX@lVLUJX°WVU@UIVWUaIUġmkVUkWUVWkwWXk`mI@¥kUVUUn±@mXkWknVUVmmU@@XVUk`@Xk@¥¯»mbĉó@mkU@kUKmX@UnmL@lULkKUWUU@bUaUn@Vb@l¦Ub@l@UKmnKUnlUVVbUVn@`Vn@xb@x@VL@nmJ@nU@mmUVkI@xVVVxkXVxmV@bbXVl@XlXVxna@Vn@@VVLaXaV@n@@V@X`V@@XVJ@XV@UºkXVb@xlVVKnbm@VXLV@nlL@VxJVULUb`lb°nXalKnx@lbmn@lbULVV°nV@z@Vl¼lb@VUV@bmLV`@nKlVnUXWVLnnlV@xVLU`VbV@\"],encodeOffsets:[[113535,28322]]}},{type:\"Feature\",id:\"4310\",properties:{name:\"郴州市\",cp:[113.2361,25.8673],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@²zVaVlnVl@nVkJl_XJlIVmnL@mV@VXn@lV@XzV@lyV¯²U@UlJ@XVKnVVIXl@UVLV`@n@JI@mlIKVLnUlVUVVLXaKVLl@nb@WXV°KUnVVL@xVJL@b@LUVVVUVXbmbVbn@@lUbm@x@XVVV@@@bkImx@Vm@Xbb@l°XU¤aLmnL@bl@@VUX@VxnVanLnW¥XKVwnUWXmVIUWÆLVxLw@wVmlU@¥XWUkwlÇn_UwWV@VU°wnUy@aVkVlnL@lVnw@VlJ@bXx@bVKnb@U@WVUl@@Vnbl@XLlK@aVLVKnxÞn@aLlmUaVUm@ÅknUmaUKmVk@mkk@UlWUkVm@w@kUU@WU¯¥@wÇ@aVIlUV@kUWU@UUm»@k@mKVkUKUwaUaUa@kkUWJkImaU@UK@maUzk`@zy@XmJkL@UUJmUkV@z@kkVmK@¦UbWL@a@UbmKmwUKXkVUUkmVkw@UUKmL@WUIWaJW_k@@WmI@mk@WkWULUUVKUUVm@Ub@nUÇ@U@wV@Ua@aL@akl@kUJwó@@L@V@`@J@xnnmV@bkJmUó@nJWUUmU@UV@LkWlnnmVXbmxxV@nbVV@XVm@UVlXU`Ukn@lWLWzm@UJVXU`@bVUn@lWVLlbVKVan_VxnVVVUXV¤bnl@bUn@LWlU@@amU@V¯LVVUn@V@x@V@L@VmxUKUVm_JUbVV\"],encodeOffsets:[[114930,26747]]}},{type:\"Feature\",id:\"4307\",properties:{name:\"常德市\",cp:[111.4014,29.2676],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@lUmkUwUyV@VW@¯VaVmUU@KVUVUVLnaWnkUÓV_@mVU@Ýw@ka@kVmUmK@IkaUamKkXWaUW@WUk@@KVU@aU@L@J@XÇVUKVak_mWkLWakVUbmLUUmlUVKUU@kUWW@UImJ@xkLkKm@@X@óÝ@UUk@UKVULKXkWWbkaIUWU@mUk@WLaUJġ@@XÈÆVIlVnz°aV@Um@X`@XWbkakJ@amLaU@V@L°@@bn`@@XWb@VVlUxmb@bUVmVUIXVWnJU@nnlVLV@JbWzk`m@UVK²VxkLVl@Vn@V°xVKVkVVlUblx@bUÆ@@nVnUllkx@VW@@VkLWxUL@bÝ@kKkVõV@bkXVVUV@VkUkVLkVa@@¯xUxmX@JVb°WXkK@Vm@kVbbn¤xUXkJblxnXÆK²l_@Wnan@UL@bJnIlV@lU@@¯ô@lWȂIVKVmU@aXaV@lwVXn@@K@UVKUUnUbn@lWXlJnULKV@l@²a@UlK@aV@naVXWV_nKlL@KUm@a°U°@VXL@a@wWmXal@k@VLnV@@bl@VnX@mwVa²aVU@mk@\"],encodeOffsets:[[114976,30201]]}},{type:\"Feature\",id:\"4331\",properties:{name:\"湘西土家族苗族自治州\",cp:[109.7864,28.6743],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@@KL@wnK±nnm@WUkÜÈn@n»@mVamkmUl@VnmmU@wUan¯VKLnVWlInyWUI@WWk@KXUn@mnUmU@WmkV@kXaaVaUmIk@kaX@Um@UKWU@UkJWkXa@IVy@UmIUVU@UJU@WXWmU@VakaU@@Xm@Vm@wnwV@VLyV@VakUUa@wUUVmlI@KUVkUamJk@VU@UmVaan_@KmU@@anm@ImWX_WWUk¯@k@W_m`@bULUKUnUWWXkKWaVmnU@@b¯UUbV±K@UKUUVa¯UUmJUVIXmI@UU@WmVmkUV@b¯w@lmI@W@a@m¯LXbmJVLklWL@V@XXmbVVU@@VU²Ul@VlX@b`XxzUmkUVÒl@bXLWxXVl@VbkLma@nmVmULVbmVUb@lnzmbUÒVl@°nLVlJkn@bmJk_VmmkblxÈx@LUbxVb@Vn@JmLVU@nV@¦VbnJ@lVVbkxbm@UxVLV@n`UnVVVkl°zxVb@VU@@ÆlXnWm¦nbVK@XVVUVVl@XKUV@nVL@WnIWXLVKVLlxUbVKXVWbn@@UnKVLVbJU@aVU°b\"],encodeOffsets:[[112354,30325]]}},{type:\"Feature\",id:\"4304\",properties:{name:\"衡阳市\",cp:[112.4121,26.7902],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@lV@XV@mXVlXLWX@l@bVxn@UVkn@VJ@I@alUJXIVm@»LXllIXVVU@Kl@VnXKlb@lVbXIVVUmVVU`@nbl@@lXLVVVKVbnXWJ@VXbWxXbUlVK¦nLVVUVVbbK@ULnK@Un@VxlUV`UnnL@VVL@JV@VUnxnKVbV@@VIVUnJUVUl@nWXllIUaKVbÞLV¼²`V@VIUwlaVmXa@IWanK@U@mkVVUVaX@lnaVLÈ@¥@kkJUWJUaXkaUmwVXJ@_lWUU@¥n_KkamUK@amKnKbV£¯W@kaWan@@UnwlJ@a@@UUU@Wwn@Va@km@UanaWaUVUUVU@K@aKUI@wKUUVm¯LWUX@mak@UKLWbUKVUkUmVUKLkJ@nJ@I@mU_UK@VWkUJmUUL@WkI@V±VU°kzU@Wy@kUm@UWU@@nmKUnkJWIk`IUlmk@mUUkUb±yUX@VUV@bk@WlXL@nVlUlk@WI@kLm@VV@XVmnnVWbnVUblJXkVlXXlWXUJk@±@nXVWVnL@xUVm@Vn@JWK@UV@UUVUVKUkkxULW`k¦m@bkJm¦U@mUX@`UImUU`LVbUVUU@LUbmaU@mJU@UUIKmxkLUl\"],encodeOffsets:[[114222,27484]]}},{type:\"Feature\",id:\"4306\",properties:{name:\"岳阳市\",cp:[113.2361,29.1357],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@@wUklmUUmU@@UVm@wUaV_mmUKmwkIkJmUUnm@@UUbUKUmÛamm¯xVLkbÇÆUVUzkVUlUUKWLX¦W@VUUUaKUbmLKm@akU@amVaUUVIVWkk@wk@@xmLlmÅwmbVlXlÝIWVkK@kkVL@VWKU@Ublnam@b@bnW`@XUJk@UUWKk@UKnn@xmLUVm@kbVbVnV@Vb@KnVLWXÆVĢ¦VblnUJWz@ÆVóUVbkVaÅx@¦lVUbVVknWKk@wKVUÅl@zkb@`m_mJ@xXmbVb@llV@n@llbXLUXalUlalVnwnLVKlVbX@@IV@blJ@bVL@VVVUXÈ¤VnkVÑXmlbnVKkÑÅ@UmaVç@±XUlIxlV@VaX¯lUVVUVJnV@°°n°Vxĸł°¦b²¦lJ@U@aUK@kUm@_m±VIXal@Kl@bV@KK@km@UmUUaK@_UJaXU@Xm_VmUk@WUk@kU@a@m@UaUUU@al@nyXXWWwkly@¯n@@bnV@k@mVIVlUUmlUJUwIbXVaUal@Kb@VKVkXVl@VkUU@ylUVVaVL\"],encodeOffsets:[[116888,29526]]}},{type:\"Feature\",id:\"4309\",properties:{name:\"益阳市\",cp:[111.731,28.3832],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@ÆxXL@lV@ĢVIbXKl@nVV@XVJlbXalXWLVKUVLl@VV@ôÞ@@Wn@lLlK@wnIVJX@VX@lVVULVnkVVnKValUXblKnXl`UbVLÈU@W@IKV@@bUV@L@lXV@VXXblWnLVblb@JnLVUn@llb@x@ÞUV@nU`VÔmlXmbUKUVUV@LVVUnUb@°UX@UVzVxnlVkVnlVnaW@wnIn`@_la@ykÆVULxl@XLlmUUVakU@¥ÆwblUUaôVU@ÅXyVImkUaġ¥ÅUWXKmU@La@UmUUUalan@VUnK@wmmL@VlXLVVl@VI@WX_m@a¯mKUkwW¥UK@_UWWLUVkUWL@WUIkVU@JwkLUUmJVI@WkXm@VmkKUIU@mmm_@VUV@kJċwUU@KUWkkW@IWW@km@klwkWVkkUV¯m@kWLU`mIkmkXm@@`@L@xUKWkU@VL@JUU@mbUKVa¯WVnL@`lXUVkU@xW@UbUWVU@UJ@lnU@mnÈmVa@bULwUb@@VkxmUUUVK@IUmk@akm@wmIkK@bVWXkm@wULUmm@UVW@UbmbkKVnU@WlxVU@UXmWUXmlnbUl¯Lmn\"],encodeOffsets:[[113378,28981]]}},{type:\"Feature\",id:\"4301\",properties:{name:\"长沙市\",cp:[113.0823,28.2568],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lVUllXkx@lln@XX@JlXXlV@LVVČxlI@VU@Un`nnV@VJlLUnn@lW@XUJnIVVlKx@IVlUVJ@XXKlVVUXKVX@`VLX¦lxVnL°an@bkmVaV@XL@UKlU@llLXUÞJWkUknaÆxnknK@w@l@xllUXUJVVUbn@blV@bnLnKVaLVbVVUX@W¥XKVLVVklUVyUVÈÅlaUK°wnnÜbnVVLaVV@n@VmnVlIlJna@Valkn@na@amwm@UXwK@aUUVUUaVawWK@kU@UaW@kKUU@kW¯XWan@kmmÅ@@I@U@KmLkaVUKkLWVUk@UVmU@am@kkk¥UVUKmaUb@UbI@aKkkWm@W¯K¯b@VmaULVxUXlVk@UxVJVbUb@xUL@ULWWLĕmxVVL@VbKUwaÅ²WwX@@WUWLU@VbkV@aU@@VUnmJ@VUn@VLUK@UmUIk@UÇmU@@UW@J@LbUmVI@aUmW@@bkXUx@lmLUbm@UbkJ@V@XmlUbkKm@ma@kUaVU@aUK@mImJUIkVUVUakbWwka@UWKkLUamKUXm`Å_UULmaU@@lUV@X\"],encodeOffsets:[[114582,28694]]}},{type:\"Feature\",id:\"4302\",properties:{name:\"株洲市\",cp:[113.5327,27.0319],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@XUnwĖKXXVK@VK@wVaUaUIVwl@kUVWUwVKnb@U°a°LX@XnllL@bJVa@VanbVLUV@al@@UV¯ÅÇ@Ummkw@¯yVwnUVVVUkmWVnKVUa@WXkVKn@lUVUVVVXIlV°VnI@VlKnV@mwVm@LXKWkU¥wWw@k@mX@KX¯V@VUVa@VnKWkV@VUkm@aWa@wkUWwkmV£VÿXUVL@mVIXaò@nW@aU@@am@aUUUmXmWUk@nUW@_maVmwUkamaUL@awW@akI@UxUm@kmKUklU@bzVm¯xUVU@XVxm`kÈlxXVW@¦kVUn@xxKUwÅKVXUJWnXmVUxWL¦XmmKbmUUwW@UV@k@VLnlbLm`@¦VVkX@`WIUxVnlbWVbXIVlI@l¦Ç@UKmbkW@UbUVUl@n@VmLXb@JWbUnkbVxUJUxWXXlWL@V@V@XXJWxzUVVVVKnXW`@bkIUlnLVJUbUIWVXlWV@XklVbnn@xl\"],encodeOffsets:[[115774,28587]]}},{type:\"Feature\",id:\"4308\",properties:{name:\"张家界市\",cp:[110.5115,29.328],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@@InWVw°w@@blUKlUlVU@VUUUlW@aöUlUlLÞ@@aVKXwlK@UX@@UlwkVkUm@m@ÅV@akwVaUkUUlUL¯w@UUm@UkKlw±UULVn@l_XyWwÅ@VUUmJUXU@@mmU@kxW@UaUIWbU@@mU@UxnUbmKkWJkUVal@aUkUxlW_@WUIU@bkKWUJVnUbbWblU@nl@XnVmV@nmWV@LXl@XJXVmzkJUXmKULm°Vb@xnVmnUk@VnnlUb@nm¼m@ÛÇVl@Xmnm²mL@xK@LUl@nULÆx@V@VXVWbXXl@nLlm@bVKXWL°bnU@VaVU@mVwJnwVK°zn@VVba@Ċ¼\"],encodeOffsets:[[113288,30471]]}},{type:\"Feature\",id:\"4313\",properties:{name:\"娄底市\",cp:[111.6431,27.7185],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lLnJ@xln@bnlV@JLVUVnVlw@U@VaxVK@abnUmÇnV@km@I@VUVVXVaX@@wlVVUkW@_mKXU°UbVLnaV@V@IUKV@XlVL@w@K@_n@lWlnnJV_XK@l°nU@WVU@kV@nbVKVl@nLlLXU@lmkw@nW@UKVa¯IVn@@aVUUKl@nXVKVn²aXblKnLlmVI@KUU@akLUaVaUXm@a@wVUVKnLnWlXln@@U@anUVm@UInm@IUK@UmKVmU_kVUwm@@VmLK@VLaUaVUUUmK¥ULkVWaXwWa@UXImWUaULUUWKk@WnXbWVWnk@UV@bU@@bJ@bV@XkmbUU`VbkaWz@klU@b@VwUL@bV@U`ULVL@VUK@Xm@XWWIUbUxm@@lkkÇwVÛÇW@¯ÅUJ@xIx@@VULmKUnUxmKULUUm@@ULUJkIWJ@b@LJUWkJWnUV@nnÜ_nJxU@VbnUxlkb@l@\"],encodeOffsets:[[113682,28699]]}},{type:\"Feature\",id:\"4303\",properties:{name:\"湘潭市\",cp:[112.5439,27.7075],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@Æ`n_VWnLVblKXL@VlbXxlaVbUVlUVJnInJ@VL@bUVVb@lnbn@lLVank@W@UlIVan@VanK@kVwlW@aX@Vn@bUJVna@KIX@@VV@nVÈl@VJn@VVLK@UVm@UnIVm@UV@@blUUaV@XKV@XW@XxÆ±bVxLUa@UKWk@wmmUalk@WXUWkXUVJVaUImKVklJ@aX_mWULUUVUyXwWI@W@U@UXKWkXWVwU@±_U»ÝKUaLVbkJkWmXk@UVVmIUVJ@UU@UamLmwUVU@mnJ@VUnmV@b@Vm@kkWmXmKULUV@x@bWnVUbVblK@bVV@LUJknmKkLWa±bUmULmWk@VLUV@bm@U°JUbVLX@@mlxkn@WVKkmK@k\"],encodeOffsets:[[114683,28576]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/jiang_su_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3209\",properties:{name:\"盐城市\",cp:[120.2234,33.5577],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@n@°ĀÞ°@¦ULWKkx@bkLWb@lUlVXXJVbnUKmxXV@bm@@XLÞÜ¦XlVnmzVJ@n@²ÞôkÆÞaȰĉwnǉÜóéVÛnĊīČǉĉ@ō@KÞUlU@kklÇÈÑÑlġXɛ@UġaU@U_W@n@kaUL@VW@kKmkUV@bkbWW@bkzma@JWI@KUKUL@U¦`@XUJU@KmXw¯KXkmy@aUIWJXXmV@K¯UU@@bVL@¤VLXbV@@JVXVK@JVn@bkKmakVVXUVVVlI@`U@nzVVb@¤n@@UlKXLVVI@V@nV@V@ÈUx@óVōkÅWó@mU@bk@Ýwk@WbXxm@@J@zV@kVbVnLWVUXWUXUWLU@Wl°z@VkxU@UVWIxWJkbĬnW@@bUl\"],\nencodeOffsets:[[122344,34504]]}},{type:\"Feature\",id:\"3203\",properties:{name:\"徐州市\",cp:[117.5208,34.3268],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@XKVX@WnIVx@K°Lnll@@I°KnVaU°x²mlx@VanU@ak@akmV@@w@Ua@aUwVwUw@w@UK@£kaĉlóIÇVk±@@kUKmVkIkxW@Ua¯UUm@UVI@WVIJV@@Um@UanaU@mI@J@XV@XaVlkXVaUUWLUyVIXmWak@XkJókJUL@KWkk@ULU@WalUIkJmImkVbV@lV°kXUKWKULUmb@VUlVnb@VV@IVKUUmU@ak@@bmV@xklUU@UKmV@nJVbkXKUamLUJ¯UUVmIbVVLl`@LLU`m@kXUVU@VlxUK@xkIWbUKx@VkVVnb¯@@U@xkmbkLÇKb@@XnJ@LmVkl@@XlUVkxakVVb@bVnUbU@@xVUVb@nIĊ`XVVôJ_K@xlU²KlkU@VaVVÈm@kVUVmnamUUaVXIVJ@ç@¥nkVLn@@XVK@VUX@JVUV@UnVJVLUJVLUVlnIbKnU@m°VanI@anVKVLanlKblKÞk@¦@¤@VKnLVKLKVzlWLX@VmV@VbnU°@UalkWXLVUKWkUUW@£Wa\"],encodeOffsets:[[121005,35213]]}},{type:\"Feature\",id:\"3206\",properties:{name:\"南通市\",cp:[121.1023,32.1625],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@VJ@bnzWl°LxnW@LVVI@W_V¥@VKVL@LXJI@nbly@aXXla@aVUnllLX@@UVKlb@@mXV`V@bĢlkČÇÆȘ¯wnĕVĉVÿUƒUĠŦğlXÑVǵ@±ōLʵĖ¯lÇbÝÞ¯xk@Çkķén¯@ğġƴǫ@kVVlUbL@xULÇóLUl¤@nkVV°VLkxVb@laUXUKWĖklVX@¤UUkb\"],encodeOffsets:[[123087,33385]]}},{type:\"Feature\",id:\"3208\",properties:{name:\"淮安市\",cp:[118.927,33.4039],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@nźUôÒɴèl¦nĖVkbmX@xVlVL@xUb@bUJVnUxlKVLÈxmzXV@lW@XVb@bÈVxnbVIXa°LaÆVVaXUlK@aXIÆVlXKVUlIXalK@alwXLVK@¥Ý¯¯ÿ@mVk@aX@mīlaXIwXJVUV@lw@U¯ybUaUġUÅaUKVknaġm@kUm@wÆIV±nLÆwÇnUUk@ƅÝU¯JÝI¯¦Ul@b@@VVL@l@LLÅmL@b@UaVaUWmLUKV¹KLWKX¥WI@mXk@UmaUVUU@VmL@WbkIUWUmVóIkbmm@UbVLUxmJkU@bkJWbnXU`WzKUÞÈlVbLmx@kè@Æ\"],encodeOffsets:[[121062,33975]]}},{type:\"Feature\",id:\"3205\",properties:{name:\"苏州市\",cp:[120.6519,31.3989],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ôèĊVnX°¤²lxƒÈÜ@²x@J@b@X`nIUÆUUV@bl@VVnL@L@xJ@X@blJXnW@@`XbWkV@UbVxXUxkV@LóxVbUVW²VJĸklUǬ@ĢƳĠ°@mƒī°»ÈÇ¥ULUU±a@bU@¯U@KnImUVWUkmXUVU@lIVaUUVWKUbUkWKU¥n£WakJUkULK¯LKkVIn@VaUVUUUkVk@U@amUkJ@UUlwX¥W@@UkVmk@JUakL@kk¯ÝmJUn@nmVXlmbVVkn@UJ@±WUxV¯a¯KōbÅ¼ÇxUxUUlWL\"],encodeOffsets:[[122794,31917]]}},{type:\"Feature\",id:\"3213\",properties:{name:\"宿迁市\",cp:[118.5535,33.7775],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@XbWnUJVzXKVVUbWklUWbU@@W@IJ@nVmbVbn@@V@UIUJ@XUJ@VVn°VVbX@lwlJnUVL@l²@lÈUôJĊklb@¤VL@@xVxUxVx@bVb@@xU@lnmnXmXLVmV@X@lxVnVJôLLXax@b@@KVL@bn@@m@@alLUUVaU¥nIV±I@mXI@aWWXU@LlUXWW_XWmaUwÇ@aaWUX@@kWUynÇwUKkLVwUmVI@aVa@wUKUk@wWnlaUmĕk¥ɳçóÑŹVmmzkVmm@a@Iók@@LWU@`WbXLWlkImJVn@`nXVbXmL@Vn@l@nUVl°Xx°U@LVĠ@z°@¦UV@Xn@VJmV\"],encodeOffsets:[[121005,34560]]}},{type:\"Feature\",id:\"3207\",properties:{name:\"连云港市\",cp:[119.1248,34.552],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@@lzXxmÆV@@¦@l`XnlKXXmKnLlab@xmbm@kL@V@Vl@@VUXJXmb@@°Æ@èÈzlW°XĢJlÈ`lInbWV_@m@UUķnôw°ÆmnaVVÛVmĸ»Ģw±Ý@@mUInyUmWkÛ¥ÝK@Wn@@aWUnwVLmUaWIUWVk@kkJUVWLUkÅWJ@bkLWVUbÅUb¯KWbUJWXX`WXkV@KWVXX@bWJ@nJU²mJV¦UbVVkK@b@@nm@@aUK@L@@awWbKóKUIUmkwW@U@UnWKnmWn@bl@bmVUb@kw±n¯wVUb\"],encodeOffsets:[[121253,35264]]}},{type:\"Feature\",id:\"3210\",properties:{name:\"扬州市\",cp:[119.4653,32.8162],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@VUXblVVVb@xV@kzV@lwVLUbVV@VU@VbUblb@nkĶ°IÞV@ƆVlmVÈÅxmKU²ÅJ@xVn@lĢnmbUlVLÆbĢVVbVaXk@VXKVVWXVWXUmKUaWaU@¥@£XWUUV@@ynam_VWkUVUna@ÆV@mnkWmXkWUW@k@@akkllWUI@UnKl¥I@VVma@a@I@U@a@anK@UmK@ÅVUnJlkI@aVwka@mVIUW@UWL@WÅbmIULkaUWUxkLUKWlXL@VImÅVUmĉLUól¯I±l@ÒUbVbUVVXUJUnVV@lnbl@\"],encodeOffsets:[[121928,33244]]}},{type:\"Feature\",id:\"3201\",properties:{name:\"南京市\",cp:[118.8062,31.9208],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@k@ma@kUUVmVIUWVUUaVa@Ñ²k°Jôk@Wmk¯KmX¯aUakKWU@XULXaV@@mUaVUUl@VmkaUXm@WUUna°IlmVmIUW@Uk@@aV@VVX@VI°»nmU@VKVan@m»UaU@U_@WlIUaaVaUala@¯n@kaUkUUWKU@mwkUUmmL@K@LmUUVKVÅImUJVkVVLèVLVU@WLV@nVÜULVUL@bW@XbWbkJUUVUxVXmVk@WUUkVmIV@nbnVWbJUkUULa@Jma@XkK@VVL@L@JLUVU@V¼nXlbm@kbUKmn@lVb@VXXVUV@b@LVbÆxXbl@@lV@UVV@XVK²VlI`UbVbUlVVn@WXn@@VUV@@KmbVLXÒLkKV@nX@VVUV@bnVllbmnbIWVXU@`lLlknVnmlLlbUmVInK°nUU@l@VU@Vn@@alI`VIXaVaVa\"],encodeOffsets:[[121928,33244]]}},{type:\"Feature\",id:\"3212\",properties:{name:\"泰州市\",cp:[120.0586,32.5525],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@lUU@@y@In@WwXal@Þxl@@anVô@ÆXlŎôU@Vw@ÇUU@@m@UJUUWKkL@Vm@@£aUUmyV@@_kJUUVUUWlUnblL@aUmI@ULUW@IU@WaUK@£UK@aV@°V@LnUWWXIlaVV@£UWlkXĕVLVWb@kUalwUKU¯lU@mk£VôKÈVK@wKVaUkķlUI±ğ¥ÝUŹ¯ôm¦ĸ@XXK@VVXUJ@nlbUx@blJkmIUV@ÆnL@VmL@b@b@V@J@bnbU@UJk¦mL@VVJkXkll@b@@lXXVWlXnml@nÅU@mbUVlVUXn`mb@zU@VVWX@¤¦V@Xb\"],encodeOffsets:[[122592,34015]]}},{type:\"Feature\",id:\"3202\",properties:{name:\"无锡市\",cp:[120.3442,31.5527],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@nLÒlxUVkLam@kVWUULUxVVVbUV@bVLUnnźÞVĠ¦XVUUaôw@KlUVwWUwVa@lUXWa@_X@WmkI@a@WI@w@KmKUUk@@aVUVVÅmJ_@W@a@I±wÛ@ƑÇkw±¯£mWĉUóçK¯VkUWK@XkV¯UWabmUaUUblln@b@xbXWX`@VxUblL@bn@Vb@`m@XbWnn@l¤n@xnVlUVLÆWkV@VbÞJ_nl@nKVU@aUU@mVk°WVLUV¯bVXbXlVn@VmL@xV@bl@nW@X@VVJ@²VJVU\"],encodeOffsets:[[123064,32513]]}},{type:\"Feature\",id:\"3204\",properties:{name:\"常州市\",cp:[119.4543,31.5582],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@LnxUbVVL@xnnWnn@VVXn@yImx°La¥n@VkKVwW@nXVJ@b@UVn@UnUV@Lb@`VLklVÞnÆ@VaXLlÈJmmVUK@aVUUaUUVwVKXVlUn@blKVUkwÑmKUVUI@±UI@U@WmX@k@aU@wnK@UUmWkaWU°aVUUK¯XUl@nVV@bUVmLk@m`ÝIUaU@lÅXUKkVmU@wmk£m@XmWan@@_Uam@@akKVaUw@W_XWa@w@akmm@mL@UJmnUK@@XnJWLkKUb@VxkWLaWVUImVULUK@L@lkLVVVllbm@@°kbVbUbbVbkJ@XV`V@Vbn¼\"],encodeOffsets:[[122097,32389]]}},{type:\"Feature\",id:\"3211\",properties:{name:\"镇江市\",cp:[119.4763,31.9702],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@VĊKnVÆUnJ@UWKXkVLlKVwXVlbVKnJÆaķn¥°óÇIkWKUbÅ@mUÝlkUK@_a@KVUVm@mVU@@aUIW@mXUxLUlm@¦bK¯nwJzm@UW@UmmXmm@wKUUVamwKm@UbUL@Vmn¯¼JUW@UUU@@bl@@VVXJnnUk¯JmbVVXn@VWlbUnk@VVUVb@nU@WbKWV@XVlLVb°bnW°Lnl@X\"],encodeOffsets:[[122097,32997]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/jiang_xi_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3607\",properties:{name:\"赣州市\",cp:[115.2795,25.8124],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@`l@Èbln@KVLl@V@bÈlnKXkVlVL@lJnb¦VKVVnXW@w°@VUmlnUV`UbVUV@xnKVI°KXKVkVL@al@XaLVlULWVVVL@bx@VXVmb@x@VVV@nn¤lb°b°KXXWbX`lbXxz@x`VIVUnKLxWXLVKVbVLVU@wnW°b@nalXmXVJn@U²mKkVlU@@xlnaVmlKn@JVLlnVl@XXÆèVlUX@xVLXVb°W@wnUWmXk@KLVwUmUkUKUw@wVaVK@k@WnkUKWkwlmXL@KVUlLVKXmWUL@aL@malaVk@aaanX@VVUblbJnXaVwn£K@UWmUk@UaWIV@bJW@KmmU@aUUUkmKkVKlUUnKVUlVaV£Å¥WUUK@UkUUw@m@mIkUUWLK¯Uw°¯@wUKUbKm@kkKUL@UUKV¥U@manw@k@U@Wm@@U@WwkmwWaUU@UUmV¯kw@@kmkKkUW@UK@ÅV@XWWkXa@Ul@Va@KVaUUU@aXwla@UkVWaXk@K@lmkUmV@Vmbk@»XI¥VUkVUVU@anKVUKUalU@wX@@a@K@ÝwL@UnÇlUIkJmn@bVVb@VmnkLV¯U@±lIWm@kaUI@aÇU@K@KUIkbWbJUIUyX¯UbU@méUUmUkWKxWIkJm@V¥U_UJUwmVkUU@@knwm@UmkWJkL@n@VW@@U@knm@kUml@xÅx@@XUJlb@VXJVxn@lbV@lULnV@VlnV@bWV@bXL@lVLVbV@blLn@VlK@xln@bX@laLVbnKUVVbKlXVVkxV@nnVUblV@@z°WWkbIkWL@LUJ@bUI@b`@UmI@mkK¯XWmUV¯@UUVUUam@@VULWUJIm`IUJKUkW@UxnWbnnmlXbmIUVmV@Vnb@VLUKWLnÒVVV@VUL@kJUV@bÈ@V°@XVV@l@xUz\"],encodeOffsets:[[116753,26596]]}},{type:\"Feature\",id:\"3608\",properties:{name:\"吉安市\",cp:[114.884,26.9659],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@lxnb@V@bV@ln@nlIn@blVXKnk¼@VUKWL@bL@`UXU`@V¦XLĠ@lJ¦@nV@l°nn@mVXna@nbKn@lIV@VanJ@_lKVVnL@LK@Vn@VbUVanKlLnbnJVbnWVnVVanI@Vb@LbVKVanXVbVJVU@aXLllbôlÆ¼XxVLVK@Xn@xnVVVmb@LnVVKVXV@@mnaVXUVnVK@_UaUmwnKV_anKVL»K@¯ÝU@U@kWlUnlknKVnaUkma@UIUwl»Åw@VwV@nn@ÈXlKVmna@kVw@anm@n_WWk@mUkUK@ImkLUnbkm@wV@klUnLV±m@UInWkWmb@¯amX@xUVUKUaULWKXwKmLUVUJ_@wyWwkaW_XaWW¯L¯akam£@mUU@U@wnaWU@Uw@aUKUXUVKUkKWbk@@bUKUlWL¯LUJmLwU@UVaVU_VkmnUV¯@@xXmWUUUL¥makI@UKUkWlLkmÇ@aUk@UKL@kmÇak@_VlkL@`lbnlLVanLnbmVÆln@kJlbknmKUbÝmmwULUK@bkLWKULUUma@Kk@UV@L@llbVzxUxnl@bVLm@IVJXVlLV`@bn²@J@V@Xmbñ@WbUJ@bm@@LUĬU¦lV@xXb@blnUV\"],encodeOffsets:[[116652,27608]]}},{type:\"Feature\",id:\"3611\",properties:{name:\"上饶市\",cp:[117.8613,28.7292],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@@VI°`nm¤²@bVJUVVXUl@Vmb@xV@XbmVV@lkLmbn`VbnU@VaUnbVllUXVa@w°VW@_VWLnVlbLVbnlKnVK@IUW@_@am@ÑUólK@U@WU@VwU@UI@aUUaX@kwmJV@yX@kan@mkwVmmI@aUU@aUUW@kVkV@@anK»XVWnIVUl`@_W@wlUV@UWKnUbn°InJlUV@VnIbWn@VklL@l@Vn²m@U`kI@bWJnV@°VXnJmXVmx@VVL@bkLmWULUmU@bWXb@llnX@xkxVVnVV@¤nLnVxnJVXX@bn`VIb@blmlLnaV@blWXnlUnbl@KVanUVmm_XK@kWWnaU@UnaWUXaXamUkKmXUWLX¯WakKmnUWwXa@KW_aXWW_@WnIVl@XULnWVknK@ImyUUÆbXKÛ@W@IÆUnVÝlkVK@mUIVwkUVaUm@aVIVyXIaÈwmmk@UnanVUmÅaó»lwW@kkUVmUK@WKLUmWULkamKLk@Wa@wk@UU@U@mbUIWVKUXWmkUmVmU@LkakKw@w@U¯UUn¯l@bmn@xkJWxkL@VkI@mkmJUI@V@b@VVxnbWlkÈkVLbkKmVL@V@²nxWkLUL@xlKVxbXmVnWJ@Þ°@nxUKUw±`UImVmnU@kalm@akwU@UUJmxU@@U@kU@Um@@KnVm@kKmkU@@WUnkLWxkVUwmKmLkUbmKUbV@xUnkJ@n±UxVXUWJ@LUblUnm@W@nknUJUVm@kXllknVbÆKVVb¼V@Ul\"],encodeOffsets:[[119194,29751]]}},{type:\"Feature\",id:\"3604\",properties:{name:\"九江市\",cp:[115.4224,29.3774],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@WUkVUkmaVUb@mVUam_nalK@kUnUWaU@@wna@UVkUWVUUI@a±n£m¯_JU@ĉ¦Ul@UVKmmLlm@ğ¹m`Uk¯@@UVK¯@UUK@amkmKkVVUa@UkUKUaL@VVXUJ@n@WUbnVb¯V@LÅlÝIJÅkÝm@UaWUU@UmUXmmwVUUKWUX±mUam@kWzUaVmÇw@aÅLmKXUWKkL@W¯IwVwlkUJ@Um@ÛÈWKUxWkaUU@KkLVl@UKUX±KUb@nVVUbUVmaUlUL@aUL@@nUlWzX`@V@lx²@Vlb@bVÞ@°nl@UxVL@lUbVV@n²xVUVmnUÞbaJ@IV°xnbl@nbÆ@VwnK@VnXlK°xnUlVXV@Vl@L@lk@W_XK@KkWxUL@JnVx@aX@VVUaIXlmL@bVVX@VbnKa²XVWk°a@UnV¤nbmLmW@XbmJUbVLaÞKL@K@U@aVKlbV@nXlJxV@VnVÈÞKôbźĕČmV@Ċ²xÆIV@Þ¦ĸ¼ÞVlVÞnxln°JkLXWVUVUVwnJVI@yn@lXlaXmWI@w»ma@UmK@akKkXmW@_kaWakKWk@@K@IWkUa\"],encodeOffsets:[[119487,30319]]}},{type:\"Feature\",id:\"3610\",properties:{name:\"抚州市\",cp:[116.4441,27.4933],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@°V°UnÜ@n@lnLlV@bV°LlnLllVzVVXlVV@@L@xX@WlXm@UVL@V@n°kVmVUnKlaXxVbnlU@lVVnaVI@aX@VJ@V@bb@Vb@X@lUL@@VlIVm@wUVanLalVnKnLVxlUXwlKVm@k@Una@mWIXKWUÛVk@a@UVWn@@kl@@WXlW@_Um@UVK@aLnalInWV@@xnI@¥Km@kKmnk@mlI¤laXbVblknV@UKXVlUXa@@Unw@±mU@ak_±a@UJUIVKW_Xa@aWUK@mmUVa@IXa@UWmannlmX¯WKXwVUVw@XUlK@klJXa@kkmm@Uww@¯W¯kw@WmbULaUUU@mVUUWmkUbKmkkK@akU¯¥Ulm@akU@m@KVIVV@KUkUVUkaUWbmIkaVaUU@mWbb@bUlkbb@nK@bKXVWnULkKUV@LWKknlxXVLml@X@lULUb@xVxVLVlVnUxK@LWlXnmV@x¯XaWUUK@wVWUkÅçm`@mn@bUx@lmbUnkLÇWm@mU@Ux@Æxk¼VxVJ@nbVlmbUmLklmkVlX@VV@°Þ\"],encodeOffsets:[[118508,28396]]}},{type:\"Feature\",id:\"3609\",properties:{name:\"宜春市\",cp:[115.0159,28.3228],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@@VlbnK@b@JLlUnx±ĀXxÆWX@l@V@@blJ@nX@xUbVVUbVV@bVmnmJ@bmbm@klUbLmb@lVb@xUX@bVVVbV¤@LVVbXlVwLXÜÇn@@VIlVkUxx°J@XlKXLVWnLÆK@bÈxUnVbylXn@VbnW²XVLVVUnxWnnV@VVVXVbn@ÞÆlIÞJÆk@K°UUamVa@UUU»@wV@VkkUKUVW£U@UmW@@aXkVUnVlKVVUUkVmU@kWaUanUVVamIX¥W@@aUaUVW@_mW@UnIVVn@VbVm@bVL@anKVUkWKUXVIkx@nabVKb@nVJ_V@VwVUVVXUlUUaV@X@VblabnKlkVaXa¯@m@UKVUn@WXkW@@w@KU@UWkUUUykkmKk¯KU@akUmK@k@mmÛ¯V¯U@L¼UKmLbU`mLxVnVb@`LmUVUUWmb@nU@UWULmU@KnaUUmUwmJ¯IUJWIkVkaWVUIUlWaUIUVkKmbUIÒlVUnn@VlLUJ@bUX¯@aWVUKUXKUbm@UwKWa@a@VkUWn@Uak@mbXWJXbm@mLaWVk@wL@WmanU@knwWmkaWLKWUXaU@¥lUVVVbnw¥nKV»@aUk@a@UJ@kmLma@mbUWnm@ULÇº@LXnmxUm@UbkbW@@akLmWk@UXmJmUkV@VUXVlULmKUxkL@lmXnJ@Xl°Vnb@bU@WbKUX@VmKUX\"],encodeOffsets:[[116652,28666]]}},{type:\"Feature\",id:\"3601\",properties:{name:\"南昌市\",cp:[116.0046,28.6633],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@X@m@VIUW@UKVbLlV@VVbUlUnLnl@bVL@V°UL@V°@Vln_Ġºn@knKnLVU@VkĊ¥Vk@U»UaUÅLUalmkklWn@VUVIlm@mXn@VmkVa@KXIVUWVw²@m@U@VK@k@WUa@a@aU@IUW@@bUJmbUU@kkVmUaWwkbmLUVUnlWbUbklmLakbUaW@U@VbkVWVUUUVUx@U`UI@maULamb@lwJWUVXLlUVmL@bUK@aUnUam@UUmJ@VnX@`UXVVb@bX@W¦nJUbUmVVbXb@lVUnVlVUUkLmUUVWl@bX@VnV@X¤VUVLllUU@@x¼VV@V\"],encodeOffsets:[[118249,29700]]}},{type:\"Feature\",id:\"3602\",properties:{name:\"景德镇市\",cp:[117.334,29.3225],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@VVX@VbmzxUlU@mbmL@V²xVbUVVblbX@VkVykValKVI@bn@n`lVWnX@lL@WKnVIVa@¯nK@alIXJVIVWUwn@nUnK@alI@a@anKm_aW@UWmIUwmmK@£UUmUUlwwW@km@kWaXaV@VnVKnXlK@aUK@UnwWUnmIUW@¯mUXI@alJV_n@m±@U@kkKUlm@XamJ@UVUkmI¯JmamVXL@VUkV@xX@`k_UVmJUXW¼mL@bU@UllX@VV@bVV@bnJUnlx@nmb@lW@zUnIlx@WbVV@bVJV@UxV@@X@VkLVôÒn@@b@`VX@J\"],encodeOffsets:[[119903,30409]]}},{type:\"Feature\",id:\"3603\",properties:{name:\"萍乡市\",cp:[113.9282,27.4823],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@VWnL@UVWLXaV@@ama¯Uk@WmInW@klKVwnLVKUkVW@UlUnVnIVWl@nXlK@bX@laVan@VnwWm@KÈ¹VK¯m@kmU@¥kIğ@WKU¥@V_VW@_K@aXKVL@Ul»mWLkU@amkJm@kmU@@a@UmakwU@Xl@VXk`UIW¼kWWX@@lxV¦XlW@Ubn@mUkL@UmJ¯UkUWVUaUlm@UXWlnUJ@LmLUnXll@bUVUUmVUn@¦xlnn@VÆÈU°kbVVxllnL@VnVVUl@VanL\"],encodeOffsets:[[116652,28666]]}},{type:\"Feature\",id:\"3606\",properties:{name:\"鹰潭市\",cp:[117.0813,28.2349],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@@XV@nlL@lUnm@Ln@@VlV@@VV@nwVI@VVlx@bknlbV@nmnUVJ_²VxVLw@m¯@ÝXImnUWaUwkL@wVKlKXmw@±@UKnUlLaKlUlÇXkmaUw@U@a@UUkwUJ@zWJw@WbkVWUL@VmUklUaWakb£kJ@nmlnlL@nL@¦mJ@wU@mXkJmbK@bUL@VVn@`kXW@Xk@@lm@UX@V@blÜUXVWLXJ@nmb@V@l\"],encodeOffsets:[[119599,29025]]}},{type:\"Feature\",id:\"3605\",properties:{name:\"新余市\",cp:[114.95,27.8174],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@m@@WULUKWwÅ»ókakkWK@bUVUIUamWUbULa@KUa@mJUbmUXUmUamImakKmLUbVUam@@UL@KKmUUkL@`mIUb@U@V@bVl@b¼UmL¦mxUaUUVk@¦VWbXVLXKlbXnmx@lmVnb@XKxl@XUbnKn@WaXIWnal@Vb@XmlV@U@bXbLVxn@VaLVWVLXUb°@VW@aVIkK@UmVmkUÑVJnalLVUVJXbVkVJXUlblUXJVI°JnI\"],encodeOffsets:[[118182,28542]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/ji_lin_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"2224\",properties:{name:\"延边朝鲜族自治州\",cp:[129.397,43.2587],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@Wxĵm@ó¤VX@@xÜ¼ƨ²xWxVV@XVbWXllaÞU°Ċ@ô¼LôÝWanV¥Ñnĉ°¥ÅX¥°¯@w°w@»°k£°mÈŹmÈbÆŎ¦K°z@kxl¦UbU¤klVKŤÞȰ@@bV@nVVUlÞ¦lUllVlU°ÑU¯V°wbXxl@V²@nô¼ó°kmVk²ĕw@wVÞÞ@@Ġö»¯@bnb°mÞ¯°V°ÈJmX¥mamUÅUlaU¯@wKkl±n@@wkÝVUUl±¯I¯bal@kLmakb@ġŹé°Þb°ékLmwXaÅb@bVlbVbÒVbUbUUanwakbVUVak¯ULmxV°UxnôŻX@JXklbkbĉabWU@kWUU¯@@klm@@Å@awWXlKkI@WbUaVIUanU@ĕ¯KmUnWUwm@£ċèkUmbUmm@@nkJUalwk@@nmWUan_óaWmnw±KIwl@UmI@an@@mlUÅmV_KUk@U`@_KUmU@U¯mmb¯@kbImV¯LkbKÛ@ÇnɱJóaÝĢkb@xÒÇll@²VÆUVVUÇ°XóxlV¯lV@bV@nx@¤@șŎnxV¼knJnKX°¦UlnVbUbÆVnÞWVX¦llb@l°VJôÒnLVbbX\"],encodeOffsets:[[131086,44798]]}},{type:\"Feature\",id:\"2202\",properties:{name:\"吉林市\",cp:[126.8372,43.6047],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ôlzaÈV°K@mLWlnVxUVÈ@ÝĬUÈnôLa²VmĀkV@ĠĊnU@bV@b@nl°UVnÞaôJ@bV¦mlkbmVXx¯@VxmnbbÈKV@bÈLwĠyônmnbÜ@nnVx@n²KJ@kal@nxÞULź±Vwkw¯LWWUkŎīVww°yVĕ°wÈVlkÛ»@wW@Uô£@nĶXwWaUamKóÑUI¯@kakkW¥XUmÝÅUVaUamVk¥W¯LmIlmU»mwȚō@£kJUÇk@am¯y¯UVwa@wġx¦K¯X°Ċ¯¦U°ċWULÅa±b¯@UkÅWmVkIUlóċ¹`óIlXWXxmbULÝbƧ@x¯bÈl@x¯zaÝ¤@nmVWb²bmn¯J¯Ò@n\"],encodeOffsets:[[128701,44303]]}},{type:\"Feature\",id:\"2208\",properties:{name:\"白城市\",cp:[123.0029,45.2637],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@óǩŁ@WlwUaƑwÛÅÇéĉamKōÇ@IôġVȁÑŹçÝUƧċĉwóóÝ@Ƒ»ğL¯ll²@ƆÅV@¦mÅb@nmlU²VxlUn@VbnWbÇbkÒn@èlnlUÒ°Lx@¼ĉb@ÒUċxÅènLVxÒbÅJ±a@_ÅJÅnVbKlnUÜĊ@UxXVÆnmVJÞ¯VĠwXw°xWLxKV¦ôUwVÝǬóÞÞ¼ÞkVôȘxÞUlVn¦ÞĊa°wb°@bÆwlŤL²`z°@V@@nJVnl@@¥nUmmn@mwnmmUnk@mlwUaLnwn¯°anWakIÇmXwÆamUXUlJXaUUklKUknmÞV@K@VWÞ@VkUwV\"],encodeOffsets:[[127350,46553]]}},{type:\"Feature\",id:\"2207\",properties:{name:\"松原市\",cp:[124.0906,44.7198],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@źèȂÒUóĢ@JŎÈLnĊbÈêÜÆƒxVbkx@XǪłôkÞ`Wb@n°abKnVw°`_X`W¦ĊIkmVakwKx°UÞbU@ll@°¦VWaÞbxÞI@mVI@VkÅUWK¥nLa@@È@°Æ@nU@KÞalkUwVékUWwkUVkkJk¯@»ókV¯ÆÇI@bĉô¯@ķw¯nmmÅL¯wVUÞy@UówÇLkmm@@UóxkkĉmL¯wVwkWWXmLõm@kÅ±V_ô»ÛÆ¯@VaVaĠVlmğwķUóÝƽ£ÇJkbǫaƽLW@nxÝ¤kzy¯XɅm@VôÇX¯Ė¯ºÝnUnLVlUÔmV\"],encodeOffsets:[[126068,45580]]}},{type:\"Feature\",id:\"2201\",properties:{name:\"长春市\",cp:[125.8154,44.2584],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@U°xÆKnn°mĸx°@Ċó@aÈJ°ÅUôl@¼l°IllUlVXxlVUêVxkllnÈUVll@Vx²IÞ¤VUlVnIôlÞlwô_bVaĶLXÅÞÇ@K¯@wÛaçn¥¯WXyW¯XwUmmÛ@manómğzxÇK@aUÇLamanUw°@WwnUalnk¥U@aóIÝbUm¯Vmk@@aU@amVğĉ@lUnÿ±UbóKmVÇÞī@ÇVUUwmXkKn@L¯ÇUbyókōè@bn@lÝX@x¯ô@ÆUV_maXm@aóJWxnX@VVnĖVnUJ@nōÆÇ¼V¼kxLklÝw@xx@zV`ÅbmxU±xUnnmknğUbUUb@Å°Üó¼U`Æ²@lönKnXWlXUx°xnKĊllôw@Vn@lnÈKôx@VÝzV\"],encodeOffsets:[[128262,45940]]}},{type:\"Feature\",id:\"2206\",properties:{name:\"白山市\",cp:[127.2217,42.0941],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@Ul¦kÒÆ°IlÒU¤ôz¼lJUnÆXVl°@²aÆbVKČXV¯°¥¯ĉ°WL¥Ģw@xbUx°V°znb@ÈlVlI@w@mU@akU°kUôwWÈ¯VUVUÅ±U@kÈkÑw@laÞġUÞ£@ƅKnÑĢ¯@WaUaVUVkkw@a¯@¯ÝVXnW@@WkXmK@xkKUb@bW@Uw¯mmb@WKUbmUbUaWbJĉIVW@Il±LkmUbUm@nkKWa¯n@`UbmaĉL@bÆ@W`L@n¯Xb@kb@xL@VkL±mlUIU¥mL@lÅx@_la@UaV@kmmK£LmKUnÅKVbmXVlèĉUUbmlĢÅ¤Il¯bÇ¦l@ô¼Ģ@x°l¤nal@xb\"],encodeOffsets:[[129567,43262]]}},{type:\"Feature\",id:\"2205\",properties:{name:\"通化市\",cp:[125.9583,41.8579],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ÆlXnĠxĢ°lÈ°K°kXm@¦VbkŤJnÝ¤kVÞVVkÈb°y@wkÇ°awƨ@aÞKVnaWwXWkôJ_ČºôVk»óyV£kÑJÅ¯lÑk¥Va@wkbmk£¯@wġó»@kÈ¥°akJÆ£ġnkVaĊVkçWUnUaÆLVmnLKU±@m@a¯UbmV¯m@_KUaÅWó¹@UanmWak@@wmI@y@mkJVa@UaIkJ@n@Um±kkxmIkbÇm@°bXnV@°ÈmlÞ¼¯XVº¯LmkWWXLmVVlkn@@lnWÆVxbmnm¯lÝaVÈè@¼VbÆ°ÞUVJkxIxIV¤ÒXxmn\"],encodeOffsets:[[128273,43330]]}},{type:\"Feature\",id:\"2203\",properties:{name:\"四平市\",cp:[124.541,43.4894],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@Ɇn°WzlyÞ£mwX@ƾKǬblaÈIƾ¤ôÞĸVĠxnmmV²wVnwÆaU_@yw@wÞxlkKlwU»È»ŎÅ@mVIUmmĕUU@mWXwIô@bWnnbU`V@Å°ó@wÞW@km@aŎç@m°Ñ°Inm±aXaUn@mƑU¦@Ç¯aU£aUġ¦ÅÒJōUŻókUÇ@¥¯ak¯mUVak@@aċçÅaUm¦Ý`XbÆ@n`IxĊÞōÞml@Ub@Wl_¯JkÇUÝÆÅb@nllUb¯±a@WĉJġĀ¯Unóm¤xôaVnxôI@xV@bmÆ@lnLmÞ¯ÞxVb¯þ\"],encodeOffsets:[[126293,45124]]}},{type:\"Feature\",id:\"2204\",properties:{name:\"辽源市\",cp:[125.343,42.7643],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@żôŎVIÆÑĢ¥VbV¤°bÈ@V¥ƒÞ£lÇUUUÝlÞ£mţIlUa@¥nlW¯L¯kÇġ¯ğwWmÅk¯UVUbWlXlmnbUx¯xVVknlUbVÇKUb@VnbmlnzUº±bmJUbWÈnèmÒ@X`WL\"],encodeOffsets:[[127879,44168]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/liao_ning_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"2102\",properties:{name:\"大连市\",cp:[122.2229,39.4409],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@IÞmVk@wXWÜbnwlLnU@nLlbXW@awnbl@XLa@Ċ¥@LULnJ@xVnmV@VXXV@VJkn@VÜKXXôJlbxl@IVbnJVLUbnlnVwJVU@XUaUUlwn@°nVKnV°_VJwl@nwlVIXWlIVVnK@IWmkIVaVU@WÈUlmU@UWUalkXġŻ@kI»mmakUmĉUŁV»²ġVĕ@aUU؍IɃ`ȃ@kw@Umwĉ@WķÑIĉÇbÝLkymbIwÇmÛbmbU¯ÜõÈkÆVbŎxnXVÆnǪ¦b¤UxÝnĉÒmĊVÈ¤ÈbÆ¼ĀÆÆÞźbVVbX°²¤\"],encodeOffsets:[[124786,41102]]}},{type:\"Feature\",id:\"2113\",properties:{name:\"朝阳市\",cp:[120.0696,41.4899],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@na@UVI@mÑWkaV¥UI@wl@aÈbm@wVak@@K@k@a@UUmUUalmU@KÇUÅ±¯@±kUKVkUaaU@¥m@@¯k@WLUmkn@mmIkm@amU@wVmkU@Klk@UmaXIWWULaULVbmk@UUmUk±_Uym@mbkImaX¯WWxWKzU@WkJWwkV@Um@UbVVVVXb@VWX@W@Vkb@VnUK±aUUlwXÇWKknU@mmUkLUVVUUVUawbkKmwnIkJ@nmb`kmVkLWwUm@UUUK@UmaUa@UUaWK@mU¯Wkk¯VmUUxVXUVmL¯ymXkWUbmXUKVknWx¯JVnkLl@VVxnxlĀVL²WlXl@bÝVUn@bnlÜaXblIVl@@È¦@VmbXV@@xVVnUn@`°@VnXU@K@VV@VmbnVn@ln@bx°Ub@bLV`ÅnW@@lUnnWVU@Vbkl@Xl`XxVUblkX@°¦VUVVbUlkV@UbVbkLUxmJkX@bbxVKÆlXXbnnala@Uk@UVVklKVUXKVU°KVan@VUnLKVLWVaU_@mmUXa@mwXwVkVWXkk@k@klm@wXKl@U@KVUUUVaUV@alLxUx@b°°VnnVxlIXJmxLUVlV@bnX@VbaVx@XJ@bn@VVXÈl@llX@lUVô°°@ÞVbn@Vk@VW\"],encodeOffsets:[[123919,43262]]}},{type:\"Feature\",id:\"2106\",properties:{name:\"丹东市\",cp:[124.541,40.4242],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@lzXJU@²x@@V@bUVmKUn°n@lnVKnV@n@VlV°WbXn@VzJ@¦@bkbbUl@bkbJ¯zWULWbklVnb¦VJ@K°Ukl@@WbVn°@Vm²UnX`UÜLXmVXlKVbUVVnUbnX@VUL@lUbWx@²kl`n@Vlb@nUVWVLVU@aV@²bl@ÈmxWXVÈUJVl@laWnXKÈkÈ@Va°bÆm@XV°IVV°UnalVUn@UwVU@@VVJI@bl@XK@wWmXUUVbkJVXnJVI@mknwlKXL@`l@VI@UUaVKÞnaVm@aÇ£XWU@aÇUU@mbkKm£@WWL@@Kk@klUbWKUkUU¯UõÛmUUaVUU@WU_W@kVkJ_WKkV@bUL¯¯±mk¯ġğÑ@UmwKUaka@am¥ÝIUWmk@wmţLKʝbȗKWĢklVbX@VVknÇV@XUVUblJXn@J\"],encodeOffsets:[[126372,40967]]}},{type:\"Feature\",id:\"2112\",properties:{name:\"铁岭市\",cp:[124.2773,42.7423],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@XJm@¯mXUlnVbUJU@bV@UJWL@VXLmJVbkXlJXxVL@b@V@n@b@`Vbk@lxknV@VVV@bUL@bV@@bVK@VXLWLXJ@LV@nbWJ@IUVx@LVJUXVxVx@VV@@LXJWL@VU@@L@VnL@bVVmVX@@VVInJmbnLWVnVULVVU@VVmX@@JVzl@nVVKVXÞ@mk_lmUUWV_nJlUÞÑÞVVUVVLUVJ@IVna@@KV@XwWknwnKlalUwaĉÝwJl_@aUaKUUU@WU@WXUÆ@@UVK@n@UnVVblK@bllb@bbW@Xbl@UlnLl°°b¦nKlVnIV@UWU@WXkw@am@nm@aVw@I@KUaVIm±XÑlknJVnVJaX_VaUaVKmwnkmmn@lU@U@mnaXlKUmUIVmklaUK@UlUVUW@UkVma@UUU@JmUU@@bmbKWV¯XUKm@ka@UVKVk@aUKmLkKUUÝUmbXbÇJ@k@WU_@m@klm@UXKVaUI@KWUXaÇWkaWUkWUL±U@lUU@UJI@V¯JmIm@@aU@Uwa@UV@VkIV¯aUkWkb@bVL@@VVVUXW@Ua@@bÝbUVÝ@LmUkVUbVllLUV@LXWbUXm@U`@kxlnnJlbnIllLXlVlUXmVKnV@L\"],encodeOffsets:[[126720,43572]]}},{type:\"Feature\",id:\"2101\",properties:{name:\"沈阳市\",cp:[123.1238,42.1216],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@ȚĊÜ°bLlÞxUbUn±@ÈnVÆL@xnLlUVbxkImJkn@V±LUxkV@bbKVKnzVl@L°@VaxÞUlbôxVV@@V±bn@llXLöXĶnal@nkVJVI@aU@@aVK@aUUUU@lmkwl@Ua@_@a@m@U@aUKWwkIlWUanIWK@UXKVIU@@aVVIUamVknW°n@WI@KUmULWnkVkUWKkkmJkamIkmlw@V_n@VWXaW@KVUkKUkValUnVK@ÞVUÞa@a@VbX@VWUU@U@UK@ala@IkKmUUa@U@VkkWVwU_@KÜUXbl@V¥XUVmXakÅlUUkIm`UIUJW@UIKmkm@UUJImmU@VUXU`mIUbUK@LJUUl@X@UbJkU@nm@Uam@@aUmLKwmWXUK@kUaÇa@JUIUa@aKVUUXmUy_@lmbkLUKWLX`n@bVL@JXLWX@Vnb@Vm@UbnVmL@V@x@LUbVV@V@LUVl@mb¯U@xU@UVVV@X@VVblJ@bnVKUnx@llnL±¤b@k`VXÆK@kV@¼kl@bWIUl@VmLnbm@@JXXmb\"],encodeOffsets:[[125359,43139]]}},{type:\"Feature\",id:\"2104\",properties:{name:\"抚顺市\",cp:[124.585,41.8579],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@XVl°bUlJ@UVU@bVxV@@bn@nJ°I@UJIVV@V@k²VVKlXXVblÈXWbXV@LVJUbWL@Vkn@l@nV`@X@lÈIWanaÞVVVlLnKVL@bUlUL@Vlbn@VL°WXULna@aV@nV@IVV@VbUnl@VXnKVa@UUnyWkXaaVk@aabnm@_WKXmWanU@alaUl@XJVLVxX@wnKnVlw@V_@a¯¥@UkKWUaUUanK@IaU@WUaVw@klUVyUUVUUÇ@Iôba@mnUma@kXa@UWak@Wal@a@WULmU@U`mIUU`mUk@@UUK±nkJbUam@kwm@@a@UU@Ua@@K@VK@kmKU_UKUUaĉWmkkL@`LnmlkLkbmK@k@Ulmb@b@xUVIUlmVXXxm@JUUk@WUk@akx±@¯x¯UmbKUUVmUU¯UmVVnWkÆlWbUnWVU¦k@WaÛV@LV`UxXllU@@VVbnVlL@J\"],encodeOffsets:[[126754,42992]]}},{type:\"Feature\",id:\"2114\",properties:{name:\"葫芦岛市\",cp:[120.1575,40.578],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ll°XnV@XLVb@VVbnb@VLVV@VVnXxlKnUl_na@mlImJnxlLaxVbUVVUVUKVlnnV@lmXLÈWkxVV²bVLm@Ula@UX@XW@UWaUUUUVan@V@lUXxlIXV@yXLwXXW°nblJnan@Vz`l²nVVVl@nUaVKbVKnXVaUaVUynXK@kVK@X@m@mLXaLWU¯w@a@UVw¥°ó¯¯y¯UÇ¯»w¯Im¯ÇUUl¯»ţKċÑţķm¯w@mU_ómk¼VnU`±IkbVlnnU¼±Lk`@XWl¦UbmVUxkXVlkbllUVb@bkVmx@XVV@Jb±aULkKWXkWmX¯aUJmIkVm@xU@n\"],encodeOffsets:[[122097,41575]]}},{type:\"Feature\",id:\"2109\",properties:{name:\"阜新市\",cp:[122.0032,42.2699],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@Xnb°lVlnXVJLlVnl@zÆxnK@bblKVLn@@VaVLVK@L@Vl@XVVInVVKVwlUXwlKLVVb@aV@XlUXbVW@nlWnXKV@@V@XUVVLUVV@@bVVV@@ln@VbVUXVIxVanJ@UIVWL@UV@@¤V@nInwWklnIVxlnzUVÇJ¦VVÜLĸUnW@aV_WĊXXaKnkl@nmLa@alUVw²K@UlmnIlJwaVUkmK@wÅKmU@Ç²VmVaÝwkKaÛ¯șĉķ¥ğ¥@kUWkƏīÝ@@akUK@KWIUm¯nU¯JmwUVmIkJÇLm@UImJUU@aW@U@@nUbJabXVWn@UVmX@V@b@l@L@lUb@xnÇabk@@xVJU¦lbXÒ@nUJ@Vmb\"],encodeOffsets:[[123919,43262]]}},{type:\"Feature\",id:\"2107\",properties:{name:\"锦州市\",cp:[121.6626,41.4294],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@nJ@nlmVnXKl@@°n@@¦VbVbUlVL²l°@Æ²ÈV@LVknVbVVnnWVU@XmWUabIVa@mV@X@@bVVnIVJ@nÈKlInJVUnx°IV°mVnXJ@LLlV@b@ÞƐĬXllV@Ġ¦ĸ¦naWW@In@manK@UVkXJ@alk@»lU@ÅLUWl_@a²£Kkm@kwVmULm@akIUa@U@WUUVUaÝ@ğwkmĉ£UW@@bÇL@ma@_mKlXUwKLţÓ@UWw@K@UI@mU@UV¥@°UnJ°@@_KUwW@UnaWUmmI@mķwUaÇLóVĵwÝUUW¯¦Ux@Vb@xV°XKWbK@n@nW@UL@lWLmzUVVbUbmWXXWJbn@Vkl@LlVUn@xnV@bln\"],encodeOffsets:[[123694,42391]]}},{type:\"Feature\",id:\"2103\",properties:{name:\"鞍山市\",cp:[123.0798,40.6055],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@lxĠÞ@bV@@w°Vna@UkV@K@UUUVa@K@w@UnKmUVan@@Uma@UXWWK@IUK@amW_XKVLlKna@kmKVak@VU@VmU@anIÆan@aUVnb@blLV`ÞLlUbnaKn@naVU@¥°IVK@anUUKVaUVak@mJkXUVwkVUUa°U@W@WlkXWlIXUlJlaxIVVXLll@nLV@lLXlKĊz¥maUlkXaVKX°yIla@aVkala@a@¥IUy@WmXa¯kU@U@mmUULkmm@¯VmnLVU@a@U@±w@VWIkymLUUkJWXJkUmxk@xUI¯`mUULm¯m@kxVVbWV@UVIUx@bkVVVxUbVV@V@zJVXUlnk@@lkLlLUU±Jkm@UIUVLUVU@K@UnnV@l@LlaUJ@zn`@nWlIUVUUUV±Ln@nmL@VUVkLVlUxVLVlÅXma@@akLmWUX@JUnVJVkXJ@X@`WXVUVUIlbW@bVUVL@`Un@¦U`@bUV@z@Jm@@XV`LUL¯J@IVKmKÅI@JnWVnLnVxV¤z@bmV@VUV@bUL\"],encodeOffsets:[[125123,42447]]}},{type:\"Feature\",id:\"2105\",properties:{name:\"本溪市\",cp:[124.1455,41.1987],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@lb@VnlnVVUb@VJ@nnJ@bmXUx@xVbkbkWLUxnl@Ul@xWx@nUV@¼UllknkK@bmbnlLVJX@VIVJn_lJVVXUmnU°VVVUnVVLna°V°w²@lwbl@XVl@VVIn@wWWnUVkJVUw@@anaVk@@lnLlalKnkmK@_lKnlĊXVbVVLV`nL@lUL@@L@VbV@@V@bn@lxn@VbalI²mVL@Vl@nV_VVnJV_@nVKV@X@bkXbl@XblylUUk@Xa@UVIlK@UUWVULlm@UUUnKWU@K@UXmXVa@U°KVUUWUk@aUVKkaWkKUknaWa@U@m@mk@aUJk@@_WKkLmxl@nUJmIUWlIUaVWVXn@xWLk@@aJUI@U@UVVxm@UVkmb¯VUU¯JWU@Ån¯aUbÇ@ÇlLmWXkbk@UIÇVUXWwÇnk@±aU@@bUVUKUXmV@kaUm@k_±l@XwVa@kVK@UWmVaUmVUUakLUWWnÛKVW_m±VnU¯@Uma@Xk@l¯V\"],encodeOffsets:[[126552,41839]]}},{type:\"Feature\",id:\"2108\",properties:{name:\"营口市\",cp:[122.4316,40.4297],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ĊĖÆn¤°Ċ¯ŎWô@xXbwnKl@nX@VUVKmL@VU@UxÝ@VlbxU@VUb@bk`IUlVUnV@@UV@@JnXlK@b@nbÆWUkUKVwUklKVU@UnK@mm²KVUVVVUJXk@mm_@yVIbk@K@kmUm@VLV@VUKVUVJn@l²IVVKklK@kl@kmVUWI@y@UUUVawUUUl@akmmVaUKmIUaJk@wkaóIWWÛL@UlmUIU@WW@UnUUm@wmIVK@Kĉ¦@bWKk@max@bWXkamK@mVkKmxÛaWX@xUlÝnJ\"],encodeOffsets:[[124786,41102]]}},{type:\"Feature\",id:\"2110\",properties:{name:\"辽阳市\",cp:[123.4094,41.1383],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@`VzWnVUVL@bVbVJ@IÈbVb@lVLXWnxLnKVb@n@Vbn@mV@lIVa@@WkVVI@KVLVanJV_VWUV@nnJVIVn@na@alLlmkVk@»VU@mXwwk@@VmkVwXKllaUa@wVwnW@amI@mUI@VaUUkmm@UkaL@UIĉyLWkkKU@mKk@kWKUUJwkbkIWVkJWXkl@X@X¯VVbUVlUxVWlnI@lUbVUbVLmV@bUL¯J@¦UVmbm@LmbakVÝKU_kK@amaVUbm@ÅbmJ@bVUn@UVl@UbnL\"],encodeOffsets:[[125562,42194]]}},{type:\"Feature\",id:\"2111\",properties:{name:\"盘锦市\",cp:[121.9482,41.0449],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@Vbĸx@nnJVnXmb@VXVxL@`¯@mI¯V@U¦@VV@nJ@V@LXx@VŤÔKLVxWknL@`b@nÈK@a@VXĊ¤nVK@aVU@UnU@ayU£UwmmKXUm@IÆJnLUL@J°IVKKU_@Wn@@I@yVU@aV_@¥Vm@_UKUV@aXkaVJVUUXW@_@WWIUlUIVm@IVW@IU@@VU@mUVVkJ_l@aVa@UVwka@UÞVwV@@UnKLVU@UmWk@mLxWa@wóUVUIÇÆĉ¦¯¦¯xʟJ\"],encodeOffsets:[[124392,41822]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/nei_meng_gu_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"1507\",properties:{name:\"呼伦贝尔市\",cp:[120.8057,50.2185],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@m@Łkklô@£kJ°ýɅķÑó¤ğLĉÅlÇğŁW¯¯ƥóÿlwkţÈéÝƛó°ÞÅxV¤ĉĖWƒ¯lȭţυ̃ɱÿķƅˋğɱřÝţϙȍƧĊţ@¯kWKUKm¹Å@ķJU@ƧÑƧō¥˹Ɔ@L@ÞVLn@VōČWJX¦@JŻbU@ţÞmVU@ȁýóbkWWLÅ¯UWġkmó±UŹôV¼ƽ¼ł̥ĖƽǬʉxĉŻȗKΕ̛ʵƨʟÞ˹»Ƨţ»Ǖō˷Ȍ±ȚʊĠUɾɜɨmÜ֞߼˸ƅȂ¯ǖKˢğÈÒǔnƾŎŐ@Ċbôô̐¼ƒ@ĊôĊÞĀxĖƧL±U°U°ĬƒČ°ÜêɴȂVł°@nxŎèbÈÞȌ΀Ǹl²IlxĊl²ÒmôĖÈlĵºmÈêVþxɛČʉÇĵVmÒÈɆôƐŰǀĊ°ÆǬĮƾbyĊ@ĠƒXǀċm»ôw°Ûk¥Çm¯çkkÇǫţǕéX_ĶWǖīŎaÆĵĸĊ@ȚȘĊLĢĉVÆĉʊÇĕóaU¥ĉ°mkÅ°ġUĠřk°mÑČÿÛƒWĸ£ʠÆxÈÞŎÞ»ʈ²ĊÇČalÒ°Ť±ĸzĊKÈ²m¤Ŏ@Ò°¼nyȂUźīǖƳÈē°@ÝĶ@Èkl¥ÇçkxkJXÇUÅ@£k»óƿīÛ@lÅJl¥óý@¯ƽġÆÅanċ°é¯¹\"],encodeOffsets:[[128194,51014]]}},{type:\"Feature\",id:\"1529\",properties:{name:\"阿拉善盟\",cp:[102.019,40.1001],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@ƏnǟƨʫŹɆÿ°¯ÆV²ˢżÿ@ÝÆŁȰ¯ȀƳĉó@ğky¹@īwl£Ź¯Ŧé@ÇÇxŋĉƩUUŃōLÇĵóÝnóç@ó@ġƱ¥çWUçÆō@éçťKçȭVһƽ̻aW¥ȁ£ʵǊǓƲɳÞǔlżÞmĠóĬȂɲȮ@ÈĢŮźÔnĶŻǠŎȭгŃċóȭţΗÆƑÞƧÅΫóȘǫɱȁġlÛkÇ°ȁÈnõl¯ôÞɛÝkĢóWĊzÇɼʝ@ÇÈķlUČÅÜķnέƒǓKȮŎŎb°ĢǀŌ@ȼôĬmĠğŰōĖƧbЇƧōx@ķó£Ål±ĀƧīXÝġÆêĉK°Ýʇƅ@ΌʉżÅÒϱʈ@˺ƾ֛।࡬ţશóЈèʞU¤Ґ_޸Ƒʠɽ̦ÝɜL׈ɛϜóȂJϚÈ@ǟͪaÞ»Ȯź\"],encodeOffsets:[[107764,42750]]}},{type:\"Feature\",id:\"1525\",properties:{name:\"锡林郭勒盟\",cp:[115.6421,44.176],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@ʶĬĊIȘƨƨ@ĬÛĢșŤĉĬĀóUÈŚÜènŦƐȤȄłϰUƨťƾÑ܆ğɲƜǔÈèʈƲĊƞƒɆ¯̼V˺Ò˺ȂŤVĢêUÜxĀˌ˘ƨÆ°ѢmÞżU¼ÆlŎ@ĊçŎnÈÒͪŎźĸU°lżwUb°°°V£ÞlĠĉĊLÞɆnźÞn¦ĊaȂīġŃ¯Iĉůl»kÇý¥Ŏ¯én£ġÑÝȭxÇ@Åçķ»óƱŎ¥çWÿmlóa£ÇbyVÅČÇV»ÝU¯KĉýǕċţnġ¯»ÇōUm»ğÑwƏbċÇÅċwˋÈÛÿʉÑ°Łkw@óÇ»ĉw¥VÑŹUmW»ğğǉVÿŤÅźī@ř¯ğnõƐ@ÞÅnŁVǉóJwĊÑkĕÝw¯nk¥ŏaó¦ĉV¦Å`ğÑÑÝ@mwn¯m±@óƒÛKˍƏǓ±UÝa¯lōșkèĬÞn@ŤġŰk°ċx@ĉ`Ƨĕ°@ţÒĉwmĉ@na¥ķnÞĉVóÆókĉķ@ÝkƧƧÛa°Ç@ÝÈUóbÝ¼@ÛÒV°@V¼ˋLÞɅŤŹǠVÞȗŤÇĖÅōbȁƜ\"],encodeOffsets:[[113817,44421]]}},{type:\"Feature\",id:\"1506\",properties:{name:\"鄂尔多斯市\",cp:[108.9734,39.2487],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ĶL²ĬVłƑkkl@ȎŘWńÈĬȗ¯ºlz@ĠĊôŦôÒĠ°kÞÜn@¤UĸèĸbŌÈXĸLlÒĢxɲÆ¤ÈÛƾJÈÝ°UÅĶ»²VW¯ĸJôbkV@ôlbnĊyÈzVôab@ĸÞUl°yǬ²Ǭm°k±lbn°@È»JXVŎÑÆJ@kLÆl²Ġ²ʊůĊġřóƛÞÅ@mmLUÿóĉƧ@»L@`ČĸmȗÑţů±ĉğl¯ĀwÇçƧŤÛI@±ÜĉǓçō°UwôǫůķƳÅ±bÅ£ÓÇwnÑó@ȁƽ@ÇƧĢón»ŏĕóĊ¯bÅVȯÅImōKULǓ±ÝxċŋV±Āȗ°Źl±Û@WÒȁŚŹНŚÅèŌô¼°ȰɞȂVĊ\"],encodeOffsets:[[109542,39983]]}},{type:\"Feature\",id:\"1504\",properties:{name:\"赤峰市\",cp:[118.6743,43.2642],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@ɲŁĢǉĊwƾōÞĭ°_ŎŃźȹƒUČÿl»¯ôķVÿǬƽɅġÅÑǫ»̐ʟȣU¯wVWÝÈġW»Þ¹mÝƒɛŎÿŎōͩůV¹ōéċóŹÅVVĢǩʈ@Ėċ@ķÛV°¯xÇÅţ¥»°Ûôĉʟ¥WýČ¥wç»±mnÅķ¥ˋVbUÒġ»ÅxğLƧbWĖÅx¦U°ÝVóŰlô²@¥ÜÞÛôV@²±`¦¯Ý@ÅVÒō¼ô¤V²ŹĬÇĊƑţxç¯Lk»ʟlƽýmłÝÆƏ@mö°Ġ@ŚŹĬţÆUĀĠǊĠX¼nźVUÒ¦ĊxÈ¼@ôlx¯łʊÒÜĀˌÇČxÆČÈƐaxÒĠn¼ŎVÈ¼Ģ°ŤmǖČĊþLV°ÞU¼ċÈUÆzÈa¤ôbknXĀè\"],encodeOffsets:[[122232,46328]]}},{type:\"Feature\",id:\"1508\",properties:{name:\"巴彦淖尔市\",cp:[107.5562,41.3196],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@²@Ζǀݴʶհĸƒ¦Ķ̒Uˌ¼ӾÇƾ¼̨UÞĉƧéÝ»ĕĉƐȍōǪakóó¯a@ôţaV¯Þ¯°@²él¥ĵğťwōxó¯k±Vó@aóbUÇyĉzmkaóU@laóķIX°±Uĵ¼Æ¯VÇÞƽIÇÜÅ£ɱġwkÑķKWŋÇķaķçV@£mÛlÝğ¯Ñťóǿƴȯ°Åł@ÞŻĀˡ±ÅU¯°ɅĀźƧʬmǠƐ\"],encodeOffsets:[[107764,42750]]}},{type:\"Feature\",id:\"1505\",properties:{name:\"通辽市\",cp:[121.4758,43.9673],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ôƲĸ¼Æè@ÈȮwƾ»ʠĢ¥VÆ@²¥@»ŎÑ¯ĊJŤ£k»ÆÇX¯̼ōī°aX£ôƾȁź¥aôŤĢL°ĸ@Ȯ¼ÈÒʈŚôVXůÆaĠƛÈKķĉôÿ@ğÈĉ»ÇVnĉVwXĠÝ°ČÿĸwV¯¯ǵ±ĉǫÅÅm»²Ż±ƽIm¥ţÈķ@¯ƧJV»ÞUÝç¯UġºU£ţóaÅÅlƧī¯K¯ÞÝğL̑ȍƽ@ōŎōĀƑɜnÞÝºX¼ÇĢÞUX°xVʠȤ̏Ǭ¼ÆÒɆĢǫƾUĀóĸ°k¼ċĀƑVŹȺōń¯`ÝĮƽŎĉxġǊɱłō¦\"],encodeOffsets:[[122097,46379]]}},{type:\"Feature\",id:\"1509\",properties:{name:\"乌兰察布市\",cp:[112.5769,41.77],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@ʠǠÞĸɲȺƒÒȂƛŎaÆÈĕȘţUÝźǟɆţÝˌKU»@U¯ÜÑ@Þ»ôaVÞÇÈ@¯ÜbƨƨÞlĸ@ĊôlôÅĊUÝĸm¦bmĊ@nĊxŤÑ@¯ƨĖĊ_@Čwl¯ȭLÝ»ƽ¯ķůǓ@ÇǓbċÅÅÆwÿĠÇU£óa¥¯aŎğĠţkw°»¯ůlÝĵkÇ»Ý°ɱƧǫaóôɱ»Çk¯ŃóʇŐŻĉǊŻĢ¯ÒÈUl°x°nÒĬónĊğ°ÇŚĉ¦ʵV°°ĬÛżÇJȁńʇʹó˂ƽŎÆţ¦\"],encodeOffsets:[[112984,43763]]}},{type:\"Feature\",id:\"1522\",properties:{name:\"兴安盟\",cp:[121.3879,46.1426],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ÆXnlŎ°@LVLĠþxĊUȮĊnUĠV@żaW¯XIŎġ¥Ý@K@w@K@I˺ŻŎ¦ƨƨÒŎIÆ@X@VºnX°lŎ@ƾĉˤƒȘǷȘÑÝÝÞbVţĸÿŤxÈĖƐêÇKnĸ¥ô@ķÞUnÒl@UÅaīˋ¯ÑƧx@±kXřƐƏÛéVˋ»lō¯ĉÅÇÓǫÞĖġV@ğ»°ĵÇÞǓ¼¯mÛÅŃĉĠÇƾb²çéż¯VğÞml»ōÑVç»V¯¯ĕÆU¯y°k¯¯V»ôÇÑ°a@ŹkġKţóbŹ¦ƽȂóW¤¯bĬ̻ŎW°ÅÈl¼ţ¤ĉI°ōÒ@¼±¦Å@Uġ¦ʟƽ¼ÞĢÒm¤êō°¦Èþlk¼ĊŰ°JĢńȁĬ°żnÇbVÝ¼@¼óĸţ¤@°Ånl\"],encodeOffsets:[[122412,48482]]}},{type:\"Feature\",id:\"1502\",properties:{name:\"包头市\",cp:[110.3467,41.4899],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@źxżĀǔÆǬVȘĀŤ¥ÅƾōôˁʈͳȂŃÈIÜŻ¯ī¯ōm¯ɱĖ¯ķÒÝIÝ»ÅVlÅôÑġğVmÞnnWçkWÜXƝÆwU»Șĕ£ĉÑğ±±ÅkK@lÅIōÒUWIÇ¼¯@mka²l¯ǫnǫ±¯zkÝVķUôl²ô°ŎwŦxĶĠk¦±ê¯@Ý°U°bóŤ@°bôlôǩbŎƏȎĊĖÞ¼êƨÝĊ\"],encodeOffsets:[[112017,43465]]}},{type:\"Feature\",id:\"1501\",\nproperties:{name:\"呼和浩特市\",cp:[111.4124,40.4901],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ʶUĊ¥ÈřĠ¯ĉômīÑ¯mwk¯ÇV°ÑżġĊǉǓɱţǓƝóX¯ɛÒóa@nÝÆôƜŚĉĢʉŰĊÒ¤ȗĖV¼ÅxWƞÛlXXèmÝmUnĠĢóÒkÆÆUÞ¼ÞJĸÑ°ɲĕ°Ŏn\"],encodeOffsets:[[114098,42312]]}},{type:\"Feature\",id:\"1503\",properties:{name:\"乌海市\",cp:[106.886,39.4739],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@Ș°ÇīXŃŗ@ȍlkƒlUŁ±īĵKō¼VÇôXĸ¯@ťê°źk¤x@Ĭ\"],encodeOffsets:[[109317,40799]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/ning_xia_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"6403\",properties:{name:\"吴忠市\",cp:[106.853,37.3755],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@nLV@VLaÞbn@@l@bUVlUVzVx¤kÞVèXn@nm°a@UÑ@VXnV@VaUVKUUU@@U@@KVa@U²@wXkWnk±lLnU@UmmVKnIVWnI@UK@UK@@UVKXkmWLWUXmlkVwUyVa@ww@aVIK@aVÈwKlLVV@LnVVVnUÜ²°WÈIUÆ@nÞ¼@¦@UÞUVW@UxUxVnbKb¯ÞU`VbǬV@XXÆVVl°InmnUô°¯anam£WVXKXmkôaVU@Vak@@wman@K@UÛUWKXUÇ@UIb@alW@akLUKV@@Ukw±InL@kmwkWmk@JUIůVmnnU@m@UKVKlkUwknVUKmbkI±KkmVkKb@U@aVkUmn`kIlaUK@UUKmbUIÝUa@mUa@am@UUULUK@bmKkbWI@WXwlkXWa@k@kKLVkkK@L@JUVmzUKlwUUnW£XVlKUwVU@aXI@aWaUw@W@_nam@¯UkWVkUWaU@nwmJkUVkWVUmUkJ@ImbUa@@WÅ_mJknmak@@mXaUV@xU@@VUnkV@Vn@`ULUbWLXVW@kbUJ@XW`@nÅĖWJ@m°@xxbnUaw²lÞ°xŤIVVULÛWbbkVVXÆ`UbVL@kx°LlV@VWbJn@bl¤ULV°@lmL@£U@@aUwmKULVxUVVx@@kU@mK¯LÇa¯@\"],encodeOffsets:[[108124,38605]]}},{type:\"Feature\",id:\"6405\",properties:{name:\"中卫市\",cp:[105.4028,36.9525],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@°@Èb°KnL@lV@@UwVUUwVKnLVx@bV@¤@nK@k¯UVKk£@amIXa@UkU¯Klw@UKVaÅ_UWlUaXaÜVKUUţJ¯wÝ±kxVbmaw@wn¯@XIÆĕm@X_@WVIlaX@WUXKVaVK@_Um@lUVm@U@Vw@VUÛwm@@W@ImKUkU@UaaX@wWaUKkw@UVaUamLUnk@»±`¯@kW@UaykbI@VWJkLWUkJwU@n¤mL¯wm@Um²XVWbnV@bmxVkxUblLUV@kVWKU¼kU@mn@JnV@bUnmJUn@k@XlxLVVnKlLVV@@LkKULVbk`WL@lkXW@kV@UÞUlÇXlkaUbmV¯@@L@V@bkb@xlWbbW@±@UJ@IU@mVkVxV@@lIlln@Vm@VUbl@JLmKÛXmVkUKULU`@LĉwKUXlVUl@VbJX¦̼bÞxŎxɜĖĠŎaô@\"],encodeOffsets:[[108124,38605]]}},{type:\"Feature\",id:\"6404\",properties:{name:\"固原市\",cp:[106.1389,35.9363],childNum:6},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Vnn@°xnK£mV@xlIXVlKXI@UJlazVbX@l°@²_@¼mlVnKVbUb@VlxVLXb@xWbVbV@VlnL@J@Xn@ÜxbW@nl@nblmnIÆ`@X@Vbna@aVUUWVk@kbWakbU@VwW@_l@nmn@@alVlk@UkmVak@@aUXaL@¯@KVa@axWI@KnkVaVJn_lJ@X@m@nVanUVb@mXLlJVWnLlaVVaVX@KXVVkVKlknKVa@aVU@KXb@klJUknUm@K@_UW@alIUamaU¯kJma@IUK@U@@UW@@aXLVVJVaXIKlaUkUV@ambUUJkIWJ@wUIV@JU@UwV@@Um@nU`@UkUmVUxWUUV@aÅb@aWXkKUUUUaWK@wnm@IVU@aXwm@UmVaUalk@anKUwlUwlkK@wmaUkmmIk@VmkUUbW@UVUnW@kV@xkVmbVnU@UbUV@ak@kkW@kLW¤@nV@VU@W_UVUU`VLUV@IUVõVULU@UUUJ@wmkUJ@WI@l@bkKkbVVbVbUL@UUJ@Vm@@L@xbVVVLVlVwX@Vb@bmUkbk@@JWIUVÅw@Km@UkWKXxWLÅ@UVUnWK@xkVW@KULwWVXVWzXVVKVXkVV@VUbV@UVV@@LXxVL@VbLnKVLVxXVmb@l\"],[\"@@@J@aU@LWK¯UUxVVn@ĠLUW@UbUUUa@KUX\"]],encodeOffsets:[[[108023,37052]],[[108541,36299]]]}},{type:\"Feature\",id:\"6401\",properties:{name:\"银川市\",cp:[106.3586,38.1775],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@UwVK@UVWÞUbwV@knV@@KU_VK@Kn@W_XWlL@Vn@Ċw@Ula@Wanamī@a»ŋó@aÆÅɲÿUaV_°ÝaLaUmVwVwX@VUVÝ@@¥Ý»@mVÅÇJ¯XÛ±VUmUmU@KUUkKLÇxU@bLUJ@bx@xUbVzUxklWnXVKnXWlUL@V@VL@VL@mJUXmJULnn@VmVkK²mlXWlx±@@VUb@L@@VV@VVULVUbU@WmU@Ò@V¯bmn@V@lVnUnVWXVl@¦VVUn@x@XL@¦lXxVb\"],encodeOffsets:[[108563,39803]]}},{type:\"Feature\",id:\"6402\",properties:{name:\"石嘴山市\",cp:[106.4795,39.0015],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@U¯ķó±ÇÛ¯ķmbXb@kb@Vĉxm@@UkKWXX`m@@LULV`@L@mU@lUxaÝVUX@VULxVkLWV@JnVLXVlUV@zlVL@V@bn@lU²WVLlLVbUVxUx@xǀLxôÒkK²VaU@wXa@WÈĉUa@bÈkm@¯\"],encodeOffsets:[[109542,39938]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/qing_hai_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"6328\",properties:{name:\"海西蒙古族藏族自治州\",cp:[94.9768,37.1118],childNum:7},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@V£°@laXô±źwô@UlżaÜnKw@Uaa²LmÈLÆÈxlaUawÞmÜbÞUnJ°akôÑkwÝVğwÇ@ÝkkV¯¥@ò»nŤ¥XImw@mVwa@ÅwmLkaWw¥l»kçó»@WÑĉğ@ĉŃUwóřVómĵ»Ý@VǕ¯kÝĊÅk°ÓUklkU±IÇÞk±@ƽJ@UġIk@W¦VÑșÓÅnťKULn¯X@¯mUÛ@WÅmóKknōbxÝ@U@kw@ÿÇLţÝUkmwklċVÅU¦LkUWlÅÑ@a@ÅÑ±UóġŹ¼ÈĉmŻ@@wkwKl¯Uġ@lÇUÓ¯_Waĉ²Åló¼VbknKÇÅ@ƧĢō°Ý@ğWÅxUUm@ÝXÛWULUè¯@mbUaLbUWġxIUJWza¯by@ōÈóLU`ÇXUlUĉV¯nmÛbǕLklUĉVóaġƏbġKţnkbÝmmnÝWȭÈÝXţWókUÇl¯U¯ġUɅĀ@°¯¯VÆnmJ@ĊķnóJUbÝXUlVkL@lVxnnmb@¤Vz`ÞÞŤ@VnÆJV°bUôJkzlkl@²ó@ÆÇ°kĖÇbÛU@lmbXVkzVɅĀXˢlńĬŹ@éÅ@ĉńÆ°ğbUlɜ_°@xŦkbVbƒKĢŤVŎ°@żÈźlĊôKôb@nôxŦÆ@ôŎL@þÆb@nnWˌbÈxInaŎxlU@Ñ²±ğVUĢƨbɲ@Þ¥ôUUķWVô¯ĊWʶnôaŤˁ@£nmnIôǪK°xUXô@Ŧa°mkXÆÞVŎkĊ°ÞLÈôyVaIlwX°UVwĢÑÜKôw@nV@m°nmnÜɞ£VbmXn°ÜÒ@xx@Vb²UlbkxVnJUnVVĊ°KČm°nxÇnn¤±¦@UXVV@lVbmVVÈVxÒ°IbźaČbVw@VLƾÑ@Ŧô¯ĊkôÑ\"],[\"@@@@nòVaw²bVxxÜaČVô_ĊJIVmLa°@Ŏ¥XlK@klKVbUb@nUĢnaÈ@lmǬ»Ġ¯nmnƨVyÑǖĠ»ɲIn@@ÅĢƳ@¯°ôVKÈbVIÇ¥¯@Ýó@ÑnīWKkk@¥¯ÅaX±VÅw@±Ġ¯@»nWmw@@¯VUUWçKĉa±VkkV¯wx@UJx@bknÇbmÅ@Uw±U¯¦UKm¯I¯ť¼ğĊ@ÇŹÈ¯@Ý»ÇnˡJbÛèÇnÅK¯ġĠŹW¼Ålm@¤n²Ýb@b¯l¯@Å¤W¼nV@x°@Vx@lbUblbX¼WÇ²lU@¼V¦@bÇlVxUbVxÞbVbm¦VV\"]],encodeOffsets:[[[100452,39719]],[[91980,35742]]]}},{type:\"Feature\",id:\"6327\",properties:{name:\"玉树藏族自治州\",cp:[93.5925,33.9368],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ɆÿĢV°°VÈklVôŤXÞWȮÇÞXnmÞnlaŤmĢLƐaĢôbĊUVlkǖKÜan°mĊUVVkÈWV_ôKŎÇ@z°abXyVIJĢwVXaKVbna°@VçVKXÜÞWn@VVÆwXĠÞ@Ŏ¯ƨġÆ@ÈLlmUaô»ÆkĊ±Xb°`ÔVkÈĢ@Vk°Llx@xż@ĊnÇź»ôĢ²VÆÒ@@bÆÒXklVKV¥ÆČUklnxlç¥ċç@±m¥wÅJ@VmÈIléÈa°U¥@kÞVK²ÑW°w²ÑK²ñyÆÝVmw»kkWĉJWUVÅwLmÅ@@mwkn¥VÑ»°°@@»¯LlaJônVUÅ¯U@W¯UmÑ¯¯k@WykU@¯wV¥kVwţk»wWÇĉĶçKÞÇaĉbIlU@kwWXU°w±@UKn£WĉKWxkĕVamwXw@Wmnk@aVkbĉLlImmwUÇWxnÝJn@¥ÆkwaXÜĉ¯ÅV¯¤mkx¯kķÜ²VWôŹVU@V£¥@°wn@m@¯@UbUôķmn@ÆÛ@ÇýVaUÇĊV@Çlğ¯xÝŤlVÈÈVx¤VxkK@@x@kVĖġ¥kIWbXŎx@nxÅUW`_@±UaLUxK¯WbkVlbbmLÛÆWIUwWkwÝV@kIéUbUUkV¯Km¯k@UmÝ¯m¯mLÞĉÛUmġ£UxkKm°Lwk@kVmKVUk@¯a¯ĢmóKUUxImlÅnÇbXèVVU°@@xXnm@¼ğ°@²ÆxU²WÆb°@¦llXLmĬ@ÒÞô°@È¦UJÇaLóU¯@°ġƴ@Æ@mɱJğ¼ǕÒUzƧmnmğ°ǫ¼knÇ@bġmmV@VaUaLkl@kLWō¦¯@bKUnJĉIó`ċUÛbwUw±axbñUm@@babÇÅXmƒÝÅôVbÞblUÞVÞU°VUx@UV@l`¼nL@ĊLW¤kXķWġXUVVVķUbVb@°kVVxÈa@Č¦ĊbaźJU@ÈVl@XkôaWĢÞ@laĸUÆb²mÞLĠÞÑôbÒĊaJVbm¦\"],encodeOffsets:[[93285,37030]]}},{type:\"Feature\",id:\"6326\",properties:{name:\"果洛藏族自治州\",cp:[99.3823,34.0466],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@ÞVŤÈK@ĀlxV@Þ@wŎalmôLnXÆÜ@nV°@°WmVKŦLÆmȚÔÒUX¥l@ĢJV@ƾI@wW°Ån¥kÅÝVwôÈç@lÑĊĕaJnaÆLVw°kny°UnkÆVČĊll¦Vƾ@@nUźÈÇIn°XwÞKô¦VWV£@£°ókċ±Iam¯Va»ČĉV¥°@mk¥l@Ċm@aUmwX@wÆxmĢ_`VnÆbKVw@@nUVğVmVVöIll@@çÛm£UÇw°@VU¯»m¯JōĖÅLa@»ĉĢ±`U_k`ÇçókXlK@akÝÞ£WċkÝkxJÝ¯ÅwxķxmIÅx@k±J@ýŋ¤UkmV°ÅÝxkwmġnÝVU¦ŤlmóXk¤UKç@mVkK@klī£m¯VUbW¯¼ċb¯ĵam¼mVXm@k¤ÇXÇbU¯J¯¯È@bVXVÒ¤V¼kxÝV@lVWxÛ¦W¯mKnlkU@nƑUĉÝ@ÇºÛċUĉ¥UÞÅz±òL±Ò¯xX±ÒLÝU@lV¦¯ÇbkêÇJnU@ÆIxn¦@²Čè¦è\"],encodeOffsets:[[99709,36130]]}},{type:\"Feature\",id:\"6325\",properties:{name:\"海南藏族自治州\",cp:[100.3711,35.9418],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@Vxń@ĊĠĊXÒ°UƾĕÞm°£nb@@LUUWÛº@nlÆǬĠ£ÞV°UXbVȂǵé@kWanm°@xzK°¯ĠVVkwLnm°kÞxÆa¥@wnĉÆ@_l_VwmĸèŤÅČU@Wn@ÑmKUnğK@°¯UÿV£nmLlUUÛé±óókkmnakV@Ç°óÝXWəÞťIţxmmVÛUVȂÓnWyȁĉkV°WnkĊa¥_K°ÿWna@mU¯wlÝIU¤UXó¥ÝLx¯WmJÇÈŹmV@ƽ@Uk¥ĉkċÅUml¯Vmz¯lUxÅKmbIbĉĖkÒ@ÇèóUxÆÞlm¦Æ¯X@x@²ÝlÈJV²klVl¯ÔlĉÆÞ°lUǖÞ@Ķ¼nUôôŚ\"],encodeOffsets:[[101712,37632]]}},{type:\"Feature\",id:\"6322\",properties:{name:\"海北藏族自治州\",cp:[100.3711,37.9138],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ōmġxƽUm±LǿþġÔ@kxmWb¯I¯mIUx@bbŹVÇkĵblĉI¯¥Um@Æ¯È@aóUlČ»@w»wXaó°ţçÝkUaV¥ÅbÝw¯lmnKlxUğU¯°Lyw¯@mnXbl@êȁǶUWa¯VÝUğ¤ǫkÅ@mÜ¹XVV@K@ma¯¤ÝnƽĖ¯V@¼ôlèk¼¦xXlbnKÆx@bUx@nnxWJţ¦m¼ñ@°¦lUÞlÈ@ĠxÞUlxÒól¯bmIÝVÛaÝnxVbkbÇwÅÇKn±Kbb@VxLmÛŻbkVó@Źxó²Wkb@¯U¤źĊ@lUX°lÆôUlLXaV°wxUb°xÜôÈKVkÈmlwkÈKwKVUŤĉŎ»»Il¥na°LV»²¯Üy@wĢ°ĸwlwĢw°±_lVk@°bÆ¯z@l_@Ģ±lÅVlUaÞLVnKlnÈ°IllČawÞÑ°xUU@wVkmĠLô»KÞýôaÞ¥ôĀÞmÆmUŎV¥Èl°²°a²¥V@@wamm@Ñn@Æ£żVĠ£@W¯Þl@»@Uk@\"],encodeOffsets:[[105087,37992]]}},{type:\"Feature\",id:\"6323\",properties:{name:\"黄南藏族自治州\",cp:[101.5686,35.1178],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ôl²ôÜêVVkKmnU¤VĀ¯°@LmĠVnLÈL@alb@al@n°V_XmWUÈamaVIn@naV£óVWU£°axÈ¥@aĊwÈ¹@óağbm@kw@maÆw@In¯mm@UkkWÑÅ@@kċÅçVkÝJÅkVykŹl¥@¯ĢUÜX¥òýmmXÝÅlmU@£WlyXW»Åbl@aI»k@klm@UxUUV¼¯XlaUnķI@x@¯KĉUU`ólČ¯ô@¤ÞJk°xVn@mbX¯ĀL`¦ĉbml¯XUlȂĊXzmȁÔUÜVUnnŤwŦJɚÝXÞW¯ô@ÈlUbmln\"],encodeOffsets:[[103984,36344]]}},{type:\"Feature\",id:\"6321\",properties:{name:\"海东地区\",cp:[102.3706,36.2988],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@@Òb¤ÆI°ôU¼°UnnWx@b¯L@lUUWbXxWlƨnxVUllXVUnL@lȀý²KVnƾĢwV»@mÞ£nÆÞÑmLKUaVżĕWVk²ÆÝ@Xw°@ô@a°wóUUmIkaVmÞwmkny¹VÿƧnÅm£X»naV±Ýw@ab@am¯ĉVó¦kÝWKUU@WanUb@ôÇºĉxb@Ç¦w¯bV¤UXôU¤bmm@UJnbÇbXVWn`¯Umk@@bka@bÇK\"],encodeOffsets:[[104108,37030]]}},{type:\"Feature\",id:\"6301\",properties:{name:\"西宁市\",cp:[101.4038,36.8207],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@@kmKVUWkVkUmwƧXkWwXaVV@k°K@aXwmmV¯V»¯óÅJ£amX@ċVţÆķçnUx`k`@ÅmĊx@¦U¦blVÞŤèô¯Wbx¼@xċ¼kVôbÇ@Å°@nV°¦ĊJkĶalÈźUa@aVwnJ°°JanXlw@ĢÓ\"],encodeOffsets:[[104356,38042]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/shang_hai_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"310230\",properties:{name:\"崇明县\",cp:[121.5637,31.5383],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@uŏu»GPIV±ÐɃŜ{\\\\qJmC[W\\\\t¾ÕjÕpnÃ±Â|ěÔe`² nZzZ~V|B^IpUbU{bs\\\\a\\\\OvQKªsMň£RAhQĤlA`GĂA@ĥWĝO\"],encodeOffsets:[[124908,32105]]}},{type:\"Feature\",id:\"310119\",properties:{name:\"南汇区\",cp:[121.8755,30.954],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@`yĉNǕDwǏ»ÖLxCdJ`HB@LBTD@CPFXANC@@PGBKNECCBB@EBFHEDDDSNKAUNBDMNqf[HcDCCcF@EFGLEBa@ACoCCDDD@LGHD@DJFBBJED@BGAEGGFKIGDBDLBAD@FHBEF@RFDMLE@SGANFFJBANPH@@E@FJjRIACDMDOEKLFD@DbDAJI@AP@BGHFBCBGDCC@DCA@CECGH@FKCEHFJGBFDIHACEDNJDCVFBDCRKRLDLITB@CjNJI^DBCfNVDHDFKHAFGDIICDWBIF@@CFAjFJNJBBHD@CJ@AEFJ@@DH@BFBCPDBMFEQGDIFCNDHIP@HDABFACBJFHEBSZC@DP@@JDBƤ~\"],encodeOffsets:[[124854,31907]]}},{type:\"Feature\",id:\"310120\",properties:{name:\"奉贤区\",cp:[121.5747,30.8475],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@~T~JjZdDbLXDLCB_J@@FHFZJJIAGH@HGR@BENBLID@@LFCDF\\\\FpDBDb@FAHKFE@dEDDdC\\\\GreNMACVMLBTMCCFCEGFAA@DAFDLMHA@OD@BMEWDOC@AS@KGAI_DcKwÕísƝåĆctKbMBQ@EGEBEJ@@MBKL@BJB@FIBGKE@ABG@@FMFCPL@AjCD@ZOFCJIDICIlKJHNGJALH@@FPDCTJDGDBNCn\"],encodeOffsets:[[124274,31722]]}},{type:\"Feature\",id:\"310115\",properties:{name:\"浦东新区\",cp:[121.6928,31.2561],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@EN@JJLNHjLJNR^GRYVBNZJRBV@PDvbLNDN@LGNER@nCNQNuT_TIVFV\\\\Z\\\\XnDrI|[Ʉś²ÏJUHOƣ}CA@IO@@CYDATGFIEDAEBBAGCO@GJMCEDCJRHEFANOCADAEG@@CI@FE@BDIC@AGIAIMiEEB@DE@AJCXJDCJEHGBELGCUCeMAD]CIJiM@DSAKJKCLQDQACUECDMIFCBDJGECHAEIWCK@GLMCCGEACNKCEJG@MMBMC@@CIJUINT@JAJSTEPZZCP\"],encodeOffsets:[[124383,31915]]}},{type:\"Feature\",id:\"310116\",properties:{name:\"金山区\",cp:[121.2657,30.8112],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@L@BIHFN@@EE@@EFBDGDAADVDD@@EF@CA@IIsRE@GDAF@BF@CV@|FBCHBLCNHAFCADBMDCFZXHILBVEEQA@MWFARJJ@DCX@@TEFBLHAAERE@AJABRPBNK\\\\BrJ\\\\VHGND@CNADKDADQjGAGNC@GJ@FCFFHC@JF@@dLBDSFADHVG\\\\DTEPDDHJALIJkJDJCDIPE@YDCBiK@DONE@EH@BAF@HLJA@EIA@ALKNA@@FIFAFHR@NALadsæąyQY@A±DŉXUVI^BF@FFF@HBJEDFFGFEBSRkVEXGHFBMFIVW@GAEEFOIAIPKABGWEKFSCQLQBSEIBC\\\\FdBLRR@JGACFDDEF@AWB@LJJYNABBA@CUEGPaO_AIE@MYMFIGAEFECHSAAKAO\\\\[JEDB@E@MMA@@AGBKMGDFFCDDFEDFJF@NPBAFLHFH@EDDHBADDC@DDCDHHCDDFDABDAD@FEFOBCJ[D@HEDDNJBDDHABJIBBvGLBJAH\"],encodeOffsets:[[123901,31695]]}},{type:\"Feature\",id:\"310118\",properties:{name:\"青浦区\",cp:[121.1751,31.1909],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@RUNKdOFDJCbRFMLAHPLDN@JGL@@APBWYCKN@TU@SHGCEJIDIJKVIZVNM`iNY@CIE@CA@KBOEGEUFCCSADEIEFCDDDIDDHC@CKIeDCG@IG@DHWFEEGCH@@GO@@O]CNpeEQDBFME[JC]DGF@CKOA@QSB@GB@@GW@@ED@AQIJIAAFE@@DO@CFI@KNG@CDACAFEGKGBEGBDCCAIFCCLIECFI@MBCLDHGNAHSF@DMB@EEKBA@@C]DEICFG@ADBHGFKCDAKKHKD@@FHGAANGEEFCHKCECBCKG@ADKCNE\\\\[A[I@@mGBDQQEO@BCE@AI[AML@JGACLOAFKEMM@EQKC@CUCBCCBCHEA@FF@@FM@GEAJK@GNF@EXPH@FD@M^@HIADJCFDBER@DK@@DE@CAKFOCCBDHIBCNSB@GFC@GQEEOWFICGDUAEJIDBTAHJHEB@DIF@NE@H|HBDBEH@DKBAHEF@HEEUB@FGFGCCCE@AHOB@NH@PRLVNNFBX@RCPbAvMtBfH@DJF@ELBFA@EH@HNED@FFB@HLC@CJ@@DJ@PIRf@HE@CFF@GPHD@DKE@FFBEFFD@DEFCA@DD@IjCRFBAHFDKD@HF@@PM@H@BlbDJDBFEF@DLXB@HCD@@IFCBIFEJD@FDC@FBALLF@PAACJERACAJCBD@EL@JD\"],encodeOffsets:[[124061,32028]]}},{type:\"Feature\",id:\"310117\",properties:{name:\"松江区\",cp:[121.1984,31.0268],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@DLDFRN@FNELPBDKHB@INK\\\\BBJF@ADP@RFCRHA@nJ@B\\\\[\\\\MFLDBCH@DLDADFGLEDFFMHBBGH@EC@GLLLCBLDHEAGBCH@DEFJ^C@DB@LAFFA@CNE@GTMBGHKCAD@NEJFDKJDDJEDBCDHAAFLHFHBEBDDCH@LMJ@DEP@@CF@BEJBJIBRC@@FX@@HA@@HTA@RPBDLE@CHD^\\\\INFAERCfFMo^D@PP@@HG@HDFFXECGH@@JDHfCLJ@DGDCCCJCCEDJFCFTBDDVEHFPFLAB@NBFCFKFC@CHIACNOHWHCAAFIDD@CDAGEI@ACFMF@R@R_@GQED@EGFEQEDE_IAHKAEXCQUOQCUDEN@ZI\\\\DDmAMHCICDSOC@EG@BKHIGMIBCGOCSF[CUHCGEBCTKA@cE@@IGDEEEDI@@HMDBHiHCRCBCLMB@DMCGH[UqI[AMLOAAQIB@BQFBFGBAKFE@SW@CDI@QIEBNXB@FRUFKAGJYWDENCCADBBEMGKDGAAD{EU@@DAEE@CB@HQFJt@JDBE@@FC@\"],encodeOffsets:[[123933,31687]]}},{type:\"Feature\",id:\"310114\",properties:{name:\"嘉定区\",cp:[121.2437,31.3625],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@F@LI@IDKJADKIEJICADGACFECCJ@HKCAFOHAJI@aCBEE@ICAEB[GFGCKL@FGEIFADMLCAEJM@ELQECEIG@BE^QKKLQCA@EHBIGQ[GEHOMGGDHKH@JOECFCjCBEFDNCACMBCILGTABDLEEOEIG@GFIMM@CGKFBFCDE@@GEAGEEACIcGaHMFITIHDN[AKF@FS@OA@BK@IHM@KCGOKBENaQIDECcPMLQVFHFB@BFBKLGD@FAJOVGIACQ@A`LPCB@JEF@RU@ANS@@RCL\\\\HIFpRBFRBBDKLLDADJDGBFDABHBEDNF@DGBBBADKDAHC@\\\\JJFBDEH[DEFDH\\\\LX@XLBLbT@DNJLDCEL@VJABJNDHB@HBHYFBAA@GNFB@@AFB@AFABFLFBHFCL@HJBAFBLC@DN@HN\"],encodeOffsets:[[124213,32254]]}},{type:\"Feature\",id:\"310113\",properties:{name:\"宝山区\",cp:[121.4346,31.4051],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@mÖoÖi½[s[YEUJU`SCIEBCCWJY_LIICDWU@@FaBCJIB[ICH[@@CDKEE@MK@@IMCAEBCH@AMFI@SMGEFGB@FK@BHCAIFJNQD@FEBDFMBKGACG@ECWH@@CDDTOEEBGEK@GC@EE@GPHFR\\\\JHGA@FDBKRLL]RAFH@FJFDKR@FINBFKDCNEBFJEHK@DLEH\\\\HFADB@JFFDA@bIJGBEPDBGLI@DDEFBDCHDBIJJFCLIBCL@JKJE@ADHDBHJ@HIBBDFHBBAEIJ@BJFAVL¢\"],encodeOffsets:[[124300,32302]]}},{type:\"Feature\",id:\"310112\",properties:{name:\"闵行区\",cp:[121.4992,31.0838],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@T@@ELE\\\\BCMJGJSNEbGdHDJFBJAFIEIFCEWG@@gMENSFCVJFAxR~B@IH@AIiI@GE@FGEAFQPDRiV[\\\\DFSGMHAXHDOMCJCDETBBNVJJI@DD@ANNNH@FILDDMFBDHNDHKL@XDFGLD@EHGFD@DDB@CDDHCDAEAHG@ABOJ@BIaC@CECLKPFNCDCJBiQEIF@@@OGBMIAEEBMTHF@NKEC@QFEGA@EBCKAACHCLJHEFHHB@AFCAIEACIC@HG@KCCDC[ECEED@KC@KJMAAFQ@GHG@BHIJYIGE@EI@A`KDWCaKcCiY}I}S[CYJM@CFDVPRRVWDFLBBG`JCFRFEFFHC@RF@HQ`Q@E@ENBDJ@HFCB@DCCEJBBGDGXMPBDGJ@DEDELEDMA@DJF@DMZ_jMNYUUJILCJIJDFGH@TSVM@DLXZ\"],encodeOffsets:[[124165,32010]]}},{type:\"Feature\",id:\"310110\",properties:{name:\"杨浦区\",cp:[121.528,31.2966],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@V@CXJDKJZ`XIDDFADJvSRMDM@mFQHM@KCMKMuaOCU@BDAJSX@HKJGD@PNJCJWAGT@R\"],encodeOffsets:[[124402,32064]]}},{type:\"Feature\",id:\"310107\",properties:{name:\"普陀区\",cp:[121.3879,31.2602],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@F@@FHDL@HFFAPFCSDC@@XGFDH@BDLHNACEFA@ERCIMJEDBAGL@@EHAFENHHJ\\\\ONQBQCIBC[MKACKI@GGGH@I_G@CW@[DMHCDIBMTDHN@JNHEH@FJFPKFACSBKHDJNABDMDECAFiDEDFDIPG@GLHCNH\"],encodeOffsets:[[124248,32045]]}},{type:\"Feature\",id:\"310104\",properties:{name:\"徐汇区\",cp:[121.4333,31.1607],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@RADL\\\\NCPHFfLJaJ@FWLGMGIK@IFMDOYYFOTSBI@IMSAMSACFIDNDCPWGGBHNET[CU\\\\QjOCERFBEHF@@HjJBJG@@J\"],encodeOffsets:[[124327,31941]]}},{type:\"Feature\",id:\"310105\",properties:{name:\"长宁区\",cp:[121.3852,31.2115],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@HFFB@HF@DCAELENSJADCNG\\\\CX@@D`H@JHGHHJ@BINBFUGEDO[MCKQB}AwQEBUIEDMTNF@hH@FXEDFJEJIB\"],encodeOffsets:[[124250,31987]]}},{type:\"Feature\",id:\"310108\",properties:{name:\"闸北区\",cp:[121.4511,31.2794],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@CSG@BQGODUPWTOBQAAFMECKBGEMFKEOHADDJARMR[PGI@TEJBNG@ADBFND@JL@@NFFCL@D\\\\@DG\\\\JJADI\"],encodeOffsets:[[124385,32068]]}},{type:\"Feature\",id:\"310109\",properties:{name:\"虹口区\",cp:[121.4882,31.2788],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@bA@E@QHSXBDIMI@OHCLI@GTWBIACQAYIOFGCENBBARSPOXCVHPARH@DT\"],encodeOffsets:[[124385,32068]]}},{type:\"Feature\",id:\"310101\",properties:{name:\"黄浦区\",cp:[121.4868,31.219],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@NEHFLAFDHDPEAMZUHQQ]IMKJG@EPERABHBGRUCCNGV\"],encodeOffsets:[[124379,31992]]}},{type:\"Feature\",id:\"310103\",properties:{name:\"卢湾区\",cp:[121.4758,31.2074],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VDHQGABAFQFOH@LIiKKHEXI@IbAFZB\"],encodeOffsets:[[124385,31974]]}},{type:\"Feature\",id:\"310106\",properties:{name:\"静安区\",cp:[121.4484,31.2286],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@DLLB\\\\NPGLFHUDMYABEeKEVMAAJ\"],encodeOffsets:[[124343,31979]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/shan_dong_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3706\",properties:{name:\"烟台市\",cp:[120.7397,37.5128],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ŤLLllVń²è°xżĢĠÆlÒŤbV¤ĊXnlĢVĊÒÈ°ĊŰÞèL±@џn»VUźċ²»ÆkôVɆkĊŃ²kŤVVwUUVmUa@KkU@mUmmk@UwUkmW@UVIXa@mw@aKULax@Uk@UbWU@yULmK¯@kXVUwm@@JUUknWKUVLUbU@wWykIa@w@mUI@aUVynIWak@@Wbl@@knmK@wnIl°Kna@V¥ğ@ġUķ»¥@UōJX¯¤k@wmI¯k@mwak@@lX@bUJ@VbknWxkLkxlLVlkLmb@bU@bU@VbU`Vb@nL@mbU@VnUVmnU@mm@kIUWVIUKVkkUJUnmL@VmLUaVWaXamU@U@KUUmVUJUVÇwğnm@mXĉV@l¯xnô\"],encodeOffsets:[[122446,38042]]}},{type:\"Feature\",id:\"3713\",properties:{name:\"临沂市\",cp:[118.3118,35.2936],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@bXll@zlV@lXXmkbVVlU@Vn@@Vmb@XKVXWJ@XXl@ÈbVLUl`@XXV@VVUxVbUxVb¦@WnXVJ@bnVUzl@°ÆxUKlU@mUUnUlUVWVUnVV@XX°V@Vll@VkaXVl@Ux@bmbXLlKlb@b@bUJn@@b@n°x°K@an@@UlLVKVbXb@bVVnK°LVa@UVa@XwKVxnLU°@naV@UWUkWULmVwÝKUUla@aó_@mK@aUU@WUkwVm@aVI°W@@IUw@a±¯@¥kUVUm@awkw@K@kVKk@maXalI@alLWXblaVLVUV@LnK@l@waXaLlnUlLmV@n°J@_VmnIVym£UKmI@WnIVm@anUVmÇ_kġIÅWUXÇm@U@Ý¯Å@@naWIVW@IkK@klKn@naWImk@abkKkLWnWkLWmk_@UaVUKmLUw@mn£WwUmUaóV@UkUm@UKULUwmJUX@WW@XÒzVblJXWXk@UVWKX¤UL@xU@@VUaU@@XmVkLmWkXUyÝLmKXnV@n@lx@bWLnVVn`knULmxUlWLXVb@VK@z¯x¯¼WxKUn@bk@lVVVz\"],encodeOffsets:[[120241,36119]]}},{type:\"Feature\",id:\"3707\",properties:{name:\"潍坊市\",cp:[119.0918,36.524],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@l@@UK@@L@bX@@VlL@JLUVnX@`ÜXn`V²mJ@bU@@nb@l°xnnĸVÆ°@Ċ£Þ@lWnÑnkʶJmó°w@kk»V@»¥k@V@kw@wVmaÅmaô£ŎXI@mlnKla@mV_UK@kUkw@alWIU»m@WUIl±UUÅUbkJ@a@wUKUaVIÆmXIWaka@m@Ul£XKVw@UIJUkmJVkU@aWKImV@UxmL@bX`WXU@U`ÇkUak@@°UblXkmLUKmL@VULóVk@@Vlbn@Ub@ċaUJUbIUlVLUVVbVKXVlVXU@mb¯@VmKUwLWx@Ub@VUb¯KmLUU@aWaUaULkK@Vm@@b¯L¯w@ma@m@UUU@U¦lJUXVmkb@nmXVWkbIVxUV@VUbWLXVLW`Ux@nk@Vn@x@VkJ@V`mXk@VxV@lVI@VULVUIV`°bVXXxV@VWVnL@xVUb\"],encodeOffsets:[[121332,37840]]}},{type:\"Feature\",id:\"3702\",properties:{name:\"青岛市\",cp:[120.4651,36.3373],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@@nUJXL@blVUnIVlIVJ@UxWLk¤@V@nlbXbWJÅnUJVbVL@x@blIaÆVVVk²VJ@XnV¼JkX@blxlV@VLU`@nkbLkm@nWJōó¤bnÆbUn@xlxU@l@¦@¼Ul¼ĊUnW@nĠmÈxUVIVnUVV@LV@nVWbXbUVbnK@UnKVmVIllUVLUJVXlJ@nnV@nmVUUm@Vna@K@mUaV_UaV@aV@@aanlKUkKklwlKXwlma@UVI@akW@l@bnxl@°nJxl@°£WŎIUÑn»lamô¹Ŏ¥VaUUkmkġWɱIUUŹ`@kk@ĉƨřV¥_Ç@Ĭ¤ÝL¯m¯£ƽóķwUW±ī¯kōaĉĕkğmó°bW@UKkLUaVmz@V@UxVn\"],encodeOffsets:[[122389,36580]]}},{type:\"Feature\",id:\"3717\",properties:{name:\"菏泽市\",cp:[115.6201,35.2057],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@@¥IVUÈmÞ»@UlU@Un@VW@UVmkk@aVUUKVÝ@UVknK@UV@VVnIV@wnmwmKXaWaXI@UV@Vy²blkVKkamU@kb@Um@VmUkmKmkXKWwkU@Ul@UnK@UVUUmKXwUVLwKU@@Wl@@wUkV¥@@I@W@_V@VWUw@UUa@aaWa@@_mKUwl¯amzmV@WKnU@kWLķaUKbÝVmV@UWÇbÛ@X°UbW@XmVlk²UJUbmLÇxÅWUzl¯Ll@VkKXUbWJ@bU@¯@kbLmKka@l_WXºVbUz@Jn²V@¤lXnV°Ln`WbXLôVlKVUxXnlXLlU@bVV@XJWLUVnVV@@nl°nnVKÈbVXÆJU°VnXVkV@@xVL@Wlb\"],encodeOffsets:[[118654,36726]]}},{type:\"Feature\",id:\"3708\",properties:{name:\"济宁市\",cp:[116.8286,35.3375],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@nam_nKlVLXaIl`_@KVVXI@m@w@@k@Knô@n`VbV@@LL@KVVn@VX@VLJl@VUUU@Uam@UkwKWaXamkJmIUVUÈblaUnV@kVKl@@lXL°kVJ@VÈnVJUX@VLXl@xVLnU@VKV@aIUaV@bĊUxKkVJXUlVUVaI@WUI@KlUnwmWk@WXIWUL@Wna@Um@@UVkUUlanWW@kkU@ykWkaWVUlÝbUU@kJUIU@@JmaókLKÇUUkKWLk@WbkUUabmKn¯°¥V@XwV@VanaVaU_@Wlk@WÈ@VUÈVVÛmaklKÈ¯lLVUX@lK@aX@@kV@VmV@VwnJV_UWUwXam@kW@wVUkKVIUUVmU@UV@IVK@aUL@aV@LmUKmx@ômLkUWJ@nXmlUxUL@VknVUU@VL`Ub±LkV@kUKÇbÛ@UWó_mJ@Wk@@X@VLxUKVWxLVnUV@VmL@Vk@VlVXxWLnlLnVlUnn@@VlaV@nlbULkl±aUzU@@VWJXbWbnLnxm@xUmJUUU@@VmLUl@VUÞVLUV@bllUn@VUXm@@VkV@VÝ¼ÇnUVJ@¦nnlnVlL@Þb°KVV\"],encodeOffsets:[[118834,36844]]}},{type:\"Feature\",id:\"3714\",properties:{name:\"德州市\",cp:[116.6858,37.2107],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@¤@VmbVXnVVbVJX@ll@zlVInl@@bVxUbĠl@ÈblaIxXVWb@L@nULWVXXWWLnL@`@LUVVL@lVnJU@UUkanVôôb°¼VÞXIÜbČabôWXÞWÈzÆmnLVJ°ÈnlV²lbnW@@UUVmnwmkkKWkla@mVIUKUaaUwmnJU@@amIk@@bVlkX@mmUklUUa@_UaUUV@wwWkXmW@I@WUaÝU@UXaWUU@UUVW@UUUWUn¥nUVa@m@k@alU@wkLWa@UUm@@wnmUwla@anKn_@alK@Ý_@@WUUUmlkaIyU@UwU_Wa¯yU_mWUwkImm@InWWUk@@UVWVkW¯U@VL@b¯b@l±¦@VV@lUbV@kxVnUl¼XV@b@lV@nIWxnb@UULxÅxm¯aUwU@mUÅVÝKULm@bmKUXó@\"],encodeOffsets:[[118542,37801]]}},{type:\"Feature\",id:\"3716\",properties:{name:\"滨州市\",cp:[117.8174,37.4963],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@Vb@`bVkVlnV@nlWUk@al@nJ@bV@InmVxbVbVLUJ@nkblXlLnlmxnUV@V@mXnlbĸ@nnVxb@lnXV@UJ@nVxxnxVbÆVn¯ƒĕ@@wÈçUÇlķVIb@Çmk@¥k@UkUK@aWakUóJW_UW@wkkWK@U@K@XUUkmUUalKXala@U@kkWlkÈl@kVmVIVmU_awnwVW@wwU@wU£wkJWIyUI±bkVUJ@nmVUklXmx@lnbWkVUkLWxkKUUmUkbJ±LÇxUKmkUmkkWamUaVkJÆ_²KĠ@UW@wU¥nUWwK@aÝUkÅVaVK@akLW¯I@bnbVx¯JWñWbUL@nV@VmbkUUV@IÇak@@bWak@WJUJWL@bXV@@VJlb@zUlUUImnbVmz@°UV@VbV@@V@L@xLmKUnmJVXJ@VkLW@UVUL@b\"],encodeOffsets:[[120083,38442]]}},{type:\"Feature\",id:\"3715\",properties:{name:\"聊城市\",cp:[115.9167,36.4032],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ô@VWnLan@VKÞLÆUnVV@xVbn°ÆwwKVV@maXwmJU@@k@aWUk»VUmlw@UVa@kUU@²¥@k°a@aK@UU@mmm@ówÑ±¥¯@@wKmwI¥kU¯UmakJmIUaVkKUkm@VUUaU@UaKUK¯@wUVUIUKVwk¥wbV@xn@lWnXxlL@`XlJX¦l°XxW¦@¦Uln@@@Um@@VXVmx@¯bllUnUJ@VULVn@bxVVL@bVlnVVblVÈnVlIVJLôlJ@xl²\"],encodeOffsets:[[118542,37801]]}},{type:\"Feature\",id:\"3705\",properties:{name:\"东营市\",cp:[118.7073,37.5513],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@ͬUǪlô@°Uw°ōĠ¯»Ģç»XÇ@wwƑaÇkwVƑ¯@ÅķUmm¯w@ka@mV@@anIU±m_ÛW@_mWVUK@IkK@UW@@a@K@L@Vk@±U@UV@lm@mUU@kLmxV¤@xVx@xUXmxxbV`UnUJnU@lÇkkllX@l@VkbWbkLVbnVVlWV@@L@VXLll@xVXX`ôIlVXb@bVLVll@@¦nlÈ@aUJkĸVÈÇè@x\"],encodeOffsets:[[121005,39066]]}},{type:\"Feature\",id:\"3701\",properties:{name:\"济南市\",cp:[117.1582,36.8701],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@²¦Òôxn@nn@V°VlXUUX@Vl@XVmX@JnnlJVxnXV`°zXbV`VxV@zJlbkVnVV@X@`@ÞkL@bm`mL@bkbxnVm@xn@VV@XbKl@xkV@b@l@nUbmVm¦XVVV@VUXVVV@XVWb@VÞVVb@X@JnXlWXx@xUVV@aVKVUX@lK@UIUWnIVmnLK@w@K@UU@a@UVU@¯nyUmanVJVVk@ykaIU@@WU@aXKIVXIl@Xb@al@Èb@JVUlVna@UmU@VKXaòX°IUwma@aU@UU@wVW@Ñw@aI±`kbUkwUmJ@UkmÇUUkmKknUV@mJUkaWka@KmKkULmyXa¯_@WmImmbLmUkVUbUVJbUkkWJkUlIUmkLlK@knaVmkI@mWaLUKUU@@VmLUVLWK@UUUWUkkVmx@Vl¦\"],encodeOffsets:[[119014,37041]]}},{type:\"Feature\",id:\"3709\",properties:{name:\"泰安市\",cp:[117.0264,36.0516],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@n¼WnxL@x°@¥Uk@nwlUVlXVV@VXLKVUnK@UV@VVLKXb@nlJUnmb@lkLKlVnJklVXIllVaIVUValUnVKannnJ@X°`WbnzKlVnL@LbXlbVlnI@VUU@UmV@U@U¥@VmV@@_Ua@m°@@kmUUm@UVmn@nX@@aanJVUVLmlIVJn@nkVLVa@KVmVLXVVL@@U°bn@VaV@@K@aVkbWaXUVymU@aUImWX@¥UaVwUaVwUUU@WW@k_VUKÇa@nmxkV@LVJ@XJUbVkUWVUIlLwĉVaU@VbJ@bUUL@mVUK@wWkK@UVWUIÇm@UUI¯lWK@kk@UL@lmUVkbÇaUVVnJlInWbXbLxVln@VbV@VUV@kIUK@UWm@UU@LK@KU@Uam_ó@m@L@l@@x@nWJUU@L`k_JWbUKkmLn`mb\"],encodeOffsets:[[118834,36844]]}},{type:\"Feature\",id:\"3710\",properties:{name:\"威海市\",cp:[121.9482,37.1393],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@VbUnVVUxĊ¼¼ô@ÞÑ¯WǬLŎUÆW¹UÇō¯ÑÝkţţóġóLł̥Uwm¥kÝmkkKóbÝ@U¦@mb¯LkmJ@xLmn@lk@a@X@lXbmJUzV@bVJ@n@xblJXzxV@VaKVUXLlmVV@In@VxUlW°@nLVK@zXVVal@@VwbVKL@bnx@WbUJ@VnXVlVxl@nnnV@lV@L\"],encodeOffsets:[[124842,38312]]}},{type:\"Feature\",id:\"3711\",properties:{name:\"日照市\",cp:[119.2786,35.5023],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@UaVUUKVkJVaVIČb@Vam@ka@Ul@UôVK@UnKVLnKlkWVa@¯l@VbÈlV_V@XWW_@anKVwUmVw@@UnyUVblKVLX@aô¯ó¥mÛĊÿÈ¥Þ¹lUī¯Kĉ¼ʟbÇVUUXmakJUnmV@bUnmJ@XnJVLn¤UzmJUn@`¯ImU@nKVkkmKWbb@xk@mL@KUUVUKkbWaXkK@bkJWbnbl@UL@lL@lxx@bnUVlV@¦²°@bVx@J@¯XUJ@bUnlxVX@VV@bL@nô`@bkbVVÞLxnU\"],encodeOffsets:[[121883,36895]]}},{type:\"Feature\",id:\"3703\",properties:{name:\"淄博市\",cp:[118.0371,36.6064],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@nlKV@nVn@@kVU@²VVaU@wmKXU@UUWwUW¯aU_JUVVK@UJU@kUw@UlnWU_@lI@U@wUml@@mVwX_KWUXKVa@UVUUwJlaXWUn@mlanUVWkIV¥V@VVVI@a@akakLWKna@aVwk@WUbUlk@k@U¯UWWU@mUUVUXkVmVVV@nkVLVÅw¯k@WVXbaUl@bV@@b@xkVVXVxkJ@nk@@VLUlVbVXUVVUzVLVbUbVVWVkLmkJ@n±@UxUVVkV@bx@ÒUX@xVVV@°JXlK@bULUblÆÞV@bLXxmV¦V@xXVğ@±LÅ`IUlVbnbXllVnnlVLÈwK²IlanVVVlLwXlKVlUXma@knwWlkVnU@mVIUl²aVJzXJlI\"],encodeOffsets:[[121129,37891]]}},{type:\"Feature\",id:\"3704\",properties:{name:\"枣庄市\",cp:[117.323,34.8926],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@yUUUkl@@aVmLXw°»°w@yL@UUaWXKVknwVKlm_UmmUXK@aw@k@mUWmUL@@@£@KbÝV@akwaULmbUKLUU@lm@°mL@nUJVxVXU`mIUxU@UnU@@lW@@bkLW@UVkKÇ°kLlbnUÜÇUUVÇ@@Xkl@XV`UbmbUbU@WxU@¯¦m°nLaVblVXal@XKlLVVÈLKôlnbI@V@VJI@lVVÞaVkXU\"],encodeOffsets:[[120241,36119]]}},{type:\"Feature\",id:\"3712\",properties:{name:\"莱芜市\",cp:[117.6526,36.2714],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@lmnLVlÈVln@VnIVlxVla²_JlUUUVVw²@@mlInlKXUUUVaUaKUVyUUWVUUaVkUK@l@@mlIUwUWlU@w@aU@@LU@Ubm@¯a@V@UKWUUKUn@LUbUKmlm@UIkJnUKUVmIb@b@mWm@Un@VVnnVl@¯@@nVb@`U@Un@¦@V@VUVnV@\"],encodeOffsets:[[120173,37334]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/shan_xi_1_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"6108\",properties:{name:\"榆林市\",cp:[109.8743,38.205],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@ýVnIW»W@»kUÇLÝU¯¥ÇIUWWÑUWwX¯m@»n@ÜÈķô@a±kČ±wÑmwçċmU»ÆkkVyImĉÿ@Ý¹WnwÇVÅazmmĉ¦ókVmxxU¼VkVm_UlVlk°IVkmJa¦kLmmV@XmKnlUôVXbb@UaÇLğÜÅw£mKnmċwÅ@UkbmaVn@m¯aUJm_k@kWXyl@@kÅamwLUÞmWÅzUKUk±@b@nnKbX¤mzVVxÇn¯@ÒknWVUbkķÈÑWkk@VaU@mUkbÝÅ@Ý¥ÇbkĬXV`kLÇVmalUUanV±nwmkJ@In°KVw¯UnÅ@¥U±bUU±mWbÛKWnUm`UƒVK@bmnmÈÅ¼@VL@xxmŤ°n@VmK²VllKkô@êÜV@VXLlm¦UV°Ș¯²ÿ@¥@ÆĊ²ImĶnnb°bKVĸLlÞ@UȮÜ°IVÞÝÞlx@ķĀWUxèÆ@°XnlĊĖ°mnV²V°ÒÆ¦aÞ@zll@bÞĀl¼nKĊ¼óÈb²±IǪÒ¯ĖV@lxnVlkJlaXwŌĉ@VnlÆĕUÆLèŌŤôxÈlU@xlaUċĕXmIWmnkVVVW_@aÈWUUmk@¯çVm»±W¯n¥VmkXw±ÇVw\"],encodeOffsets:[[113592,39645]]}},{type:\"Feature\",id:\"6106\",properties:{name:\"延安市\",cp:[109.1052,36.4252],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@@kkÇmImUwVkUU²WmVkm@m`mIĢĕUVa@mXÿVVkyUýĕ@l_UmnWKVkţ¥awğ@@aôWakUma¯¯a±£kxmmxUwÝ@xmUb¯KwóÝ@kmm¹Ub@lklVbmnnVUV@xUknƧJUX@LÇWkwLķƧÅwWJkLkþĉxWzJUnÇk@Ɛk¼ÜÔÈKè@°lÈÆk¦ln@l¼@l¯L°UUVÇ°¹`m¼mXkbUaV@U¯x@¦ÇUUmlmUVmnnmlkw@@¦ÅÇLmx¯Ikl@¦mÆ°VUx¯Lm@JInlmxU²mVbkVbUnÈlKU_WlīÈaÞ¦Æ@ÞlanV@VUbl@XlÇÒĸlVaUXlm@Ñ°ÈmUwUnyW£amL@ma²@lVVLÆynXÝVKnxÆb@lk@WzX@lln`IV°b@nmUnbaVlÆ@ČxmnnL¤ÆxĠÛÈKVb@aWaUókVmnL@WUnnKl¥bnIlU¯JlUkVkn`lUUV»wnwlUôĊ¥nnyÆb\"],encodeOffsets:[[113074,37862]]}},{type:\"Feature\",id:\"6107\",properties:{name:\"汉中市\",cp:[106.886,33.0139],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@lKnb@nlWb°bkxĸwVb@łnlĊ¥L@XlÈVblÈKbakVwôml²`n@nVKlk²xŎ°¦VUJĊw@çnWçÞVkUóÛ@¥kwUmX¯WÑk@UymIUwlUn¥mUk²a°¯V»@ÝVÈÝċÅÅVl»@l@a°±@_kammÅba@m@Å¼KknõĠ@m¯LÅwLVxmb@¼kV@mw¯wVakKW»X±¼¯Vkxb¼W@nx@x±bóakb@ÝmU@ķÓÛLkVUmk¯¤ÝLUlÝ@Ýzx@x°bmX¯aUJW¯k@bÇWwÛwWx@XWlb@VÈUlwLnl°VlUô¦U°¤VUxVXUxlbkVVlI°ÅVlU°m@kÇU¯xUlLUlVL@b°ĠInĠ°ÈnK@xÞa²naUyXUKVkWô¼Èaz°JXUVÇV_JVz@nb\"],encodeOffsets:[[109137,34392]]}},{type:\"Feature\",id:\"6109\",properties:{name:\"安康市\",cp:[109.1162,32.7722],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@bĊaƨèwôô¼b°aXVÞVUÞ@aXm¥kImx¯¯V@anU@UÇéğL@¯¥V£m@ÝÈbKX°wČÿb@xÈblxÈ¯ĊmÆUVnÈ@ƨÜLĢ¥Źn°VnnKaô_ÈwUaXmnW¯klLXÇō¦ÝaÅVmbğUn¥±wÅéVan¥U»°am¥£Ý@wVw¥nUÑUmmVwmķIÅaóVWxkblb@ból@ğÒĉ¤ċX¯XxkÇ@óÆÅx@xķ_kmÝÇ£kblb@`¯²@bk@k¼ÆUČÆÞÇÞU@U¼¯°±bVlnm¦kVVxnJVz@lÒXW°nVlx@¦ôÜVUlÝXèm@è\"],encodeOffsets:[[110644,34521]]}},{type:\"Feature\",id:\"6110\",properties:{name:\"商洛市\",cp:[109.8083,33.761],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@²nlôb°aVwnKÞI`°wXôw°VĊ°@ÅÞÆVzÞK@x@aLÅ@b@nLl@lnmnLVwabVVnbU¼V°blbÈ@ĶŦb@nÇ@amIyUI@ĠVmôUVwkwlanJ¯lwó¥@an°J_@nóƒó@£l¥UwmaÑ@Um±V_J£JUW¥¯@_k¯¼mUVUè¯b@wmL»ğVmağI¯¤ċIUWXKĵ¦ķaJUbIlUóVmk@WÅÅÇ@mUÅVnĉÇ°kwÇa@waċĀ¯xWLÇa@ÞnU¤°¦@ĠKÈê@VmV@bU°°nwlJn¦WbÝ@V\"],encodeOffsets:[[111454,34628]]}},{type:\"Feature\",id:\"6103\",properties:{name:\"宝鸡市\",cp:[107.1826,34.3433],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@@£@°Ib@¯°ynŹaUlU£Umĵĉ@@ylUÞ@@£kWU¯WaU£¯ÇV¥@kb¯wn¥ÇkUÇnU@¯±kULm@m±_kónUxlbaÇLkUaÇkW@Kĉ¦km@ŁUaķxlw¯aXak@mmakL@mÛ@¼m@lXV`nKU°°@²¤UÈ@VxmôxKlVV²aVwXlaVlx@UVnÇnk°VVLlkIJÇk¯V@knÆn@lznmlVkzVVVx@Uxz@x±¼VxxUlkb@¼ČkVXlĠkôV²wLUKlwJ@aIV¥Þn¯Ün@nkl²kÆ@°aVbnI@Ťn\"],encodeOffsets:[[110408,35815]]}},{type:\"Feature\",id:\"6105\",properties:{name:\"渭南市\",cp:[109.7864,35.0299],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@@ÈôLxU°Þ@mÈnl¤nUôLwX`@ÞÝLUmLôôbVbnºlnÞ@ôx°LanVwÞ@Vxnwnlw²¤b°°bVnlXbó@bĠ@xb¦ŤVXġ£W¥ƽɽó@ýóƝÝ»£XmƅĊkU@ókťaĵÇ@aka¯UV»maUUabUxmKnkm@kmK@xó@¯n¯KÇ¦@ôÅèlxkx°nƾ¯KU¯WķL@VÝIUbyWbX¼Ç°\"],encodeOffsets:[[111589,35657]]}},{type:\"Feature\",id:\"6104\",properties:{name:\"咸阳市\",cp:[108.4131,34.8706],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@IXyĊwlýKlXIVaķ»a£¯aVU@awÈōaL²»VUln°WÈ¯W»XazVaÞJ@U»@¯Ýbğwly@£kÑţ±WÑ@kaIUn@¯ómţUbU¯lÇIÝb@¤Ý@kV@zĊ@ĶnVV¤kVbmź¯z@°a¯J@¤@bUxb@`xUÔ±ºVXWUnUJLĢ¯ÈKlblmÈXŎ°U°LlkÞK@Èxl_°ĶUÒkbl\"],encodeOffsets:[[111229,36394]]}},{type:\"Feature\",id:\"6101\",properties:{name:\"西安市\",cp:[109.1162,34.2004],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@°²@mVVÈÈl¦m°xla@U¦°ÈV¤XbV°lXÞaÈJ°kVaŤVôn°@mVJlb@XÒŤ²lÒ@¤kzĠxÞa@°¼ĸK°XV°Lƽ¯mlwkwÆç@óÈ¥°L°mô@w@aÆK@b@wÝLyÅUÝÆ@ĉ¯¯UóxW¯x_ÝJmLUx¯bóak±mÝUUW¯ba»óóxƧçĉbaĉxIUV¯¥ō±wl\"],encodeOffsets:[[110206,34532]]}},{type:\"Feature\",id:\"6102\",properties:{name:\"铜川市\",cp:[109.0393,35.1947],childNum:2},geometry:{type:\"Polygon\",coordinates:[\"@@ÆxĸƨKlxÈXK@VWƨIlmV@wVUmUnmUalk@kVaUaóaónKVÞK@ÝW_xóKmVk£ÇmnÝ@¯VwóK@Ç¯XkmVU±¼KbÇŎx@bUV°b¤b¼ĸUb\"],encodeOffsets:[[111477,36192]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/shan_xi_2_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"1409\",properties:{name:\"忻州市\",cp:[112.4561,38.8971],childNum:14},geometry:{type:\"Polygon\",coordinates:[\"@@Vx@lnbn¦WlnnUm°²VVVVVnUnºlz@l@J@kXWVXl@La@KULlbnKlLnKLnKÆXn°bVV@bUVl°Un@LnaVJUbW@UX²l@ČwlVVIWnkÆa°anVKn°UW¯@aVUVk@Un@aV@ValwUanmWUk@WVUUanaVwnLVl°@nk@mVU@UVK@wLVKVU@K@UUKVUV@@bnLaVaôlIXmlKX_°KVV@bVV@zV`kblIVUlL@bnV@VĊllVlIXW@kaU²blKVnIlJalbXXlWVn°JnnL@l@XlJlaX@XW²@l_VmnKUblU@mnkVK¯@U@ma@kX¥VmakkLa@a@WIUUVXWWnk@a°a@kkm@kUUmJm@WUUUIk`m@VkaWWkXKmXk¯@WKLkak@±bw@aa@aka@ma¯@LKÇÅkKWbkmġ±ÅULUKVVkm¯LUVVbUwUW¯bmULxWJ@klmkUm@@KnwVkVK@akw@@a¯bKknVUIb¯mmbk@UbmKUL@xUU@klmLUlVXIVVVUVUU`mLXVWbXnW`Å²°xmxU@mĉwU@mbU@UmbkVW¦kJ@X@`¯Im@UlUVVnb@bWJXnmbJUUUUa@UamIkax@@x@b\"],\nencodeOffsets:[[113614,39657]]}},{type:\"Feature\",id:\"1411\",properties:{name:\"吕梁市\",cp:[111.3574,37.7325],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@@a@w@wlbnJVb@VbVVVInaWmXI@aaUmVUVkn@°J@_W@lIX¥lUnaVV@naV@xĊnV@wn¯wÆ±X_WmXaWUnKV_VVUUUUWJkUVnKlk¯@@kmKUaÅ±KkU@WmI@WUIlUUmVwXw@UlUVwV@LnbW@anU@UaVkô@l»n@naJnUÈLVaÆUUVmVKV²L@mU_lK@UVWkUa@a@U¯aUaÑóÑUbKk@@ak¯mVaUwVÑkWUmK@UUKmXUWÝwUaLUU@aWJUUU@UaÝU@WL@VKVaVI@WnU@alIVK@kImIkJ@m@@@_K@x@kaW@U@Vmn@UK@mIJUXV¤XXWlkKkkK@XmJVakImJU@ó¯LWKUV@nUVLkxmKkLma@kXKmmLabLmK@V@mXVÆUxX@`nLaV@@VmLUVnLlLb@°²nx@bVUxlb@V¯bUV@zVXVĊXVx@lVn@VnnmU@LlJXVz¯VWVXbV@bmnVUVkÇþÅ@XVxmbUlVUlnW@Xl@VLXÒ@bÞJ°¦Lò@nUb@°X@XbmVUVnb@xx\"],encodeOffsets:[[113614,39657]]}},{type:\"Feature\",id:\"1410\",properties:{name:\"临汾市\",cp:[111.4783,36.1615],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@nW@@UnLKabKnnWL@lnblKnLlwKVU@mVUXL°KôV@nIlJUbnI@WlLllLXkWWU£VWInJ@VL@nm@UVX@lb@@wL@`@n@V@lw@nVmVXWmwnUla@_lKwVlUn°xVKVXXWlUVVI@K@Kn°KwlVlU@kna@V_WnmUVm@kXml_@mLlKXw°m@_ôJVUV@Xl@UaV@Va°Ilk»VwUkVmwUmmVn@V¯@KUwmK@U¯wUVÝ@mJUnWK@@UnKVa_lykUmKÛnm@x@UUlwVkXW@a@U@@K@kIVnammVakUl@wX@@k¯@VVbml@°UbULmlVbnbÅK±VKVXUJWa@ULWaUU@@U@aWK@UkxUKLUUUJ±UkL@V±kk@kam@UV@l@LWl@n@VVUxLlUUx@VUVU@aIUlL@°mLUbkUUaWUUaUU@aWKLWJ@bUL@VUVVbU@m@a@kmKmnĉlUKXWUblbxmIkU@xWb@lkVxLXmzVV@bklVVUzm@bk@Vx@xlU@lUbVnl@Wxnl@n@UbVmLmb@`X@lUX@@xlnkLWaUJnnWVVn@l@bULVV@lV@XnJVX\"],encodeOffsets:[[113063,37784]]}},{type:\"Feature\",id:\"1407\",properties:{name:\"晋中市\",cp:[112.7747,37.37],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@@lInJlJ@ULkJ@bmV@XUJUbL@UXKV@ÞVbV@VVXI@bVVKVbÞxVXnWVL@VnLVlXÒUVxUb°nl@bl@LVaôÒÒVb°b@VnLnnV@lmn@lbUV@JUVVXkl@lUzmJ@xXklbUnJVUbnUlbV@nlLX@lakV`Ub°@XVJnUL²KlxnI@KV@lbUbVVKnVl@zlm@U@nI@WUaVl@@mVU@XkW@nkVKV_Vwy@knwVa@XalU@Vnml@X@VLKVaÞbnnlJImVKnVVVInVlU@m@mXK@UmyUI@mWUUakamw@wUwmLkakwVmKw@wUam£y@am_W@UU@knmmamU@WUa@knw@UUUUV@nJm@mVUkKVUUUkKmwKULKUImV@lUnnm@mbUK@°bUnmbUmkkWUb@am@UXkK@a±@V@ĉÅVUXVxUVkLWl¯@@bULUlm@@nm`XlWakIkmVUbUL@Vm@kI@@Km@VaXI@W@aU@kUVU_KbJkkÇb@nkKmLwÅW@kVUUVU@WUIJmIXmma@_kyVaUUlkUm@kUx¯Lm@L@LUJUkVWXUWUL¯wVmUkxkL@`bkmVnxXUWUnm@kxU@\"],encodeOffsets:[[114087,37682]]}},{type:\"Feature\",id:\"1408\",properties:{name:\"运城市\",cp:[111.1487,35.2002],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@VlnJwkaVaXWVLĊknmnLl@@bnV@UaVU@UVK@aXIKXL@bVVVbXVVblVaVnK@¯KVkJ@bVVU@UVwkVKVwUUm@@Xk@K@kVUn@lbl@²l@UlK²VVIVVKVLlw@VXL@b@VV@VXbVK@XbVIUWLU²ÆLmaUankVKVa¯@nkUaU°@n@@kWaUVaXUW@IXKVw@UWU@W@@UUU@mn@`m@UUULkUmJIU@@UK@U@anak_@wmKUwmakVkmKVk¯bw`kwUIÇx¯»ÇaÅmn@@mmUkV@wkKW@kxmLUkĉLÝkxÝw¯lóVUmV@ĀVVX¦W¤kz@`Vx°²ĸ@Ul@xêĸǊ°¤VVlXLWnXxmV@nUl@\"],encodeOffsets:[[113232,36597]]}},{type:\"Feature\",id:\"1402\",properties:{name:\"大同市\",cp:[113.7854,39.8035],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@²£yl@ČĖ@bĸĢbĸXaKŤnn@ŎôllÈxnVnÞÇV@bnXllL°KbVb@J@b@UxlKXLlKlXk@UlkJlkUVKXUÇVIVm@_nÇLalwVnU@UUwma@aaÝaLmUk@@W@U@@XwVWÝUUUk@@VmLKV»nwUwaUL@`mzJUIVUaUwKUaVIlJôanÑlLVUn@a@VV@@UUwVK°Vn_lJÆLéW@UUUÅ@»lm@aÞIVwXWUUkkm@U@aU@mwU£VWU_kWmXwW_°yUkkK@UÇK@kkUVymóKU@KWIbUak@mJ@bkbmLkUmkVUW¦@lnb@@V°ULml@nkVaVmLUnk`±@XWW@kbÇ¦X¯WxI@xmbmxXlWV@bÅUz@Jb@bÞbU@Wbk@xk@WX¯VÛWÝbÝUkVUU@alI@a@akLWam@U¯UUmÇL@K@aU@¯VUkKmX@`@kJ@nVUb@lbVÆXVWULU`VbkLUV@XWl@bXJ@VbV@Vl\"],encodeOffsets:[[115335,41209]]}},{type:\"Feature\",id:\"1404\",properties:{name:\"长治市\",cp:[112.8625,36.4746],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@UkLky@IJVa@mÞaWy@_W@_WXVlUVw@nw°K@mUVamVkU@mmmnLVUmKXaU@IlKVUnK@UmWkX@WV_V@akU@aKWIXyIUVmUnUa@WaXUVKVmkUWVkULU@@VbKbIUm@mbVLxWUUkn±V¯wbÅJUbmLkbmKÅKbVnUbVKUbKUbmLKmbaKkUm@UnnVnxUVlUxl¼k¯JUbU@Vbk@WU@UVóI@`¯nWxkLK@nk`Wn@lUnVnmXU`@mb@lkV@VnklVVUblz@`nbWnnJIVJ@XUVVUV@lÆXxnKlL@maÈllIaLV`UlVV@@b@XJWUb@n@L@lJn@@UVKVaUlnlJXbkWn_@mn@VkVK@a°@XklKVUUwVWUĊÆ@U²@@blLVWn@@bVaXllVnnaVma@¯VLnan@mVm@knUVJ\"],encodeOffsets:[[116269,37637]]}},{type:\"Feature\",id:\"1406\",properties:{name:\"朔州市\",cp:[113.0713,39.6991],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@XXWVXVWnnlnn@èÆ¼@xlVnblVÈUVl@blnLÜĊmUkU@Ua@WI@aXk@WVUlKUaV_VKXWUUÅka@VaU@mlI@@_nWLVl°UV@@b@LÈKVn°V@VnXblK@b@bkJ@bVVlUÞVÞaXÜ°UXWl@wl@XaV@Ýa@aa@IVyÆ@aXUWknwna@wJXw°WÈ¥kI@W@kmKm¯IUmkXWWkabkImJUkL±aVb@lWXkJUkĉk@UmU@aKkVUkJlaU_y@UU@aUU¯LW`kLWnkJóbUbmK@aU@UVVL@VL@UVULK@xUL@VUV@nml¯@UkmKUxmbVbUV@XlXVmnVbkxUbU@bm@@VUlUVb°@VX¯m\"],encodeOffsets:[[114615,40562]]}},{type:\"Feature\",id:\"1405\",properties:{name:\"晋城市\",cp:[112.7856,35.6342],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@lVLbanLnKVaLVaLUVaUmaÆLnLlanKVaÆIa°x²UlmVVXwUKna@VnJaLa@UV@@alUkKVKnkmmVwUkw@@kxWUXW@@mk@aUa@a¯aLkKmwkUm@kL@K@aWIXmVXWkUVakL@UVKw@aUK@UUKmLU@¯nKUwVUIWJUWmka@UXJk@UkmW@kLWKVx@bmI@VUaVU@a¯@UUmVKmX@±`kÝKVxUL±akL@VbLkKmV@XWVUbVXb@lm@@lW@@xklVUbnnmbUlJ@@L@@Vb@WXUlkxVV@wn@ÜmnLlVkz`UbmL@V@XLmVnIÞ@VU°x@VnLxV@LU°\"],encodeOffsets:[[115223,36895]]}},{type:\"Feature\",id:\"1401\",properties:{name:\"太原市\",cp:[112.3352,37.9413],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@@VV@wVKnLVal@na°naVJUlmL°a@b@lx@bULUlmx@Ln@lVknl@XIwKVn°aVXVxUaVU°KnUlUVLKÆV²ĢlnXalLÈÆLKUaVkUanmWUa@WwkUWU¯y¯Ñ@anIl@@aVUmIymULUUVakaU@@LmJkw±LKmVUI@W¯VaU_lkbW@kK@mUkaVmVaUIVmalkW@wnIVy@klkWUUVI@UVkam@knU@mmmK@bblVUX@VkLV`@n±KUULUnVVÅUbÇKmVImbm@k¼ó@Ulb@VmV@bXmaK@UUxkVV@xWUxVnkVVJ@XnJ@XlV²LÆVbnL@l@°\"],encodeOffsets:[[114503,39134]]}},{type:\"Feature\",id:\"1403\",properties:{name:\"阳泉市\",cp:[113.4778,38.0951],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@°@nb@lb@bbb@x²al@lbKXU@mkUWkkmUUVwV@XUW@naVklKXblKnLnLVanImaXKlLaV@U@KUKWalXK@£WKXUV@VUUUVW_V@W@@K@UIWmXUmULnJkImmÝaUbLK@UWk@mnU@kVWb@Ubmx@lzUx`UULml@XWl@UV@nk@UVb@XJm@@Vknyk@zJnUV@bk@mJ@b°Ò°zXVlVXx@bXVmnVbUlVb\"],encodeOffsets:[[115864,39336]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/si_chuan_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"5133\",properties:{name:\"甘孜藏族自治州\",cp:[99.9207,31.0803],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@aXam¯wm@±°wUwV@UaVw²KU@UU¥a@£ÞôxKnkmX¥IUÝUwlk°V@ÈKUwlkUyV¹mx²XllÑW»lw°UŎnJl¯°V@wôIVÇnnUllLVÇLô¼XW£@±@¥k_ÇJkUékwXa@Llw²Vxbm¼ÈxlLÈVWÞn¯mÇÑUÝlÛkwlĉmULmwUJç@wkm@ÑlUXÑôġVaUÑ¯@wķÓkbVmnU@@y¯IķKV@¹aé@kmÞU°¥@a¯@anKlblU¥@óğç@Çw@wklaçÝ±k¯±@ğÝUÛmÝ¯w@kb±¯akXWÜkXUÆÇU¤X_ƐwV@¤XUbUIUlÇUkġ@aXČmlUlèUV@mVk¦Vx@¦±¯¯¯anlW¯nÅw@w°KVak£m@klKknÇU»óKīlaUaV£@¯@ÆUVÛÝÇXÇlÓlŹ»WUğJ¯£mxLĵôºXVlUll²bllxónn°ÝU¼mJU¯nV@êĉ°Uĸw@m@¯kmXamÑ¯aUwÝKU¥mÅn¥Wmn¹n±ƑƆÇôXê±ǊnUôlĖkȂVÒ¯¼VnȮ¯ĀnƆĢ@k°V°¯ĢVlkVxm¼X²Ŏ@VxknWÜ°U¯nÆÝ@`ôÝ²ÒÇznmX@xè°K°ÅUČĬóĖÝó¼ÅêÒbmk@V@Òl@nĉÜêx@ĖmlÅJ¯¦óxȭ°Ým¯LĵèĀ@Æl°żX@xmkV@z@°blnÞ°J@bn@Æ¼UVUóóL°X°ÝLxUn°Ĭn@lnL@Æ@nKÆxnUnVInĬmÆnxŎ¼ĊIĢóÞ@ĊƨbUmV¥lkwnLmÅÆ¥XwU@wwUÞ@alUUÅUVkkm°aU°Ó°w°Ub°a²K¯ĕ@ÈbÞĊa»XVm°InĬk¼VbaJô£VĊankůnÜU@anKnĮbÈmÆ»nIé£Ġ\"],encodeOffsets:[[103073,33295]]}},{type:\"Feature\",id:\"5132\",properties:{name:\"阿坝藏族羌族自治州\",cp:[102.4805,32.4536],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@l@@þ²I@lVL°wnJ°UĸŎèIlwV°¤nĮ¤ÝlèL@@xlè²ôĊ_ĊġVÈôJżīlbXÆÈVkxÇVn°¦Üb@è@nn@@°UÈ¥WÇ_Uala¯¯UÇk»mVwk»k²°VxlL@¤_@x`ÈĖöb@l²alXa@bnK°¦VK@nnWmx@nUnl@@llĉk°l°UXkmW@Un`kÇLWÛÈVxVVlVk@lIXb@ylXÈWĮWŤzy@mI²J@n°@VJ°aÅ@ŎkVÇkaUwKVwV@nkm@±ôkôĊJ¼InÑm±nIÞXÈĊxĊUÈbÜyÈ£Vkw@kVUVm@a»ÜbÈmUXwÝxUn¥@°ġÅaJVkaW¯Û@W¥UŏĶ@¯kUŃ@aI@mmanwÞW@mw°»Uřk¹±WxVx¯¦U°zţWw@°ÇVÑk¯@y°a£@mnl¼aÝÝakwU±aĉImlĵn@m@kkV¯Ñmĸ°xl@XVÞmlÛÝĉUÅ¥mwÅ¥VaUwXġċaVůÛŹlwU¯Uó±xÛV±¯¯n¯mċLmnĊm@_kJWaXmwUĉK»@mwXÝUÇkKÇw»naUw±kxK@WbxlVêlÈIl`@¦@²X¤Wó»KUÈKkkmVmUÈóJ@x¯Uk°Imō¯VxkX¼Òkk±WwnUºVzklVxLÇ@¯UklVxÞVJW¦nmlLówÝ@¤b¦V@VV±LUxVbU@Vx¯x@²n°xnWbb\"],encodeOffsets:[[103073,33295]]}},{type:\"Feature\",id:\"5134\",properties:{name:\"凉山彝族自治州\",cp:[101.9641,27.6746],childNum:17},geometry:{type:\"Polygon\",coordinates:[\"@@ĶóKnw°¤ĠIXV¼kźÔkÈWÞÈÜUVÅ°@@U¤VbkbĬôL¼ÈVlmLlkn@l¤Ub¯L@xÆx°mXmk°b°°²@¥Uwl¥nU@VUkçVnkWċbĢ@lÈVVkJVaVW@£UƏxW`£ÈVVÅlWXÛlW°b²la@°xnÞVÜĠÞ²@l°Þ²èkbl@xÈx@Ġènal£nUÇ²@ÞKnn¤@¼°U¼nVXUbnĠUVbUlV°LX@lVèÜUnK@_yXVyUwmIU»VkÇ¥ÿkkV¯m±n@n¯ÜanVVÆz@bwÜbm@wa@kmk»@a@VUUów@nb°mXmnVbÞVôanwJak£lwLÅnÝ@wl¥IÇÓ@UL¼kVÇÅó¯kVmmw@n_Vn»°LÅ»@éÇçŹīVÇÝ@ÝğUaVÝ¯ķlŭġl@óÞÛċ@¯nkUÓm±IVġUwóKUn±¯Kw»KÝVnl@óxUwţ£ĉUmÅÇÝKÝUlmK£UV@ÞÈW¦Ò@Ĭnny@nÒmV¼@°Vbl@VlnUUwl°a@@llnk°lbnKWĀnUVxU²Åm¦ÛÇÅaUVb@¦m`móXUmmxÅ@±Þnè²U¯»mVm@wU@wÝÝmLa@VÇUkl°¯VlkV¦UmxaULUèVx@kIUxmWV¼¯VmÈ¯UnlÈ@m»ÅVWxÅbÅğW@km@kVV¦mlnn@ōl¦ÅÆxk\"],encodeOffsets:[[102466,28756]]}},{type:\"Feature\",id:\"5107\",properties:{name:\"绵阳市\",cp:[104.7327,31.8713],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ńlV°@ŐĵVX»ÆUĊÑJw@È»m»£°Kk@ÇnÑÆ@w°JUwnw@wbVb@VlźLUwa»aUklyUUVakwWXwWUxkLmn¥mwkUXlJw@aIk°X¥W²l¥aUIlmkklÈL@m°nlWUaW@V@UaV¥@ak@Çk¹K@aK@kKkÇX@VU@kx±VèkIWwUVUkkKÇ@a@wkml¯@kUWn£WaaVwnaVÝw¯@UaWxnJÅUxUma@L@mbUU±VVnkxUÆVm@kkKW°X@¤ÇUkÆÇnU¦¯kmLVwÅK@UóbÇÆV¦L@±êX¦mVÞkÜÝnWU@k¯wķn°ÒUlln@@ĶmnkĊJ²bVlxÞbÞbk»mn@¤¯bz@l°UÒ¯È@xŤXyV¯°¥Uww²XlºVŚ¯¼nx@XÝmxnb@nJ@b\"],encodeOffsets:[[106448,33694]]}},{type:\"Feature\",id:\"5117\",properties:{name:\"达州市\",cp:[107.6111,31.333],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@Uxn°bnlUnÒÆnn@n¤LnxlUV@Ælx°XXxl`XVWLè±nÈb°b@²x°KÜ¼°ĉV¦lJnU@¦ÞJÞğmLÞ»xUlbVÆannalVÆX@lnŎVmUmaÅXa@aWm@£@wĉJVkkkkmnk@mna@alKJ@ÞwmÅÅ@ambkU@KUġKU@mak¯±a@aĉÑÅaVwXlw±V¥l@@ak@@£mĉÝónWV@nÝÇÇxUmbaVkkk@m@m°ÝýXmakÅī@@mb@@xmnb@mxkWL@¯b@WUXmWWKkbm@kxXmm@LUlxlêóKnUallLlLó°m¯JVUK@xK²Āô¦l°\"],encodeOffsets:[[109519,31917]]}},{type:\"Feature\",id:\"5108\",properties:{name:\"广元市\",cp:[105.6885,32.2284],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@ÆLĊx°»Ŧ¦WLÈ@xÞKÜ°ÞnVxÅĀlÒnJ°a@wV¯l@XWknKnwVÈ°XXalX°VI°bWna¥@w°n@yÆ@nkÞ@°¯lJn°IÈlUlXÅ@ķlUV¥VUUÝÞUU@UwJUkĉm@ýlkWUwVwWJk@VUKlUkaVUmLkm@@UIk`@UmlUkV¯ÇXKÝ_mm¯@U`kwml¼±KV¯¯Vk±Vk±kzmaKUnÇ±bk¦±X¦¯WlJ@bxkIWVlxnm¦nlKVwXWxXlxUbVVkzVlb¼bVxŹKUk@Uaa@xmxVx¯Ix@ÅmÒ@Èl¯L¤n¼\"],encodeOffsets:[[107146,33452]]}},{type:\"Feature\",id:\"5118\",properties:{name:\"雅安市\",cp:[102.6672,29.8938],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ln@xèVInxVKnĊklxkÜVÞÒnÈm°nx@¼ĊLVnxWXblI`@nmĉnKČôÅlUÑmUK²¹@ÇÅVÓÅ¯VýÞWUVmXÆbnwKUÿ@UmmIUb¯¥Uw¯ÇmçmanUm»UUlk¤a¯bVU_WĕmÇÅ±ĢUlUlÛVçkU@W¯KUVkUağVmaVWUmV»¯@»m£mÝL±@ÈmVk¤mb@ô¦kVkamL@b°@b¯¦ÝVn@lêb@ºUĸL°J@zV@nmUlaĸÔ@x°VÒUbóĢÒWkV@Ò\"],encodeOffsets:[[104727,30797]]}},{type:\"Feature\",id:\"5115\",properties:{name:\"宜宾市\",cp:[104.6558,28.548],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@VlÈnlXnWLX`m²nV@b°xĢçlnVmnn@@°UzlV°nÞÒkxlw`UnVbmL@albÞKÈÛmÜ¼°@XÇ@wmW@ÅKĊLlVLVŎçÞL²±ğkw@Uy@¹lKXlKVa@wČ@w@aÇU¯n@@wġakaōK@Å»VakUWmķwkbğ¥mLak@ġÞ°¯xVVÞ@VxVVWxXlxU@k²WVÅULmèULVĊklĠVJVx±nÅ¯¦mwğ@mlğkkl±@kUk@¯±ÇKkxl¤bImx\"],encodeOffsets:[[106099,29279]]}},{type:\"Feature\",id:\"5111\",properties:{name:\"乐山市\",cp:[103.5791,29.1742],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@kVkÆkV²UlºÈIlxLXèÜlUXUmkbVèx°@@¼°Knnn@mÆIUbnJ@bVI°b°±@nK@mVakkKl¯nbmĸèl@VnÈlUUwwmwnm°¥LlLnU@VaImbkmKnk@mbLVJVUUVnkVmb@a¯JUaÆkk¥IW¥KlwÑmÝU¯kVy¯@@mmnUkmġè¯w@aU±mnW_XKWmkÇmUkóbUÝUanmW¯nma@xVôUV@b@l¼n@lb@xnÛaxa@yUÅmUÛbm°@mn²U°llĀÈ¦lUV¼nJVxUzWz@`mL\"],encodeOffsets:[[105480,29993]]}},{type:\"Feature\",id:\"5113\",properties:{name:\"南充市\",cp:[106.2048,31.1517],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@È²VmLnblyl²²UUl°U°²L»knlx_V°@nnÞ`WL°ÈUVlnkV@l_JV@n@lnKV£ÇUV¯m@laXUUbVx@VkôJU°Jn@wUk°wnUV_nJmknmm¯Vwk¯ó¥±ÿL@wLVUkUbX¯mykI@a±Kk¦ULmaXVm¯Kz±klUIVbÇJkL¯lUÿUlUkJUmUUkVVklKk@@aU@J²x¦kĬ@¼±ºXnWbxU@xx@lL@bLlº@Èl@bU¦Vb@U@XbVkX¯m@nÇKkllknJV\"],encodeOffsets:[[107989,32282]]}},{type:\"Feature\",id:\"5119\",properties:{name:\"巴中市\",cp:[107.0618,31.9977],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@VUlbkVVLUl@XIUxVxXkl@þĊnVlIVx@VVÝVÞUVU¦kV@ĸWÆô²@VÞn@Vaôb²W@K@XUmÑUW°¯°Ina@y_lWn¼lLUbô¼Kla@nkUyôÆx°@n£Ý@¥mVkIU¥Ċ¯Û»¯L±w@¯aÇa²mçKXUWk_Ww¯WwÅk@UkVmwK£@mmmÅmÑkVmamnnlmIU`Vm¯xVlx@m¯IVóIUl@UwVaVWkb@nU°VÈU¤\"],encodeOffsets:[[108957,32569]]}},{type:\"Feature\",id:\"5105\",properties:{name:\"泸州市\",cp:[105.4578,28.493],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@VVXwVKnwnVnl@b¯xmKUbVn°°X°@blLènV@Vnl@ULnmmUnaVV_ĶV@wnJl@@kkKVólaUwnJmwUlm@aUaôKVnJWbÞ@VwVLX¥VV_Þ`wWÞŹmmnIn¥W@kWV¯@°kILk¼Ç@k¤±XknmÝ¯UlÅÛKWV¯klUwkLÓ@U@w@ġXVWX@UbVbV_kÇVlU°lnwŎ¦ÞaÆ¯nmm¯Um¥nkVmkl_ó¥¯UÇl¯@Lk`¯ķLUy¯@mw¼ķ°ġ_ÅU°mlnÇVUÞ@_JUnVUXblĢb@x@mV°Èb@xċ@@xUbkLWkL@ºzV@lxĠ±²\"],encodeOffsets:[[107674,29639]]}},{type:\"Feature\",id:\"5101\",properties:{name:\"成都市\",cp:[103.9526,30.7617],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@°n°m²°ÜUw²ôV°VkxÜźUŰČbĢlaÈL»@kwVÇ@nÛÆ»ÈUÝ°Kl_V°U`Vbn@VbÈLaVU@ƨ»VnIlUUa±lIk±@VnKmÅ@WaK¦lVōkKÝ@maXÇmw¯IU@kVwUmVIçÿU±Å@¯È@xK@wLUbÇKÅ@mÝ£@yóUóóUxkI@WlIUabaVĀLmxÅaWUnVÝXUþÆ°UÔÈÆ@±ºLnVVÒkóÆ\"],encodeOffsets:[[105492,31534]]}},{type:\"Feature\",id:\"5120\",properties:{name:\"资阳市\",cp:[104.9744,30.1575],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@èUJVnxU@lV°JnxWÈnbÞ@lLŎUk¥LXbÆ@nmLU@zlbXmlnVynLçJVbUnómUnamUan¥lKV_²aValWôn@nbVK°¯VblW@kklUnlV£°W@wUXk°KVwmVkwVyVI@wkmVÅ_Umm@Uÿmbk£xUaVw±V¼V¤kLWxU@UkbyXóm°V@@zÝÒkKn±U@@_VVkÇaVwnLWalm@@kkVVl¦kIV`±n@wKk²aVUUV¤nkxmUkVWVnLUbVb`kUUmLUmX@`ÅbÇXbWLXn\"],encodeOffsets:[[106695,31062]]}},{type:\"Feature\",id:\"5104\",properties:{name:\"攀枝花市\",cp:[101.6895,26.7133],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@bKÞnÞ@xV@xnUn°¼V±mç²ÝÆ@wnnVWnôn_@¥UaVbÆÈÜn¥Æ±VUwVmXÿmLkal¯km@k@¯bkVxmVUkk@Ua@¯»UnmÑ@mzm@īÑX¥Ç@ÝxU¦ÅÇUkx@lbUWVXmV@xĵĖ±@@¯xUÆLnÆmx@nXL±lUUVwKWak@WxkbÞĉbUn@@@xó¦Ŏ\"],encodeOffsets:[[103602,27816]]}},{type:\"Feature\",id:\"5114\",properties:{name:\"眉山市\",cp:[103.8098,30.0146],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@Vx°¦VanJVn@baVbkJ@XlJVwôôôV@zÞ¤@nÆÈLVaK@xL@w°ÇÆ@²VĀmWXKWaÈÆa@_nWVnKVlV_UaVamKXUWwnmmwÑm£@ynUkWĉUkWVkkV±çkJmkKK¯¦mnnxxVxVÇkUmk@çķnmak°LllUb@nmL@¯²¯aUJ@amIVaÅJnm@mm¯L@»¯@wUçanlVWVÛkWçKkwÇJk¹±VUÅlġV²ÈÆnXĖV`U°ab£lkVVn¼mVnbèÈn°\"],encodeOffsets:[[105683,30685]]}},{type:\"Feature\",id:\"5116\",properties:{name:\"广安市\",cp:[106.6333,30.4376],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@VlIVkVĀVk°lKÈIUaVJlk²yLn°UWnbVKl¥²L@blJnzW°alV°Inô¯KkKkkbVmôLkéwVk@KnnWlwn@laXLnXVW@X°a@XKlnw@man@w@na@@wĕġġwUkUWb@mk@¦¥mUÛb±yÅn@bml@kV@lknVbmVnlmbÇk¯bWyk@V_UamJ@I@WaVXamIVWkUkbVaUUx@VnkVU¼bkKUxmK@WxnV@n\"],encodeOffsets:[[108518,31208]]}},{type:\"Feature\",id:\"5106\",properties:{name:\"德阳市\",cp:[104.48,31.1133],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@nUW¥²é@K¥UÈÅôa@VÆLUxnKl°V¥ÈmlÅÈV@£WX¯lLln@UVÅlwUm²UVVna@@KnbVVwÆImXwWkIVwÝĕVUaIèmKUzkmWnka@y@l²kJ²VbVkmJUƧ¼@UVbÇKUam@Ua_¯VUk`¯LVÞÇÅ¼mÜ@UÈx@l¼ÇKkbWVxUbÆ¦nxÆ¦ĊV\"],encodeOffsets:[[106594,32457]]}},{type:\"Feature\",id:\"5110\",properties:{name:\"内江市\",cp:[104.8535,29.6136],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@²èlUUllXĊVXlmV@zn¤ÒnxmnXxlUnVlwmU£VVUbl±L@x²mU_lJ¥UklU@ln@kXbmKUxÈblUU@`V@²mlLÞÑ@yU@¯ônWzaVlV@XwlKU£»aVaUwm@mwUVUwklVÇ²LlKVm_@ykUm@mUçkKmxkIUÝ@LUJ@n±kºLXb¼@mmIXa@mamnkWKUx_U`UklwUwmUbV²akbmkn@`UmÒVxUbI`UaÝÈ\"],encodeOffsets:[[106774,30342]]}},{type:\"Feature\",id:\"5109\",properties:{name:\"遂宁市\",cp:[105.5347,30.6683],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ÞĖUxlJXVb°@xUÞmbUxbXbm¤VX@lk°ln@xbÈ@lLVlVUXxlJç²UlwV@@UÈWlLw@wVwXaWm²¹@»lī¥w±I@V@bl@kLUllUVVn@mmUwXċbVb@VUkbmamW@ka@k@laUa@¯b@mmwó@@lkXUa¯°LUamm@ókXUb±bU`kLm¦bnVmbnVmô\"],encodeOffsets:[[107595,31270]]}},{type:\"Feature\",id:\"5103\",properties:{name:\"自贡市\",cp:[104.6667,29.2786],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@lIÞÇbV_JVaUwnÑV@_lmnlab±UVanVxkxVlV_`wVLlXnmnb@WbnJ@n»WaKl¹²@mVI@KÞVlJnw@aW¯¯¯UmVanL°w@akmmUxmULWxUUÝKōèUKUkĉKL@ÆnX@xWÈ¯@Û»nÇÜÝLka@bKnUaVm_xkLX¦Jl¦ÅlVb°I@bnaUmlUVUVIUKa@nmlnLlnaJUbV@\"],encodeOffsets:[[106752,30347]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/tai_wan_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"7100\",properties:{name:\"台湾\",cp:[121.0295,23.6082],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@\\\\s@pS}aekgKSuSsMß`¡CqZ·be@Q^o@gieMp]}}Ľc_Kk{ùA¡r[uom@ÑĥJiq©mŉq¯Bq]ÙYgSåk_gwU­isTEĕiqiUEkue_OSsZaWKo¡­qycY£w}ĩĕS§Z©SN¥SyLÑ¡±Ks^IYPdY[UoFp}´\\\\¬\\\\j]eÜò¤¡ā a\\\\bnUãº¹Ìs¼j®[cíȈEĝĆ`ļf¶®K|VØDdKGpVnUFjpHF`B[pMºxÖjbpÎxp¬|ÎŸÜÒC²®ÜApZG~dÞàV¨|¸`|²tx~\\\\~|dFf^zGĄŚhdL\\\\hĸ¼OªP®lV`p\\\\]Xpllæ¤CpQ|oF}fMRiNSon_²qämMNM\\\\\"],encodeOffsets:[[124853,25650]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/tian_jin_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"120225\",properties:{name:\"蓟县\",cp:[117.4672,40.004],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@EUDAEI@WNMNCBFAHFFNACDJDPBD@@GD@DIFFHEFGDBDEQOFG@EI_KG@OcJQM]RMEKBGPG@[LaCIICBWKCEEG@WBQHCDFD@HSLEJI@IHWECFGAAEKCGDBFCBSBIDCKKHEADMJMFABKOKEQAA@IEEG@GIQAEK@OZEESMOLlu@SLUTYFQCMG@@SQUAYKAACA@IB@BDB@B@DC@@BGAEFAA@BEGKJCC@AGAIHA@@JC@QEIP@@A@EGIDC@O@C@@@@CJCWKABFLBBEBSQGBAAMIEM@AKBcJEN@BEBCFMAEFEF@J@BG@BFABECKFG@AFQ@@F@BEB@@A@@AAAKAE@GFGDECEFEECBKIKDELDFEDYH@EIACDCHKBEB@BAAC@ADBHABKJIAIJICEDGDCD@@A@A@DHCHJHDFEFGBKRKBGIK@GIMHSBCH_BOJECCJCFKKMD@DNJEDEGC@OJCJHRUL@HRJ@H[DCNKDZHCTFDHCFFKR`TANVDFZRDLFARB@HPAPG`ILAR@TERNDFNHDLCLDDCXDYbHF@FEB@LDDVE@JPNfXPINCVDJJD@NJPAJHLXHDNANHhB@DPNLRMTBFRBHHr@`NBFEBOCCBIAQJDHCHLHFA@HSDCRLFTB@HEFLNF@PELBDJALFLTC@EPFLLP@tUHQJDfIHGTB^JTCPDLKAIBATFPADIEGECEMJ@JIAIHGECFEAGDI\\\\SPOXAFCL@BQTQBBTMZECYGAHA@GJAE@HCAEME@IECFKJADDBABLTHHG@ILEAMNDJCDHEBF@@JNFJELDFKTOT@JETBFFHBHEHKI@@IJEJ@XKEOUMS@AF@CEB\"],encodeOffsets:[[120575,41009]]}},{type:\"Feature\",id:\"120114\",properties:{name:\"武清区\",cp:[117.0621,39.4121],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@FWôµ@IFCLIB@EHNBp]AGEAKAEDMGZKFGBGME@ILGP@HEFB@BXMEAHUGC@IHCLOD@X[NWHWPKAEF[@EKIOL@EKGBNMJ@EIEHKBIC@BAKMIACCFQZCF]DB@ERAKADIHGEIBCGIIECFaGLZO@EFCNGAGDGAKL@BMG@IE@ADSDEH[JGC@CGA@BMDeK@EIACFE@@GG@FIAMM@CCGC@EM@ADE@CFMAAGHBDKIEAJG@DOGCDEKAGIS@KFCHKAEHIE]BeKNO[IFIOELC@A]GMBKVYCDDgGAICARc@MW@AQE@DGI@@AQ@@BKBAIQQYEFW@CEADIGGBCEIiMEMF_LGEKMBBDWEBGRC@E_CHYGCH_IAED@FFBQh@FGJaJ}AHRAREF@bE\\\\C@CT`FHC@\\\\BBF@BID@HGDDJ@@FAHKBARECKDAZBJIVNHCTA@EREAMLHDAFFBVFFC@RNRETHD@FOJMACH@CAB@P@DF@@FGDWE@FFSIEMKQDYCCHKb^JADOCIDGNDBdBCFJB@EC\\\\A@BJEA@JAAAD@HHD@LFBCFF@BERDHNhZQHMBGHOACCEBWEGD@PSJKCGEUD@CINLFGHE@AJK@HDABBHTB@F`DBFLBBHEDARCFG@ABJBAPVFE^FBGLGCFG_BMLEXGAAFE@@JNRVJHFALFBEHQJCTbNDHCF@PlFLJSXCHFHfVBTNJ\\\\BPJXC^FAVNFCHFB@FFH@JF@\\\\ABCFD\\\\BDMCAAJKQBGAILOEGHILECQLWFENJHADC@QxNHFJNLDFA@CBA@DUÂmR@FBL@BD\"],encodeOffsets:[[119959,40574]]}},{type:\"Feature\",id:\"120115\",properties:{name:\"宝坻区\",cp:[117.4274,39.5913],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@TZbB@JHD@DODCLM@AP@LL@BNH@ETFN@`E@DNG@CHLBCJA@AICFKDDBKA@\\\\N@AFNAGRBFjFFFL@DHLBLFQPcXAZMJ]GAVHAIZJFNE@JpDRRDCLFDGXA@EFF@CFFPDfEBDB@DCHCFCJDJIJBLI@I@CB@@ADBB@FALADGDC@@H@BB@FZGFCCE@@FMLALJDAFFFEFDFCB@@AHCF@L@@BBB@BB@FC@E@@R@BEL@HEFD@G@AH@AIB@@@FEFEBALDDEFAFO^IF@JCBBFPNJJ@D@PRDCEKBAXL@BIFD@T@JE@BHHJORFDI@@B@JGH@@B@BDDLIFFHCD@D@DEE@BAAAB@DAF@B@H@NGLJLMRDNMfGIEPMI@GDAKK@KIDIJ@GE@CFDN@FE@GFEPGV@TCDFKHBBF@RW@DD@@ID@TJFKIKLI@EP@IGBCLAEKLEN@KSHIGYACSD@SEAMBBMGEBMQBCMIGKFB[D@HDLPHDBC@IFITDLG@IIIFGVBNJDLN@VIRI@YIAIHIC@CLKZCBEE@JECEIHEAKGDGECBGEEM@@DA@CCCBBEGA[GEDBBoNAAH]MKiIAWKQoIIPMFQAEEDMH@FMSUYIeF@EK@BIOEKJEBICFKaKPFAFSE@LWCCFMHDDEKESBOGBKIEIODLG@CCDEQCEDWEMDIEIB@EHGEEDAEAa@@HqDEJGF[AECCFa@WCEIKAAEQB@FCAE^YDERDDJBLNABD@AJGLJF@FNIAMLH@FPKLJ@FE\\\\BFOLGXMXW\\\\C@KPGD@JHDGVFBWN@AEAGFO@KH@JNFAHEHYLNHFCLBFBBHo^MAFGA@KJED@Jó¶EX\"],encodeOffsets:[[119959,40574]]}},{type:\"Feature\",id:\"120223\",properties:{name:\"静海县\",cp:[116.9824,38.8312],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@NGFMDATCNDR@CCbINEHNJA@C\\\\EEGVE@IhE[wepc¢·²^QEKIEKIgiQDkehY£uSDBMkUDOJDHC@GF@CAFBFEN@CQ@BeP@@G@HD@@MHQKi@[IGCOCESE@GMA_OcCGDu`a@VZzKDkJBLNXGDqKEWE@cFEFA@ISIi@@KMABJGBcMuFEzGVH\\\\ATSEUBeALCEMG@CEBUHUCGXaBPtUBBFIBFTDFF@DDKBFNGBJPHXDDMDCLJ^mBIHIL@LR\\\\@LCR[@@z@NFD@LLBNb@RHDBNTPT\\\\F@BJF@BXCFBHHBDLFB@HODADE@@JHVXCPDHCFTLBBFNCDCCCU@@GAABEHHZHBCAEdEjFDD@GfD@DXFCHF@ERFDLBH@\"],encodeOffsets:[[119688,40010]]}},{type:\"Feature\",id:\"120221\",properties:{name:\"宁河县\",cp:[117.6801,39.3853],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@BFLBFJXDb@DEFD\\\\BHEFIrC@Gb@FBCBFFGH@FJAJFNCXFFCRDCFDDH@CKJPJFALPHTALFCFGCENDDKXF@ETEBObLELJDFALIPFAJL@@FfEZJTVENG@CNFFRBNEJOpJLRBXjJNLG^BBpMAAFC\\\\HHBAFDADDB@@CN@FFAHFDCHLHFBJGFCFUNKJJTD\\\\XUXF\\\\^F@DDDQXXBRLRCBDFEVCDLVDpUl@LEDJHAPRFGL@CETGPBTCDDVI@CFF@GFDCCVGLKEK[Y@MECISG@BKNSCGCKWEAaEBEKNGFSECO@GGM@GYI@DÅCMLHPTF@DJHAVVNKEGDETJ^[TJNNd@NOAMFYJ@@GFANDPEJB^aOadSTQSI@MHBDIEOKCG@EEFCKCqXO@@DMFENCDDHCCGJ]AKFoDaGGHYFDHKJiCMFGC@EQ@AEHGAC@IEAATKOHGIC@IXIFEoGE[JCFCDHNmRADFZMF[EEBMO{GU@AOW@@]ZeHBDEHBKEfQkuIWBs@EC@d[@[^EDMTKCEEcI@cDAB@FCBCACmOCG{PYHeBgPwPFDDALFFFCHQGSD@BHFAR[TaFYXMASUiGFL@DQNCJI@@D@PLDN`ETEFIGMCGBCE~CAIFDPEHGEQPHJADFJGHCJLB\"],encodeOffsets:[[120145,40295]]}},{type:\"Feature\",id:\"120109\",properties:{name:\"大港区\",cp:[117.3875,38.757],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@JFFL°_`ONJKDDFIFZN xlb~yFVNRrdJGzDPVFBCTNND\\\\UR@E`F@@Ip@IWGUoawOEE@ÏDgK{İEEMFëCb@KwOCDHHKBDJCDEEEAGHOABFABMCgDLSQ@CFEBMgYIDQINE@AUSwSAdYEHQMEyK[KI@GRMLE@@OqOoBOnpJ@BmEAFHL^FDB[C@BBDVFAHFJENB@sNEjQAMYsUgCSBGDJH@\\\\LjGR@NC@@G@HO@AfR@DM@EFEADBE@@HGDICCPlVANTC¤vgZlfRChjLJ\"],encodeOffsets:[[120065,39771]]}},{type:\"Feature\",id:\"120107\",properties:{name:\"塘沽区\",cp:[117.6801,38.9987],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@|ODHnPBDADEDA@CB@ddJFFLDNSFC\\\\]\\\\@@cFD@nACOMW@M@ITURBRZNHNWRQoOj½fcqAqeiDÿÍyÓįFL|Ch@ÐFFxPpbHVJXo@@JCTR^BPABQA]^MB@bE@@FQBFVJRH@FXtPNZSBAja@@NDTLJrQTHFXZFB`\"],encodeOffsets:[[120391,40118]]}},{type:\"Feature\",id:\"120111\",properties:{name:\"西青区\",cp:[117.1829,39.0022],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@LHAHRHATh`LHNHDG`HDGZ`D@FQDAHXFACNAFLVRTBFOfHDCVBFQH@HSXHEPFB@LDBF[bDbLFKJBFLADBDjLvCPEI]FGEIGCBEUSjcFiBIVWfaHCjN^HtwBBFGPBJGjFBEGECGDONMFAP]TDHQOWCMGAMHKIJEIGQ]aDlUG]VGEGDC{PEbBZmE@@GH@BCA@FMQCFMYMJECELCMI_P¯`]R±¡¸odfx\\\\gF@JUFFH[F@DIBGMMFaJDDQ@MCSDCBENMH\"],encodeOffsets:[[119688,40010]]}},{type:\"Feature\",id:\"120113\",properties:{name:\"北辰区\",cp:[117.1761,39.2548],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ROHFFGCOJEDB}DFHANDJHFEFSM_KC@O@CJ@DIRM@CEKKALFKACHoLSJSIBETDJaEIIE]E]K[MYUYQILC@GF[MGNKEK@A@BCWECAIFEFYAGFOMI[OFuDiKACBCEKIAELaKaCE\\\\CA@KEAFOWGGTG@ERUACDeGEPSAUQKHE`FNjNFJADHHCJFB@DEXZFRRBJLA@AR@@BJ@CHF@BRX@@NQdDBBJhHCCZDLUNA^H@BKDPFEJ\\\\JMPfL^AJFFGLBDGLET@HJLBCFHDCPH@BIJFCLGABHNBDEF@BCN@@FHDDDN@BNEJH@@HF@DEJB@FfLNC@AHB@DHD\\\\IFGTCBCF@@JNH@ALKHBHCHBDMFEP@KYbHDEJF\"],encodeOffsets:[[120139,40273]]}},{type:\"Feature\",id:\"120110\",properties:{name:\"东丽区\",cp:[117.4013,39.1223],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ZV\\\\N^L^FJFFJIbSCAFTJTIpKDGLBEKLBjHTVNBZWbE\\\\SBQGE@ATCRHDGEEKECBECxOhOfAZGA_YEEWSGqRKISC@Mb@BiTAMYsOEWG@IQEURA@EF@@acUOXQRYCUDCHDTEF[SUEgAYDcVGJM`iAWDWLQRMHUHgDsDBLHJFCFDFGHBFFVEAGHCJN@RJFPIhBD\\\\FENCPWA@LFBAFHBEJUEARCDIAEDQBRNa^\"],encodeOffsets:[[120048,40134]]}},{type:\"Feature\",id:\"120108\",properties:{name:\"汉沽区\",cp:[117.8888,39.2191],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@LMEI\\\\MTABKN@FCDMH@COAcH[AoēAM¡Wa[MeqpQRMXMGQYQASV@J@NNXDPmBAtJXlveRLFGACFGAYf@^X@BPV@|HNPFA\\\\FNEEYBCnQGMDCDE\\\\IHFpEFWJ@JJDGHLPBSFB@JBDGHBFR@@FHDNEjDLICGZEHGbHpCLE^BHIDDCGDCFMNE@CP@rWLDEDFFH@\"],encodeOffsets:[[120859,40235]]}},{type:\"Feature\",id:\"120112\",properties:{name:\"津南区\",cp:[117.3958,38.9603],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@TLv@CNHFFBHGZFETNPhCVGNGRQXKXCjBN_HIdUZChBVF\\\\TFECSDGVCZDRQPWdVNA^]RBBAAOQ]DSE@F_Q@[VMCSMADUECOHycIqMQEU}zkawENRDENB@ADG@@HF@YnaAOF|CDFHUHH^kVbCR^JHIFLJNGHBDNPXGRSCO^EBMNCPDHHFAFiEIHOAEH\"],encodeOffsets:[[120045,39982]]}},{type:\"Feature\",id:\"120103\",properties:{name:\"河西区\",cp:[117.2365,39.0804],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@d@hZNFdcLYXKRCtCMOFSYEGHEAGEDMu@SKAAsx]GMTGt\"],encodeOffsets:[[119992,40041]]}},{type:\"Feature\",id:\"120102\",properties:{name:\"河东区\",cp:[117.2571,39.1209],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@ZBVFFIGABEEA@KXBDOFM[EACJgOIE@QIMGDBHUFEEGAEHECEDGIAKQDWLKZcdQPEP@FOFBJTJ@HNORJf@DBCN\"],encodeOffsets:[[120063,40098]]}},{type:\"Feature\",id:\"120104\",properties:{name:\"南开区\",cp:[117.1527,39.1065],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@NMVDCG\\\\E^B@HlB@YEDS@CHsNSiMGDebUXAJEjidVTAFHDFJ\"],encodeOffsets:[[119940,40093]]}},{type:\"Feature\",id:\"120105\",properties:{name:\"河北区\",cp:[117.2145,39.1615],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@DBXFADB@L@LFHM\\\\NHED@JKZRb]QMRAFCJBDCBQYADMCAe@QIMP@GSIAIPE@E[EGH@ZEF]^HJAXK@KF\"],encodeOffsets:[[119980,40125]]}},{type:\"Feature\",id:\"120106\",properties:{name:\"红桥区\",cp:[117.1596,39.1663],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@J\\\\PNHEZBFEJELEL@BWGI^]FEkA@G]A[FDHUCMNEHJ^\"],encodeOffsets:[[119942,40112]]}},{type:\"Feature\",id:\"120101\",properties:{name:\"和平区\",cp:[117.2008,39.1189],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@DT@FCHG\\\\FFOROMEgYc@\"],encodeOffsets:[[119992,40041]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/world_geo\",[],function(){return{type:\"FeatureCollection\",offset:{x:170,y:90},features:[{type:\"Feature\",id:\"AFG\",properties:{name:\"Afghanistan\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࡪ͇وŐǬϠڐŶӂʮǚڦ۾ǌƀ̚ІɣʪҴMوǯʲĹ،˒˰ǋ˖ϪԈiżŬĘͺβ̈Ҕȏĝʱʪ¡ý۷ͪ˟̊ǰώĊԼϖׂ×ࢀAƬʋӧĥяƹ७ĭࣗǭӫλȤΣĪллΛ͑ɳ̡ߛͦ։՗ɅΥԕ²ԋ͡ɿ̳þٝŋğɻسDҵӇ܍થΓבôǝȁԇņ࠿űටіހހåզُƚßՔ˟ڢάҢιŮɲؒ΂ਸ\"],encodeOffsets:[[62680,36506]]}},{type:\"Feature\",id:\"AGO\",properties:{name:\"Angola\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ȸصʌԋȘ˕͐ѯ֊æˤŠҬşŲɀɂӨԶ®ƤіHñ̡৴RfՉǞ͕ūԑÖԫ˪̷­ৃȼüκsԴŴϦ¹ĘʹĩСƨϿů̿î́ყZᦵ֤ۋպԽ໳΁᎝Š׋Ж₭ŵÏԃϞկ~ԉƝЙǅÿՈŜ݊̂ޒªΰ˚ݶȨΆӘռːϐĘج«ӊʣ̜ɡԚȵԎ®Ǩʶͬʭ߼ǣ֚сՐĄǎΌŔʒg̎ĸៜ[\"],[\"@@ɉėɣلͼδʪƘ̀˽̩ǯƍɍλ\"]],encodeOffsets:[[[16719,-6018]],[[12736,-5820]]]}},{type:\"Feature\",id:\"ALB\",properties:{name:\"Albania\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ń˷ŢέΒȳiə˗ŧ»˙ϷСƛÐgȂү˰ñАîֶŖʼƗƂÉˌθаÂƿɨôǴɥȪďȨ̂\"],encodeOffsets:[[21085,42860]]}},{type:\"Feature\",id:\"ARE\",properties:{name:\"United Arab Emirates\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ƭ¤ɱڂƂ۞uԖ{ֺ֪ظՠՎԮǆ˹ŖڑѕGçճƪŝϝǑE΅ʓΏuͷǝǱᡋъ͏࡚Ț\"],encodeOffsets:[[52818,24828]]}},{type:\"Feature\",id:\"ARG\",properties:{name:\"Argentina\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ߗ§ѓ̔ԑx࣑@Aሞ͒ϵрؿનԋ୲ȿϙп\"],[\"@@Ӵ؇͠ڰॠƊǷ໶ോۊŷਆاࡾ͡Ŧχࠡ౧ࡒɭ़ŷڔƈނ٢Ǝݐжǈфӝiڣۻҩ֟΁ॅࠃ૭ଧȽڥɣࡹT࠷ǽȇÝիËѫ੨ܙŗ׃Հν§Ч߯ઁఛ҉။ǩउĎǰԅǣػƺщԋ̏ࡱř̪͕߱ɗŜ࠳֨ʧҠˆʢѧޛʻڭԹūࡋȣ҇ߏEڃљʋؿؙࠞߦǝ˿ݭ঳Ӄձটލͧ΅Ͽ˔ࢍ֔ӡΟ¨ީƀ᎓ŒΑӪhؾ֓Ą̃̏óࢺ٤φˈՒĭьѾܔ̬૘ěӲξǄę̈́ϵǚˢΜϛ͈ȝॺ͸Ǣƙ਀ȠࡲɤݢԊ̨ʭࠐEޚَոo۰ӒࠎDޜɓƶϭฐԬࡺÿࠀ̜ބռ߂צԺʥ͢Ǭ˔ඔࣶд̀ࢎĹɂ۬ݺશȱ\"]],encodeOffsets:[[[-67072,-56524]],[[-66524,-22605]]]}},{type:\"Feature\",id:\"ARM\",properties:{name:\"Armenia\"},geometry:{type:\"Polygon\",coordinates:[\"@@୞ƀǨə͌ƣǛɁ҄˽ʁˋΦɫϘƏl׋̣}΃ӢHżχCʝɤǩuͧʖرȼĄФƛ̒\"],encodeOffsets:[[44629,42079]]}},{type:\"Feature\",id:\"ATF\",properties:{name:\"French Southern and Antarctic Lands\"},geometry:{type:\"Polygon\",coordinates:[\"@@ը˃ߐĿǅɽϣಇÃq҂ŮΎÊǢ\"],encodeOffsets:[[70590,-49792]]}},{type:\"Feature\",id:\"AUS\",properties:{name:\"Australia\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ߺ́ҜŘپǊԎÉÐঽ˽́ēگ̉ɰ׍בǧ®ԫԭܘŗֈӝܸtϬռõ\"],[\"@@̢ڇբ̈́˦ΡЖ͟đϋǴܛŸнɄĹɬܕąѥ˖֭࣬ѭצЋ֞λŋȯӔՃࣧ͜ͲȂ;ηȴźƢࢹ׬ԩϸ͋ڀڹʀڭtӏËԳА܋µݓơϵɩݡjӕǕ׻χއثЭ̫ٱ˫гʝܧ͕нɅػŉׁªˇӕ̇वޡ·ϫ͙ԕέ۟ψԥƪżѬҝǃ݁؉ܩɪӉƄӑÔ߿ʐիԮƻْțьЭ;߱ĸˢРȯزЧ׉ݝƷѮҬŶӞ͘ЬãجہܑԿ˽͏ڛٽΊ~ҀԿ،ѹ̀ǂȘઃԚןz߯Цຓāછ̝ख़˫ߡÈࢻљܯȗǉѱ̳Ϳ܉qՅõݑƶ׿ğֽԁ҃ʕуʁЗˋؕ֛Bࢽ՜ҋǄlӖкŘƚȒ̠ĺאģӼѻࡖƏӒӎͭնsʚϋͰĽڄӓڔřΪτε˳ެиʑʞ͗aјеڎă˄țʦĠӠǢȸŘрęӮΎ؀Úٕ΢׀ۀˬЦΪٜ̰ϤàɴĻڎ̺ԚĤŶȀɞüҬoࢨʖҚώɊ҆ӲѐͲvҘט܎ΠܩΦǚ̗Ј˂ТψǻĸٖҠаȮͨцƜ`ɼτĭdɂτŦОŔبϫҲӽՂMՖÿǱҦДڪϜɘſȾκӒԘ̒јıۺǂeі؛ˢ҂Ū֎ȻҀ·ۼɋʈĐԶʵӬʊ͂ñȠǊϬеɡ͉҇ͻ˿Įͱʙп̗ЭÔʁڜҫ٨ˏѠ́؈ӻʂBѰɍŶʷߤ˵ֈ˼ǐҊǠόľҤʰڞŝОÔʔīӔŌنǈǠŽˬȮѾǆҦtʈ̸̾ʂЩÎՃȾķΛ̨ёÚӇ̥\"]],encodeOffsets:[[[148888,-41771]],[[147008,-14093]]]}},{type:\"Feature\",id:\"AUT\",properties:{name:\"Austria\"},geometry:{type:\"Polygon\",coordinates:[\"@@Û΃ӁCǎǻ˧էǇƗܽsщȏۛÞயɐȉ̊ࠧƣĭǅԗŢѕxϝƶźȴƬʪ²ьɹŤɜݎ׸ƮЖ}ˀǣþƜšո̠ń̒ϰز˓ӀΆ̐ÚٶʱЂªϰǁãŃČ̅\"],encodeOffsets:[[17388,49279]]}},{type:\"Feature\",id:\"AZE\",properties:{name:\"Azerbaijan\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ʞɣψDGŻ΄ӡֽŒщϰƃ͆Ǫv\"],[\"@@ϊËƞɈԈͺѴѵђ׭ϺʸɧۗãƣٵƟ̭̍ȝvзȽ¥ԻѲ̂дʝʚ̿×যإk׌ϗƐΥɬʂˌ҃˾ǜɂ͋ƤǧɚȶƎضʍҐ¹ŘĲбҔɔŚʀ׀ԙ\"]],encodeOffsets:[[[46083,40694]],[[48511,42210]]]}},{type:\"Feature\",id:\"BDI\",properties:{name:\"Burundi\"},geometry:{type:\"Polygon\",coordinates:[\"@@Á০ɃϢԜßʲӎҀÅ¸ͧǸȏT˗ȹǭ͛ѫ̧̥΍\"],encodeOffsets:[[30045,-4607]]}},{type:\"Feature\",id:\"BEL\",properties:{name:\"Belgium\"},geometry:{type:\"Polygon\",coordinates:[\"@@؜áުǪՐοҦȝħ֧ɕĝһܿϦћßדІϷͶϷ`ũ̒ڪǔ\"],encodeOffsets:[[3395,52579]]}},{type:\"Feature\",id:\"BEN\",properties:{name:\"Benin\"},geometry:{type:\"Polygon\",coordinates:[\"@@ۛįȹ׆ኞǛǦЮ̇̌ʱʞņѶ̀ĨǠξЪĀȀʤˮʘ̠F٘ә˩ȎӽǓͷĘɧСԳʵʳǁՉt՗µണ\"],encodeOffsets:[[2757,6410]]}},{type:\"Feature\",id:\"BFA\",properties:{name:\"Burkina Faso\"},geometry:{type:\"Polygon\",coordinates:[\"@@ֹɐϽ̍Ƀϗǰƥ˦ϙǾÅӦɮΤo˴ښۢŬּɲȴОœΚǢŘɎٴϖǆˀ޼ΒҦŢɀǇՠJáСŔϣӀչНॺȏmֻǿʣЩÿǟν˿ħ݁lϳâ˓ƉωÖร¡qӉŘم\"],encodeOffsets:[[-2895,9874]]}},{type:\"Feature\",id:\"BGD\",properties:{name:\"Bangladesh\"},geometry:{type:\"Polygon\",coordinates:[\"@@i׽̉ŶÆگʉѬµєǅКΕӨޟü΋˃ҳΧǠũƵʃĠ͗øŽۖ̅لƜԒԫɤȆ̪Հ̼؅Ѽ֮̔ږεВ£ô׏ߞřު^Ӟƛϯ܅ϕµʷӍҢѥƎ՞ɶFѶ೯\"],encodeOffsets:[[94897,22571]]}},{type:\"Feature\",id:\"BGR\",properties:{name:\"Bulgaria\"},geometry:{type:\"Polygon\",coordinates:[\"@@ʎΉ͚Ö٦ſ௾«иɌবȜ̩ؒӴĕѥΏ̫׹˔ӏܣŒࡥ˃Uлޅÿס̊ڧɱة|Ñ֊сːƒŢĝĴƘˌ͌ˀСδ÷̬ȸȐ\"],encodeOffsets:[[23201,45297]]}},{type:\"Feature\",id:\"BHS\",properties:{name:\"The Bahamas\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ȵ£ɇӜ̿ʐǾՔʨۣ̎Jӥ\"],[\"@@ࣷƅÏ̴Ђäֈ{~ɕ\"],[\"@@ƟׯƷņ`ѮϓͪCĪڐϗ\"]],encodeOffsets:[[[-79395,24330]],[[-79687,27218]],[[-78848,27229]]]}},{type:\"Feature\",id:\"BIH\",properties:{name:\"Bosnia and Herzegovina\"},geometry:{type:\"Polygon\",coordinates:[\"@@̦FȿσМ͓ūЃȡƽû˙țūҥݓ͈ͅΘ͋Ȅϭ̾ǻʺЩϾǬΒ̞ȕǼǨϾnܠƓ׈\\\\Ϟȅ\"],encodeOffsets:[[19462,45937]]}},{type:\"Feature\",id:\"BLR\",properties:{name:\"Belarus\"},geometry:{type:\"Polygon\",coordinates:[\"@@߼Mࣰ̈́ȚӄېːÿϔԜƚ͖ࣘࢮɁŢȻѲĴࠒȧĊЁǷɧՄս΂Ƴ»Ʊ֦Ʃʎɡ͝ǿڳǉÿȠ˧ȸ՝ܝ¹ʵȁÃхͭĆݷ¡əȞ̿ƥ́ŨڍjफȬࡕàٱmҡɩГeϐʷϴԌǢLͰɷ͌ϊ\"],encodeOffsets:[[24048,55207]]}},{type:\"Feature\",id:\"BLZ\",properties:{name:\"Belize\"},geometry:{type:\"Polygon\",coordinates:[\"@@OŮĸƴı̞ԔǄZHūǄGaɭƋεôŻĕ̝ÀăīщǓɟƱǓ̅ʣ@àॆPژ\"],encodeOffsets:[[-91282,18236]]}},{type:\"Feature\",id:\"BMU\",properties:{name:\"Bermuda\"},geometry:{type:\"Polygon\",coordinates:[\"@@OEMA]NOGNG\\\\Q^McMOI_OK@CQSGa@WNLVWHFLJXVFGJ`ZRTDLeeWKIHGIK@@[MQNi`]VDTBHCJAPBJLVFjT^LV\\\\RJZRn^RH`TfJjZHHOTTFJP_NOX[EYQQKMEJOLANJH@HQHAARF@ZEPS[U_IcRQXE@EEKKOCGGCQCOGISKYGUC\"],encodeOffsets:[[-66334,33083]]}},{type:\"Feature\",id:\"BOL\",properties:{name:\"Bolivia\"},geometry:{type:\"Polygon\",coordinates:[\"@@य़͟گӳ؈વȲ۫ݹ؅ŗ͡୆ҋऺˆ߾ѳ΢ŏ؆ЫֲՌ࣢αۺȖ˰ƭ̶͠рh܎¤נǸ˶ܩഠزíѠnȈʪ݀;Ѷ͂સƚęؽļ͓ãࣰ֛ݫऴƑ̻ͦ֨ǕΐʑՈTӦʟӟǐʕZγʓa͒এྖūӟĜͧҞɽȤԹƫڋɯρĄӏʿǥaʶ޳јޭ^ัʓЕ݋sҋͥ৕ƉǸ\"],encodeOffsets:[[-64354,-22563]]}},{type:\"Feature\",id:\"BRA\",properties:{name:\"Brazil\"},geometry:{type:\"Polygon\",coordinates:[\"@@૮ନॆࠄ֠΂ۼҪjڤуӞеǇǒӜŖӼBҦ̡ƴ̿Ƌ̻į͔ýޔƿʤ֥ɪ΃ǏࢱǈÈଜʝҴˀǦăӐɰςƬڌȣԺҝɾěͨŬӠྕ͑ঐʔbYδǏʖӠӥʠՇSΏʒ֧ǖ̼ͥळƒ࣯ݬä֜Ļ͔Ěؾષƙѵ́ܿͽȇʩџmرîӃƟϡĪÈ౨ۏӷݏv҄ͅ֏¶ǲΰұԞΓݴɜƶA΢ԖʎċҔɊ̈Ôϼ०ֲێǊŔŴݴϚᘰpθſӔύ̬LؐӀƒǚē͐ӯĔYՀ࿖k˦̂ɸˉǐӷǂļҨѻٸÆǌʲشȞΊƐĮΤ׸ʆ¯Ǯ܅ðśՊ֞ϓɒǀþجŅڜȿʐȤ؀žल̮͎̾ŏʂѪȜȗŉσ̀ŵȖϷɷ̏ƅ܏ɌыÔϳԬϿЮ¥ĢǒˆϠƦ˚ɢҬíȲҚçøǢƗǘĎʐͺõЈĒӔǱξǥʺɪȊŘɿДÒ͒͊ʴؤӼޒ˺¢ȺҫҼ฽҈Ƒxׅمەʾʩ๤Ɓࡃٔր੐̟ඊԡШӱƏҫ঎ʶ࿐ѹఴఔ۝੸व٪ʏܖ̦˅˸੭Ɣԗͯ൹ёշஅୡՙोثܯȿgɻءÒ༽ɹಓęօˇͧƫ૱࡛઱ƛࢁڹηȟԋ࣯Fೕ͓סύवʗ঩ڝ܅࠯ũطƔҫƽࡓȏЧחҥट๕݉ڗ֯Ͻϥߛ։ӑɷӈψЊӟֲڇҬࡹՠ̹{ࡅٰձę\"],\nencodeOffsets:[[-59008,-30941]]}},{type:\"Feature\",id:\"BRN\",properties:{name:\"Brunei\"},geometry:{type:\"Polygon\",coordinates:[\"@@ͬ̾܎ҢЯ·՛Бǭ˹ϥѦ\"],encodeOffsets:[[116945,4635]]}},{type:\"Feature\",id:\"BTN\",properties:{name:\"Bhutan\"},geometry:{type:\"Polygon\",coordinates:[\"@@΂ˍÏԩۇ{ۿÈՇſޅ͊kǚ֌زҒɈ׸șѺqπɥ\"],encodeOffsets:[[93898,28439]]}},{type:\"Feature\",id:\"BWA\",properties:{name:\"Botswana\"},geometry:{type:\"Polygon\",coordinates:[\"@@ǜƭ˄ӡॎइήĝD̑ʚՑٰŹ՚ϝ஑أݭع˩֓ʧ́ҙãƧГďʽ՝țہ¤БɾΟĸХșȵГЉʧпϑ׻đȇ̐üԠӽߚɧŲAរࠤ|Ჾشಖ͎̎΍՜ͤʮDӂȎưÙ͔ڣ\"],encodeOffsets:[[26265,-18980]]}},{type:\"Feature\",id:\"CAF\",properties:{name:\"Central African Republic\"},geometry:{type:\"Polygon\",coordinates:[\"@@ۜÚƺɎƔgȾȏ੔͐Τ͠Ѭ̌ĉ̐ʂüߺ½߆ϴ؊ࣺю;ՐƜĪΫӜԿF΃ƋΓÄʻ̆ʍٖοҢͻT˗֠ѫΖεɆԋغͩƊˉˣęաpكĘ̹ïųȱ˕}ͧǲधнϥĎŗÝʥԕطǐؙĊ՗̴ۓ˸҉˓͛яùדգ²֩ƘԅѻѯޱėʐϦϧ˔̳Ѡï̠ЇѮæʢċΞÞٴȬƴц࡜\"],encodeOffsets:[[15647,7601]]}},{type:\"Feature\",id:\"CAN\",properties:{name:\"Canada\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@؎œުxЯ΅̵Å੥Φȿˬ͆ʸ̎С\"],[\"@@Хcઝ˂ޯІ̄î૆Ɂ࡮Η|Ʒ\"],[\"@@хŝൡϢʥ̘ݩ̌Ưʈࡻư͕ҜðȚࢨǿԨŵ߄ė˺̃дЋ࠼΍Όҩ\"],[\"@@։ܿո˴֠ǵ̏̉ݚɱϰȴ࠼ʵʹ؛טƞņѿʼԷΝ݉ϝփǂǾیɻńইܯԅצЂ߫Ȳࣙ¹࿅~ŹʠԼ̐λɬ۸Ԓࢄ೾Զӎܲ̂϶ǋɫ҅Չ\"],[\"@@@@@@@@߰äʥ॓ܶگͯDԑϪ̵ϮчʾƻτºˎЂŋ\"],[\"@@͡ѳχîəʢ Î͖ʦΆkɈǣ\"],[\"@@ঝҧץnǿɪزϲ଼SiǍ\"],[\"@@ƼυјżӨɗं˽४ʽöЍؤÞ׶˥ݙ˃ಳȬҽϚ࠭ҁ஡ѣ˿Ӯଗăܴдņڌ˺ޔ؈å\"],[\"@@ष¥ȿЪΦҼޖŜپɷXέħřձʛ\"],[\"@@Է̍ଉʬۃğଫϘ݊ʼטζࢼʃԎƯʦǅԠ͍\"],[\"@@G࡭૰ڄ৐եʡح߾֥࢚؈ؖܨ°ईஞÝఔūૼй¼зس҃פ҇ŃУ࿩חୡŻࢃʨʣуߵ۽ʓοই֩ளÇڏΡÇձ঍Ŀਉڻ࣭ु͙ڏ±উంƕϜ޻ϼّ୲ǔ༞εࡀ͋׺Ѕ੆ɳࢸΟ൶µࣴąƍܫʼࡋ،ळనߗ٨˚ҔࡺѭೢףѶഎЀ॒לҮהç֭֘܌৷لলࢤνݾ˫ಾגȘ෸ɫࡸć۠ɚ޴˵ਚӣʮ͙ຄÛ}۷˪ਜ਼ގſ،ӵ௖Ұߦऔ֌ϸٺݣબੳघ৙͵Յ૤Ӂݰӓംɏբˍͬ܃ټŏͶͅÖऻ؍́׽̏൯̗੏ۑ෇ƋᅛǮుPࢇÍ۱׽ੳω௉૗ॵޡ܌Ɛഘૄᄈ۪సČݔЫߍ֟ˊࣟ˜هતп൸ŨࡆीÎ؍ժ̥ਣսᇷԁ࠯ͽय؁ٓÖ܆ฤ۞഍णĹջӆBନύʐ֛ƛ˧ɚٙىʱٹ̕ϡΥŽˏ¥čȹ໽A౥MϛƷࢵ؃Ŀßˍ͝ޗBࠛGϛƅƊǑøʯeďષлࡽſউ҅Ɂ@˷ƂĥŦnĔȂ̎ЂҦʘӺǙܴǵނ࢕ЂľƬūĺɳ@ǛƆ¥ȤǍēɥ¾ĊȡĊćɚٵːڹ˪ࠑ͘߁̨ݧʃ˝Sਕɔڻŉࠁʺ࡫Ɔו¾ʻƜƫҤ˳IE͓჏BᮝA᭯@ᡃ@ᠿ@៙@ᢡ@ࠛ@᠁@ᛷ@őF྽ࠜ׵δຽΐҳݖŤԨ੻ΨƧڴ৭؎iѠҲКwՌෙ՘࡭ॠՁ׾ޑϚ֣ΈѿѢࡇ˕ࠇҹݛւדπࠋɸࠟ|JⷎNᷲ༬ȭ೘Й࢘û݆ΖৰˀఢĹ఼τ൘Ⱦ־ΑظȠȊЄ׈ęෆݫ૦֬ŖّਔƐ͆ʖৰ·౼Λዸ̭ୄƛࠖÄଊэ஁зຶǷᗘĲܒƦࣆԋࣴьࡩΦժ˼৾ڦĎڴȩࡊҗरä๢ϛಬƄ௬oĭԺݞƦದ˵KߑՖڠڰuϞࡊ࣑԰কͺäघশ؎ૌƇࡘχଞॅݗЭ༠ǝ\"],[\"@@нϿሎʬୠщॊіސ˟یࠛфΒ׭ࡰ݊Ŭ࠲Ƈश͹ՆࠉʼץථеະЉĝσൡã՚͓˱ູ̯Ƃฃɪঋ»ཅ˷ᒃű๻āҕІଫɮݙģਛږ֔ĚಘƜஈરƦྷȞᅗã஗jѷ̴ዎͲಗ[ืɚ۶ـגͮᖬԠ࡬ǋ\"],[\"@@݉ևಹך˸Ş૸ٔȁ\"],[\"@@öɵࢿ|ࣟjࣿőʑ¼ऍѾ̠ИÈነěชң\"],[\"@@ڎԽޤڴᒆΈ෺ࢅůջဒʒߒͮሀыୄЏŊν༚Ȑ࢘՗᎐ܸͩ͹ߐ޻໯ϹጘչೲȁீޙೖÇʽכ้ঋਗά೓߲ઙĿŁӕࢪӥଜϯΌɟմࠩ́׿੕ɪᑏڨஎܣ࢔ԕƎ̉ᗱͲᅩӤ৳Ц̌ʂయќ௥Т`ʑᝡƅ܃˾ֆؤ཈dႸņ˫̜̊оચࠊɳϊ͕˾౿Рၳ˺՞ɆࢷԺ݋´ڏ˸҇ʛ຿ŅᵝȈᄫʚഹŴۥ̐࢞Ϧ஝Hˉ࡚٦ݨࡺ΄ᓪɢأի\"],[\"@@৊ǯຄńɖʑ޷Е౜αƱݳ൝͗߳ê׉͎ᐡٮjˎ႖ĽएռসР\"],[\"@@࣓عय़Խ݆`кѮΨ࠰ɮცྈȱళݟ৉Ǎ\"],[\"@@ᕍЙѷςኹѺήΤ׌ؘܰւࠑԦᭊƀ஬ǧᒰ±ࠄʑࣖΝ੍ɃᏝןਫי@ν\"],[\"@@ҙ͙௝Øৱɖ҂Ϛீɨܼ̬̍ˇ\"],[\"@@ٞϵљϣس൱đࣗƈjӬ൝ÝÁٮࣜౌ˺ஂµÜŎ\"],[\"@@̙͢ݠƘࢢƪЩԝЋ᭗Žᑯη౩mŅ˜პϊ④ĳ୯Ʈପࠐ߈ɾᛄ˳๶ӻฺÛறߨޔ̪ࢄĭ˲Џ\"],[\"@@ढ˓ကFܨˡȑ́८ȍՔȧଊ௬ë೸ǼႊðീÏ࣒ͅȊ΍ԽɟభǷ੽ĸᜱŻႫcഫļᖁ˔̃ҦĹжࡇξ჋ĺঅʼ͂ΈႾÁ\"],[\"@@ŗ٣٩̇޹£༝Ϋ഍ŹଗǼ@@ුؼႮծಆ[ସŬ\"],[\"@@ϣy༽Âɡɼၜ]מƻĵĩ\"],[\"@@༩ʋఝ˔ڼˎ௮Đஈſ˩ʥ\"],[\"@@৽ǏඉBbŤࡴʦҌદǝ\"],[\"@@కǥۃȚέ͂áΎજӪÅ৐̇ɫ̣\"],[\"@@͜Ε൏Ĥ൩˘ሏߺʠ৫ȮÕ͐࿶ŕᗢ̫ٞЍ\"],[\"@@০˕ଽʟ༇ك๥Óდņࣗ΄^̦ڔɢ໡Oए˨ՑϠ׌ώ׊ʲࡴÎοȖዜ¨੶҅මǵ൞ǃڒև\"],[\"@@ᖢßᅮŅ໤ɫɡᏅη᎙ǟݻȉᆬJጡԙേʃ෯ۇႿƓՙǡᡷěୈĿׇƭ۞бߙ˽ಛʃЋ͡୫ʣŞȏ෬lȳᖟԋᔧɴឿŻధĸཟªĿЖ༊Ȑб؆ԢÐᖤγ଩բഹǈڼ͘๰Ȩʄ̊஋͠ΥѠᘞڒĝ಼̪ቃĬ᰽Á๣˸۩ͼগʘȁ˺దǈঘ࿲ƌం̺ਬ©ࣤɽٔҒૐƈບĢᢲҀĝ᝚ƚᆔÁᆒÁ\"]],encodeOffsets:[[[-65192,47668]],[[-63289,50284]],[[-126474,49675]],[[-57481,51904]],[[-135895,55337]],[[-81168,63651]],[[-83863,64216]],[[-87205,67234]],[[-77686,68761]],[[-97943,70767]],[[-92720,71166]],[[-116907,74877]],[[-107008,75183]],[[-78172,74858]],[[-88639,74914]],[[-102764,75617]],[[-95433,74519]],[[-123351,73097]],[[-95859,76780]],[[-100864,78562]],[[-110808,78031]],[[-96956,78949]],[[-118987,79509]],[[-96092,79381]],[[-112831,79562]],[[-112295,80489]],[[-98130,79931]],[[-102461,80205]],[[-89108,81572]],[[-70144,85101]]]}},{type:\"Feature\",id:\"CHE\",properties:{name:\"Switzerland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ƫŹȳϞƵіwá΅χƙةŀǻ͹ЏơƄһ˵Л¡αǶ˽ςБſ^ϠؚҾɈϤûɲƞ܎MǦǼ࣒ʱ\"],encodeOffsets:[[9825,48666]]}},{type:\"Feature\",id:\"CHL\",properties:{name:\"Chile\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Bም࣒@Ԓw˧ͻܛʻЭӻä؏ʨ࢟ŨੑҸ࡫Ҏୃशۘǭ୼֗૜̟ѢϬ˘ֺޠΎװı\"],[\"@@͢୅؆ŘĺɁ˿ࢍࣵгඓǫ˓ʦ͡ץԹջ߁̛ރĀ߿ԫࡹϮฏɔƵCޛӑࠍpۯٍշFޙʮࠏԉ̧ɣݡȟࡱƚ৿ͷǡȞॹϜ͇ˡΛ϶ǙĚ̓νǃĜӱ̫૗ѽܓĮыˇՑ٣υôࢹ̧̐֔ÄgؽΒө᎔őުſݝPЙȷݷ̣Ɖ޹Σoॅ˚१ג@@ਲ਼ӔˁՒʄӰх֒Ņ෤Φ߰ࢴٰౣʔߞݒ˸ඊत̏Ѯგ֝ɠʿ਻ՉŠ˂ல˺༒ϮָʍࠎéूΠԨപ׈എΤబȗ఼ʤۚĵਞӮਆưྺ˒ნˀሤÕ൘ǩ஄ќɌɦњЬֱŐ؅ѴΡ˅߽Ҍह\"]],encodeOffsets:[[[-70281,-53899]],[[-69857,-22010]]]}},{type:\"Feature\",id:\"CHN\",properties:{name:\"China\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ԑഓΫۏѷ܂ĩخӶࠜڦَϨʡƣԓ\",\"@@ܩЗۏʺyܢаϠࣾɾӚoȊ͍σσșӟ\"],[\"@@ฬˍ঺ׯͼ߃౨Cܰͨ൸ʜѳݱ͙̭˽ः֡ࠇ৵ƪܝ̑ɜܙť঳ѕwLяթӺͯһಙαƀѹܩЍ˂ֽ׭ऑҋۃա୭ʑأϽࣝɭ҂ϴǭ͞ږ֠ѹѲܷ̓ॉ׏ԫթ࠙¡ѓϻѸ֩یƏϕڔʕस׶ݚ͝լuƌѱஓɻϻҏࠇућיࣜҥͦࠝԞޓ֮٥_دՅɯȪ҃ӶʻŻۃɇڗҷ÷ؗࣧڹિޭোିޡୟۻृĩԣύ̃˘Ӈй୭сࢵŹ˻ࢱҭ·ə؎Ȧ͘ૻːЇƍࡍɔЏ΀ƄӜޏƶЙܑ̀҃ࠇīڡJ҉ȳѥūŶ॥҃x÷Ȣ}Ύ؝ʓεƸر͂ʔۤՏǎȧޜࢱƓĴাߔۮۚ{٠νȨ˭ӶӭÙࣟŲ˴ΜϿԺ׳Ν۵ȸॷ՗އسڳĿοɦѹr׷Țґɇ֋رëڌԟǭওĈोȖڿτٵǔ˯ЖҽŦࡓոکʴΑȩଢ଼טࠛՒɽऐ׾őіͭјĐۆࣙঠ൧ͼʝ٦ةϼƫʌųӎ͜ԛȔ˟ďɇިʈȔśȠߤЈ׈ǐࢸő͆՜ંĲͮ̚೜ҔŠȐãӐּɔݱฦဘͲјȈ؆ຒဠˡҲϞ¢ࡆۦĀٖ֔͢èɚו۸ѽப̿׆ڱ͕ঙ̢ηূƝଆŝ৪ԻԲġϤޟӲӿऒnჄȉ૤Ŝࠦůఔԛ৮BόʽঐҌബ̈ాঘ̒׾҈ך˰Ƌˤˍ͔ѴըӀùࡺǝ࠸Ѿ౲͚؞֊נʆ௠ŐڐĥĠ̘ݿזګː٥̳ࠣžӇŃɏΆר࠾Цو৚̓ஆՎQτݸࢾҲːWҪңȦۜмਰƲ૜vసʡ݈̱԰ࡏ̀α̊ԩ̶ࠕ\"]],encodeOffsets:[[[124701,24980],[112988,19127]],[[130722,50955]]]}},{type:\"Feature\",id:\"CIV\",properties:{name:\"Ivory Coast\"},geometry:{type:\"Polygon\",coordinates:[\"@@ϣUוǒ՟Wহƥ׍ʍ̯ࠫǋvÞۖĄŀ}ͨΣΚˉÈʕɲǾώčО ʔƄB¸ξÝǌĄŜ̸ĶȹڨȗΎæ˸ǘÞŊúɸųٮOƸʖƢgʎĦžΫȞłΌŰϚǽƦ˥Ϙǯ̎ɄϾֺɏɠ஡Ο۷ɕेθܣͧ\"],encodeOffsets:[[-2924,5115]]}},{type:\"Feature\",id:\"CMR\",properties:{name:\"Cameroon\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ľ°ӻŇԝŒЋÅ൅nŬڒ͟֊ϧƚǟϖɋŦXɶɎתЎ߸ʒRԄӮ͈bҾΉ־˲ĀΔȌͺžь҆ΊǞךǲȊŢѨɜ՚۾ٲ¬˨ĠƲͫͰˌʂ¶ͮ՟Ê֏֏ҜޅҷTʁÏϥČǻЅӸөμƛŠΏˆ׃ſɩх࡛ȫƳÝٳČΝåʡЈѭð̴̟џϨ˓ϥĘʏÓґڛȤڷɜ੗\"],encodeOffsets:[[13390,2322]]}},{type:\"Feature\",id:\"COD\",properties:{name:\"Democratic Republic of the Congo\"},geometry:{type:\"Polygon\",coordinates:[\"@@»ঙͶŕˑ̗͓ɟ͍ѫǯϷ±ګț͍OهʍɹԃŗÝýҟɄϡÂ৥ưޝċѧǘӣӤҹҒ੕ͥĒ૿ƙɣĵʇՙȊχƫষĻࡇɨƫט͝ɲƴìٟࣟR·Ҧ̳ΨٟŠȋѰԣ˅ڧŞ˫ϢՕüϽqµʾ́rϥºԳųιtȻû®ৄ˩̸ÕԬŬԒǝ͖eՊ৳Qò̢ѕG­ƣԵɁӧűȿҫŠˣş։å͏Ѱȗ˖ʋԌȷض៛\\\\̍ķʑh΋œşʼɊĘμƎɎ̪ǰɚđ˼͐ҜSÄʃ̼ƩӶՄӨШɆː۔θࠆϬўքМĪˌt̰Ǝ̆«ӊŀݖǐԾʦ҈¸Ԕúה͜ѐҊ˔۔˷՘ؚ̳ĉظǏʦԖŘÞϦčनоͨǱ˖~ŴȲ̺ðلėբoˤĚԘۙϘķɤƖϲÅҶǲȦΫ݊֏\"],encodeOffsets:[[31574,3594]]}},{type:\"Feature\",id:\"COG\",properties:{name:\"Republic of the Congo\"},geometry:{type:\"Polygon\",coordinates:[\"@@̿˾ʩƗͻγۏࢸٖҪ̓֌˾ɂ֦ĺäό҆ЗݐʴЈł֒ĝڀЉӺζ঄ȽǘسçɻѢÔξ੘ڸɛڜȣÔҒѰ޲ԆѼ֪Ɨդ±·ԓʥ҇ǏԽĿݕ¬Ӊƍ̅s̯ĩˋփЛϫѝηࠅۓɅˏӧЧӵՃ̻ƪÃʄқT˻͏əĒ\"],encodeOffsets:[[13308,-4895]]}},{type:\"Feature\",id:\"COL\",properties:{name:\"Colombia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ΫȤЭ˨ʅƅ܉Ŝȱΰƽ_࠿Ӓŕʺ̼ÚтȢ̦иÊΞՆ͐Ѵ̳ȦǄӦȏސǸɚƃ܄ͻ҄ņТ˔ÑǂʠțӶĺŬѢـהΌĚT˦ƺ܂ӖϸՊfäǪڂéڌъ͞ȊОК̖»ɚɛǍ˱գƕɇп͗ʋʓ̷Ĺ׵ɷӭѢÇņϭȄȁâ͹ĳ̵ǫȸéȨ̉ઊĄӦŃעܡͼĚ؂­ӐĪ̔ƟƱҍȇ˯ß׻ǜ֑ʆʟȉэл̨ȃɠ̋ʰ࠹ǁĻǏӸɷˊ˥́࿕lZԿӰē͏ǙĔҿƑK؏ώ̫ƀӓoηϙᘯп҂ʣpժࡤٟϾԍị̈ƤҧɝصŀӵࢤϳɐˍІ֑Њɡā\"],encodeOffsets:[[-77182,-155]]}},{type:\"Feature\",id:\"CRI\",properties:{name:\"Costa Rica\"},geometry:{type:\"Polygon\",coordinates:[\"@@җȆǟǮĬƤȄɷȪͥǔ́ņÅʖəƮÄʑǗȩȓɸˑĊŗǞLʮŎˆʁŠȖǌŴňֆɝȖŊˊéƔǥʜÇȪǲɈҙ͖ͷЂΩ͗õLͷǪűűıƱëǟ©Ǖ\"],encodeOffsets:[[-84956,8423]]}},{type:\"Feature\",id:\"CUB\",properties:{name:\"Cuba\"},geometry:{type:\"Polygon\",coordinates:[\"@@ܨÑڊW߄˹̭ͮ޺Ĩ̔ȡ܈ԳԺϛˢ\\\\ԆǟÕʁئٌ΅ıȟ֑Ń֡¥׃âளą֜Ҷ΁ɔէÈ̃ʐȥӎӃ޵ɦʥǬભž̋ǐ̀ɀࠗ¨׿ѧΏ[ťȳеğΫĂѺʸǼ̤ϞȈіǎَĄȰĢ\"],encodeOffsets:[[-84242,23746]]}},{type:\"Feature\",id:\"-99\",properties:{name:\"Northern Cyprus\"},geometry:{type:\"Polygon\",coordinates:[\"@@ÐJŨȮ؄Yކʢ֧ΧÔƿęǇÙűj¥iĎÑ¾ǋVɫïƿ¬\"],encodeOffsets:[[33518,35984]]}},{type:\"Feature\",id:\"CYP\",properties:{name:\"Cyprus\"},geometry:{type:\"Polygon\",coordinates:[\"@@ãࡱͿЩŊȟͶЎǀ«ɬðǌUÒ½jč¦ŲiǈÚĚ\"],encodeOffsets:[[34789,35900]]}},{type:\"Feature\",id:\"CZE\",properties:{name:\"Czech Republic\"},geometry:{type:\"Polygon\",coordinates:[\"@@ϯǂЁ©ٵʲ̏Ùҿ΅ر˔ӃΰѕȬėΠƧʠؒǾ̸Ⱦ׾ǎɂǆɜīϒĖЊ˓ؼñ¿ɳҘǧŲɒּĥĄʿز»ϮЯʡCŽƯȕÅȑǇ¡wý˹ēϋbšȁ\"],encodeOffsets:[[17368,49764]]}},{type:\"Feature\",id:\"DEU\",properties:{name:\"Germany\"},geometry:{type:\"Polygon\",coordinates:[\"@@d͗ࡔțS̗ࡢǂҾɰॊͧІˋȞёɹɣ̨̙Ⱥ҅ß́Έ՛ϑĕɛĬɁǅ׽Ǎ̷ȽؑǽƨʟĘΟіȫӄί̑ϯ̟ŃŢշýƛʿǤЕ~׷ƭݍţɛыɺʩ±࣑ʲǥǻ܍Nń״ьֺ௅ƸЇɘ´ςǗȐĨ֨ƗࢢԎ@Ɉ͂Ⱦޔƿ˴ǐǲ۰°Ƽȃ֮вȓ̀ӈٌōՠŸ\"],encodeOffsets:[[10161,56303]]}},{type:\"Feature\",id:\"DJI\",properties:{name:\"Djibouti\"},geometry:{type:\"Polygon\",coordinates:[\"@@ȤʹΑӏȩήɯ̱҇ȅƬȭÏҷb_ʮßɶ˴Ѐ̐ϊήñʪȴ\"],encodeOffsets:[[44116,13005]]}},{type:\"Feature\",id:\"DNK\",properties:{name:\"Denmark\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ԋڹ࢟ӄŝΒ௼˨ˎу\"],[\"@@ȵ̓ʡĞ؁؁ɮХ՟ŷًŎͽҲ}࡬Ɣɪʌʦ݌À̐ɴڮʂѝʟ˙ĶɽҘŵ\"]],encodeOffsets:[[[12995,56945]],[[11175,57814]]]}},{type:\"Feature\",id:\"DOM\",properties:{name:\"Dominican Republic\"},geometry:{type:\"Polygon\",coordinates:[\"@@ŀƞپIӾɏɜtƴ̕ҠhʡϐЮ̷̯ͿЍǼϫˡ¢ƱƵ͑½ŷȲˣťͳֻɏƆ§ʎjɬɍʦȲƚÞ͒óҜ\"],encodeOffsets:[[-73433,20188]]}},{type:\"Feature\",id:\"DZA\",properties:{name:\"Algeria\"},geometry:{type:\"Polygon\",coordinates:[\"@@ᮩཽᝩ࿷இϑटćU՘ϵƌԹʊȧЀᬻᆴᬻᆴṕᎠfǌ@ÊQ঺ബب࠼Ÿێɦ͎тচͪجӢòϞ̶સƚƸ͜ɛǲ̃ࢲ¹Ԟ́ՠ߰ҠࣦƢՌΎ߶ʰ෎Ƭർæшůߊͨ࣌P΀ȝֺ¾ǟћƄߟȡۙԭҵôمۊԃRȯԮ͹Ϊຝ˖ݏ°ϵƧۇÔϥŃҟòՇͫΗӺؓέ̘ҵϼƸڒϷςՃ\"],encodeOffsets:[[12288,24035]]}},{type:\"Feature\",id:\"ECU\",properties:{name:\"Ecuador\"},geometry:{type:\"Polygon\",coordinates:[\"@@҂غǻξ͍ϵԉςǞʀƙބ̎ŴƺԼ͆զÍ΄ҢǸ׀Ͱࡀӑƾ`Ȳί܊śʆƆЮ˧άȣŞٓʽճࣷ࢟য়ͧԥܵǃ֣Ӆ΋ΙъͻĞ΍áw̮ʈȨıΔ\"],encodeOffsets:[[-82229,-3486]]}},{type:\"Feature\",id:\"EGY\",properties:{name:\"Egypt\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɽͷǹىɫѩȝƥ˩˔ϛϒ׵ஸđùΐࢯԪࡋٌವ̴ҙ˒ӃݮछǗƣճ঒ݭƨǣΏ@Ὁ@⁩@@ᶶ@Ჴʥڲɐ԰Żά̤Ж૦b߲ɝ࠲ʛϴſ٨ˊΌʊݎêװŃɮеȜ˜ڨȣټ³аɄւ෽\"],encodeOffsets:[[35761,30210]]}},{type:\"Feature\",id:\"ERI\",properties:{name:\"Eritrea\"},geometry:{type:\"Polygon\",coordinates:[\"@@˻˖ΉӰϋ˒ɏܷ̄ͶֻXȭǬӯȡԛϢʽط঑ǬęʹβఀĊ֒ˆʴؤƐьӒӦঃɴޗҢУବߏҲӍҖӝˀ˿аʧʩȳέò\"],encodeOffsets:[[43368,12844]]}},{type:\"Feature\",id:\"ESP\",properties:{name:\"Spain\"},geometry:{type:\"Polygon\",coordinates:[\"@@¦״΃θஒ؆ਊƱ૾NࣂƝۦªമͰ͛໺ϡ̨ǺीϝআŊ®ӥߓ֓ઁǯõ˱ԩү͕ہ͞ӑӟϑǹճىǗש٥੧_ߟhՃ͍̓ͅЩê̵˴ʃӚ޷žé˦̶̀Śɬ̃ʢɶրͳԌδèЈƎŬZپϲɪɻфөƝŁӹCɁЬ΃ū̥ɇ\"],encodeOffsets:[[-9251,42886]]}},{type:\"Feature\",id:\"EST\",properties:{name:\"Estonia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ĮӸ̱ŁՓ̘ñӘਫ਼ɼ੔Ũ࣮Ƒࢂ|Ŵƣׯӝʞ޵ΫˉۙDܡ̸ρļ܏Ʃ\"],encodeOffsets:[[24897,59181]]}},{type:\"Feature\",id:\"ETH\",properties:{name:\"Ethiopia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ԜϡӰȢȮǫּWܸ͵ɐ̃όˑΊӯ˼˕̏ω˳Ͽàɵ`ʭҸaȮÐȆƫǽ̴̕ҧ̴Й̛͎ᩨঽۺNᛛᡃફݟףաeɯ˅ַB͹˴ލΙʝΓ֕àȃĬȟwˇT੟܌ב@˹ˢ@ҾѧƘӻࣴϥȚƧʹэЦԧÒ˸ӐҀrŲʰ[ݲʞࢠЊɾĎ΄ήٜԔи΀ࠠƆܠ঒ǫʾظ\"],encodeOffsets:[[38816,15319]]}},{type:\"Feature\",id:\"FIN\",properties:{name:\"Finland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ūיಀ֓ޡى঎ख़֡ܛݴس΅յఘֻ́ѓޭӟᅡੵໃá๑̯ൃǯӡҞ߿ˠȈࠢСݶАӪނՆ኎࣮֖Ǭē΢ୟЈ˳͜uಒ಻ֲ૩ЪԊɞतѻલ¦ࣘȭߠϊЬ؞ಬ˶઄ͯΡכ\"],encodeOffsets:[[29279,70723]]}},{type:\"Feature\",id:\"FJI\",properties:{name:\"Fiji\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@̂ʍƓѭԳŗҩļąτ͖̀ϤĻȼƐ\"],[\"@@՛ǯŅ̼оǤˊ°Ӱˀ@ЧՕȷ\"],[\"@@é­@ШǨĽЗ\"]],encodeOffsets:[[[182655,-17756]],[[183669,-17204]],[[-184235,-16897]]]}},{type:\"Feature\",id:\"FLK\",properties:{name:\"Falkland Islands\"},geometry:{type:\"Polygon\",coordinates:[\"@@৘Ԍ܎ȿԌʹڦϙʥ̋ଋʥϙ̌܋ϙпϚ\"],encodeOffsets:[[-62668,-53094]]}},{type:\"Feature\",id:\"FRA\",properties:{name:\"France\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ˣ٭ϡǠș֢ǜ̺ը͎Ɯܛ\"],[\"@@הЅќà݀ϥȊñʎjЈɗெƷыֹŃ׳ɱƝϣüɇؙҽ]ϟВƀ˾ρʁʚ̿̅ʯɐٱҖŃĩηݿӅစɬ௧˗ĩԑঅŉिϞ̧ǹ໹Ϣͯ͜ѢԎǆူࢁࢤإю౹͒čؖઠǾථɏˇॎߌέዠپʨێܾǞŪ̑ϸ_ϸ͵\"]],encodeOffsets:[[[9790,43165]],[[3675,51589]]]}},{type:\"Feature\",id:\"GAB\",properties:{name:\"Gabon\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࡹࡔ։ۚԙࢄ˨ǾˎȲؔǜخ˴¶௢SOৠЌÆԞőӼňľ¯ÓνɼѡشèȾǗεঃЊӹĞٿŁ֑ʳЇݏ҅Иãϋ֥Ĺ˽Ɂ̈́֋ٕҩ\"],encodeOffsets:[[11361,-4074]]}},{type:\"Feature\",id:\"GBR\",properties:{name:\"United Kingdom\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@҉ֽًǦԱ[ǦҊǥ҈۴ࣔԳ\"],[\"@@࣋ࣧࡦŘऄIɕۅݯݩࢄÃäĕݠ঱ֺƇԬढ़ʈͧৰǅķ՝ѓʗͲѣݱѯ૳Rෝɱϻǒ։ϿޥĪם͍ҁǘ௼ࢨݪǺOBಽƔʃͰ࢜ʺҡҐǆռఢ÷D@ŮӤ֛Ԯ_\\\\৵ƨȧɬ̨ϒˡɴҍЇ·߶щє̨ࢆٶھڤá০ì\"]],encodeOffsets:[[[-5797,55864]],[[-3077,60043]]]}},{type:\"Feature\",id:\"GEO\",properties:{name:\"Georgia\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ųάȿִӟ̲ҭĬ̯ʴĺĲ܄ƝఆƋଦЕƦƻԚƂ޶ǭʴ·Նșɓřвғŗıҏºصʎȵƍଢ଼ſ߳Юࣅ¡\"],encodeOffsets:[[42552,42533]]}},{type:\"Feature\",id:\"GHA\",properties:{name:\"Ghana\"},geometry:{type:\"Polygon\",coordinates:[\"@@೉ӯҳ˽ݳʑݡʆͨηܤɖैΠ۸ɟ஢ŗنrӊฤ¢ϊÕ˔ƊϴáÕʿΖџC؍Ąڍɂ̫ȅݳäйɢՓȈ̍\"],encodeOffsets:[[1086,6072]]}},{type:\"Feature\",id:\"GIN\",properties:{name:\"Guinea\"},geometry:{type:\"Polygon\",coordinates:[\"@@ʃtǡͷʁJǏǴÈͶΗԨɕħǵmɳ³V̮ƇɘʔǻΜɹ̜ڥDțǁɵoƝǷīɹ҅σρӼ͛͢ɋŊȿǖħϊūȂʓƐώЦʮeɖƘȄDƄŎï˨ĢĖd˶МU؀ȱȄlÚĤҜáŨ´¶̭ƆBɖŒƔɸɇάãɲǺ˖ŒȬŠǚuȈȁĴɳΆΙǣɏ˙ǴĊŀį«ʡʲʍǗÝå˷Ș΍Ⱥڧ̷ĵăśÞǋ·νƃA\"],encodeOffsets:[[-8641,7871]]}},{type:\"Feature\",id:\"GMB\",properties:{name:\"Gambia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ņόࣶzȎȦˊ`ͨȷʼIˢƚǞʏεȋιdέǰ̷ȗƭQȫŝއl\"],encodeOffsets:[[-17245,13468]]}},{type:\"Feature\",id:\"GNB\",properties:{name:\"Guinea Bissau\"},geometry:{type:\"Polygon\",coordinates:[\"@@҅ΘΝÈȕʀLŸʯǴÁǶѼƌ˦ɦĨ༈c˵ġĕð˧ƃōȃCɕƗʭfύХ\"],encodeOffsets:[[-15493,11306]]}},{type:\"Feature\",id:\"GNQ\",properties:{name:\"Equatorial Guinea\"},geometry:{type:\"Polygon\",coordinates:[\"@@ƿŴ़̀െmPয়௡T˳µ\"],encodeOffsets:[[9721,1035]]}},{type:\"Feature\",id:\"GRC\",properties:{name:\"Greece\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Ҡ˱ٺ¶شÑqƣҜĶĿʛ௃íTƒਁǎƺΦ\"],[\"@@ʹՁȥĥԟ|ѫĀৱɓ׌ҿяƋҳAѻўƿȁȊԅрЁ̓ǿҴϯжʑ^ӅޥɠʜѕՓĕ͈ݏ֏Yۍμ̿ڦƧ֒͝ϮљӐÉʆϸТ¼˚˘Ũjɚռö͌ȀҖgƒƦǆت{ڨɲע̉ކĀVмЦɝ\"]],encodeOffsets:[[[24269,36562]],[[27243,42560]]]}},{type:\"Feature\",id:\"GRL\",properties:{name:\"Greenland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ᬜԆ᱒ੴ̴ᲈĄ䀦Ŀ㉊ڗ༅͕ộ⭏ćшƫᲐĠᡚ́࿈ʴۦ̝इӧᒞ̺✘͚ᠼǋҾΫ⃝ױӃȕ᧑ơወ¡ছؕگկध৚շಽ൧ˇ༂ѽȢ܋࣍ýઞܡህÑঈ΁˟̑இŽ୥E੆֩\\\\Ϗပΐћɣଌȿ઼ԣ͈ڱກǉ٫͖ਣӘ˼֭উѵᕖ୆¯ᖯܵᗿڏឧ́ओIࢅ͓ୟࢱᅵכׅ૧ȷ஽ȝܛԱ[כыտോڧͺٿϗ۝љࠍஅ½఍ۈဿLࠁҢ֕ࠐฝਲэոŗݮ୓ޢ̢ئ֗̒ࠪচొ̺ͨΘǬڀॡ̕қůݯţਏ˜Éְ͢҂ެ\\\\႔ɟ෿Քݩ˾࠷ş۫ȼम޴ԝ̺ڗ׈ৡࢼ੯͚XΚᖷӮᄻÖᖟᏅ×ইˌวՈᕂ˄ၚ¬≹ɖ቉΄Ś͜ẊИᶎИ̪͘ᗗ̠ܺͰ᯲ז௢ĚΓϘጲɜᣚƂᣖRࣺʽᕺҨፘ̽୺áპ˙ፅҐŘή\"],encodeOffsets:[[-47886,84612]]}},{type:\"Feature\",id:\"GTM\",properties:{name:\"Guatemala\"},geometry:{type:\"Polygon\",coordinates:[\"@@ћƦԻfϩǖҍΌrʖĮȠšƾКۆ઄Ft˸Ƌ¾ġǺ̵Ț̹ˬϜDBӂ޸BަUOڗßॅʤ@˚ƱòŰʘŃϥ͍ЉɻÏǉâǑǧɇȟ½¬ıƿġ˽Ƀ}ŭ\"],encodeOffsets:[[-92257,14065]]}},{type:\"Feature\",id:\"GUF\",properties:{name:\"French Guiana\"},geometry:{type:\"Polygon\",coordinates:[\"@@͉͑ГÑŗʀȉʹɩνǦɈΪòϤƢή͛ӸáֺѪܠ˸ğؤȥࢸۿƔ·ӻޑʳأ\"],encodeOffsets:[[-53817,2565]]}},{type:\"Feature\",id:\"GUY\",properties:{name:\"Guyana\"},geometry:{type:\"Polygon\",coordinates:[\"@@ր̯Դյzџ̈́o҈Чͪ̇Ƈݱԛɕ°ȣƹџϊ؏ːAŎӃԢܳȱҫî˙ɡϟƥ˅ġǑЭ¦ԫЀÓϴɋьƆܐɸ̐ȕϸ˿ŶŊτțȘѩْ֩ɬɲiϲԬƊȾƾ˽̸ô̬ږӲ\"],encodeOffsets:[[-61192,8568]]}},{type:\"Feature\",id:\"HND\",properties:{name:\"Honduras\"},geometry:{type:\"Polygon\",coordinates:[\"@@ơˀʭòÐʹŗĞǣÒσĳŔʩƈǷǚʛìǨɈáǒÐǊЊɼϦ͎ĔȂƨʊ\\\\þåž¦ϸùϲv˒ĢİĦˎ©ȪÉɘnǖòϨśƄkʲƿʐį̏Źɜɳ˽jśŕ̇ŋɃAȅŃǙƛźĕ{ŇȩăRaǥ̉ɳƹıđĽʛǞǹɣǫPȟqlЭūQĿȓʽ\"],encodeOffsets:[[-89412,13297]]}},{type:\"Feature\",id:\"HRV\",properties:{name:\"Croatia\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ȳ͗ˊʇ͓̓ϝȆׇ[ܟƔϽmǻǧ̝ȖǫΑЪϽǼʹϮ̽͌ȃ͆Ηݔ͇ġƛ߃̶ӣ̢ޑʠ۹ؤǞØϥΞe˲եƄʱγʝˮn̆bגƸƚ˸ƍͤgGɼ̈ĒĈͺڞɠˊĻؼέۜǉ̼Ų\"],encodeOffsets:[[19282,47011]]}},{type:\"Feature\",id:\"HTI\",properties:{name:\"Haiti\"},geometry:{type:\"Polygon\",coordinates:[\"@@ԢܰƁôқÝ͑ȱƙɎʥiɫ֏ƜЅÍԡÔϽƿ҉ʾö˔ޜśيã̢ȈϧθP͎ՋžȌɶ\"],encodeOffsets:[[-74946,20394]]}},{type:\"Feature\",id:\"HUN\",properties:{name:\"Hungary\"},geometry:{type:\"Polygon\",coordinates:[\"@@˨ըǍǼӂDÜ΄ђɋ̲ğ۸ļäǚͮ~ЦžĜÃЂŀȠȢˠ¼࣒ʭǴĒҲɭÎɣԡǭЉ֫ԕ֭کǁԽ١ə̻űۛǊػήˉļǍ˴ƗV\"],encodeOffsets:[[16592,47977]]}},{type:\"Feature\",id:\"IDN\",properties:{name:\"Indonesia\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Λe૝ך޴ǒѴʭ̎ʭ»ɩ\"],[\"@@ܙȁĳĶø˸ΰԢࠨͬĐǓfʫշع\"],[\"@@̢ɣԲèȼΥॿǛ׉őҍP̀ӚҤPɤ̖\"],[\"@@ūұ౅ʅૣľE̬ښǪՂʥ֔Üݬ̮\"],[\"@@ྔċȂΌ༘З̪կీƵਐӿय़͋ऍ͸ݻwࢍØ޻ưঅ͎؝ČΓŁ໕ΌƣΰޑØּߤ৶·ڴ͡ΒÛŘ̗\"],[\"@@ѝֱćنƬ̠Ǭ˴ȒʗCЏ\"],[\"@@̿˥ׅƸǏΰࡘ¢Ⱦˣ\"],[\"@@̨ٝۿΌۯìӃÅׇȦҦਠऎʕ\"],[\"@@ɼയ࢈ԉ۰ࢼ८ԔݜBܘ̉خ̛ࣘǇbᩑbᩑݟې࡟ǜȷʇ੡}ΦۂՈɺɕࣲЕ۸࿃܆ۗêృަʛУ͑óȏ̮GκٛЮ̢ࣞ״gëɠ௵DͩԄݥƺΡдଈȰњ˜ഘ·Ƃ̹\"],[\"@@ڭ࠭كǉ߱ǐඓ¥ܽŧţٍݪݛҒϠ༪˸çϯλŪιӯ͙݉ߒ੿Ƶ˿ݲॻQտ҅ʙ̐͡Мی࠙͗ȻɶŊ͖؅ӲØࠌ֕ʭîওறՓũίʚʌޜŽ߸ΛPʻֺΎվŤښф౎ǮΎ܎ذپʛ੖śॴࠨ؎Ʀȉ\"],[\"@@©ܽџĈŷԝΌѷɽĵ͹Ւʟ੺ǚڤ˨̨ÔҝӸóĀ΃\"],[\"@@सާহį˫ֵݿַ߱u࠷͕౻ŭ̚ॕϙͫԤ׳´лːৃ̟̩Оս¯ۗĬŹૺнɺЕܘŝ݀ĮުԂ֐Ɩָ֗ӅըǠ՜ÑӪъЖôߒɽۆǶњୠ͔̈̆क़ॲ@ܰƙӍݷآߓơϭ\"],[\"@@छkۻ۰અۊέԚٍۄзؾٕ୴۪݅ʙܠ̳ڀݵՊѭܘمҺࢗऒóђզಢǋݔࠓٮ֫ҪΓߔࣙࡢ_ۺֹӠ۳٘ϥͳۉӖ̞̅sƜו̊ҵؠõФՏɁ਱ಟ\"]],encodeOffsets:[[[123613,-10485]],[[127423,-10383]],[[120730,-8289]],[[125854,-8288]],[[111231,-6940]],[[137959,-6363]],[[130304,-3542]],[[133603,-3168]],[[137363,-1179]],[[128247,1454]],[[131777,1160]],[[120705,1872]],[[108358,-5992]]]}},{type:\"Feature\",id:\"IND\",properties:{name:\"India\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࣚটďۅͮїѕ׽ŒɾएࠜՑ୞חՑϟ͛޻ࠀͅߊЭરһସŉӜёٮāৠȝ۪bĪͪŋՖÞβԠǮìڋlǙކ͉Ոƀ܀Çۈ|ÐԪ΁ˎڴŀވشॸ՘۶ȷ״ΞЀԹ˳Λ࣠űÜ͇̍Ʒèԫ׷Ʋછׅ~ӓҩ۵§ХϏۗځȒࢇȏ˹ĚΣгȥѵ೰ɵEƍ՝ҡѦʸӎϖ¶ϰ܆ӝƜީ]ߝŚóאБ¤ڕζ֭̓؆ѻԿ̻ȅ̩Ԭɣƛԑ̆كžەţֱ̫Zਛǩ´ك҃ӻ௃֡ळ঩كՋ࠷ջCϭлȹݳ̝Ͻ«ʥٙǪધ®ۡΣߙI෗ѣ¡ϣٙʰˣދʃ˱֯͵ʍߑ޸ϳ୴͑ࡒ̍Јѿ߰ȻੂơՀޅ଼Α࿀ʣ੾HৰǍ޾௣ԉףĶ઱৲И̤ʝͤড܊֖֔ᇜCǗܞҽюĩ٨ջϘऒࢢঊÙ࢞ࢢՄ࡞ࠄࡈ_״ܒӠڳд֪݂̇̕Ьβ౤ȱपŰߺ۸\"],encodeOffsets:[[79706,36346]]}},{type:\"Feature\",id:\"IRL\",properties:{name:\"Ireland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ƒ׷ًݣ๯ӹ஑Ŷڼ࢚ѭࡢତڄٌϼǦ҇ǥ҉Բ\\\\ٌǥ\"],encodeOffsets:[[-6346,55161]]}},{type:\"Feature\",id:\"IRN\",properties:{name:\"Iran\"},geometry:{type:\"Polygon\",coordinates:[\"@@݈ǌװӔ֚{τƾװýघэڤğ।ݓظòۻ΁਷ɱؑκŭΫҡˠڡàՓِƙæեݿݿжѵ͸ԓߦυx݉ДƋêϯ௉ѡ̓উཌྷʪࣷȖेŊΧਐЕƪ٣ƭࡑНਇ˦ࡑ٦߳ʈ֗ߘا૪ҍƋՕ˦̻͝ҭѴS҂ˍ@Ɛ،ѝٔ਍Ң׉ߜȜپц̂ÙӬտʨխ৊ҟڨǐʼʿ६ּʈƄͅъϯ־ő̤~রئ̀Øʞʙ́гԼѱȾ¦ˈإߖǩ׎у஠ƟಾɞĄȞ\"],encodeOffsets:[[55216,38092]]}},{type:\"Feature\",id:\"IRQ\",properties:{name:\"Iraq\"},geometry:{type:\"Polygon\",coordinates:[\"@@րʧÚӫх́țٽ׊ߛ਎ҡўٓƏ؋ˎ@TҁҮѳӿ¤֟ê؝߭༟äᛍၖఫךৡɪ͹৾ᇶ࢔͆৬āؘҢȺјԾΰž঎Ň̐ɉЖƚծ৉\"],encodeOffsets:[[46511,36842]]}},{type:\"Feature\",id:\"ISL\",properties:{name:\"Iceland\"},geometry:{type:\"Polygon\",coordinates:[\"@@șիॊֵથٙᝓֹܣƵૉŮᚑˈࠠψᆧЪ๪ǎʘᄋȜ֨նౠŰಸ֭౨Ҝ੒ʃൌ҄ආÑ\"],encodeOffsets:[[-14856,68051]]}},{type:\"Feature\",id:\"ISR\",properties:{name:\"Israel\"},geometry:{type:\"Polygon\",coordinates:[\"@@ƥ˅̣Ŝǫ֓ɂĥɋřɛЄŖp͛нഉց෾ʔˢË¶ɞϼǠيŤɆzVˬCþƦɤ\\\\`·ŕŵhM\"],encodeOffsets:[[36578,33495]]}},{type:\"Feature\",id:\"ITA\",properties:{name:\"Italy\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@̟ڋŲʹǭѝٝ̈́ёĞ୩ѐŞќজûࡪĠْò\"],[\"@@Ԍ׭ş૕ϣÂ΁˫͇ɞ২ȓӒҨ¥рʼ\"],[\"@@ரɏĝЯȬΧڝŪہ̗²зĻʇˠё߀чцۛदڱچLȲȃɽǗݪ̥ؠʩܜѫĔƿƽ̛үϼܳƐΝի؈̷ıѫΗ¹҅ܛΕÝHʲǢҊǼǶ͝ӤʱшΑŀʛδգƴεͶثÆٿϜޑմ֯ӜʿࠪйĮہˤϯŕӝϵΓÕĪθҕńɏٲ̆ʰʙ̀ʂβǵМ¢Ҽ˶ƢƃАǼͺتĿψƚâΆԘšĮǆࠨƤȊ̉\"]],encodeOffsets:[[[15893,39149]],[[9432,42200]],[[12674,47890]]]}},{type:\"Feature\",id:\"JAM\",properties:{name:\"Jamaica\"},geometry:{type:\"Polygon\",coordinates:[\"@@֢÷ҀȫƔɯןeʭƗҹƊӑ̪ĶȔΜÎȒ\"],encodeOffsets:[[-79431,18935]]}},{type:\"Feature\",id:\"JOR\",properties:{name:\"Jordan\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ʀˆपͫ࿪ࣆͺ৽ǅų၅у࠸࠿ˣƛƑ˭ٙřȩ̡εʵधƆŨоഊo͜Ůʚ@Ԥ\"],encodeOffsets:[[36399,33172]]}},{type:\"Feature\",id:\"JPN\",properties:{name:\"Japan\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ņ˽ҿԕΉːљțɝӭշʈRЊҬԆӌīΊΜؠǹ\"],[\"@@́ڡƤсѩף੹Ѓ๏½ணॡ͔֡غษȃষЃঝe࡞أ֗෗իΝН͜ȶݶՏʒͿ־ߐʶѲՈࡌѢ؞ָာʤ࣎ǣࢠ๺֔Б௾ࡀӌ͜ՈਈƟा΢ՎࣀƸҞୗ}ڻޥࡍbࢁ\"],[\"@@נǵרΤȈहఝɯ݁࠱೓ָқँण]ř࠴д٨࣌²ʖ୐ʜټন࢓٤˯\"]],encodeOffsets:[[[137870,34969]],[[144360,38034]],[[147365,45235]]]}},{type:\"Feature\",id:\"KAZ\",properties:{name:\"Kazakhstan\"},geometry:{type:\"Polygon\",coordinates:[\"@@ӕƹ્דο׹̹KɱЊ੫ǡێХNÚࡆ৓ؘ෷ßডũߣݶۋ͆ಥ׼ƽðᓗӹᶽљ£יچ֧ɼॕǩχ˧±ȲȶΖǅ̊অ˺ϛݮҩɆ˜ࠊāؘ܎ƎܼűƲࠎƭԲ࠿£܍ȴঃσ޵ǭяƌĐўՙ֘دw܉֬ӞِʕǢڢऊࡺӣŀؘჄࣴಾtᇢ׉঺ͻࢼΠ೰j੺ѥʔʠ୼ɂЊഷ׀߮Цƿɮ߮ɔ؅ֺϬ˼Ḯ̈ШȺᑆ̴ݰΒຢǹ˄ࢉ࢚Ȳઆ˹éҝ߮´ᑌߎ̭ˁ੶٭ሠᒑ҄ѰୄӛீɎҪƯКӟטǋΨΥ઎ŒѾԣٕ֓ۥÿ¡ࡅұϝဟˢ؅ຑїȇဗͱݲลֻɓäӏԭŬу̠ఝĖඃx̧ġ஥ΞӉǧŽӹ൩̂փşȉρ\"],encodeOffsets:[[72666,43281]]}},{type:\"Feature\",id:\"KEN\",properties:{name:\"Kenya\"},geometry:{type:\"Polygon\",coordinates:[\"@@ӾۙיͱȹΕ̿Õšףˑ͹Ǐ֑ͷ˥஻ࡀËӤᵁႌƙĢSࢺʊ;а֌̨ؔσ॰įтЉ׎ԬԈ֬ֆѨƗ@ҽ˺ˡג@੠܋ˈSȠxȄī֖ßʞΔގΚͺ˳ָAܽ॑Xᵣ\"],encodeOffsets:[[41977,-878]]}},{type:\"Feature\",id:\"KGZ\",properties:{name:\"Kyrgyzstan\"},geometry:{type:\"Polygon\",coordinates:[\"@@ȊςքŠ൪́žӺӊǨ஦Ν̨Ģ඄wఞĕф̟Ԯūşȏ೛ғ̙ͭઁıͅ՛ࢷŒׇǏߣЇŜȟʇȓཟŵਡ˘࣫ÝĂӜࣴƕ̮ʸٖĉ੾؂঻ѸױȽإ͂۶ծʟĊ\"],encodeOffsets:[[72666,43281]]}},{type:\"Feature\",id:\"KHM\",properties:{name:\"Cambodia\"},geometry:{type:\"Polygon\",coordinates:[\"@@΁Ѭыࢄȣ২ՠۨઘǆ߀ťۚ͡Ϟׄݖ̱Ȝ֕Ļ৕ඳ٧τԙࢥÓܫͷ۱Ū\"],encodeOffsets:[[105982,10888]]}},{type:\"Feature\",id:\"KOR\",properties:{name:\"South Korea\"},geometry:{type:\"Polygon\",coordinates:[\"@@ܨযȺխPॷ̓ҥݽǉڥΏݳïĥҚƼـχ࢔ذƚֻܘÂúϒ͞Ϝצ¢ΨÈŨȮ\"],encodeOffsets:[[131431,39539]]}},{type:\"Feature\",id:\"CS-KM\",properties:{name:\"Kosovo\"},geometry:{type:\"Polygon\",coordinates:[\"@@ǣŃPĘ́ȩĐǳɦƾȌȪÒŜ˨ư²Ţşƾ¿ŌƅƒǎƻŢLĥȳĳĳ×ȉӹŻ\"],encodeOffsets:[[21261,43062]]}},{type:\"Feature\",id:\"KWT\",properties:{name:\"Kuwait\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ǭχõȓ˔هשuȽАݟĆ؞߮֠é\"],encodeOffsets:[[49126,30696]]}},{type:\"Feature\",id:\"LAO\",properties:{name:\"Laos\"},geometry:{type:\"Polygon\",coordinates:[\"@@˚Ϝ܆ڹܸ¿ٕࠦھٍÎǛ̉ӯyʣƨࢯԅoݬȸࢮ֧³ԎηʸǴ̲ܐնøȡ҄wŵ०ѦŬӮڏϖޅਚO͚ܹ՝ɗʉ̟৔ԉۦ঳Ռ݋َ׏ɄץƵ࠿ݕ̲ϝ׃ۙ͢\"],encodeOffsets:[[107745,14616]]}},{type:\"Feature\",id:\"LBN\",properties:{name:\"Lebanon\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɣ[ýƥ˫D̘ۄмעfϘ§Ɛͣқ̓ȷҟ\"],encodeOffsets:[[36681,34077]]}},{type:\"Feature\",id:\"LBR\",properties:{name:\"Liberia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɗQࡽАޅٖ܏Ң֣ըȪː¬ʔϜҘϺϺǶnɖĨΘԧÇ͵ǐǳʂIǢ͸ʄsʓĎНǽύʖɱˊÇΤΙ~ͧăĿÝە\"],encodeOffsets:[[-7897,4470]]}},{type:\"Feature\",id:\"LBY\",properties:{name:\"Libya\"},geometry:{type:\"Polygon\",coordinates:[\"@@ק̷ҿҤ೧βρՄڑϸϻƷ̗ҶήӹؔͬΘñՈńҠÓϦƨۈ¯϶˕ݐШȜðΠėΒ־͔ʶːЦʌ´٦দ́ΜðۮƓ૞ϓЀݛݮǍஆΙࣆйЦɔЖϮț٠˂Ф؄ЀׂŘ଒ǣ˺ϑ̺Iˌƛ࠴ıȲˣ̣ЕżΫɏԯʦڱ@Ჳ@ᶵ@့ॱGYΙ‧ྐ‧ྒࡓҟ\"],encodeOffsets:[[15208,23412]]}},{type:\"Feature\",id:\"LKA\",properties:{name:\"Sri Lanka\"},geometry:{type:\"Polygon\",coordinates:[\"@@ų࢓ΙʇܵȓЍڜƫீϠ഼׆ұϺסО࢓\"],encodeOffsets:[[83751,7704]]}},{type:\"Feature\",id:\"LSO\",properties:{name:\"Lesotho\"},geometry:{type:\"Polygon\",coordinates:[\"@@̆ʩʳУƛ˛ҳſƹˍ̛ċؿ٨҄ՐҖ͢ϼǠξʵ\"],encodeOffsets:[[29674,-29650]]}},{type:\"Feature\",id:\"LTU\",properties:{name:\"Lithuania\"},geometry:{type:\"Polygon\",coordinates:[\"@@ãɊĚɲχƄࢡƨǱ۸२ʴඬÁࠜĊŞǩ҂Ã߲СĀϓۏˏșӃ࣯̓߻NȫʶљĜ\"],encodeOffsets:[[23277,55632]]}},{type:\"Feature\",id:\"LUX\",properties:{name:\"Luxembourg\"},geometry:{type:\"Polygon\",coordinates:[\"@@ǘȏ³ρʍiȉòĞҼɖ\"],encodeOffsets:[[6189,51332]]}},{type:\"Feature\",id:\"LVA\",properties:{name:\"Latvia\"},geometry:{type:\"Polygon\",coordinates:[\"@@نЮՆߊ˼ڜعڪhǊ٤ܐƪςĻܢ̷ۚCКȕîС˒ӷ͕ࣗԛƙ߱ТҁÄŝǪࠛĉණÂ१ʳ\"],encodeOffsets:[[21562,57376]]}},{type:\"Feature\",id:\"MAR\",properties:{name:\"Morocco\"},geometry:{type:\"Polygon\",coordinates:[\"@@ԒΥߜÎࢊȃκU͂՟ºԝ̄ࢱɜǱƷ͛ષƙϝ̵ӡñثঙ͍ͩсۍɥ࠻ŷഫاRহŷ@@@p҉Ա˓ȑϡ@̥Ŋ۹ě˛ٻʿÕЁ੕ୟ࣡ˣୋ΅ϗĵ̡ቅãaD ϶͒ɮ˞ѪÃ˶̀פҴՖ˲ƊɞӬp҂̤Բ̪֔Ւ࡬f\\\\ц͔ްĢڎָтɠۮۮȿਸ਼͊ܢŔѶդ֨ࡈϦخΐ֘࢈˄ԪؤI\"],encodeOffsets:[[-5318,36614]]}},{type:\"Feature\",id:\"MDA\",properties:{name:\"Moldova\"},geometry:{type:\"Polygon\",coordinates:[\"@@ȨŮ֒ĊؤʽΊϞɥÑ˵̪ƏŨΗ̊ɇÏűƾčɝ×ӷ|ĉŜǫãÒƭɱˍƥ˽ɁĝƯϦĘΪςӝԂˉΠʹʠʯĈ\"],encodeOffsets:[[27259,49379]]}},{type:\"Feature\",id:\"MDG\",properties:{name:\"Madagascar\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɠΥȺ։Ɗঢ়ɒϽĉЗƩʙ˷ӰǁʝǈثõΥɵȗ¿܅ͧওб୅ԯཧ͑ୟϛইہȣܻΡӛɊڙ̜ɳѺÇݘ̑ڠù؂Ʈ؄ϰƢD˪Дِø՚șЈǃՌãޠ̊ҺŔՒмҶǤ̶Ʋτ\\\\ӐӎۖԮʦцŗάΦĵҪ׎fԐ˦ϔ̊ί\"],encodeOffsets:[[50733,-12769]]}},{type:\"Feature\",id:\"MEX\",properties:{name:\"Mexico\"},geometry:{type:\"Polygon\",coordinates:[\"@@͙݅ƥ؁Õ૷ąЧƤқʺЧǚٳ֎سȞӏ͢бࢾɝΐΙ݄ɾٚĎؼưՊƠՖ΂ȨӬè۸Ƣʖ֬ɚࢶȚݔԚîȬǱЙҋԁȥԝƸƥűγɁٽɅɎǭcǃY̝ԓƳĲķPŭޥV޷AAӁϛC̺˫̶șĢǹƌ½s˷ઃEЙۅŢƽĭȟqʕ्ࣞџ˘ۇɖҷÓګ́чĉץɜؿǄ޹ϬؿŠ्ϸ۱ВɃɤҹº࡯ˈΓϦࣗӊсՌȧЦ˪ĈđʈȖɔJ̄˱Ϙùͮ˭ъ݋࠴ࡋڀУԼܝ΄ƷȴŸԲѓȞӹФȽהҍæӣѸϿФˀҍو̓٠^͔؇ͬ˫ӑɴƇͿƔЕĆف̀΋خׁƒȡŸÓŎ˽Ƭ\\\\ǜթʮɇǴ̕Նё˨ޯʠρɸϿ²ѷКͶϡ̨ϑqƭΝ̱ƫJɛԞջӎ؃РїɈؚŵҖЏʺֿϒŏŇɃɖԭȰӷӦÖÚΊ³̸̼Ϝ٩׶ӱɶ̱Հ̷վϳڦͿݲॖÞ੪ĞÿǑ౔СኀףဪPژ@DΌผ@̪̕јˇԀσ˨ѭȾҥѢʩۤʥՊڒۊhפͱфֹ̄ӯӸӏȂחɾЃپʹ׮ȁ͞|\"],encodeOffsets:[[-99471,26491]]}},{type:\"Feature\",id:\"MKD\",properties:{name:\"Macedonia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ńOǤӺżȊ˺¶ϴbтˏÒ։ǅƑƥҕh͋ǿջõΑȴšήń˸\"],encodeOffsets:[[21085,42860]]}},{type:\"Feature\",id:\"MLI\",properties:{name:\"Mali\"},geometry:{type:\"Polygon\",coordinates:[\"@@˰ƶƘӶˊpזɻӄǖ͖ÇŴȈ⁚^ȈךƣļЛ⋈Л⋆౾dᬼᆳᬼᆳȨϿԺʉ϶ƋV՗ठĈFካҟ֗íԭݛƃ଩ï̳̗ա՟Iȿǈҥš޻ΑǅʿٳϕŗɍΙǡНŔɱȳūֻڙۡp˳ɭΣÆӥ΋ůȝŁŽάʍĥơhƷʕ٭PɷŴŉùʱʎ¬ʢĿİǳĉ˚Ǥɐ΅ΚĳɴȇȂǙvȫş˕őɱǹΫäɷɈƓɕőƅAµ̮ʾí̽͘ʀǓӔԺ\"],encodeOffsets:[[-12462,14968]]}},{type:\"Feature\",id:\"MMR\",properties:{name:\"Myanmar\"},geometry:{type:\"Polygon\",coordinates:[\"@@ӫηץϥࣥΟƳО݅ՔؗΈօ̭ܵ̃ƹȪу֖ڙĪҷ_ϵ͠ދң޵Сࡷăذʴ٠˯ӼæࣸͽѤ˛৔Ʊਗ਼εۢօуॕ׳ҽöԳȠ̂ਪǫ޾څॺļ̢ӭņ׭ۆÅڰ̊ŵj׾дȦęΤȐ˺࢈ڂȑϐۘ¨ЦҪ۶}Ӕજ׆׸ƱçԬ̎ƸÛ͈ӮÚˮӵξȧ|ٟۙߓۭĳঽࢲƔȨޛՐǍʓۣز́ζƷ؞ʔ~΍܏յǳ̱ӓȗ\"],encodeOffsets:[[101933,20672]]}},{type:\"Feature\",id:\"MNE\",properties:{name:\"Montenegro\"},geometry:{type:\"Polygon\",coordinates:[\"@@ÁǀηЯÊˋǫÞɽ˞εǖĢƜŬҦ˚ȜƾüɠƟŬśˠě͌ǧçïƽȋɧó\"],encodeOffsets:[[20277,43521]]}},{type:\"Feature\",id:\"MNG\",properties:{name:\"Mongolia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࢮƢ྄ܤ౬Єܴʳ࢚]֘Ͻ࠼ௐɁࠈגͿӶࢊࢊश΍ނįনɍǈؿஜΛߐƺਫ਼ŌࡆōࠖЗԚѕެT੒Ƌޜȼૈƒ௸פԌĝѰ˭ৌêХهק࠽ɐ΅ӈńࠤŽ٦̴ڬˏހוğ̗ڏĦ௟ŏןʅ؝։౱͙࠷ѽࡹǞҿúѳէˎ͓ƌˣי˯׽҇গ̑ఽഫ̇এҋϋʾ৭AఓԜࠥŰૣśჃȊऑmӱԀϣޠԱĢ৩ԼଅŞুƞ̡θ͖চׅڲன̀۷Ѿəז\"],encodeOffsets:[[89858,50481]]}},{type:\"Feature\",id:\"MOZ\",properties:{name:\"Mozambique\"},geometry:{type:\"Polygon\",coordinates:[\"@@لæ৞ʁɖńגt̚ʦԌaऀ͜ڞӤƊϕ࠷ľ݅ಿƨЫʣ׷͙׍՗Եޏ͉ृСॉ͓ࣕƵוׯ΋ȗí׳ЌُǔӱZʣƪ¦{ࠗƋϷȤƝűΓΗ̗ۗ˳য়ҕρ̳ðΟɊÉíѵّRïϊůϖí̠ƬपɓװГஂࢬ॔ɜ؆ŶúĨӶƉʞغǐ׌E੠ѥ˒ЏÔǹȼϳǰ۫gÅ̼āװᢈۘӚЕɴüͨɅ¸͵ǯϷØסոԱʲ׌ζǰíઊΙ؈̣˖̅]ɽદɾٔ\"],encodeOffsets:[[35390,-11796]]}},{type:\"Feature\",id:\"MRT\",properties:{name:\"Mauritania\"},geometry:{type:\"Polygon\",coordinates:[\"@@և־ԗؤ֍ɞГʚҵUЧǽйð˽ˏïҐɺаŀߊģࠨĵкČмɑЎѵδǾˬᾔMǃ௎ȴќ߀øᒸ᪂©F౞Ṗ᎟౽cМ⋅М⋇ƤĻȇי⁙]ųȇ͕ÈӃǕוɼˉoƗӵ˯Ƶ\"],encodeOffsets:[[-12462,14968]]}},{type:\"Feature\",id:\"MWI\",properties:{name:\"Malawi\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɽٓɾથ̆^̤˕Κ؇îઉεǯʱ׋շԲ×עǰϸ·ͶͧɆɳûәЖѵɔʮޮ˄̈Ǉۢǚڼƞɪɉ܌Ѕϐ࠘ƽǜɵ˶Ϲɾଡ\"],encodeOffsets:[[35390,-11796]]}},{type:\"Feature\",id:\"MYS\",properties:{name:\"Malaysia\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@àћֈĶ˞ΈȘýӸԓΜ֛¶֣ęϡĆ˿Öӻ̒ɵͤݑe˳׫Éߑخ঵ښįђӟ֚ś̡۠ҜĠؔȃΤƤƮۈρ\"],[\"@@أ˹ܯƚॱ@̅ॗ͓̇љୟۅǵߑɾЕóөщ՛Òէǟַӆƕ֘؜˽ٮǀǜ܆άǂ৖Ǻ׾ڔЬՐϦѥǮ˺В¸՜а٪אшڀͼHќыιֆɻ۬ʧÑ֝͡¥ƮЧ\"]],encodeOffsets:[[[103502,6354]],[[121466,4586]]]}},{type:\"Feature\",id:\"NAM\",properties:{name:\"Namibia\"},geometry:{type:\"Polygon\",coordinates:[\"@@رٌؖ͡ȃࠊȷ،˯ಒm৒ŅҞ͛Όѡۜѳ৘ǽՆۃࠐ»٢КǆԊƞհ}ԄϝŶÐ₮׌Е᎞ş໴΂یȒհµͨȍPéӁȍʭC՛͍ͣΎಕ̍س{ᲽࠣBយA᷋ݣѕҋÕՇǄϗÔƗάͩɰГг\"],encodeOffsets:[[16738,-29262]]}},{type:\"Feature\",id:\"NCL\",properties:{name:\"New Caledonia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ېԵѨϭ͉ȫҥɪ׹ϚէѼ։פś˶β[Һ˹φ˷ˎɻ\"],encodeOffsets:[[169759,-21585]]}},{type:\"Feature\",id:\"NER\",properties:{name:\"Niger\"},geometry:{type:\"Polygon\",coordinates:[\"@@nּॹȐОҿպœϤâТբ̴̘ପðݜƄîԮҠ֘Eኬஈϒᝪ࿸᮪ཾ೨αӀңר̸ȸಯ̾ɓ`ˋΔ˽ǻί͕ၻ«ધੳߋγૉΔ̵CեբmčЃʁµˋƻm֩ंȟځҷٱʔҍ¸ʏşӯ~ӷΧѓq৯ѢЉȵѓb̿͆ࡅ̼ࣗıɕǻşӗʋ͹ÍݣٗӚ̟E˭ʗ\"],encodeOffsets:[[2207,12227]]}},{type:\"Feature\",id:\"NGA\",properties:{name:\"Nigeria\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࢍ̡͉¬͓ȉڥl҇Ղˡ؊שֆكYݍB¶തs՘ǂՊʶʴТԴėɨǔ͸ȍӾ˪ÎݤʌͺŠӘɖǼࣘĲࡆ̻̀ͅєaЊȶৰѡєrӸΨӰ}ʐŠҎ·ٲʓڂҸȠ֪ँƼnͬͯğƱ«˧۽ٱɛՙšѧǱȉǝי҅ΉŽыȋ͹ÿΓֽ˱ҽΊ͇aԃӭʑQЍ߷ɍש\"],encodeOffsets:[[8705,4887]]}},{type:\"Feature\",id:\"NIC\",properties:{name:\"Nicaragua\"},geometry:{type:\"Polygon\",coordinates:[\"@@̃ˆϽͺȁ˲Ο˄сϜĤžƒŵÚÒʾŀȔŬRkЮȠrǬOǺɤʜǝĒľƺĲ̊ɴbǦĄQňȪĖ|ƜŹǚȆńɄB̈ŌŜŖ˾iïă§ȉĐ̫ȗ˹ěͷυ®ɏtϙŹĉýΫÌɛǣɋ ɩźƏȩǱʛÈƓǦˉêȕŉօɞųŇ\"],encodeOffsets:[[-87769,11355]]}},{type:\"Feature\",id:\"NLD\",properties:{name:\"Netherlands\"},geometry:{type:\"Polygon\",coordinates:[\"@@ۦyǀ˳Ƚޓɇ́ԍ@ƘࢡҥȞՏπީǩ؛âѠɲ݀ఆଲΘ\"],encodeOffsets:[[6220,54795]]}},{type:\"Feature\",id:\"NOR\",properties:{name:\"Norway\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@᥆ؙઍɣऄՅෛ͵ڵû΢לઃͰಫ˵Ы؝ߟωࣗȮ઱¥णѼԉɝԷūփནƊɝҵ߭Hևױ࠿झಫ஁̨˹̇ͫ࠯bձ޿¾૟՞э˥ধֻۧυӛ֝Ԫဋঁ૫ȟ୏є̛ࣚˇ኶ޞզᕠ۶ဌࢂ໤୦፺ྴඦلᘼ੊ᇎπ൪­౮ۢ໖ພǘ\"],[\"@@ም΅๝Ȝ׆ɐԕˎეǚͮ̿ொȍ\"],[\"@@᪖صᑟͥұأ݅ǁЍۡৣᅵԢނ̘ఽʐ࿕܂ٷڄᘎ̜Ң̋஦\\\\͊˼௾੖̋\"],[\"@@࿮̏ఝҍ᝱ı៙ƖƫɴஹdँϬᣴɼ௞ȫࡘʤᑺȽ\"]],encodeOffsets:[[[28842,72894]],[[25318,79723]],[[18690,81615]],[[26059,82338]]]}},{type:\"Feature\",id:\"NPL\",properties:{name:\"Nepal\"},geometry:{type:\"Polygon\",coordinates:[\"@@ÝαŌՕĩͩ۩aয়Ȟ٭ĂӛђଷŊયҼ߉Ю߿͆͜޼ՒϠΒȪڪʳࡔշҾť˰ЕٶǓۀσौȕঔć\"],encodeOffsets:[[90236,28546]]}},{type:\"Feature\",id:\"NZL\",properties:{name:\"New Zealand\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Ȓ΋װ;ʐΡBΝ̹ϳչإїͷ̴З٭Yܗ̓ɣջӋࡗڇϓнʇޝlխˢࣱÐƗ̰Ҍذ੐ࠦժǀ׾͌ܜѰԎѦώظ͈ɆŰҶלϴȆΧ\"],[\"@@،ࢫlָϜɯŲًڰ˛֨ãӒ͎юĭȯݗʯӫٛjɡʭþαūƻͅҏзֹ٭ͯƟɘΕŨӞ۔˟ҨࣛͲz̦؈̌ƚ٨լͻ֜vƪБΎڋݔΗת̸àҚұٺɑʂݡ\"]],encodeOffsets:[[[177173,-41901]],[[178803,-37024]]]}},{type:\"Feature\",id:\"OMN\",properties:{name:\"Oman\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ֹ̻ϟªǩȧƉэļ֗ÿĻϯFԽ̻ćХȓǯԹP͡ɃJͻПɷҩĂ֗˳ϱ³˝טٿ൴ᠾ࠾֖၂ϩתv͸ʔΐFΆϞǒƩŞèմіHϖֵҸ̧؞ŋӼƳϜӕɨ˧̞ŃCȉ̩ԃƅɽΟˏ\"],[\"@@ŉƳǅ˺ʔ˺ľñā΍\"]],encodeOffsets:[[[60274,21621]],[[57745,26518]]]}},{type:\"Feature\",id:\"PAK\",properties:{name:\"Pakistan\"},geometry:{type:\"Polygon\",coordinates:[\"@@تϻʞ٥൨ͻ߹۷ऩůౣȲЫα̖݁̈֩ڴгܑӟ`׳ࠃࡇՃ࡝࢝ࢡউÚऑࢡռϗĪ٧ҾэǘܝᇛD֓֕؛Ɇʣ؀٭٘໻ǁിeஃŝ̈́ঊொѢéϰГƌw݊ߥφͷԔеѶඨѕࡀŲԈŅǞȂגóદΔ܎ҶӈشCĠɼٞŌ̴ý͢ʀ±ԌΦԖ՘Ɇͥ֊ߜɴ̢͒мΜĩмȣΤӬμࣘǮ८ĮѐƺӨĦ\"],encodeOffsets:[[76962,38025]]}},{type:\"Feature\",id:\"PAN\",properties:{name:\"Panama\"},geometry:{type:\"Polygon\",coordinates:[\"@@˫ʎǵҒȺɢɅÎƿˤлɸοÁǝ̇ͻɁǽĉǩВҗɯŅŧŭϷ©ơԈŋƛˡ¸ǝ͸·ÈɓİέCǻĩŶªǖìǠƲŲĲǩŲK͸͘ö̠̝iǱͲĀæɴȵЮÔΨɄԜǞ˺ʤҬ·ĉҶώơ˜ʧ̈́ɵĹūȜӵǁʟ˓ÒŅС\"],encodeOffsets:[[-79750,7398]]}},{type:\"Feature\",id:\"PER\",properties:{name:\"Peru\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɥљћɋࡅӘñΈရࡊທࣾ٫԰ΏۜƐʎ܅ાࠣ༄ߍီ΅Ϥ˃ؤٷպױͼ˖ϒПߢʼךڢՎĲΓʇȧx̭ΎâͼĝΚщӆΌǄ֤ԦܶৠͨࣸࢠʾմŝٔɢĂ֒ЉˎЅϴɏӶࢣضĿҨɞ̤ƣԎð٠Ͻթࡣʤoрҁݳ œųۍǉ॥ֱÓϻɉ̇ČғԕʍBΡɛƵΔݳҲԝǱί֐µ͆҃ݐuېӸÇ౧ϢĩӄƠܪടǷ˵£ןg܍͟пƮ̵ȕ˯β۹Ջ࣡\"],encodeOffsets:[[-71260,-18001]]}},{type:\"Feature\",id:\"PHL\",properties:{name:\"Philippines\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@Đ֏ºҽ˹ޑ̫ࡨϽэˎإʉϿ঩Ӧɿ؊ʰЎՑЈˁΑЃثҵƑʖ͢۾ՌʀҜ̈́̔ϝٔɰƎϒרv·ٰڼЋêхÐ̱\"],[\"@@̟ˡˁՍ˃ʝԫ׈ǦɤɂɾĢԸҨ¸Ɖ֣جߺāߡ\"],[\"@@ૣߕЬט؈԰Ԏ׊Ѱ࠲Ʈۅևҧѳֿ\"],[\"@@Ԏʹ՘BgΗϳΣՕʧϸÒєŽА\"],[\"@@ʀभ٫ɞj˭ȶԯЍȋעʧªƁԘӶãY͈ԣٜ߮mɴ̻\"],[\"@@ɟܩέоѓ٘ܚ̡̈\"],[\"@@ԮʉʶɖüɇƍΑ˼׻ɛۥӷ˥ƁڳȊڝѾġϊĲਾүăҙ˜ȫēϯٻЮ̵Ѵɍ̯՗ԊރůлȆ¨ΎˀɊʣȘŇ̡бӚűμߨͺˡĔೄ˜ހԘA\"]],encodeOffsets:[[[129410,8617]],[[126959,10526]],[[121349,9540]],[[124809,12178]],[[128515,12455]],[[124445,13384]],[[124234,18949]]]}},{type:\"Feature\",id:\"PNG\",properties:{name:\"Papua New Guinea\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ɽčε͔ρՔǷ٘ŜĆĜʡʬȏРՑЈ˵ŝɽ\"],[\"@@ѯçƃɽҟȱћȟѽBۏʔӑɺêʺݬũҠàŶЖŦrĆѽӐÜʂ˼Ҹ̚ġӸԌfǜƏgү˯ԡ\"],[\"@@ݤտղࢻӖω٬ƛʥǁࣀΝġʏ֋ÏȷɔܟĦࡕŴٷ՚ӉҦѧ݀ભπ܇ʇԡˣńإڇ˿һƖࢅaᩒaᩒภ׃༊ӓׄїҴхŸӵඔԱȲѽޛěȄ֕\"],[\"@@ʿɡǁӸȝ͘ϝ˞ӍΪ؇ʚɺȮҒɻ˸ȁΜȫʹΛ͊ˏĶѧ\"]],encodeOffsets:[[[159622,-6983]],[[155631,-5609]],[[150725,-7565]],[[156816,-4607]]]}},{type:\"Feature\",id:\"POL\",properties:{name:\"Poland\"},geometry:{type:\"Polygon\",coordinates:[\"@@·՜à̂ȹ̧҆̚ɺɤȝђָʘ಼ϴ੒˴࠼ƙÚȱ߸Yਚħ໶^њěȬʵωɸ͋KͯԋǡʸϳfϏцܻěɽзįރۥɒϗǿ¶ߙ͔؁šЇĒӹǵч̖Ήŕ³¼ϭаر¼ăˀֻĦűɑҗǨÀɴػòЉ˔\"],encodeOffsets:[[15378,52334]]}},{type:\"Feature\",id:\"PRI\",properties:{name:\"Puerto Rico\"},geometry:{type:\"Polygon\",coordinates:[\"@@јõưǕɋɃمLӫ·άŢŬیK\"],encodeOffsets:[[-67873,18960]]}},{type:\"Feature\",id:\"PRK\",properties:{name:\"North Korea\"},geometry:{type:\"Polygon\",coordinates:[\"@@Şƥ͉ºη˵ʣ˷׽ѣȅƫƧ̓ʝ֓ƏηɥηįġͰƋӈσŧȭΧÇץ¡͝ϛϑÁùСǆĵƿʙéǀɑüɥƆɰφȤİõƶɆҒÅƎөĠЇɤۄբऒҌ־׮ЎˁܪſѺಚβͰҼժӹ\"],encodeOffsets:[[133776,43413]]}},{type:\"Feature\",id:\"PRT\",properties:{name:\"Portugal\"},geometry:{type:\"Polygon\",coordinates:[\"@@̦Ɉ΄ŬɂЫӺDƞłӪɼуϱɩYٽƍūЇγçʹԋɵտ̄ʡřɫ̵̿ê˥ͷɓѷŠџġŸڂÿԬϓþȩ͈äռͰ̨ÒͼǪԎkΤǙ̠˲\"],encodeOffsets:[[-9251,42886]]}},{type:\"Feature\",id:\"PRY\",properties:{name:\"Paraguay\"},geometry:{type:\"Polygon\",coordinates:[\"@@ͦ৖tҌЖ݌าʔޮ]޴їbʵʞҳÇଛࢲǇ΄ǐ֦ɩǀʣþޓİ͓̼̀ƌ̢ƳAҥŕӻǑӛƍݏށ١ړƇऻŸࡑɮࠢ౨ťψࡽ͢ਅبۉŸ໵ൌ\"],encodeOffsets:[[-64189,-22783]]}},{type:\"Feature\",id:\"QAT\",properties:{name:\"Qatar\"},geometry:{type:\"Polygon\",coordinates:[\"@@ÇؔɨѲɰĜʬˁdӯǽӳɵÑʫǖ\"],encodeOffsets:[[52030,25349]]}},{type:\"Feature\",id:\"ROU\",properties:{name:\"Romania\"},geometry:{type:\"Polygon\",coordinates:[\"@@δǶԴġՠGϸȳ˺źبĄɄȠΠ@ʰćʺʟˊΟӞԁρėΩưϥϒƹЂƊϠƟpɏПǹʯĀɻ৥ӳĖ̪ؑফțзɋ௽¬٥ƀ͙ÕʍΊƵƦȚƘȷŀ˃ȋөʔßΌԟȢĥˌҕͤڪǂԖ֮Њ֬ԢǮ\"],encodeOffsets:[[23256,49032]]}},{type:\"Feature\",id:\"RUS\",properties:{name:\"Russia\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ࡌ๫కˤԫ்ࠌࡳyוُԒսٱƻ۸Ĥࠊħ࣢Țٌ૴ӯࠜôରަϮͭϴϐŠɔ։̆ߵuࠟΎࡑ\"],[\"@@໵]ਙĨȒτ୊˚ࢢƧψƃęɱäɉ\"],[\"@@֦Ƚțؐᗸű࿨޻࠭λ൛ēsࠑͳǩ޽~ٗ̊ૣʖȉθ࡟Ǝॗŉҗ̎Ǽ̸৓ȥϚЃӉΣ@„Ꮪٛᔺ࠳ïԷ\"],[\"@@ः©ƭˌੲΖ@ַ\"],[\"@@ળ»@ָň܈E௒ʉïŗࡽȩ\"],[\"@@ౡMႣĤƧ¬ߘͪੀþஞ͏ĸə\"],[\"@@ॿͩഉø༛ͨȪ˖༨ųᑔɗ\"],[\"@@ډرᶽzඃȣမղҎ׀૎ǂᕞᴬѽ\"],[\"@@ӹóᩣŊɟώູɦūҒ࡮ǶҞသܒޙĺ፨݆ɩϢሤѺ᪪բ᫠ǀ෴̸࿐Ŋאͩ֟ʻᲗз᢭Џᤙߝఫࠍ೉߱Ǡۥྎۏ\"],[\"@@ɨгސȲឤYቈЧڬ̿ȽѧङʝᕅүفʟਬşఖɃݴǄєաτɔഊƂ᧪ƑȴϽ↲ů´ٜᄼƥഄLബѷϮ՝ӹΙੌڋ೔Ϳ߸ࢦഖϙ෢ɦྼʵؤʀൖş؅ޮૐζ䢀ձܐӿᔲٛ₎ǄာƑ۪΍Ĺؙਜʇ૴Ǥ๰vཚǑཪĢะݛਪˎڷ՞ϐώᧆɻფºᝂБ୲ν@”MKઇσઝÖݶҁԄەϲɧĮΏɑɝ༧Ǿ᚝مݛĭ౽ן௛ԧ̱ϣய׊ᔗڇϣ̸ߵΫ૱Ř˓ց৙߽ͻड़ȋő௣ޭΫ۱Δα฽ѕ̅ॡభȳʥ࡟ே޳ׂ̳έ௬ҵለИ୘܀ԆªϾರȊຊ੒คࡺຢڢڮஆ৷ëԍۗᒉइۍਖᓧ˷ᑃටۚԧሙɕಝēÔ؊ಯŶ਩ЭᢵƠ᪏ʟᨩ࿛ủጝ೚ŁаՃࠄȅ՞оईÃௌऍ܍ځ࠽ë্ϛഉ్௓˯ׇଙ঑ଇॻթӹ૩ӱՉYՇФૻؙſ˩ŝƦKѐіxŦ঴ɛܚܞ̒৶Ʃ֢ࠈ˾ऄ͚̮Ѵݲ൷ʛܯͧ౧Dͻ߄হװหˎ̵ࠖ̉Ԫ̿βԯࡐ̲݇షʢ૛uਯƱۛлҤȥXҩұˑݷࢻRσஅՍ৙̈́োéѯˮԋĞ௷ףેƑޛȻੑƌޫSԙіࠕИࡅŎ੝ŋߏƹ஛ΜǇـধɎށİवΎࢉࢉ΀ӵࠇב௏ɂ࠻֗Ͼ࢙^ܳʴ౫Ѓྃܣࢭơ͡çѽԤઍőΧΦחǌЙӠҩưிɍୃӜ҃ѯሟᒒੵٮ̮˂ᑋߍ߭³êҞઅ˺࢙ȱ˃ࢊມǺݯΑᑅ̳Чȹḭ̇ϫ˻؆ֹ߭ɓǀɭ߭ХസֿɁЉ୻ʓʟ੹Ѧ೯iࢻΟহͼᇡ׊ಽsჃࣳĿؗࡹӤڡउʖǡӝُ܊֫ذx՚֗ďѝѐƋϥӽ߿Ƒ࠳ࢁކߕĉ֣ࣼফԇ͹ƝɇωÌֿԚɿՅȚʳΈ޵ǮԙƁƥƼଥЖఅƌ܃ƞĹıੱ܂य़̈́ܩӴؒƈۤ۰ҹͪఌ΄uȀݯƉώѠɼ߼ÖƄ˪ȅҪ΀ѰWʚఉ˚ӭUԯЀ١ƃ੩̐lǒ̗θڟ¤éʼɀǞ՝ӈࢋąʭ¦Ƀȑ̽ȷ՞ȟ˨ǊĀڴ͞Ȁʍɢ֥ƪ¼Ʋ΁ƴՃվǸɨĉЂࠑȨѱĳšȼࢭɂˑӸíТЙȖάˊʝ޶װӞųƤक़ҬࢡЎᅢ੶ޮӠ͂єగּΆնݳش֢ܜ঍ग़ޢي౿֔ŬךڶüොͶࢀ̈൦ԕᘨȧṺो٤ЋÆ֓टѳ൏ɡ⏷ٔ؟Ńൌ؛ÂϵÆ࡫ઌʯڂɓňРԑΰ՘͈᎖Թ۾Ȳ֣؜ዦࠖޢµ޸̋Ӫ׀۫ԄЪԊءԶᚠˑӔҹ੡ĻNҳڌ˽ಜǼȶ՚ჶАᰪܞي£ࠣԙਬĕ׼˼༾xఢΐफ़ԏॖ֌ࢡӢѪˤ២ʫ୒ʿᴾॣ֚ѰࡡѺ{ǴৣĈˢЌ҅ټ}ː༄ݾրކزǒᕮɛǬұߕڽԺˋ˒חȏଵऒԧέ֕࿫஝०ŭ̢ͮऎɎɞжܮЎөӌϼֈࣿêȫҲڢࡈણۆຒ֦șװмnѴүͧ߷࣐Ƶϥ؄ඤͦლ¬༈ӏݛ۪ċࣆศǞ፾ᆘŌہѮংւॲx࿎иᕠŐ˪ɲᕂþیȋሴҀ໲aɶδߤΨጤΈ෸˗ଥȷበŹ\"],[\"@@ⵙ͕ໞીےĦقÃᒈӋʟͿ\"],[\"@@૽ōݱÛśƏঙƑ࣫ȦӐʾል~࿞ƶ౨XǢɧӘȬߊƐఞǿ͗ŷ\"],[\"@@ᆳĿᚉʎඅ͎٣׾଩ǔᔆָᆎȎ࿌чኬ߻ȹݯ\"]],encodeOffsets:[[[147096,51966]],[[23277,55632]],[[-179214,68183]],[[184320,72533]],[[-182982,72595]],[[147051,74970]],[[154350,76887]],[[148569,77377]],[[58917,72418]],[[109538,78822]],[[107598,80187]],[[52364,82481]],[[102339,80775]]]}},{type:\"Feature\",id:\"RWA\",properties:{name:\"Rwanda\"},geometry:{type:\"Polygon\",coordinates:[\"@@ͬӃµӵʏŁѿÆʱӍԛàþҠŘÞԄʎɺȰďԈʸ\"],encodeOffsets:[[31150,-1161]]}},{type:\"Feature\",id:\"ESH\",properties:{name:\"Western Sahara\"},geometry:{type:\"Polygon\",coordinates:[\"@@oҊŸ@@ÉeǋEౝ᪁ªᒷ޿÷ȳћǄ்ᾓNǽ˫΢bCቆäĶ̢ΆϘˤୌୠ࣢Ђ੖ˀÖ˜ټۺĜ̦ŉϢ@˔ȒԲ\"],encodeOffsets:[[-9005,27772]]}},{type:\"Feature\",id:\"SAU\",properties:{name:\"Saudi Arabia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ŉΪʩʨÝͲѡ̞҃۴ʁۆׇ׀ϑƐ֋ߠīאӾӕञϿ͠ґǨˡӖ°ȎɹѦʕȊ͝زԟڴѓ־лIžҦ̌ļͲनƅζʶȪ̢ٚŚƒˮˤƜ࠷ࡀ၆фǆŴৢɩబיᛎၕ༠ãݠąȾЏתv͠ܥаȓƠִ̏Λ¼΍ċ˩ł˯ʎɽŐ˟ŲȵʬǕɶÒǆ͍ș࡙͐ᡌщǞǲϪש֕၁ᠽ࠽ᝑ͑޷ϙ׻ࢥϹƕɁˬ͏§߻ĎƷČॹmɫùΉɔɝЭĒΟρˋ\"],encodeOffsets:[[43807,16741]]}},{type:\"Feature\",id:\"SDN\",properties:{name:\"Sudan\"},geometry:{type:\"Polygon\",coordinates:[\"@@śhdмĵ̀џͨĵ؄ĶبϳÌÍȇԍ©Ȭʕðԍңңл؅џđ۹Ӫͅǥđʓџǃǥ࠵@řǦ؃̡ƝɳîѝӬƟɲ؃ŗɱϵɏݣ˿ǁʳğå ̅ʎÃʼƌΔE΄ӛՀĩάZȰ̱ʜUӦǭ͖̍µĎ̰ɒΖħΐˢʴǫȞɞ԰ϨئܦÏ¥ ZΚॲH@း⁪@Ὂ@ῼ@˔ࠗȁƳŪࡻ্̰͌ȷҠ̳ыӑأƏ˅ʳĉ֑α௿ĚͳƅܟͿࠟԓзέٛč΃Љɽʝ࢟Dĳ\"],encodeOffsets:[[34779,9692]]}},{type:\"Feature\",id:\"SDS\",properties:{name:\"South Sudan\"},geometry:{type:\"Polygon\",coordinates:[\"@@Xٽűʯѿq˷ӏԨÑюХƨͳϦșӼࣳ֫օԫԇԫϭסFگȟՕȊ΋ɭ݉֐ȥάҵǱϱÆɣƕϗĸԗۚƉˊعͪɅԌΕζ֟ѬS˘ҡͼ֯͠ʴĠ̀ǂɐݤɲ϶؄ŘƠɱўӫɴí̢ƞ؄Śǥ࠶@ǦѠǄĒʔ͆ǦۺөѠĒм؆ҤҤïԎȫʖԎªÎȈϴËĵاĶ؃ѠͧĶ˿cлŜg\"],encodeOffsets:[[34779,9692]]}},{type:\"Feature\",id:\"SEN\",properties:{name:\"Senegal\"},geometry:{type:\"Polygon\",coordinates:[\"@@΍ٺн̚φǄРמȦќ˾ːкïШǾҶVДʙ֎ɝԘأֈֽԹǔӓ̾ɿî͗ʽŧ³қâÙģȃk׿ȲЛV༇ɥħ˥ѻƋƏ٢ވkȬŞƮR̸ȘήǯκcζȌǝʐˡƙʻJͧȸˉ_ȍȥࣵy\"],encodeOffsets:[[-17114,13922]]}},{type:\"Feature\",id:\"SLB\",properties:{name:\"Solomon Islands\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ɾ˿חN͉ԬԈȯǜ\"],[\"@@͝mԧĎǫżÀͮֈƁ˜ǭƎə\"],[\"@@ųƹحܰǫԈ˺@̠ڥʹЗ\"],[\"@@ǛڅΦҟ̠̿˪ŰĐϮȫېϭȢˉ\"],[\"@@Ǘ³οȒ·Ί¨ƖԈΡͰ˛\"]],encodeOffsets:[[[166010,-10734]],[[164713,-10109]],[[165561,-9830]],[[163713,-8537]],[[161320,-7524]]]}},{type:\"Feature\",id:\"SLE\",properties:{name:\"Sierra Leone\"},geometry:{type:\"Polygon\",coordinates:[\"@@ɧØ؁ͺѩ҈Ƨ̬Ĺت҆τĬɺƞǸɶpȜǂڦCɺ̛ǼΛʓƈɗṶɴ´ϹϹϛҗ«ʓȩˏ\"],encodeOffsets:[[-11713,6949]]}},{type:\"Feature\",id:\"SLV\",properties:{name:\"El Salvador\"},geometry:{type:\"Polygon\",coordinates:[\"@@ġȡӡ^̡Ą΍ǘұÀʃǶ~Ů˾ɄǀĢ«ĲȠ¾ʜëǸǙʪƇœτĴǤÑŘĝÏͳ\"],encodeOffsets:[[-89900,13706]]}},{type:\"Feature\",id:\"-99\",properties:{name:\"Somaliland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ϛԩד۫۹Mᩧা͍̜̳К̳ҨǾ̖̲҈˚ƹǒΏϜΗкGߊɌࣴĴ݌ʼиÆ̚ƶӎKaE΋Aࡑ@ѫ\"],\nencodeOffsets:[[50113,9679]]}},{type:\"Feature\",id:\"SOM\",properties:{name:\"Somalia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ѼĎЊ˾͈FpɵýӧHѳǯ̣ʁࣥЙयԱ੷ܝ௷ܓवধ଩ࡁڹష࠯޳ٕँৱȗѷȍȣӽۚWᵤܾ॒ɰˆբfݠפબᛜᡄה۬ϜԪ@ѬBࡒFΌLbːhϰŰ\"],encodeOffsets:[[50923,11857]]}},{type:\"Feature\",id:\"SRB\",properties:{name:\"Republic of Serbia\"},geometry:{type:\"Polygon\",coordinates:[\"@@Ԡȡà΋Ӫʓ˄ȌȸĿșƗƶƥȷȏø̫Тγ͋ʿƗˋĞĳƑšϳa˹µØĴĴĦȴšKǍƼƑ ŋƆƽÀšŠƯ±ś˧ȩÑèð͋Ǩ˟ĜūŜɟƠȢŬЄЛ͔ɀτ̥Ë͔́ˉʈȱ͘٢ɚԾҖͣĦˋ\"],encodeOffsets:[[21376,46507]]}},{type:\"Feature\",id:\"SUR\",properties:{name:\"Suriname\"},geometry:{type:\"Polygon\",coordinates:[\"@@৔ǙĞưڶÔࣚɥѩܟâֹͤӽƥίóϩɉΛӓǲЇđ͹öčʏƘǗ÷ǡҙèԡܴōӄˏBωؐƺѠ¯ȤԜɖƈݲ\"],encodeOffsets:[[-58518,6117]]}},{type:\"Feature\",id:\"SVK\",properties:{name:\"Slovakia\"},geometry:{type:\"Polygon\",coordinates:[\"@@´»ΊŖш̕ӺǶЈđ؂Ţߚ͓ɷɓǏ͹ǳđ࣑ʮ˟»ȟȡЁĿěÄХŽͭ}ãǙ۷Ļ̱ĠёɌċ̆äńŢȂόa˺Ĕxþǈ¢ÆȒȖžưʢD\"],encodeOffsets:[[19306,50685]]}},{type:\"Feature\",id:\"SVN\",properties:{name:\"Slovenia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ۜÝъȐܾtǈƘƘUǎ˳ڝɟć͹̇đHɻͣh˷ƎƷƙבȈúȫΨĞа\"],encodeOffsets:[[14138,47626]]}},{type:\"Feature\",id:\"SWE\",properties:{name:\"Sweden\"},geometry:{type:\"Polygon\",coordinates:[\"@@ࠁוƀԥ೹ڭྱܡؓஃײףߦүޗॅ࢑ȝ͍තӋ޿৳ĆӅڗঃˉߐ۳॔ٓஐφӜּۨ˦ন՝ю½ૠղ߀࠰ä̧ͬ˺ಬஂࡀञֈײ߮GɞҶཔƉŬքԸ૪Щ಼ֱv಑˴͛ฃʃ\"],encodeOffsets:[[22716,67302]]}},{type:\"Feature\",id:\"SWZ\",properties:{name:\"Swaziland\"},geometry:{type:\"Polygon\",coordinates:[\"@@ǡύӭěԅҖS̄ɰ̀ĂʔʐÒшƵŰϕðω\"],encodeOffsets:[[32842,-27375]]}},{type:\"Feature\",id:\"SYR\",properties:{name:\"Syria\"},geometry:{type:\"Polygon\",coordinates:[\"@@࿩ࣅऩͬgNŖŶ_ΈȸҠҜ̈́Əͤϗ¨ÿٞȶΌɤȀɤȀ°Ҹ˞Ǐऎɺ҂ƿۖFॴ̀Ґaक़žїԽҡȹĂؗͅ৫ᇵ࢓\"],encodeOffsets:[[39724,34180]]}},{type:\"Feature\",id:\"TCD\",properties:{name:\"Chad\"},geometry:{type:\"Polygon\",coordinates:[\"@@ĎЄաnDզΓ̶δ૊ੴߌ¬ન͖ၼǼΰΓ˾_ˌ̽ɔȷರࡔҠ…ྑ…ྏ¦ ܥÐϧإɝԯǬȝˡʳĨΏɑΕč̯̎¶Ǯ͕Vӥ̲ʛYȯՏƛэͽ؉ࣹ߅ϳ߹¾ʁûĊ̏ѫ̋Σ͟੓͏ȽȐƓhƹɍۛÙƀɪ˅ׄşΐλƜӷӪǼІϦċʂÐҸSқކ֐É֐ͭՠ\"],encodeOffsets:[[14844,13169]]}},{type:\"Feature\",id:\"TGO\",properties:{name:\"Togo\"},geometry:{type:\"Polygon\",coordinates:[\"@@ڱǳȇ̎ɡՔãкȆݴɁ̬ăڎD؎ΕѠÖˀ݂kŅѵʲʝ̈̋ЭǜǥኝȺׅ\"],encodeOffsets:[[1911,6290]]}},{type:\"Feature\",id:\"THA\",properties:{name:\"Thailand\"},geometry:{type:\"Polygon\",coordinates:[\"@@ݭϬܗeŬڈ݉Káऋґ௯˙ݏÌ؋ն΀ދưܭҶӓԚĭѤѧ˝·ևĵßќۇςƣƭͧ͒ƝжҁӄПЌƏӳǃҲĠԾʚ߬ТࡸҤ޶͟ތ`϶ĩҸ֕ښȩф̄ƺ̮ܶ·ֆՓؘН݆ΠƴϦࣦצӬθӔȘθʷ´ԍ֨ȷࢭpݫࢰԆʤƧӰzǜَ̊ÍٖڽÀࠥںܷ܅˙ϛ޿Ŧગǅ՟ۧȤ১\"],encodeOffsets:[[105047,12480]]}},{type:\"Feature\",id:\"TJK\",properties:{name:\"Tajikistan\"},geometry:{type:\"Polygon\",coordinates:[\"@@̭ʷࣳƖāӛ࣬Þਢ˗འŶɈާˠĐԜȓ͛ŴӍࡿBׁØԻϕύĉ̉ǯͩˠþ۸ʩ¢ĞʲғȐα̇ė͹Żūԇj˕ϩ˯ǌ؋ˑʱĺӀࡘǹض؟ȨɔφۮЌҬˌբ૲ȜǩϵŤɹΎv\"],encodeOffsets:[[72719,41211]]}},{type:\"Feature\",id:\"TKM\",properties:{name:\"Turkmenistan\"},geometry:{type:\"Polygon\",coordinates:[\"@@ñۼطॣݔڣĠगюׯþσƽ֙|ׯӓ݇ǋƻרŪ࢞ٽ˶Ɏֺ֏¸Ȇ۾ߊȵ݈ˎؓԎʉӔڱɋď؛ʿհψ˨ॖǪ֨ɻךڅњ¤ॆ\\\\Əцܖ̂۾ӦଆѹĜڡ͐ǣࣦˮƳаࡽ०ׇոЃ࢞Щ૤ΫwԥʩЅɤſ̙۽ǋǙڥӁʭڏŵǫϟهŏࡩ͈\"],encodeOffsets:[[62680,36506]]}},{type:\"Feature\",id:\"TLS\",properties:{name:\"East Timor\"},geometry:{type:\"Polygon\",coordinates:[\"@@ĲȤܢȌזˀŀ͆Ľ̯ɫ࢕ο۳ʋeʬďǔ\"],encodeOffsets:[[127968,-9106]]}},{type:\"Feature\",id:\"TTO\",properties:{name:\"Trinidad and Tobago\"},geometry:{type:\"Polygon\",coordinates:[\"@@ӚŊǮصۭġƯúʒɲiͪ\"],encodeOffsets:[[-63160,11019]]}},{type:\"Feature\",id:\"TUN\",properties:{name:\"Tunisia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ΩພԭͺQȰۉԄóنԮҶȢۚƃߠǠќࣶͺךĵ}ы܊̲ÒǉпЫMϱ̆ȽōܫփхǄқѤaɄЍ͊ſ³٥Хʋʵˏֽ͓ĘΑïΟЧț\"],encodeOffsets:[[9710,31035]]}},{type:\"Feature\",id:\"TUR\",properties:{name:\"Turkey\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@஺͗ঐżܤõলѬࣆ¢ߴЭƜ̑ăУزȻͨʕֻʇˀ५ǏʻҠڧЕƙ̏Ɋ঍ňίŽॗŽҏbॳ̿ەEҁǀऍɹ˝ǐ¯ҷɣǿɣǿ̱Ϡ͈͂ԟí۱ȖֿәౣĥڹҊࣟȗΑׇĳ߻҄ࣻeӽ࠶ؗҰЦٸՓВठߨಒΜྀٔŏ৞հ঒ʄർlุף\"],[\"@@۫ҏ˃Ϻ\\\\ǦȦĦʺՂХɞࡦ˄ܤőĴ͓ܼ˓Ƶȵি±Ωʷ\"]],encodeOffsets:[[[37800,42328]],[[27845,41668]]]}},{type:\"Feature\",id:\"TZA\",properties:{name:\"United Republic of Tanzania\"},geometry:{type:\"Polygon\",coordinates:[\"@@ƚġᵂႋÌӣ஼࠿ϱਙ¸Ӊՠ̩~ɓɳԓ¶ʭÇГ̌Ճΐ̰ࠡǿڝӣࣿ͛ԋb̙ʥבsɕŃঢ়ʂكåɽଢ˵ϺǛɶࠗƾӉʨՕƘͯƘΗɈґ੖ӣҺǗӤČѨƯޞΎ ̨̦͜ѬȺǮS˘ǷȐ·ͨʐł¶Ӷͫӄ̎Ķऄ[ႎà\"],encodeOffsets:[[34718,-972]]}},{type:\"Feature\",id:\"UGA\",properties:{name:\"Uganda\"},geometry:{type:\"Polygon\",coordinates:[\"@@ः\\\\̍ĵԇʷȯĐPوȜ͎²ڬǰϸ͎Ѭ͔ɠ˒̘͵Ŗ¼চΌɮՖȉڰȠעEԬϮЊ׍İсτ९̧ؓЯ֋ʉͽTࢹႍß\"],encodeOffsets:[[32631,-1052]]}},{type:\"Feature\",id:\"UKR\",properties:{name:\"Ukraine\"},geometry:{type:\"Polygon\",coordinates:[\"@@̾ɄȒʮ¥ࢌĆ՞Ӈȿǝêʻڠ£̘ηkǑ੪̏٢Ƅ԰ϿӮVఊ˙XʙͿѯȆҩƃ˩߻Õџɻύڡã֑˕޽«ܣ̻¸ԹЪȭࡨ¼Ǐ̛ँơଛӟұǠȄЂࣽʘƨǈߪ˪ʑȔಯɆË̼ީĻ̷ҧٱةϟƠЁƉϑƺɂĞƦ˾ɲˎÑƮǬäĊśӸ{ɞØƽĎÐŲ̉ɈŧΘ̩ƐÒ˶ϝɦΉأʾ֑ĉȧŭΟ@Ƀȟاă˹ŹϷȴ՟HԳĢγǵÍɤұɮǐͺɸɔȀµɑϘބۦиİĜɾхܼДҢɪٲnࡖßबȫڎi͂ŧ̀Ʀɚȝݸ¢ͮąÄцʶȂܞº\"],encodeOffsets:[[32549,53353]]}},{type:\"Feature\",id:\"URY\",properties:{name:\"Uruguay\"},geometry:{type:\"Polygon\",coordinates:[\"@@ղĚࡆٯ̺|ࡺ՟ڈҫӠֱχЉɸӇεՇॉұاǚғěޥΰ֫ԟҬÞլǾȈS࠸ɤࡺȾڦ\"],encodeOffsets:[[-59008,-30941]]}},{type:\"Feature\",id:\"USA\",properties:{name:\"United States of America\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ũƕȽŤ|ɾƓ̨¦ĤƤƎÍǔ¸þÜe͐ƙƬñƌőɊ̍q¯͟ǵˏſ\"],[\"@@˭ÑƟǮīèQÀĈî̘āɘŹëĵ\"],[\"@@ĝ҉|Úĸа\"],[\"@@­µÓŻŃȒɤŚêÃʐ˥\"],[\"@@ıĉ˱ƴªÖŸĈȘijȝ\"],[\"@@Ƭңʼƛז½࡬ƅࠂʹڼŊਖɓ˞Tݨʄ߂̧ࠒ͗ں˩ٶˏĈəȢĉ½ĉɦǎĔ¦ȣǜƅɴ@ŬĹĽƫ࢖ЁǶށǚܳʗӹЁҥȁ̍mēĦť˸Ɓɂ@ঊ҆ࡾƀસмfĐ÷ʰƉǒϜƆࠜHޘAˎ͞ŀàࢶ؄ϜƸ౦N໾BĎȺː¦Φž̖Ϣʲٺٚي˨ə֜ƜώʏAଧռӅƢ˝࣋Пࡷ̃ࢱʝѻӿƛȋSѽˤѽΒsė̬ʦȇãʇ֥ƋЗhةƥλ¥ӥ¥۫ʏఀǂʠǃ୳ʥ՗C|ĺʭɷʚǹ׽ؑ٧×Ɏȁª˟ɀǪҍȼƭ^ͅˏ͛ҿڡûʺֲѕ͎įۦǉεǴՑևƀׂ˓ߛʊÍĖ̃ŠࡁՕدࢇʝցӱнÁэ̱ţ˭इձӁЍЅӽŻׯƪ׍ˬܗώשLεЊঅ֥͛ȿԡʣŃЯĺƁς͋ȖѻܢϹٞű͢Ǥ֐ɽҦٻ۲͟źࡑϡƭ¦СϼՃȺोŁݗĤٙÍΏſƲɟaͽǴǓǇō̵Ů́ǃ؍طѺܻĿ؏ȚԹÏۻȝއح࠳γҝБȕϗUׅ¨ЕǄ˹͝{׭ȂٽʺɽЄȁטӷӐ̃ӰуֺףͲۉgՉڑۣʦѡʪȽҦ˧Ѯӿτїˈ̩̖ป@C΋ڗ@ဩOቿפ౓ТĀǒ੩ĝॕÝƙіխӚϻĴğʌһ¦̝ɪޭĊɉƌĹҢࠁࡊ۩ୠȚχˤٯ۴řۆ҃ҞȀۢܜˍ٢͠ߊĸނĺނƱૼˇܘʓ϶ĸǐ௒˷҂ߋȺɜƇې˷ێᛸ@᠂@ࠜ@ᢢ@៚@ᡀ@ᡄ@᭰@ᮞBაAF͔˴J\"],[\"@@࠽͋ѕɐŽЀބ̘҆Ÿ֐ÉΤʻܫЍ\"],[\"@@ԧŽսƾԛɮࠦƞښùĂ͑\"],[\"@@԰ǅԾĒڸɛ࠲őéĝُǱٕǾ͋Ʋݍµȧôº̈́\"],[\"@@؊ϛώǌහ»¹ȕ౾ƛࡨČᄚ˅ྤā٨ŉ૦Ǝౢʧࣲŝ@@MᷱIⷍࠠ{ࠌɵהρݜցࠈҺࡈ˖Ҁѡ֤·ޒϙՂ׽࡮य़ේ՗xՋұЙҥ͂ݍˌʃܺએںҍߎ߯Ä೷rটʌ჉ࢎߩǄ฽̜୑í࿻ϬৃΨटǯǦ׏ҫÁঁǫ݉˱झǳťӶϚࠚࣀʶɱɂੱҵֵ֑௅ױؚСߏ׿ࣗΗࡁʱȻωಽѡ˅ϿছΫֽÞ޷ɻ࡝˹ۧ˫෹ʉſƘऀϾࠔʸࣆҠਬĨвΈ୘ԊȈǚب̒ƢْђӸॹʫ˓Ơҕ̧շюɧ̝̽м࠿ͳԩBïԄƲ̮ե̚થǇ܁ЀַȬIӈ٩Ϊ͘ӘۆҸ̚њںÖ־ƇڴМ؎ï٘ʼƻϨҹưج͖ԩWࢻǽʯȃڏȄஏĥ௷ȬΛ͸੟Ӧ୾ΘመШ۔@ŕнᄢڽԶਕ͌ױр߫ΨଽˈҺѲ๰ਗ਼ϦȨФ࡬ЎࠊĪཪώޜÉಐ҄ౚǭ\"]],encodeOffsets:[[[-159275,19542]],[[-159825,21140]],[[-160520,21686]],[[-161436,21834]],[[-163169,22510]],[[-97093,50575]],[[-156678,58487]],[[-169553,61348]],[[-175853,65314]],[[-158789,72856]]]}},{type:\"Feature\",id:\"UZB\",properties:{name:\"Uzbekistan\"},geometry:{type:\"Polygon\",coordinates:[\"@@xԦૣά࢝ЪշЄ॥׈Яࡾ˭ƴࣥ͏ǤěڢଅѺ۽ӥܕ́Ɛхॅ[ᶾᓘӺƾïದ׻یͅߤݵঢŪ෸à৔ؗÙࡅЦMǢۍ੬ɲЉ̺Lπ׺૎הӖƺʠĉ۵խئ́ײȾ়ѷ੽؁ٕĊ΍uţɺǪ϶૱țˋաЋҫۭ ɓυؠȧǺصҿࡗهǰҳN\"],encodeOffsets:[[68116,38260]]}},{type:\"Feature\",id:\"VEN\",properties:{name:\"Venezuela\"},geometry:{type:\"Polygon\",coordinates:[\"@@yȣӱĭ˜ϡYѭυӥ͆ڙδÆȌ؈ʻ̒§َਸ਼΀řІ̎ˆ̞ןל_մҵ˧ݮQ࣌ĔӖϕٞĻҼʾXɄਨ¼৖\\\\܉ʛ˼Їڦ×ِЯƆڧѬn͢ȣڕӱó̫˾̷ȽƽԫƉjϱɫɱّ֪Őʁ̭͍ऱ̽׿Žʏȣڛɀثņƿýϔɑ֝ŜՉ܆ï°ǭ׷ʅĭΣΉƏسȝǋʱٷÅҧѼʯ࠺ɟ̧̌ȄюмȊʅʠǛ֒à׼Ȉ˰ƲҎ̓Ơӏĩ؁®ͻęסܢӥńઉăȧ̊ȷêǬĴ̶áͺȃȂŅϮѡÈɸӮĺ׶ʔ̸͘ʌɈрդƖ\"],encodeOffsets:[[-73043,12059]]}},{type:\"Feature\",id:\"VNM\",properties:{name:\"Vietnam\"},geometry:{type:\"Polygon\",coordinates:[\"@@૭ܗ۫ߍȁ׍٠ࢭ޺ળނԱԞګϪ།ŕ๓۫փ१եۇ۫਷ޱ̧ՠʀ֬دӌܬ͸ࢦÔσԚප٨ļ৖ț֖ƶࡀɃצٍאՋ݌ۥ঴৓Ԋʊ̠՞ɘ͙ܺਙPϕކӭڐҊȴڢIࠈĬܒ҄К̿ސƵƃӛАͿࡎɓ\"],encodeOffsets:[[110644,22070]]}},{type:\"Feature\",id:\"VUT\",properties:{name:\"Vanuatu\"},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ˣō˭ςɤՆӗ\"],[\"@@ƌڱɥŀǩ­ťɴi٢Дʵ\"]],encodeOffsets:[[[171874,-16861]],[[171119,-15292]]]}},{type:\"Feature\",id:\"PSE\",properties:{name:\"West Bank\"},geometry:{type:\"Polygon\",coordinates:[\"@@@ԣŭʙЃŕɜɌŚɁĦǬ̤֔ś\"],encodeOffsets:[[36399,33172]]}},{type:\"Feature\",id:\"YEM\",properties:{name:\"Yemen\"},geometry:{type:\"Polygon\",coordinates:[\"@@؉ɥǋύo˹࠷Οഇϻݩףυ±ʥºӭΑ՗ǉ۷©ɃµǿɛəÕŻɇеlˍœ׉¨ɓӬzҠƍʜǑتʋΊǚ¤đϨĸǊξςˌđΠɞЮΊɓɬúॺnƸċ߼č͐¨ɂ˫ϺƖ׼ࢦ޸Ϛᝒ͒ڀ൳˞ח\"],encodeOffsets:[[54384,17051]]}},{type:\"Feature\",id:\"ZAF\",properties:{name:\"South Africa\"},geometry:{type:\"Polygon\",coordinates:[\"@@ǏŧΣяɻћӇ׻ोࢁףԋًϣ࢛͙ѓ«ŇɷԛŰеǅ࣫ǊԙĹΏ¬ࡿͩܓƃԱͅϡoΣ̚˳fαϒśŏɦLӰ˙֞˔ƴs٤ս޼х܈AF׽તДдͪɯƘΫϘÓՈǃҌÖݤіB᷌ɨűӾߙûԟȈ̏׼ĒрϒЊʨȶДЦȚΠķВɽۂ£՞ȜĐʾƨДҚäʨ͂˪֔ݮغஒؤ΂UОƛ˲Ķ҂ċД஁ɔׯƫऩî̟чƶʏÑāʓɯ̿T̃ԆҕӮĜǢώْQȿؑıۥɑϛֵщ\",\"@@νʶϻǟҕ҃͡Տـ٧̜ČƺˎҴƀƜ˜ʴФ̅ʪ\"],encodeOffsets:[[32278,-29959],[29674,-29650]]}},{type:\"Feature\",id:\"ZMB\",properties:{name:\"Zambia\"},geometry:{type:\"Polygon\",coordinates:[\"@@ІϏɊ܋ƝɩǙڻǈۡ˃̇ʭޭѶɓᢇۗĂׯٍřӍͯĹ̛̅ßܵۓҭխ˳o˗ĬऱĠƯÚOêͧȎկ¶ۋȑչԾ֣یᦶშYí̂Ű̀ƧЀĪТėʺ̂q¶ʽϾrՖûˬϡڨŝԤˆȌѯ٠ş̴ΧΈҥ٠Që࣠ɱƳח͞ɧƬļࡈƬসȉψʈ՚ɤĶ଀ƚͦđΘɇͰƗՖƗӊʧ\"],encodeOffsets:[[33546,-9452]]}},{type:\"Feature\",id:\"ZWE\",properties:{name:\"Zimbabwe\"},geometry:{type:\"Polygon\",coordinates:[\"@@ҁČ˱ĵНƜ΁VՙϞٯźʙՒC̒έĞ्ई˃ӢǛƮ͓ڤलğ˘ī˴pҮծܶ۔̜àĺ̆ӎͰَŚÆ̻۬hϴǯǺȻАÓѦˑF੟Ǐ׋عƊʝħӵŵùɛ؅ࢫ॓\"],encodeOffsets:[[31941,-22785]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/xiang_gang_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"8100\",properties:{name:\"香港\",cp:[114.2784,22.3057],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@@}ScTʟ@cWuJÁ]l¦RLj¼BĄà H@TOHCTDDDHDNAT@PEHDDNJLX@BABALHFF@DKHADBBLDHHFBLEJB@GDBBFBADDB@@KFAFBBJJA@BB@@FFDDADFF@FADDDBJC@AFBD@@DDD@DAA@D@DB@DHHBFJBBFEHDFAN@DGDC@DLCBDDCFDlAFBFCBEF@BC@GDAB@FD@DZJX´HĐMja@Ý`p_PCZ@lLnRGSDMFK|a\\\\Y}­§Mën\"],encodeOffsets:[[117078,22678]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/xin_jiang_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"6528\",properties:{name:\"巴音郭楞蒙古自治州\",cp:[88.1653,39.6002],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@@ÈÒĊanwŎVȮ¦ͪŃĢÜōȂçČéƐżLɆóĊĊaʊŁ±¯²Um»ˌmÈ»VʠţWÑÅ¯ǓéôƑƒğÆīŎī@Ƿwô˺LÞ¯ƨVǪÑƒĢȘV°wĢôk°¯ƒ»΀@Ȃ»ĸǔ@΀͔ôôLɆó̐ÝɜLɲōͪƨóŤK@ī@IU܃ÛmȻţǩÝ˹ÛǉťǓǫō@Ɲ²¯VçōKͿŁΗÇţ»ƽɅƑLÓŏÅÅɱV@ÝĊU¯ÑĊĭÞLÞŎJ±̃XȣˌōlUÈ¯ŎKÆƅ°XÑÜ±nŗġV¯óaUƧUōŁÑ±çɲ¥lĉkğ°k¥nğţL¯ÝÝUƽĬ΁lķ°@ōXÿÝ¯V»ŹLʉÞɱŤĉó°ÝJ¦ÝKÝ£ţÜÈĉ@xǩUċƑ@ky͓¹`U²ĉVġ»ğa¯¥ť@ĉó@ŻÛÛJw¯nó¯ġWƽʩķÝɛwĉĕÝ¼ȭÞķō@ó£Å΀Ƒ¯ôȯÞ¯ȰÆōèĉXÇ¼ó@ÝnºĸÞVƜĸȚUʶõˀĵĖɱŎÝĖVࢰӒѢ°˘nϚVˌÈmɼĵŦW¤öʊõʔ@°ÈXVènŎȁb¯ǫĉ±Èğ`ġwōÔğ»mVVÝ¥ó@ĸķô@bXĶmV²²`Þ_ɴbͪÈ°ÞWĸÈŌmÞkɲÈUÆ»n¼ǬVķĸźô¯°n¦ɄÇÈ\"],encodeOffsets:[[86986,44534]]}},{type:\"Feature\",id:\"6532\",properties:{name:\"和田地区\",cp:[81.167,36.9855],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@ƨ¥èź٨ΘƑᩄbUࢯÞĕɲōĶĕöʿVʵķșUƛÝķm¹Þô@È»ĊWŎçÅ°ȯȰÝ°óƒÆͿĉ»̽çnmɱĵƧºóUƽ@±wóL¯°̻L±Æ¯Vƴķb¯VÇ¥ğ²Ǖbk¥ÇKlÅɱġ@ÑóK@ÇaÝXğţxĉČǫķê¯K@ÑaŹƑK¼¯VóaónġwóÞéUġbóĉğÇl¹aUóğKWVÅ¯nÇŋƑķnʇ»óxĉwçÇ°Åw°ċXób±kÈÇJm²ţx@ÒÝŦÇºnó¼n°ÇbUÒ±¼XĸĠłƽXmwĉºzÈÜmnxmx²ĖmÒbnƧêUºĊêÆVóĖóUĉ¼ÅĬƑ°ɆƆŻŚlłÞL¼nĠ¼@ÞÞź@ŎÞ°VɄɴжϼِ͈Ŏ\"],encodeOffsets:[[81293,39764]]}},{type:\"Feature\",id:\"6522\",properties:{name:\"哈密地区\",cp:[93.7793,42.9236],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@WnŐÆĶLĢ¦ţºźlxÅĸƽŚɄĮè@ô²ÞUĔƐńV°¯ĸX¦Ɛm̐bƒ»Ɇa΀ĢƐLˤȘÑnІǉĸÿn¯ĶaŎ¯ĢĕȘ¯°΂la¯¥ǕǔwˤӱlťО̻nŻmɃĕċţUw°WUóƨÅţķ°ýV±óÅǓéʉ¯ƽŁéōǖȁÝƏůǕw˹ǫȗǓƧǕVýé@ĬţLƧôͩɱŎɛK̏ÞɅôóK@²@°ōŘ¼lŦ¯ŰóƜÛlV¼ķ¼°kȰŰĠǬŚÝŎmĖ`@ÇÜn\"],encodeOffsets:[[93387,44539]]}},{type:\"Feature\",id:\"6529\",properties:{name:\"阿克苏地区\",cp:[82.9797,41.0229],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@VÆxˌŎÞŎ°nȂÒ°²VĊ¯VğƾˍǬƨÞÞKÈÞĊVźôɆÞĢèŌôWČ²ŤVÞĸʶbl¯ôn_VÆĸlmÞnVź_ĸ¼ȮmǖéĸW°°ĸJkʠ¼Æw°¤ÈlxɆzČºĶI²ÆǔU°ô@Þ¦UnUĠ¼ŎÓĢxĠ_²ÇĊǬ°ȂamōçUÇW@¯öʓõʉX£ĶťnɻÇUˋmϙ¯˗ӑѡᩃaΗƒɜ°xWƴUxɃÒˣ¤ɅwğʉōóÝŹ±°ȗ@¯Æƒ²¼\",\"@@ōгwȁ¥Ƨ°ŹÑķV¼ÞêĊ»lĵm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘnIÇŃÛÝĊÑĠƏ\"],encodeOffsets:[[80022,41294],[83914,41474]]}},{type:\"Feature\",id:\"6543\",properties:{name:\"阿勒泰地区\",cp:[88.2971,47.0929],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ɲˣĊIÈ¥ÅU±Ċýkō°ĉƽó»ĶƽXóʵʵȯƑÅȁɅ¯ĉ@ÇሗK֛@@ˤV֜ʵрƒǬVĸƑŎ@ƆϯÑóķ@ʇ»ķ¦έmlÈĸĊX¼WźÛÞÝѸĢČþĀĊôάVö¼ĊUƨ°°èŎČUÜÆóôVôô²êȘlˌç°`n²ǬĊaÛ°±kğmm»@°ÝɆÛÅÇVaÝVm͔ğôÝÈb@n¯ÜUĢÑĊ@źīżWŤÈǖWôŁÆI²ÓƨL@ĊXmmÑÆ»ȰÑkĶō@ý°m¯\"],encodeOffsets:[[92656,48460]]}},{type:\"Feature\",id:\"6531\",properties:{name:\"喀什地区\",cp:[77.168,37.8534],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@Č@°ĠôÓô@Ŏĉ@Ƴĸ@Ť£ĢlVôWVóřXĉŤêÞ@ƐÒĢÑlèÈV@ĠIk°ÆŘ@ÈÈĀ@ǶťÒğ@@ÒĉlŻ_@ƧĖÅĬōÆ@bźÞnƒlVÝĬWÆ¼ʇÝÅ@ÇÅÈwWóĉ±ğzĬČƨÆÝIĉÝ¯bÇÑĉ¯ʈV°xUŰĊ¤ƪ_ôÓɚI@lȚXȮŎlɴȘ՘¦ɲÆʈ_ɴźôÞʊŎĠɆxˤ£ɄÑVwXƳ¯wɛŹ٧çƧ¦ōُ͇еϻɃɳUÝ¯@ōÝŹ@Ý»mğ»ÝKkŁżřɅƅƒ¯ÆīĊ»ôVôĕÅUĉéV¹ƨémanÑ±ĕnwmwnÇÛyĉ¹ŹlŏkĵèķmōÞġKñÔċKÅèĉzômxȗÿƿI@þÅČÝKÝ°@¼ÈVº@ÅĢÆUċłnÝÆǕČĵJm£ÝJ¦@ĊxV°ƏLċ¼ǩ@m@ÅĢómÇÆğ¹ÇÆĖÞKxwô¦ÆÑÆL²ÆƾU±ŚÅŻĖ@ĬŤÈñ@ǔÇxÈÇƒ\",\"@@VÇţ°ğUĠ¯mk¯ó¥ķIġÿƏbĉa±ÒĸĀlKU_m»nwm@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁVé\"],encodeOffsets:[[76624,39196],[81507,40877]]}},{type:\"Feature\",id:\"6542\",properties:{name:\"塔城地区\",cp:[86.6272,45.8514],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@ήnĸ¥ʈ¼ĸ@ôϰÒ@ƅƒōUķƑǫʶпU֛܃LګK@΋ĸ@Æ£ÞġÅĠċLVÝ»@Å»Ýnm¯»nŻĊ@nķŃ@¯ómóÛÝǟ¯aÝóȭ¥ōUmxĉbÇÑ@bUº¯X¯ÆƧbVÒĉnǕw¯°ƑVÇ@kx±UɱnÅK¯ƒĠǠU°ɜL@°xnĬĀŋŎÇLğϱÞέƜkôÅĀǕłĸĊŤUŰĢ°¦ȂϰÜɨ°x@°żǠÆƈČVĠ»ČL°ÇbĊÑ̐óÞlĶwÞɆVÞwǬxǪţÈ¼ÜLŐĶˢ@\",\"@@óKĵĀV͈ĉłƾǊÆŤzXl°ÆL²¼źôÈĢǔ¦lô°ɜÞʊĠğÅm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI»ĉmğnaċƨbVğwġ¯@UōaĉÝJğÑÆŎkŎÞĀlź¦\"],encodeOffsets:[[87593,48184],[86884,45760]]}},{type:\"Feature\",id:\"6523\",properties:{name:\"昌吉回族自治州\",cp:[89.6814,44.4507],childNum:7},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@መL@È°ĊȂɆƒÆĊ£ťôWÓɆbĢÅŎÆ¦ČÑW¥°ķU¯ƏŃVē±Ý@óçĭɃƾřÆķkwŹŤ¹ġ¥ĵKŏÅXmˍщwǓ¤Ƒ@wóōVķ£ɱġôÛa±ÒȁóèţIVƽ¼k¤ó¹ġJmx»ÝU²@ÅÆĸǫŎĊmŎǬ՘\"],[\"@@Þô°bÞǠôÜôn@°ĸńǶkł¼UÞKğČÆÝĢÅ¤ķ@@ΌڬL܄K@ˣȂ˭lĉÅW¥ĵVÆý@ŃÞēUŃȗƅ@ŹƩǕĉ»k»ÇVğóřXŻKƏċêȁèÛŎġͩń\"]],encodeOffsets:[[[90113,46080]],[[87638,44579]]]}},{type:\"Feature\",id:\"6530\",properties:{name:\"克孜勒苏柯尔克孜自治州\",cp:[74.6301,39.5233],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@ˎǫĠƽ°UUĉ¯±ȁÑm¯ÝōˋōwUÅ±»ÅƑ°Ș@²¯ɳʇ`ɱÅ¥՗ɳȗōkȭșW@kəJóÔƩ`ĉ£Vů¯wU°ʇĊÈÒ°aĊÞÞJÅċƧīĠyĊ²XôÇxÈÆÆ@ÞʈÅ»XÞīUƑkmŹÝ@aŎÅÆīƨĕ@ż`Ċk@ÑĠ@ŦÑ@ǵÇÿ@ÇÅŗl¯ğJ@ÇUkçġÒƏÑÝ@ţéWĊôŚUóXUġkţ¤ķ@@ƴōĊó@óÔğ¯ċ@@Ò¤kôˣŰ͓k»KX¯ċwƧôğɐÒôIVÆ¯UķǬķn¼ôb°ÒȰVVÈÞ°ĸó¤V¼°V°²êlĢÒUƨ¦ôȰƴĊVV¼ǖIċĊÞɜénČW˸ǸařÈw±īçĸ¤ĊôwĸUĢ¦éǖĬĀô¼lÞkÒ°x°ƆÞxÆV²ǔ»b°wÞȘ¥°nŎV@°ʠèŰȂb\"],encodeOffsets:[[80269,42396]]}},{type:\"Feature\",id:\"6521\",properties:{name:\"吐鲁番地区\",cp:[89.6375,42.4127],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@ôKĉǪa²¼lÜô@ʠê°ĬôȂ²ÑÜbĢóɲĸ¤ŎUô@xƒǔ£ъxˎmÈÛ@_nĕÞōřǫğůlȯ¯ĸ»U»Ükôƛ°ůkť»Ŏŗ@¯@±͓óͿǓ@ķȁ¼Ϳ@Ƒ¼¯°ólġ¯xȗUġƑǩÒƧUÝ°˹Kóx@ǸōĬÅĬƑĠóƒǔêÆ°XÒʟŤUÇ¼ˋnn¼±V²°ȂUŌÝbʟǔɅô@żǬaҎÈ\"],encodeOffsets:[[90248,44371]]}},{type:\"Feature\",id:\"6540\",properties:{name:\"伊犁哈萨克自治州\",cp:[82.5513,43.5498],childNum:10},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ĉÆŘȁ̐mÞ¯ĀX°±¼@ƾ¯ƴ°ŎÝþŋ¦WÜÞbȂĉźUÇmwVUȂóô@ȰÝ΀nÆJnƾʠŌLČóǪ¯¥ǔaǖŌaôÝĢLxÆLɲm²VlwÈ@Uƒ°¯ǖxĊmUÑƨa°Å°WV¹aÇɃÈm¥°¯ŹóĸķǫUm»Å¼ÇVɱlÝŋnķÇÝX¯ͩÇɳaÝ`±_U±ĵnWa@ĸóķ¯ǓV±ÅĵJċ¹ɅykwÇ¯£Åxʟ»lķI¯X¯ķêǕȭnķ»Ź`±kÞ@Ýô@Þ°xŤŎIƨÆUxō¯²ǔĬǬlUŚ\"],[\"@@ÞĀlź¦¯ĸŤKÞċƨbVğwġ¯@ţƽJ\"]],encodeOffsets:[[[82722,44337]],[[86817,45456]]]}},{type:\"Feature\",id:\"6527\",properties:{name:\"博尔塔拉蒙古自治州\",cp:[81.8481,44.6979],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@ήƛϲÝĠÈKŌōÿmīw@¯ɛKV¯ğǟ°ƑwġKóÞŋbǕǓb¦ǩ°ċôŋKʟƽmÅImͿȯÞó@ȁôUVnxÈŹVȁĊÝabŻ£¯°lóxȂŤĸkĊÞyĊêĊmĢxVƨÈĠXΘÆĠÔźɆţ°LXƾŤŤb\"],encodeOffsets:[[84555,46311]]}},{type:\"Feature\",id:\"6501\",properties:{name:\"乌鲁木齐市\",cp:[87.9236,43.5883],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@WôŚUĠÈl¼Ċ¼ƪǖ@źȘƆ@ýlÜXVŘÞ¦V¼kĖóÒèkĊȁˮ֜@ǫ՗nōĉǬōķÆÅ@±ÞV¼nwĢIôºl£ƾ»UŤJôçó¯īʟéó@kÛ±»ǩbĊóLҍÇǫb@ŻɆóʠǓaŋÞȁVʉłĉbĉɅô\"],encodeOffsets:[[88887,44146]]}},{type:\"Feature\",id:\"6502\",properties:{name:\"克拉玛依市\",cp:[85.2869,45.5054],childNum:2},geometry:{type:\"MultiPolygon\",coordinates:[[\"@@ɜÞʊĊýVaÅm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI»ĉmğnaÝţL°ķóKĵĀV͈ĉłƾǊÆŤzXl°ÆL²¼źôÈĢǔ¦lô°\"],[\"@@ƾIŤ@UUwōaĉÝJğÑÆŎkŎ\"]],encodeOffsets:[[[87424,47245]],[[86817,45456]]]}},{type:\"Feature\",id:\"659002\",properties:{name:\"阿拉尔市\",cp:[81.2769,40.6549],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@nIÇŃÛÝĊÑĠƏōгwȁ¥Ƨ°ŹÑķV¼ÞêĊ»lĵm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘ\"],encodeOffsets:[[83824,41929]]}},{type:\"Feature\",id:\"659003\",properties:{name:\"图木舒克市\",cp:[79.1345,39.8749],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@VéVÇţ°ğUĠ¯mk¯ó¥ķIġÿƏbĉa±ÒĸĀlKU_m»nwm@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁ\"],encodeOffsets:[[81496,40962]]}},{type:\"Feature\",id:\"659004\",properties:{name:\"五家渠市\",cp:[87.5391,44.3024],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@çôÑlĕU»¥ÝUŗWkÛ@þVńÝĔ@ńÅþĶUX¦Æ\"],encodeOffsets:[[89674,45636]]}},{type:\"Feature\",id:\"659001\",properties:{name:\"石河子市\",cp:[86.0229,44.2914],childNum:1},geometry:{type:\"Polygon\",coordinates:[\"@@lŁǵmĉ@mż¼n°ÞmÆ¼@\"],encodeOffsets:[[88178,45529]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/xi_zang_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"5424\",properties:{name:\"那曲地区\",cp:[88.1982,33.3215],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@ƨʔĸbÜºÞwnxźbÞ°ô@ĶĸIÈ¼ĊJŎÈôUÝƒ¤ǔLÞŎ@ĢȘblôLÇźçÈ¤ôL¥ÞIÞ¯ĶxʊťƨƿÑĉXVķŦ¯ȂKÇǕÑ¯IU£¯Óƿ£VĕÅÞÿÆwƑ£ǖxÞĕ±ÇÝaUÑÈU¯UōÈÝwWŁĵ±ÝóĢÿ°IÞ±mÅĢ¯mÿ¥°UnÑŤĢĕĶwǬŻͪwŎ¼źÇĢĠĕˎŁ°óƨ¼Èam@¥°wǔǖ°ƨÇŤġƨŎŃôbÈÛŎĊ°@Ġw²ÑÞJÆÆb²°êĊUÞlÈ²VÈKĊÒĸĉ»ÅôťUÅÇk¯@ÇÑklÇÅlĢVÑó@°@ÛĸV¯ÇĊn¯Uĕƽ¯m¯bÈ@Ò°Ĭbĵ¼kxķýÇJk£ÝaUÑÅóĶǟkÓʉnĉÝ¼Ƒó»Þmn£mČ¯@ȮÿV¯ĸk@Ýów»ğġ±ǓLōV¼Əèķĉè±b@ÒţUÑóakl£Ó@¯L@ÇlUóȁ¯aġÈÅĕÝLķ¯Ė¯@WĬxÒÈnW°ţôU²ǓÓġ²V°¯ôǔÝLċk»Ý»Ý¯ÞVwÛÝÇōͩÈĉċ»ĉm¯£W¥ţKkóġƏW@¯±kōÈb@ÒÇaÆ¯akóÛÇ¦Ýa¯Ýĉ@Ç»ÛmǓxķƛ¯lVĀÅÞġbÇJUÅVĖƑWzō»ōWn@è¯ÞóVkwƩnkźÇÞÒÞ¯ýğÇUxÆÈnè±bĉÝ»ÈŃwwÞ@m»ÈV@ýÇ°ķxaÝ¯Xċ¥ÈóW@ôkxlnxVÈóĊkŤġ¼@°¯ŰƑL̻Ű±ŎÝVÞVÇÞÅÇakƞ@èğŎĸżƾ°ÒLÞôĠKȰĖźVÈÒĠ¤VôUÈþťL@ôǬÞlÜÈnÇÒUŚ@ĊƨW°°X@ČÇþƴĉÒķ¦@ĢôWĀôłUÞĢǬź°¼@ôV°bUÆnzm¤ƽĸÈ\"],encodeOffsets:[[88133,36721]]}},{type:\"Feature\",id:\"5425\",properties:{name:\"阿里地区\",cp:[82.3645,32.7667],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@Çƾķn£myVÅaU¯ó@¯»ŹġǫVÝóŁXÿġó@ĸ¥ĊÑƳÈý@ċW¯X¯ĉƧ@VřÈÑÇmkÛǫÝ@óŦKÇýVUó£ğÇÑŹUȯĕğLÝóK¯ÑƽķŻĠō@çlƝÈbÆÈÝUÝÞU²ō̼ůƒK°ů@¯UK±ĊƧbōÇmçÈġóÅóbźó¥kīÆ¯ólçKôĵUÅVŃķ¥nÅŏm¯¹Å»@ÑÇóxÝkʇȤU¤ķb@ƒ¯ĊÇx¯ĸĉKm°Āk¦lKnĬȀƾÛ¦WÆÅmǊĉ°ōUţ¤UŎ°ŎKÞłÆǓ¦Þř¯bmUÝl¯Umğl¯£șwÅǫaÝnĉĶk@¯Kō»ĉnaÞ»ťnkmlĸ¥UÅŻkÑťĉVôó°LôīĠUÿĉǕÅz±K¤²ō¤¯Ė¯UÝ¥VĵóÈťÝwķÈÑk¤óWýĵĕVĠVóǓķ°k±VU±ţ¦UǟÝÅJVÑ¥XUċUÅlÛƆǕÆȗƆ¯wŏÞÅ@ĉlÝóÒnUôÅlxólÝôÛ±LÛôÝL@ġ¯X¯ÇUÅ¼óaó¤¼XÒġŎóLk¦ôÅ¼ĸĠ¼KġƆô¦ÆƑÔĉĶ¯ImÒ°¦n°¯ÞlÝČnƒÒKĠÞĕklýƾťôIĖŤÒnƜm¼¯lnżóÞ@Ůó¦ôƽĖċŚn°Ý°ôÈUƜblÞó@ǖô°UÈƆ°XþôôlѢ²Ėm¦°@¤XĊblÜzkºƒĖmXŎWVóÞn°lĠxȚa°»żLźb@Æ°XĠÝȚxĊĕŤaȚ°È@@èŤ¦Ü¼WÞkÈ@V°lŤkŎ±²¦ƐUǉ°aÈÑŎbĢŎbÆ¥ÞIȘlôVÈUbkɲĶnmnXb̼òƾĖŎ@ĢȂÑôÓĠĖʊĊÔ\"],encodeOffsets:[[88133,36721]]}},{type:\"Feature\",id:\"5423\",properties:{name:\"日喀则地区\",cp:[86.2427,29.5093],childNum:18},geometry:{type:\"Polygon\",coordinates:[\"@@ĶĖXþôl£ÒĸÇÞxÇŦôUĶÞ¦°V°ĕŎ£±£²LÆyĊǖĀğVóĬ¯KóôUĊŦlÒżVÆķ¦klnŦmÝ¼bĊmŎ¼L@°lĊĵÞmǬbÆȚx°¤Ġkn°VÞkVn°aŚÝǔ¥ÅÝŁōL¯ōVŤ£ŎVĊ¯nǉÆXÅÜ¥ǿƽmīLkl¥ÿn¯ĊL°ķÈw°ĉ@ƑĸaV£ʈȣÞlôwÈ@Ò¼Æ°ºŐnmÆĸ¦UńÆVóĶLèôkÅ°lĬ¦ŹôôaÆôÇĢnèŎÈƨaĉ²VLĢ»lţôĉUÇwkmlw@óôXÇČ¦°WÞbwĸÈ¯@þÇUn¼Ý@xxÇńÞ¼Ċ²amçÅÇVwĠÈþ°ÝÑÈÝlŹƪmlxôU°Ý@çmXŎŎ¼yƒXĕÆUVÈIĢaÆÝUÿ°kĸƜǔwnÜÈ¼Ċ@Þ°ÞbÈ¥Üôl°bÅÈb@ÑaÇ¯UU¯Vġ»¯aV¯Ç°ÅmnÑŤçǬVǬ±ĉ¯¥Vĕ¯Ýk£ōw@±ġÛ°ÇVÑ@Ûa@ČLƳÇa¯¤ÝIĵ¼U¥ƿōķÅţŻókÝóĕ¥¯U»Æ£X¯ġŃÛkÝ°V°ó¼¯èWôÞĖȎkĀƧĀówm¥¯JÅ¹ÝJÝōVVÅaÝƑ@ğŭÇ¯_ĵVnxÅónĵxÇĖĉVÝÈğVÒó¯±Żĉ£ķÆÅLǈĉýţÛ¯VnV¤ÝÈ@°ÅÞÝ¤ŰğŁm¦ÝxóK¥ɱÈUĠôêVôÛ¼ÇWÝçĵaō¦óĖƧlÇĢƑnŎÇV¼¼ºÛ@m¦ƽĉmm¯ÝKÛç¯bŏłĬb¼ÅLmxť°ÅUÝXkÝmĉ¦W¯KÒknÝaVÝè¯KɅńÝKnÞ¯¼\"],encodeOffsets:[[84117,30927]]}},{type:\"Feature\",id:\"5426\",properties:{name:\"林芝地区\",cp:[95.4602,29.1138],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@VÈłVôÈk@°K@Ôk¤lôbVÒŤ@Ñ²açĸĊƐçU»ŎǔKĢ²Ġ¼ôx@ÞlƨĬUl¯ÈLVÞJ°ÜnʊwÜbXêVÞ¯°anaU°wÆ¼ɴÑWÑ°mÈýÈam¥Þ£Ť@¥ôblÞĢź¥ôxÈÅmÝĕÅV»ĉōŤōnó»ÈīķIUĠÑ°ġĸLÞ¯VÒÆ@Āb¼WôÈ@V¼ôóŤKÈÑU»wVǫżnWÒÈx¼lŦ£ĊōŤx²¯@ÆU¯çÆ@¤°£é°k°lůÈó@¯ŤÇÈĉkkÿó¥ÝXķÑÜ@ÒóŚÝ¯°ĉówÇ±¦ÅJUÒĉĀķw¯°mĖ¯±akxÝÅn»lÑK@¯lU¯UVÑ¯óĊ¯mōğVǓƅÞWÝÈÛ@ƿô¯ÜġzÅþ¯ólmôʇġĊÅUͿřŏȁˋŁóÇˡōƧÇbw°Ķôk¦ÒnUþġÒÔkǔķèó@²@ŘōńĵyzġaÝ¤ÅI¤Ƀť¦ğÑ¯¤ķbó¯ó±U²°¤ČÜVnÈÆŚŎ°ôĢþÆzèVĀÇĀÇXŹÑ¯¤ówċķk¦łUÒġzÇ@ÆÝx@²Þ@Æ¤Uô¦U°xU\"],encodeOffsets:[[94737,30809]]}},{type:\"Feature\",id:\"5421\",properties:{name:\"昌都地区\",cp:[97.0203,30.7068],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@VĖm°ĉÈU°ķÜ¯@@ôUÒġkÆkÈlÒ@Èl°ÈVÆóŦÆ¼aÅĢɄwnōw@¥Ŏ¦°ŹÞmV°wnÿwwÝw@¯mÞŗ°wĠĸkÞğlĔ²¦°@ĕĸwVóal@nĢÇĊn°@¦źUXçǔůĸVÆKÈÝĠ²ÅĔô@lÈ_mzǖlaU¼ôwV°¯¦ĬÈal@ČÇ¼nIxô»ɜ@ƨ¥ɆŁŃǪȁkƛƨȍʊȡóĭ@ÈÇVůÞĸƅmēƨťÅÈʉVǵ°ġVŭÅɧ°ÿnɛ£mķ²ŃóÑUĉ°mÇ»¯@mxUĀ¯èţ°ȁÝçġU¯ÆÇţÈ@°ÇôŰ¯k¯lê¯¤£Å@èV°Å@±°ţwĉŎť¤k»ÇwXÑŻmUǬxV¼ÇÒţLóôU»Ç@Xó»a@ÿÅUÑÝ°ķK¯ĢğÒVĸJÇĬ¼môţŎĊŎU¼ÆĖnÞÇÆówŹ¦ġkÝóa¦ţ@Ý¤n¦ÇbÇþ¯nXÒɳÒÅ»¯xVmbb¯Ý°UWéÛaxʉÛm¯ÝIUÇKk°VƧīķU°ȭĀ@ċ°nm¤Ýnô¼ƒÞ»ĊʊmlÔĵǠÆôVÒÞbl¤ÈIĸþlw»Ķa¯ī@ÑÇ°anƾ°\"],encodeOffsets:[[97302,31917]]}},{type:\"Feature\",id:\"5422\",properties:{name:\"山南地区\",cp:[92.2083,28.3392],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@°ÞUĖ°¦²ĊôÇÜLǖĀɜȘŰÞLĸźêÞ@UÜUŤ°ɞ¯Ü°WŦĀmŎ¦ĢyVÑŁl¥Čĸôx°£źÒWÈÿÈUÿçÅyýóġō¯řÅmÇÛUċ¯£V±²°ôôĸa°£ĠÒŦ¥Ʉ£ÆJÞ£ĢbyĶzŎŃ@ŗ±ô@ĸçlǓÓĢÑVýmÑl¥ĵó¯̻̥ƛǫÝһÇƧĉyţ¼ҍēVĶĉŎ°ĸmÞVÝĸÒÛaċóŹĖèÈÈl¼k¤ÝX@`Þŏ¼Æō¼ÇçĉKUÝÝ£ğ¤@¦ġl¯Òġĉ¯ómóxÝÞğVƴċK@b@ÜUÒ¯ÈĢÜ@²xŎl¤\"],encodeOffsets:[[92363,29672]]}},{type:\"Feature\",id:\"5401\",properties:{name:\"拉萨市\",cp:[91.1865,30.1465],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@Ŏ²l@°XĢƐlôŤLX¦°¤ĊnČ¼ÇĊŎͪÞÈÜxU°ÝÞÞ¼¼lČÞKǓ°óU¯Ģ±ǔÔV±ŤóX¯ÇmÑwXī°@°ĕĸÞKÆĖĢÇ°bȂÇŁUV¯wVó¥VÅ£Ý@@±ÞwÅÈ@¥nōťÿ¯XÛɝ°ţ¯ÛVVÝ@ŹéķÝKȗůɛǕÿÛKóÈǫǫUţèmÒn¯Æ°ÈU°b¼UĢV°°V\"],encodeOffsets:[[92059,30696]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/yun_nan_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"5308\",properties:{name:\"普洱市\",cp:[100.7446,23.4229],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@Uô²a@²²Ķ¥V°Ķ²bl¤kVxl@°Ś²@y@ô¦¯@xxVxUVbVÜm¼ŎĢmºXXWÆ@ĀmmXU°ÅÒm¼Þx°w@°XêĠ°»nV°Ul@k@V±ôī@£ČŃÆ£KÞý@¥k@ya@nWVUVwm£Jknm@wmknXX¥mUUlUnb¯°nkVInlIUw°nmk@@mlanXlanmk@wVWUw_@éĠanmUaÜ£mX¥¯@@óUmÝ¯¯ÞÝlKnxô£»»ĠJ°aVUÝÿV¥ÛbI@wmón¯yÛL@WkÅmÈ`IWa¯K@¯mUnmaXmbmak¯ĢÒÝm¯mV¯KÇb¯KÛWWX@aVknċLUWVkXóW@ka@ób¯Uwmb¥UUlaU¥U£maķKXkmÝ@kwmÑ¯k±ċbUUVakaġ¦kL@`a¯xmÅLUW@ċnÅUV°LkL@b°°@¤²nôôkl°kèÒÈzV¤ÈWôônV@¦@¼Ux\"],encodeOffsets:[[101903,23637]]}},{type:\"Feature\",id:\"5325\",properties:{name:\"红河哈尼族彝族自治州\",cp:[103.0408,23.6041],childNum:13},geometry:{type:\"Polygon\",coordinates:[\"@@°°nÞôV@°@¦WnÛ¤Vbmnğb@ê`VxUX@xÆÞUnnWÞĸĢÈ@Çè@zÛÜWÅêl²KnV¯ĖĊx@bk@@°JÆ£Èblnnm°nlUkVUUwVmKnnVÞxVLX¥laX@@xl@VzÈVmk@b°ÈĸmV¦`WXbUbbX¼°x@aVVkn@lþnXUlVxŤÅyIUkaIŎĊ@lXx@bz@ô¥_V@ln@ôy@al_l`nmÈ»@kmXwWKU¯»aÅ@wmUÝKUaUUwW@w²»@kÆV£mm£VKkÑV@@»nw¥@kÆnllIVlnLVakalknJWmnaUaVÑVVÞn¥m@¯Uÿl@VçaXaV¯UyVLVk@nJlXLlkxlbla²Òl@nVJVkxKlkUaVķÝÑU@Åm¯@±Uó°ğńķĠmUÑ@Ç¯¯Å¼@nml@°¯¯`@w£@¯Çk@»nmċ¯U»I¯LÇĶÛn@bó°Uwm¯UmÇ¯aI@ykIVU¯bIğ¼¼ó¤mwkLÝÞ\"],encodeOffsets:[[104243,23429]]}},{type:\"Feature\",id:\"5326\",properties:{name:\"文山壮族苗族自治州\",cp:[104.8865,23.5712],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@wô@²¯maUmôUÆx@XbÞInlVUVwJVaUK°¥xmÞXnlKlnna°@ĊČÆwUmnkl@°£nyn@VV@Vak@@kÞÝbmx°Vnw°klÞInĖÞVlKl@Xa°KlVU@JnxU@ÈĢbUKlm@ak_wanWUk°l»k@Wk@lwU_@UalóU¥ÇnkJW@mVXx±bK@nV±a@Åa£ÝK²WknamKknÇk¯aVV¯ĀUÒ¥I@mm¯¯xÅW@@`k@ó»UU¯lm£ÅWlĵw@mmwÅmWU@y±UxmwU¯U¥Ý¥¯£m@kÇVUV°VbklLwUlUImk@±ÑkbkalwkWKkmI@UlUKVzU°WbbUè@kVĀ°@nm¦ÝUUUÒVbmbXnmIkllbUbmKUkkJmkÅ@l¦mx@¼U@lÒULn¤nU¤Å@l±¼@xXxVVVbÞLVn@xÆb°¼V\"],encodeOffsets:[[106504,25037]]}},{type:\"Feature\",id:\"5303\",properties:{name:\"曲靖市\",cp:[103.9417,25.7025],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@È¦lKÞĕUV¯Um¯ÇVUnVVUĉnĊÇƾLn°°ÈJÆw@lbÞa¦VXJ°¯W¯aÞJVkUa@lKnÅmWUk¯a¯»@m±@ÑkkbWWX_WÓU»_lkÑm@U»m@l@IWċn¯l@VanVUVUVwVxKÈVmUē@n@VÝÆLwVVwnVlmkUVÑÇ°ka@kÿÝaÞUl£ċĕX±±ĉa@UnVnalónk@wlUVmkÝJaW@ÅwóVVnnb±°@óxXLWxn@lÇ¼nmk_k`@bózm@kU@`¦ó@nW@ÜÅXWw@yb¦@ÒlnUb@xlÜk@²Ç@U¯bmy@kV@bb¦U`lLVx@bLl¼Þ¤@°VVÞU@WÞUbJ@nn@lnnmxUUUbK@ÇwklkUVWakn@lbU@@ULVxkKUn°¯Ò@¼km¦m@klȰ@lUl¦@Vl°wnnþĊUÆbUxbVĖU°annaVal@@b\"],encodeOffsets:[[106099,27653]]}},{type:\"Feature\",id:\"5323\",properties:{name:\"楚雄彝族自治州\",cp:[101.6016,25.3619],childNum:10},geometry:{type:\"Polygon\",coordinates:[\"@@mÒXU`Wn@Xl±¦Uxnbl°knmKUxxVôUx°¼ôÒÈ°JlnÞKĠW°¦Vx²JVw_°¥@UV@@wnymknK¯I@²b°£V¥wUV¤nLkÆJÈwôô°l»Č¯ġVUU@@°ÝXl@U»°Å@U¯@w±¯VmUUlm@mÑnIVyUwmak£Vwm±@Çw@n@UxkwlÇnLmkÅ@±kka@kóJV¯Ç»U£lw¯Xalbl¥¯UX@aUaÈL@ÇVIVkaU¯mmakLWkUJ¯Umxn@kUx¯xmWÅīÝkkbŤbkxWmXwWk¯wKkLÅ¤ċń@¤óĬU²@@lk¯VmU¯¼@xV@k°l°kbU°nmVnU@°UVèÞÆbUÒÞnU¦V¼lô@Vl\"],encodeOffsets:[[103433,26196]]}},{type:\"Feature\",id:\"5329\",properties:{name:\"大理白族自治州\",cp:[99.9536,25.6805],childNum:12},geometry:{type:\"Polygon\",coordinates:[\"@@lbKVIUa@²m@bxôÒÜxXLmbnl@K°¼kUôxôlV¦nJUÆnm@xÆwbXÆôôLUVwôK@wlmaVw@WknmIUmlnJla@_@kÝmKUaÑm¯Xw°aUaVl»²JVbÆJkôĶĀ²VVkmbVwUówVwnLlmk¯maVw²¥Wk@XmV_WnÑUk@kó»UV¥ÝmVÑÅaÝUçV@¯VUmn¯mVlak¯l¯U@@wğWé¯@¯xÝw¯¯Jċa¯U¥mLU¤bÞȤbÇLWUwmIUVW¼kb`UVb¯L±ĊÛkÿÝKkwKţêUĉþÈV¯ÞVbU°KVk²ÝmImV@kmUkVxm¯KXÈķJU¦V°ULWxL@môb@bkx±LnVUVLnkÜWnwlLÅƒmW@kkJU_VWĊÞ\"],encodeOffsets:[[101408,26770]]}},{type:\"Feature\",id:\"5309\",properties:{name:\"临沧市\",cp:[99.613,24.0546],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@xĢl`²X°Vx@x°Þ°KXağUÑWbnIl`X²°bxl°V@xVxk¦mbl@xXVÆzX¤Æk°kx@lźêlaX»VUnJVxXÈKaÝȣaV£nKV¦°Čb°I°n»ÆÑV¯nWn@ÿXÅWWn¹ġōn»ÛUaUVUww@w°ó¥@z±@ř¯@kUwlk£±aĵ¯Uĵ¦±±@bó±VÝ@ó¤w¯I@mÅóm±X¯IólK@°UllbzkKlln@@ÔºUmVk²ôÒxŎUVóLbmÈnmbnlax@z@Æ¦k\"],encodeOffsets:[[101251,24734]]}},{type:\"Feature\",id:\"5334\",properties:{name:\"迪庆藏族自治州\",cp:[99.4592,27.9327],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@WXw@akk@yk°īX¥Uóķ¯w@n»UaVaUÛ¯mV¼kÞċô@n¯xÛÒmV¯Ô@x@kwmÅa@UaÝ¯VÅyVa@ÿn»ÝVmankmmÞÅô@n£±ğzÇmU¦VmnÜmbn@°nV@xmzÅ@mºV¦k°ln¤¼õôn@xkÆIUxU@Ť¦VmVkmkXW¤XzVx@Æx¼Þ¯b@lVĸÞVm¼Xm¦VÞ@Æ¹Vón¥ÆKnKX¯x@èĊÈ±łXaÆxnlV@UÛlȻkğV¥m²ǉmÅÞĕƒƛm°ÆmX¤mznÆV¦ÞVVb°bnÞWbn°l@VÈ@VĵĊ±@óInxÆw¥@£ÞW¯ĸ£UUKk±akkkbmWmÈķaÆÇUÈÆW@wmknmU¯\"],encodeOffsets:[[102702,28401]]}},{type:\"Feature\",id:\"5306\",properties:{name:\"昭通市\",cp:[104.0955,27.6031],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@mnK@wmUÅ¥móXǓŏmX@VmL@xţnk@mlUŻÒğŋ@L@mmLkm@bXÅW¼ka¯lÇŹ¯aÇ»ÝÝ_@m@@a@UklwUm@ak@bUmbmbV¯ĕUaVwÅaĉVmým¯xUk@k¥VUX¤VÈm`@ńÇÜ@ĀknĔkƞÆĠÞUVôƆÞI@UxÆ¦nl@ĊĊnxUÒ°¦Vb¯WUnWIml@xnUbô¤¼ÈxlI»KV@ÈÔJkUĖ±ÆVb@nVÜVUVLwĠlknĠ@nx°¥Æ²mUw@mmÅUl¯UÑÑUmLllIl±@VkwW@w°@U»kUóI°»ĢÑL`nUĠ²lmbôV@nJUxÆ¦X¦l@ŎUV@lVKVÅV£UaÞUnW@¯VU@ó\"],encodeOffsets:[[107787,28244]]}},{type:\"Feature\",id:\"5301\",properties:{name:\"昆明市\",cp:[102.9199,25.4663],childNum:11},geometry:{type:\"Polygon\",coordinates:[\"@@n@VkVUn²°@x°V@¯ÆV¼k@WÞ¯@@VVUĢċ°k¼VĊx¤Ōx°mVkÑÈL°x°X°VmĊLVxUĖ°bX¦VW@kȯlkn@¥ln@»°Ñ¯VmlLUwVK@V@ka@lmXbUlVlkÈx@LVaVVwnmm@km@mIVaÝ@XVUÝ¯U@Ý£k»K@aUwkKV_¥a@alU@nz°aVÈ@@±lÛk@wVakm@Ñ¥az@XxÆW@ÛX@m@y@aWw@kōĉJlbVJzţÆUwVkmWkým@UlU@b¯wVºUVUêĠXUaUbVĊUWXUmkKWnUUUVVVÝ@kk±¯Lk±WkXlVkl@wXbmLVUIVmk@Ubma@kkaVKUkmlXLWnJ¯ÒĊ°@zkºlLUŤn@@nô@lÆnmKkÈlxVw@@mÈx@n²Uxl¤nbVxUzmJÒn\"],encodeOffsets:[[104828,25999]]}},{type:\"Feature\",id:\"5307\",properties:{name:\"丽江市\",cp:[100.448,26.955],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@l@@w°ÓUnÜÑ°w@mČóÝlU»n°VÜUbVbm¼@°xôĸVW¦¯Ĭl@zll@bWxXaX@ÆĠÆaXwl@XaÆ¦n¼Jn@mnKW¯È»V¯°akVanXVwl@VyUĕVUbÈīlaUk°k¯l²VUkƛô@I@mVwĊaVakaÆbUVLaXIWKUwaWÑÅKUaVk°@Uw¯¥XğÝLkm¯IÇóÑ¯»anUl±UĵÿlóÅIaU±Ik¼UVb¯bWxn°ÒVbnLlÞ@@`kbmIkVnJmnXl@Uxbkn@xóLUxVKóóÅWaÅxw@nÅmVôXLlVU¤b¦m¼@ĀbUzUÆ°ÞVb@Æbnx\"],encodeOffsets:[[101937,28227]]}},{type:\"Feature\",id:\"5328\",properties:{name:\"西双版纳傣族自治州\",cp:[100.8984,21.8628],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@l²°nÒlxÞ@nWlLĸnbV¤V¦kbVV¦nax°Vôa@b@lôXlWUVXČKlmU@bWXXÜ°LÈa°LnU°ÞnÑġ°lnba¯¯KWó@kmK@UĉV@k°VV¹a@y_ċl_nÓlL@anI@óWl£VUlkĕlKVwU@kVam¯ÅL@bÝk@VnUbÇbÝwÅ@ċ¥¯lk¼ÅÒ°b@¦nlUn@ÇVmÆbWôU@ÝÅōm¯aUmkWWw@±n¯UèaL¯mLkwl@°mnÈÒ¯ów@VxĀU¤°Į°Xl\"],encodeOffsets:[[102376,22579]]}},{type:\"Feature\",id:\"5305\",properties:{name:\"保山市\",cp:[99.0637,24.9884],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@X°Il@¦È¼m¼ÞaÞÅlÈxV¼lVôÈÆlLÞ£ÈºlkUUw¯UĕVwĊ@n¦mlnVĸIWÇ°LnUwlVn@lnUnJÞl±U¯LVUa°ÝUÇĊýVŤéLlxÞLĀÜl²ĉ°KUaV_Źé@klw¯lÅW£ÅyUW@wknal¥Uw@wUk¯w¯aW±k_mJaXVÒĠWb¯L¯Ý@wwU¯±Wk_ġwwōKmb@¤bk°lĖôUJVnÅlťU¯°VbnbWxXmÞWUĀLyWzÛKmbUxVKknÝkVĀċ¤Ux@¯m@¦\"],encodeOffsets:[[100440,25943]]}},{type:\"Feature\",id:\"5304\",properties:{name:\"玉溪市\",cp:[101.9312,23.8898],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@lL°xXlWxXnlwaţlaÞlÆĬnX°wVwl@mnw°VVIXllKbnnV°lbUUJ@ÈÇKVb@bW°Vk¦kaWb°kxV¤È¼U°ôI@llbl²@@ó@mm@VţkKl¹@yĉ¯°ÑIXmWKnklVULlb@lnbVal@UnVJUnKWax@lkkUlW²XlK°l²@lÞUUUVVVXmlLVnXWVUĉVaVbWğVéUVU¹W»aVaaWX_U¥nÇķ¯@alUnÇUyk@@wW@kbW¦UKÝwUmmLUnVxUVVlk¯mmnmkÇaÅ¤¯I@l@@aĉw°ĕmUL±kÆéXÜÛ@yÈç@ÇġÝķXmmÝVÅlmnkbmWkb@nl@nm¯VxkJmUJml¯°makVVnV¦WWmnl@xmnlI¤nxUVUmX@b@zl@¦Ýþ\"],encodeOffsets:[[103703,24874]]}},{type:\"Feature\",id:\"5333\",properties:{name:\"怒江傈僳族自治州\",cp:[99.1516,26.5594],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@WyX£lWlnnUU¥@ţVVwJlÅ@wmöó»£kml¯U¥n¹Æ@ny@wmU@¯mnamÛnUV¥ÈnĠy²m¤@ÆónÝnmlnbÞU¥aV£kUKWómIU¥ókwVól»¯Lk@mnaWKÛwóÑw@a±n@VbUJLkaÝXĉUV`lI@lnXÆƑkKmxÛXmlUKVmU²Klw@aaó@nKXwVKU¯V¥mUnkm¥ĉ@UxVĖ°VxVklmÞkKWĀkVWnl°Lnm@°UxlV@nk¦JVÈ°VÒ@nX°@ÆlUômlnô²nxmłnVV¯x@Èm°XblVUl°@xkXU¤WXXWXÆmkÅJmÞw±bxUīkKmÅVUĖÝèVkx@lXlnk¤LkĖk¦xUL°¯Ė@LnK@b°xVI¥Ua°Ñ@»nm@¹KŎÞÈWln²n\"],encodeOffsets:[[101071,28891]]}},{type:\"Feature\",id:\"5331\",properties:{name:\"德宏傣族景颇族自治州\",cp:[98.1299,24.5874],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@¥n@°@VwČ£ÿUlÞlmULVwnaÜLXyzKVÿXÝnWXwmaUa°¯VŦÆkUmVIókĕl¯a@£nama@¯m¯ó@óyţbġkÅm±ÛammVkLwU`Wk@VkUmÅlUUKmbkkUVUw¦ó°¼bn°ô¦lºz@x¯@U°nU¤ţU°VƆ@ÈmlnzÞl°¦ÆaxUxLkxWƒn@²ŰW@°ÈXl°Llx\"],encodeOffsets:[[100440,25943]]}}],UTF8Encoding:!0}}),i(\"echarts/util/mapData/geoJson/zhe_jiang_geo\",[],function(){return{type:\"FeatureCollection\",features:[{type:\"Feature\",id:\"3311\",properties:{name:\"丽水市\",cp:[119.5642,28.1854],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@@VbVl@XnUXKV@¦nxlUXVnKVmnLUV@bn¤lLXK²`nnlJXIVJIVnn°KnnVll@VLXWV@UkVaVKzV@VVaUK@U»VUl@@WnUU@wVLn@Vwl@XW°LVbn@VU@Xl`@XnKVbkl@XVJlUnlVxlL@lnXl@VUnV°°@aUVLXblWVXn@VVUV@L¤VLVUVbnalLUUVX_laVaWVzXKV@@a@KUmImmXama@kU@yVIUKaVa@kXK@aWU@VIUmW@kkVmU@VwUa@K@k@U`@kUKVk@UV@VaUm²Vy@klUUWUkVmUa@_KVaXaXmU@mUlWkaUX@mmkL@wJnVVÅbWKXa@@I@aJUUÇ@VULW@akLmb@K@aXXw@mVmUVkUy@£@aU@@VkUWm@kUKXUWU_mW@wkkmJUUkLWWUXW@IkJ@k@mW_kÓ_UlLm@I@aUa¯m@ka¯LUJ@mVVxUba@LUKkXbm@Uak@@a@Um`IUbUJ@nUVW@@LnVV@lUbVlUX@`@blXklWUmXlm¦U@@V¯bml@@nUb@llnn@VbX@lV@UVULmU@JVnbVbkbVWxU@@nUVk@\"],encodeOffsets:[[121546,28992]]}},{type:\"Feature\",id:\"3301\",properties:{name:\"杭州市\",cp:[119.5313,29.8773],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@X@l°KXXlWb@²`bIX`l@@bWl@n@VnLUV@V@°¦@l@XVlU@@xVbUb@Vkb@@XVJVzJ@LÞ@VmLUxUJ@LUVxbxXUl@VaÈwbaÞa@Vl@XUVx@V@VLlbnVal@lbVnnLnKnL@VlbVJXalIb@KUU@mVInJUVl@xUVLnU@UÞaV@lkV@UanKL@UlKVUnbÆmn@@nUlVnVJl@@UXUL@WVIVJVxVLXV@IÜKnbn@V¥V@@I@y°b@UUwnk°ÆƨVlUçXm£aÇIkV@WV@@aWIUWUIkb@WW@UnK@UU@kaWVkVIVVnU@UWVUV@VmVkKkWIkVWaULU`UImJUImmU@wmwUVIUWVkUamaU@mVkb@KVU@aVU@anKULVJU@kÛUJUVkkVakU@aVwkW@UWkXmWaULUaUK@XJUUmVU@UVUkJ@ImwmKU@k@lUW@@akKmkamIkWl_UwVm@UkaVUUa@UamakbWlkL@aUalU@mkL@U@UlmK@XkKm@Ýakb@xnXb`nUUU@U@wU@@mKkkV¯U@lULUbVbUb@Va@LºÝb@bLmKx@VUL@bk@mxULWl\"],encodeOffsets:[[121185,30184]]}},{type:\"Feature\",id:\"3303\",properties:{name:\"温州市\",cp:[120.498,27.8119],childNum:9},geometry:{type:\"Polygon\",coordinates:[\"@@ll@xnXV`VXWVL@lXnlV@UV@@b@¤VzUlnVU@nWxW@b@LnalK@bXVKUÈ@VVI@b@J@WbXLÆaUUmI@xlKnn@VWlbkXV@nVWnWbUbL@`VbUnVlVXkV@lUz±VnUbU@@VUlVL@l_@V@l@LVbV@XLV`VÈlxn@lU@aaVVk@XJ@nl@@LU`°LVbL°a@aUVy@anI@aanV@²wÜJX@VVV°kna@WVkaWwU@m@kaUĕÝÝŤnÈaaóI»@±XWkUķ@kV±kwUkWwUÝ»ÛkɳlImaUaWóXÿǬkUnWVmmkKţnŏÞğlUlUx@XWbV@JkX°mb@VULVxUVk@@LWWk@WIkUkJmUkVmI@y@UakLmU@mUUUkaVk@mK@UlUU@UmKmbUUUJ@n@KVLUL@VkJWXX`mnULWlkL@JVLVb@°kxkU@LVV@VLV`UL@VUX\"],encodeOffsets:[[122502,28334]]}},{type:\"Feature\",id:\"3302\",properties:{name:\"宁波市\",cp:[121.5967,29.6466],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@Ċ¦ĸĀ°nXÞVKkƨƑźÿ°»n@wô¥ÜbU°ÆXÞWóçĉÝ±IUÈ¥@U°wÆ»²mm_@aXVKÞVlk@akk̅@£X»VwÆXWa¯aȗbKƽŰĊxLók@@¯nKUL@xkLÑkWULUUmJUXVU@mUX¯@V`mbXbV@@nn¤WXx@kJ@nVVUVl²UbÝVUVk@Wx@V@VXzmlaL@VlLU`XUVVVUnl@VbnJlnUVVnlUKkbmnnVxlJnxmbU@UL@KUVX@xmb@lk@mnVVUè\"],encodeOffsets:[[123784,30977]]}},{type:\"Feature\",id:\"3309\",properties:{name:\"舟山市\",cp:[122.2559,30.2234],childNum:3},geometry:{type:\"Polygon\",coordinates:[\"@@l΢ƒʠþÆVĢLĊǬXĊÜXôVÑÆwlƏÈóVĭVǓ@ĉwɛkmK@ĉXīWaĉUĵÝm¯ĉwĉ±±nÅ¼¯x@VÇ¦V²JĊÞôèÝXÅW¯VÛaó¦@xm¯¼ŹĀ\"],\nencodeOffsets:[[124437,30983]]}},{type:\"Feature\",id:\"3310\",properties:{name:\"台州市\",cp:[121.1353,28.6688],childNum:7},geometry:{type:\"Polygon\",coordinates:[\"@@lVIVWVz@bXJl@Xal@°nLll@nVxnVK@UJVb¦°k`UIWJXnÆ@bUJXl@lbWn@UzVV@bVVmVnnJVXnabKUKnUVVUnVLlKVLXaJm£@mU@WanaU_°@VWnV@UVWnIVVVKlXÒlK@wVKL°m@l@ôKwĉƾůUl£@»UVkm@ƅUaÛIŏmUk@mw@a£Wk@ţIm±@ankôUlaUUw¯ōabÇbţmÞÞVĖbl@@nVXxbUl@Xmb¯lUUUW@ÛI±xU@mb@bmJ@bUzV@b¯bKUa¯KV_@Kk@@mWI@lUUb@bkVm@kwUÇU_WKU@Ux@VUnllX@VnJ@UXV@bWL@lUbbVLUJ@zV@lnbWbnnnJV@L\"],encodeOffsets:[[123312,29526]]}},{type:\"Feature\",id:\"3307\",properties:{name:\"金华市\",cp:[120.0037,29.1028],childNum:8},geometry:{type:\"Polygon\",coordinates:[\"@@nbVb@VbUVlb@VUnVxk`lXnJlbnlL@bX@V@klV@nLnx@JlIVU@VUVnVVI@WVLVbVKXbWnXl@VlXUxb@lVUbllVUIÜVnalKX@@bV@@aUUlUwUw@naWWUVaUUaVbLlxXJVk°UlkU¥@ka@LVlXLVlVWznVn@lxJl_@WX_@mVaa@alU@kVVnaKVLlKb@UUaVabnUWmXU@k@yVI@aÅWmXIVJl_¯¥UaVI@LmUUw@mkkmK¯k@Wbk@WI@aUyUXJkU@bU@WLUyXUbkbW`UVVkKmbUaVUUK£@KVUUUm@UWkXWaUKV@b¯¯mUV@UkmW@kkKwUmkkVUI@WlkUamL@Wk_W@UVm@Ua¯KWXk@Uxm@UK@xVmV@Xk@UVV¼@VLUbUU@yULUbVlU@@XlVUVVbU@lXXVW@XUVl@@VUVÈn@VVU@lVa@UmL@`X@`WL@VUX@lUL@xlx\"],encodeOffsets:[[122119,29948]]}},{type:\"Feature\",id:\"3308\",properties:{name:\"衢州市\",cp:[118.6853,28.8666],childNum:5},geometry:{type:\"Polygon\",coordinates:[\"@@XkVKnwl@@aVK@UwnLK@aÞa¹@Kb@UVaUaVaVK@k°VUllnL@V@xV@V@VVm_Wam@wlaÞbn@lL@WnLk@V@VlK@nkVVb@blKXklakw@wVK@kVW@UXK@_W@_nKV@Ub@kVUUm@ÇVU@Uk@VU@WUXWW@kVUaVUkU@WWXUKk@Ukmm¯LmmUJUIWJkImm_±WLkKm£@aVUmKUnLmWUkVmw@¥ULVWm@WUka@UmmLmm@@bUX@@WUIm@UVUK@UVUUUVVJmb@bXnmV¼nnn¦mJUVLV@VW@UzUlVnUbl`UnVl@XU@kl@bmÈUxVk@@J@¼W@ÅaVVnzmV@WJk@kWJ@lXbWbXxmVnlLXb@°lKVXnWbWVXmbV@XlbI@Kn@@x@VLlm\"],encodeOffsets:[[121185,30184]]}},{type:\"Feature\",id:\"3306\",properties:{name:\"绍兴市\",cp:[120.564,29.7565],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@x@VnnVJnIVJV_VKXblUXJllLUUnU@UVVX@mVUUUJlXUlbV@@VLVmX@@XlaVJVXXJ@b@XU@lUJÈb¤ŌJçVUUnml@@kna@wWVU@LVKV@namwkIUwmnmlaVLkUmVUkmmIUak@VmUUVUWV_kK@UKbnkWyU@@UXwl@VUÞUVak±VUUU@mlI@wXWIWbUKkLUKVmUUmVVLLambUWmIUmnUU@aUUVym@Xkak@W@z@lWVXnmVaUbVb@VakLUKLmbUU@lkV@bbUb@nW`@Xk`Ikwm@mUXyUUkWKUk@Kb@lV¦klV¯UlWIkwKUabVVUbVXXmb@VxxkVVV@bU@@aW@kLmb@lVUIVKmL@bUV@bUV@LalnUV@nbVbUlVXJVUnx\"],encodeOffsets:[[122997,30561]]}},{type:\"Feature\",id:\"3304\",properties:{name:\"嘉兴市\",cp:[120.9155,30.6354],childNum:6},geometry:{type:\"Polygon\",coordinates:[\"@@@blIX@@VÜVUnn@lklKnI°Þl`²LVKVbnbVaVLUVn@W¦@VkVVb@VI`@blLnLaX@VVb@U@XlVa@@kVaUKV»U_lWXU@albk@VllnLVKn@@UVIUw@y°IVVXU@VV@lwm@wVkƾaJLkΡƧƒlLÝUmW¯ķÿĉ¥IŋWnèkVƧU¯ÅmlVx@V¯az@@JU@U¦m@@nVmn@VLV\"],encodeOffsets:[[123233,31382]]}},{type:\"Feature\",id:\"3305\",properties:{name:\"湖州市\",cp:[119.8608,30.7782],childNum:4},geometry:{type:\"Polygon\",coordinates:[\"@@kLlkm@VmÛU@UW@kJ@aUK@UnmmU@maÛL@JWUUKUwUIUJ@XKWV@Vk@UIUmVk@mm@ÅnmaUVkL@VKmLVbU@klU@ÝbV@mVUKV@wUkVmIUJ@nVV@LakJWbUIka@UmKmLKmmUUVk@@nmLX`WXUV@@nUlkmlU@UbxVVIlVnn@@nUÒ@°n@@xmb@VbnV@@b@`@L@L@x@blVklVbnnV@aXb°VlU@Wb°ULXWVUVVwÈwÜ»ĸaĠnUVw²X@V@lVU@wlaUUVm@knUV\"],encodeOffsets:[[123379,31500]]}}],UTF8Encoding:!0}}),i(\"echarts/chart/gauge\",[\"require\",\"./base\",\"../util/shape/GaugePointer\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Rectangle\",\"zrender/shape/Circle\",\"zrender/shape/Sector\",\"../config\",\"../util/ecData\",\"../util/accMath\",\"zrender/tool/util\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"../util/shape/GaugePointer\"),a=e(\"zrender/shape/Text\"),o=e(\"zrender/shape/Line\"),r=e(\"zrender/shape/Rectangle\"),s=e(\"zrender/shape/Circle\"),l=e(\"zrender/shape/Sector\"),h=e(\"../config\");h.gauge={zlevel:0,z:2,center:[\"50%\",\"50%\"],clickable:!0,legendHoverLink:!0,radius:\"75%\",startAngle:225,endAngle:-45,min:0,max:100,splitNumber:10,axisLine:{show:!0,lineStyle:{color:[[.2,\"#228b22\"],[.8,\"#48b\"],[1,\"#ff4500\"]],width:30}},axisTick:{show:!0,splitNumber:5,length:8,lineStyle:{color:\"#eee\",width:1,type:\"solid\"}},axisLabel:{show:!0,textStyle:{color:\"auto\"}},splitLine:{show:!0,length:30,lineStyle:{color:\"#eee\",width:2,type:\"solid\"}},pointer:{show:!0,length:\"80%\",width:8,color:\"auto\"},title:{show:!0,offsetCenter:[0,\"-40%\"],textStyle:{color:\"#333\",fontSize:15}},detail:{show:!0,backgroundColor:\"rgba(0,0,0,0)\",borderWidth:0,borderColor:\"#ccc\",width:100,height:40,offsetCenter:[0,\"40%\"],textStyle:{color:\"auto\",fontSize:30}}};var m=e(\"../util/ecData\"),V=e(\"../util/accMath\"),U=e(\"zrender/tool/util\");return t.prototype={type:h.CHART_TYPE_GAUGE,_buildShape:function(){var e=this.series;this._paramsMap={},this.selectedMap={};for(var t=0,i=e.length;i>t;t++)e[t].type===h.CHART_TYPE_GAUGE&&(this.selectedMap[e[t].name]=!0,e[t]=this.reformOption(e[t]),this.legendHoverLink=e[t].legendHoverLink||this.legendHoverLink,this._buildSingleGauge(t),this.buildMark(t));this.addShapeList()},_buildSingleGauge:function(e){var t=this.series[e];this._paramsMap[e]={center:this.parseCenter(this.zr,t.center),radius:this.parseRadius(this.zr,t.radius),startAngle:t.startAngle.toFixed(2)-0,endAngle:t.endAngle.toFixed(2)-0},this._paramsMap[e].totalAngle=this._paramsMap[e].startAngle-this._paramsMap[e].endAngle,this._colorMap(e),this._buildAxisLine(e),this._buildSplitLine(e),this._buildAxisTick(e),this._buildAxisLabel(e),this._buildPointer(e),this._buildTitle(e),this._buildDetail(e)},_buildAxisLine:function(e){var t=this.series[e];if(t.axisLine.show)for(var i,n,a=t.min,o=t.max-a,r=this._paramsMap[e],s=r.center,l=r.startAngle,h=r.totalAngle,V=r.colorArray,U=t.axisLine.lineStyle,d=this.parsePercent(U.width,r.radius[1]),p=r.radius[1],c=p-d,u=l,y=0,g=V.length;g>y;y++)n=l-h*(V[y][0]-a)/o,i=this._getSector(s,c,p,n,u,V[y][1],U,t.zlevel,t.z),u=n,i._animationAdd=\"r\",m.set(i,\"seriesIndex\",e),m.set(i,\"dataIndex\",y),this.shapeList.push(i)},_buildSplitLine:function(e){var t=this.series[e];if(t.splitLine.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.splitLine,V=this.parsePercent(m.length,r.radius[1]),U=m.lineStyle,d=U.color,p=r.center,c=r.startAngle*Math.PI/180,u=r.totalAngle*Math.PI/180,y=r.radius[1],g=y-V,b=0;s>=b;b++)i=c-u/s*b,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:p[0]+a*y,yStart:p[1]-n*y,xEnd:p[0]+a*g,yEnd:p[1]-n*g,strokeColor:\"auto\"===d?this._getColor(e,l+h/s*b):d,lineType:U.type,lineWidth:U.width,shadowColor:U.shadowColor,shadowBlur:U.shadowBlur,shadowOffsetX:U.shadowOffsetX,shadowOffsetY:U.shadowOffsetY}}))},_buildAxisTick:function(e){var t=this.series[e];if(t.axisTick.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisTick,V=m.splitNumber,U=this.parsePercent(m.length,r.radius[1]),d=m.lineStyle,p=d.color,c=r.center,u=r.startAngle*Math.PI/180,y=r.totalAngle*Math.PI/180,g=r.radius[1],b=g-U,f=0,k=s*V;k>=f;f++)f%V!==0&&(i=u-y/k*f,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:c[0]+a*g,yStart:c[1]-n*g,xEnd:c[0]+a*b,yEnd:c[1]-n*b,strokeColor:\"auto\"===p?this._getColor(e,l+h/k*f):p,lineType:d.type,lineWidth:d.width,shadowColor:d.shadowColor,shadowBlur:d.shadowBlur,shadowOffsetX:d.shadowOffsetX,shadowOffsetY:d.shadowOffsetY}})))},_buildAxisLabel:function(e){var t=this.series[e];if(t.axisLabel.show)for(var i,n,o,r,s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisLabel.textStyle,U=this.getFont(m),d=m.color,p=this._paramsMap[e],c=p.center,u=p.startAngle,y=p.totalAngle,g=p.radius[1]-this.parsePercent(t.splitLine.length,p.radius[1])-5,b=0;s>=b;b++)r=V.accAdd(l,V.accMul(V.accDiv(h,s),b)),i=u-y/s*b,n=Math.sin(i*Math.PI/180),o=Math.cos(i*Math.PI/180),i=(i+360)%360,this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{x:c[0]+o*g,y:c[1]-n*g,color:\"auto\"===d?this._getColor(e,r):d,text:this._getLabelText(t.axisLabel.formatter,r),textAlign:i>=110&&250>=i?\"left\":70>=i||i>=290?\"right\":\"center\",textBaseline:i>=10&&170>=i?\"top\":i>=190&&350>=i?\"bottom\":\"middle\",textFont:U,shadowColor:m.shadowColor,shadowBlur:m.shadowBlur,shadowOffsetX:m.shadowOffsetX,shadowOffsetY:m.shadowOffsetY}}))},_buildPointer:function(e){var t=this.series[e];if(t.pointer.show){var i=t.max-t.min,a=t.pointer,o=this._paramsMap[e],r=this.parsePercent(a.length,o.radius[1]),l=this.parsePercent(a.width,o.radius[1]),h=o.center,V=this._getValue(e);V=V<t.max?V:t.max;var U=(o.startAngle-o.totalAngle/i*(V-t.min))*Math.PI/180,d=\"auto\"===a.color?this._getColor(e,V):a.color,p=new n({zlevel:t.zlevel,z:t.z+1,clickable:this.query(t,\"clickable\"),style:{x:h[0],y:h[1],r:r,startAngle:o.startAngle*Math.PI/180,angle:U,color:d,width:l,shadowColor:a.shadowColor,shadowBlur:a.shadowBlur,shadowOffsetX:a.shadowOffsetX,shadowOffsetY:a.shadowOffsetY},highlightStyle:{brushType:\"fill\",width:l>2?2:l/2,color:\"#fff\"}});m.pack(p,this.series[e],e,this.series[e].data[0],0,this.series[e].data[0].name,V),this.shapeList.push(p),this.shapeList.push(new s({zlevel:t.zlevel,z:t.z+2,hoverable:!1,style:{x:h[0],y:h[1],r:a.width/2.5,color:\"#fff\"}}))}},_buildTitle:function(e){var t=this.series[e];if(t.title.show){var i=t.data[0],n=null!=i.name?i.name:\"\";if(\"\"!==n){var o=t.title,r=o.offsetCenter,s=o.textStyle,l=s.color,h=this._paramsMap[e],m=h.center[0]+this.parsePercent(r[0],h.radius[1]),V=h.center[1]+this.parsePercent(r[1],h.radius[1]);this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+(Math.abs(m-h.center[0])+Math.abs(V-h.center[1])<2*s.fontSize?2:1),hoverable:!1,style:{x:m,y:V,color:\"auto\"===l?this._getColor(e):l,text:n,textAlign:\"center\",textFont:this.getFont(s),shadowColor:s.shadowColor,shadowBlur:s.shadowBlur,shadowOffsetX:s.shadowOffsetX,shadowOffsetY:s.shadowOffsetY}}))}}},_buildDetail:function(e){var t=this.series[e];if(t.detail.show){var i=t.detail,n=i.offsetCenter,a=i.backgroundColor,o=i.textStyle,s=o.color,l=this._paramsMap[e],h=this._getValue(e),m=l.center[0]-i.width/2+this.parsePercent(n[0],l.radius[1]),V=l.center[1]+this.parsePercent(n[1],l.radius[1]);this.shapeList.push(new r({zlevel:t.zlevel,z:t.z+(Math.abs(m+i.width/2-l.center[0])+Math.abs(V+i.height/2-l.center[1])<o.fontSize?2:1),hoverable:!1,style:{x:m,y:V,width:i.width,height:i.height,brushType:\"both\",color:\"auto\"===a?this._getColor(e,h):a,lineWidth:i.borderWidth,strokeColor:i.borderColor,shadowColor:i.shadowColor,shadowBlur:i.shadowBlur,shadowOffsetX:i.shadowOffsetX,shadowOffsetY:i.shadowOffsetY,text:this._getLabelText(i.formatter,h),textFont:this.getFont(o),textPosition:\"inside\",textColor:\"auto\"===s?this._getColor(e,h):s}}))}},_getValue:function(e){return this.getDataFromOption(this.series[e].data[0])},_colorMap:function(e){var t=this.series[e],i=t.min,n=t.max-i,a=t.axisLine.lineStyle.color;a instanceof Array||(a=[[1,a]]);for(var o=[],r=0,s=a.length;s>r;r++)o.push([a[r][0]*n+i,a[r][1]]);this._paramsMap[e].colorArray=o},_getColor:function(e,t){null==t&&(t=this._getValue(e));for(var i=this._paramsMap[e].colorArray,n=0,a=i.length;a>n;n++)if(i[n][0]>=t)return i[n][1];return i[i.length-1][1]},_getSector:function(e,t,i,n,a,o,r,s,h){return new l({zlevel:s,z:h,hoverable:!1,style:{x:e[0],y:e[1],r0:t,r:i,startAngle:n,endAngle:a,brushType:\"fill\",color:o,shadowColor:r.shadowColor,shadowBlur:r.shadowBlur,shadowOffsetX:r.shadowOffsetX,shadowOffsetY:r.shadowOffsetY}})},_getLabelText:function(e,t){if(e){if(\"function\"==typeof e)return e.call(this.myChart,t);if(\"string\"==typeof e)return e.replace(\"{value}\",t)}return t},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},U.inherits(t,i),e(\"../chart\").define(\"gauge\",t),t}),i(\"echarts/util/shape/GaugePointer\",[\"require\",\"zrender/shape/Base\",\"zrender/tool/util\",\"./normalIsCover\"],function(e){function t(e){i.call(this,e)}var i=e(\"zrender/shape/Base\"),n=e(\"zrender/tool/util\");return t.prototype={type:\"gauge-pointer\",buildPath:function(e,t){var i=t.r,n=t.width,a=t.angle,o=t.x-Math.cos(a)*n*(n>=i/3?1:2),r=t.y+Math.sin(a)*n*(n>=i/3?1:2);a=t.angle-Math.PI/2,e.moveTo(o,r),e.lineTo(t.x+Math.cos(a)*n,t.y-Math.sin(a)*n),e.lineTo(t.x+Math.cos(t.angle)*i,t.y-Math.sin(t.angle)*i),e.lineTo(t.x-Math.cos(a)*n,t.y+Math.sin(a)*n),e.lineTo(o,r)},getRect:function(e){if(e.__rect)return e.__rect;var t=2*e.width,i=e.x,n=e.y,a=i+Math.cos(e.angle)*e.r,o=n-Math.sin(e.angle)*e.r;return e.__rect={x:Math.min(i,a)-t,y:Math.min(n,o)-t,width:Math.abs(i-a)+t,height:Math.abs(n-o)+t},e.__rect},isCover:e(\"./normalIsCover\")},n.inherits(t,i),t}),i(\"echarts/chart/funnel\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"zrender/shape/Polygon\",\"../config\",\"../util/ecData\",\"../util/number\",\"zrender/tool/util\",\"zrender/tool/color\",\"zrender/tool/area\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Line\"),o=e(\"zrender/shape/Polygon\"),r=e(\"../config\");r.funnel={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,x:80,y:60,x2:80,y2:60,min:0,max:100,minSize:\"0%\",maxSize:\"100%\",sort:\"descending\",gap:0,funnelAlign:\"center\",itemStyle:{normal:{borderColor:\"#fff\",borderWidth:1,label:{show:!0,position:\"outer\"},labelLine:{show:!0,length:10,lineStyle:{width:1,type:\"solid\"}}},emphasis:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,label:{show:!0},labelLine:{show:!0}}}};var s=e(\"../util/ecData\"),l=e(\"../util/number\"),h=e(\"zrender/tool/util\"),m=e(\"zrender/tool/color\"),V=e(\"zrender/tool/area\");return t.prototype={type:r.CHART_TYPE_FUNNEL,_buildShape:function(){var e=this.series,t=this.component.legend;this._paramsMap={},this._selected={},this.selectedMap={};for(var i,n=0,a=e.length;a>n;n++)if(e[n].type===r.CHART_TYPE_FUNNEL){if(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,i=e[n].name||\"\",this.selectedMap[i]=t?t.isSelected(i):!0,!this.selectedMap[i])continue;this._buildSingleFunnel(n),this.buildMark(n)}this.addShapeList()},_buildSingleFunnel:function(e){var t=this.component.legend,i=this.series[e],n=this._mapData(e),a=this._getLocation(e);this._paramsMap[e]={location:a,data:n};for(var o,r=0,s=[],h=0,m=n.length;m>h;h++)o=n[h].name,this.selectedMap[o]=t?t.isSelected(o):!0,this.selectedMap[o]&&!isNaN(n[h].value)&&(s.push(n[h]),r++);if(0!==r){for(var V,U,d,p,c=this._buildFunnelCase(e),u=i.funnelAlign,y=i.gap,g=r>1?(a.height-(r-1)*y)/r:a.height,b=a.y,f=\"descending\"===i.sort?this._getItemWidth(e,s[0].value):l.parsePercent(i.minSize,a.width),k=\"descending\"===i.sort?1:0,x=a.centerX,_=[],h=0,m=s.length;m>h;h++)if(o=s[h].name,this.selectedMap[o]&&!isNaN(s[h].value)){switch(V=m-2>=h?this._getItemWidth(e,s[h+k].value):\"descending\"===i.sort?l.parsePercent(i.minSize,a.width):l.parsePercent(i.maxSize,a.width),u){case\"left\":U=a.x;break;case\"right\":U=a.x+a.width-f;break;default:U=x-f/2}d=this._buildItem(e,s[h]._index,t?t.getColor(o):this.zr.getColor(s[h]._index),U,b,f,V,g,u),b+=g+y,p=d.style.pointList,_.unshift([p[0][0]-10,p[0][1]]),_.push([p[1][0]+10,p[1][1]]),0===h&&(0===f?(p=_.pop(),\"center\"==u&&(_[0][0]+=10),\"right\"==u&&(_[0][0]=p[0]),_[0][1]-=\"center\"==u?10:15,1==m&&(p=d.style.pointList)):(_[_.length-1][1]-=5,_[0][1]-=5)),f=V}c&&(_.unshift([p[3][0]-10,p[3][1]]),_.push([p[2][0]+10,p[2][1]]),0===f?(p=_.pop(),\"center\"==u&&(_[0][0]+=10),\"right\"==u&&(_[0][0]=p[0]),_[0][1]+=\"center\"==u?10:15):(_[_.length-1][1]+=5,_[0][1]+=5),c.style.pointList=_)}},_buildFunnelCase:function(e){var t=this.series[e];if(this.deepQuery([t,this.option],\"calculable\")){var i=this._paramsMap[e].location,n=10,a={hoverable:!1,style:{pointListd:[[i.x-n,i.y-n],[i.x+i.width+n,i.y-n],[i.x+i.width+n,i.y+i.height+n],[i.x-n,i.y+i.height+n]],brushType:\"stroke\",lineWidth:1,strokeColor:t.calculableHolderColor||this.ecTheme.calculableHolderColor||r.calculableHolderColor}};return s.pack(a,t,e,void 0,-1),this.setCalculable(a),a=new o(a),this.shapeList.push(a),a}},_getLocation:function(e){var t=this.series[e],i=this.zr.getWidth(),n=this.zr.getHeight(),a=this.parsePercent(t.x,i),o=this.parsePercent(t.y,n),r=null==t.width?i-a-this.parsePercent(t.x2,i):this.parsePercent(t.width,i);return{x:a,y:o,width:r,height:null==t.height?n-o-this.parsePercent(t.y2,n):this.parsePercent(t.height,n),centerX:a+r/2}},_mapData:function(e){function t(e,t){return\"-\"===e.value?1:\"-\"===t.value?-1:t.value-e.value}function i(e,i){return-t(e,i)}for(var n=this.series[e],a=h.clone(n.data),o=0,r=a.length;r>o;o++)a[o]._index=o;return\"none\"!=n.sort&&a.sort(\"descending\"===n.sort?t:i),a},_buildItem:function(e,t,i,n,a,o,r,l,h){var m=this.series,V=m[e],U=V.data[t],d=this.getPolygon(e,t,i,n,a,o,r,l,h);s.pack(d,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(d);var p=this.getLabel(e,t,i,n,a,o,r,l,h);s.pack(p,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(p),this._needLabel(V,U,!1)||(p.invisible=!0);var c=this.getLabelLine(e,t,i,n,a,o,r,l,h);this.shapeList.push(c),this._needLabelLine(V,U,!1)||(c.invisible=!0);var u=[],y=[];return this._needLabelLine(V,U,!0)&&(u.push(c.id),y.push(c.id)),this._needLabel(V,U,!0)&&(u.push(p.id),y.push(d.id)),d.hoverConnect=u,p.hoverConnect=y,d},_getItemWidth:function(e,t){var i=this.series[e],n=this._paramsMap[e].location,a=i.min,o=i.max,r=l.parsePercent(i.minSize,n.width),s=l.parsePercent(i.maxSize,n.width);return(t-a)*(s-r)/(o-a)+r},getPolygon:function(e,t,i,n,a,r,s,l,h){var V,U=this.series[e],d=U.data[t],p=[d,U],c=this.deepMerge(p,\"itemStyle.normal\")||{},u=this.deepMerge(p,\"itemStyle.emphasis\")||{},y=this.getItemStyleColor(c.color,e,t,d)||i,g=this.getItemStyleColor(u.color,e,t,d)||(\"string\"==typeof y?m.lift(y,-.2):y);switch(h){case\"left\":V=n;break;case\"right\":V=n+(r-s);break;default:V=n+(r-s)/2}var b={zlevel:U.zlevel,z:U.z,clickable:this.deepQuery(p,\"clickable\"),style:{pointList:[[n,a],[n+r,a],[V+s,a+l],[V,a+l]],brushType:\"both\",color:y,lineWidth:c.borderWidth,strokeColor:c.borderColor},highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};return this.deepQuery([d,U,this.option],\"calculable\")&&(this.setCalculable(b),b.draggable=!0),new o(b)},getLabel:function(e,t,i,a,o,r,s,l,U){var d,p=this.series[e],c=p.data[t],u=this._paramsMap[e].location,y=h.merge(h.clone(c.itemStyle)||{},p.itemStyle),g=\"normal\",b=y[g].label,f=b.textStyle||{},k=y[g].labelLine.length,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i;b.position=b.position||y.normal.label.position,\"inner\"===b.position||\"inside\"===b.position||\"center\"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?\"#fff\":m.reverse(i)):d=\"left\"===b.position?\"right\":\"left\";var W={zlevel:p.zlevel,z:p.z+1,style:{x:this._getLabelPoint(b.position,a,u,r,s,k,U),y:o+l/2,color:f.color||L,text:x,textAlign:f.align||d,textBaseline:f.baseline||\"middle\",textFont:_}};return g=\"emphasis\",b=y[g].label||b,f=b.textStyle||f,k=y[g].labelLine.length||k,b.position=b.position||y.normal.label.position,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i,\"inner\"===b.position||\"inside\"===b.position||\"center\"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?\"#fff\":m.reverse(i)):d=\"left\"===b.position?\"right\":\"left\",W.highlightStyle={x:this._getLabelPoint(b.position,a,u,r,s,k,U),color:f.color||L,text:x,textAlign:f.align||d,textFont:_,brushType:\"fill\"},new n(W)},getLabelText:function(e,t,i){var n=this.series,a=n[e],o=a.data[t],r=this.deepQuery([o,a],\"itemStyle.\"+i+\".label.formatter\");return r?\"function\"==typeof r?r.call(this.myChart,{seriesIndex:e,seriesName:a.name||\"\",series:a,dataIndex:t,data:o,name:o.name,value:o.value}):\"string\"==typeof r?r=r.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\").replace(\"{a0}\",a.name).replace(\"{b0}\",o.name).replace(\"{c0}\",o.value):void 0:o.name},getLabelLine:function(e,t,i,n,o,r,s,l,m){var V=this.series[e],U=V.data[t],d=this._paramsMap[e].location,p=h.merge(h.clone(U.itemStyle)||{},V.itemStyle),c=\"normal\",u=p[c].labelLine,y=p[c].labelLine.length,g=u.lineStyle||{},b=p[c].label;b.position=b.position||p.normal.label.position;var f={zlevel:V.zlevel,z:V.z+1,hoverable:!1,style:{xStart:this._getLabelLineStartPoint(n,d,r,s,m),yStart:o+l/2,xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),yEnd:o+l/2,strokeColor:g.color||i,lineType:g.type,lineWidth:g.width}};return c=\"emphasis\",u=p[c].labelLine||u,y=p[c].labelLine.length||y,g=u.lineStyle||g,b=p[c].label||b,b.position=b.position,f.highlightStyle={xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),strokeColor:g.color||i,lineType:g.type,lineWidth:g.width},new a(f)},_getLabelPoint:function(e,t,i,n,a,o,r){switch(e=\"inner\"===e||\"inside\"===e?\"center\":e){case\"center\":return\"center\"==r?t+n/2:\"left\"==r?t+10:t+n-10;case\"left\":return\"auto\"===o?i.x-10:\"center\"==r?i.centerX-Math.max(n,a)/2-o:\"right\"==r?t-(a>n?a-n:0)-o:i.x-o;default:return\"auto\"===o?i.x+i.width+10:\"center\"==r?i.centerX+Math.max(n,a)/2+o:\"right\"==r?i.x+i.width+o:t+Math.max(n,a)+o}},_getLabelLineStartPoint:function(e,t,i,n,a){return\"center\"==a?t.centerX:n>i?e+Math.min(i,n)/2:e+Math.max(i,n)/2},_needLabel:function(e,t,i){return this.deepQuery([t,e],\"itemStyle.\"+(i?\"emphasis\":\"normal\")+\".label.show\")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],\"itemStyle.\"+(i?\"emphasis\":\"normal\")+\".labelLine.show\")},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},h.inherits(t,i),e(\"../chart\").define(\"funnel\",t),t}),i(\"echarts/chart/eventRiver\",[\"require\",\"./base\",\"../layout/eventRiver\",\"zrender/shape/Polygon\",\"../component/axis\",\"../component/grid\",\"../component/dataZoom\",\"../config\",\"../util/ecData\",\"../util/date\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondragend=function(){r.isDragend=!0},this.refresh(a)}var i=e(\"./base\"),n=e(\"../layout/eventRiver\"),a=e(\"zrender/shape/Polygon\");e(\"../component/axis\"),e(\"../component/grid\"),e(\"../component/dataZoom\");var o=e(\"../config\");o.eventRiver={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,itemStyle:{normal:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,label:{show:!0,position:\"inside\",formatter:\"{b}\"}},emphasis:{borderColor:\"rgba(0,0,0,0)\",borderWidth:1,label:{show:!0}}}};var r=e(\"../util/ecData\"),s=e(\"../util/date\"),l=e(\"zrender/tool/util\"),h=e(\"zrender/tool/color\");return t.prototype={type:o.CHART_TYPE_EVENTRIVER,_buildShape:function(){var e=this.series;this.selectedMap={},this._dataPreprocessing();for(var t=this.component.legend,i=[],a=0;a<e.length;a++)if(e[a].type===this.type){e[a]=this.reformOption(e[a]),this.legendHoverLink=e[a].legendHoverLink||this.legendHoverLink;var o=e[a].name||\"\";if(this.selectedMap[o]=t?t.isSelected(o):!0,!this.selectedMap[o])continue;this.buildMark(a),i.push(this.series[a])}n(i,this._intervalX,this.component.grid.getArea()),this._drawEventRiver(),this.addShapeList()},_dataPreprocessing:function(){for(var e,t,i=this.series,n=0,a=i.length;a>n;n++)if(i[n].type===this.type){e=this.component.xAxis.getAxis(i[n].xAxisIndex||0);for(var o=0,r=i[n].data.length;r>o;o++){t=i[n].data[o].evolution;for(var l=0,h=t.length;h>l;l++)t[l].timeScale=e.getCoord(s.getNewDate(t[l].time)-0),t[l].valueScale=Math.pow(t[l].value,.8)}}this._intervalX=Math.round(this.component.grid.getWidth()/40)},_drawEventRiver:function(){for(var e=this.series,t=0;t<e.length;t++){var i=e[t].name||\"\";if(e[t].type===this.type&&this.selectedMap[i])for(var n=0;n<e[t].data.length;n++)this._drawEventBubble(e[t].data[n],t,n)}},_drawEventBubble:function(e,t,i){var n=this.series,o=n[t],s=o.name||\"\",l=o.data[i],m=[l,o],V=this.component.legend,U=V?V.getColor(s):this.zr.getColor(t),d=this.deepMerge(m,\"itemStyle.normal\")||{},p=this.deepMerge(m,\"itemStyle.emphasis\")||{},c=this.getItemStyleColor(d.color,t,i,l)||U,u=this.getItemStyleColor(p.color,t,i,l)||(\"string\"==typeof c?h.lift(c,-.2):c),y=this._calculateControlPoints(e),g={zlevel:o.zlevel,z:o.z,clickable:this.deepQuery(m,\"clickable\"),style:{pointList:y,smooth:\"spline\",brushType:\"both\",lineJoin:\"round\",color:c,lineWidth:d.borderWidth,strokeColor:d.borderColor},highlightStyle:{color:u,lineWidth:p.borderWidth,strokeColor:p.borderColor},draggable:\"vertical\",ondragend:this._ondragend};g=new a(g),this.addLabel(g,o,l,e.name),r.pack(g,n[t],t,n[t].data[i],i,n[t].data[i].name),this.shapeList.push(g)},_calculateControlPoints:function(e){var t=this._intervalX,i=e.y,n=e.evolution,a=n.length;if(!(1>a)){for(var o=[],r=[],s=0;a>s;s++)o.push(n[s].timeScale),r.push(n[s].valueScale);var l=[];l.push([o[0],i]);var s=0;for(s=0;a-1>s;s++)l.push([(o[s]+o[s+1])/2,r[s]/-2+i]);for(l.push([(o[s]+(o[s]+t))/2,r[s]/-2+i]),l.push([o[s]+t,i]),l.push([(o[s]+(o[s]+t))/2,r[s]/2+i]),s=a-1;s>0;s--)l.push([(o[s]+o[s-1])/2,r[s-1]/2+i]);return l}},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1)},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},l.inherits(t,i),e(\"../chart\").define(\"eventRiver\",t),t}),i(\"echarts/layout/eventRiver\",[\"require\"],function(){function e(e,i,o){function r(e,t){var i=e.importance,n=t.importance;return i>n?-1:n>i?1:0}for(var s=4,l=0;l<e.length;l++){for(var h=0;h<e[l].data.length;h++){null==e[l].data[h].weight&&(e[l].data[h].weight=1);for(var m=0,V=0;V<e[l].data[h].evolution.length;V++)m+=e[l].data[h].evolution[V].valueScale;e[l].data[h].importance=m*e[l].data[h].weight}e[l].data.sort(r)}for(var l=0;l<e.length;l++){null==e[l].weight&&(e[l].weight=1);for(var m=0,h=0;h<e[l].data.length;h++)m+=e[l].data[h].weight;e[l].importance=m*e[l].weight}e.sort(r);for(var U=Number.MAX_VALUE,d=0,l=0;l<e.length;l++)for(var h=0;h<e[l].data.length;h++)for(var V=0;V<e[l].data[h].evolution.length;V++){var p=e[l].data[h].evolution[V].timeScale;U=Math.min(U,p),d=Math.max(d,p)}U=~~U,d=~~d;for(var c=function(){var e=d-U+1+~~i;if(0>=e)return[0];for(var t=[];e--;)t.push(0);return t}(),u=c.slice(0),y=[],g=0,b=0,l=0;l<e.length;l++)for(var h=0;h<e[l].data.length;h++){var f=e[l].data[h];f.time=[],f.value=[];for(var k,x=0,V=0;V<e[l].data[h].evolution.length;V++)k=e[l].data[h].evolution[V],f.time.push(k.timeScale),f.value.push(k.valueScale),x=Math.max(x,k.valueScale);n(f,i,U),f.y=a(u,f,function(e,t){return e.ypx[t]}),f._offset=a(c,f,function(){return s}),g=Math.max(g,f.y+x),b=Math.max(b,f._offset),y.push(f)}t(y,o,g,b)}function t(e,t,i,n){for(var a=t.height,o=n/a>.5?.5:1,r=t.y,s=(t.height-n)/i,l=0,h=e.length;h>l;l++){var m=e[l];m.y=r+s*m.y+m._offset*o,delete m.time,delete m.value,delete m.xpx,delete m.ypx,delete m._offset;for(var V=m.evolution,U=0,d=V.length;d>U;U++)V[U].valueScale*=s}}function i(e,t,i,n){if(e===i)throw new Error(\"x0 is equal with x1!!!\");if(t===n)return function(){return t};var a=(t-n)/(e-i),o=(n*e-t*i)/(e-i);return function(e){return a*e+o}}function n(e,t,n){var a=~~t,o=e.time.length;e.xpx=[],e.ypx=[];for(var r,s=0,l=0,h=0,m=0,V=0;o>s;s++){l=~~e.time[s],m=e.value[s]/2,s===o-1?(h=l+a,V=0):(h=~~e.time[s+1],V=e.value[s+1]/2),r=i(l,m,h,V);for(var U=l;h>U;U++)e.xpx.push(U-n),e.ypx.push(r(U))}e.xpx.push(h-n),e.ypx.push(V)}function a(e,t,i){for(var n,a=0,o=t.xpx.length,r=0;o>r;r++)n=i(t,r),a=Math.max(a,n+e[t.xpx[r]]);for(r=0;o>r;r++)n=i(t,r),e[t.xpx[r]]=a+n;return a}return e}),i(\"echarts/chart/venn\",[\"require\",\"./base\",\"zrender/shape/Text\",\"zrender/shape/Circle\",\"zrender/shape/Path\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"zrender/shape/Circle\"),o=e(\"zrender/shape/Path\"),r=e(\"../config\");r.venn={zlevel:0,z:1,calculable:!1};var s=e(\"../util/ecData\"),l=e(\"zrender/tool/util\");return t.prototype={type:r.CHART_TYPE_VENN,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._vennDataCounter=0;for(var e=this.series,t=this.component.legend,i=0;i<e.length;i++)if(e[i].type===r.CHART_TYPE_VENN){e[i]=this.reformOption(e[i]);var n=e[i].name||\"\";if(this.selectedMap[n]=t?t.isSelected(n):!0,!this.selectedMap[n])continue;this._buildVenn(i)}this.addShapeList()},_buildVenn:function(e){var t,i,n=this.series[e],a=n.data;a[0].value>a[1].value?(t=this.zr.getHeight()/3,i=t*Math.sqrt(a[1].value)/Math.sqrt(a[0].value)):(i=this.zr.getHeight()/3,t=i*Math.sqrt(a[0].value)/Math.sqrt(a[1].value));var o=this.zr.getWidth()/2-t,r=(t+i)/2*Math.sqrt(a[2].value)/Math.sqrt((a[0].value+a[1].value)/2),s=t+i;0!==a[2].value&&(s=this._getCoincideLength(a[0].value,a[1].value,a[2].value,t,i,r,Math.abs(t-i),t+i));var l=o+s,h=this.zr.getHeight()/2;if(this._buildItem(e,0,a[0],o,h,t),this._buildItem(e,1,a[1],l,h,i),0!==a[2].value&&a[2].value!==a[0].value&&a[2].value!==a[1].value){var m=(t*t-i*i)/(2*s)+s/2,V=s/2-(t*t-i*i)/(2*s),U=Math.sqrt(t*t-m*m),d=0,p=0;a[0].value>a[1].value&&o+m>l&&(p=1),a[0].value<a[1].value&&o+V>l&&(d=1),this._buildCoincideItem(e,2,a[2],o+m,h-U,h+U,t,i,d,p)}},_getCoincideLength:function(e,t,i,n,a,o,r,s){var l=(n*n-a*a)/(2*o)+o/2,h=o/2-(n*n-a*a)/(2*o),m=Math.acos(l/n),V=Math.acos(h/a),U=n*n*Math.PI,d=m*n*n-l*n*Math.sin(m)+V*a*a-h*a*Math.sin(V),p=d/U,c=i/e,u=Math.abs(p/c);return u>.999&&1.001>u?o:.999>=u?(s=o,o=(o+r)/2,this._getCoincideLength(e,t,i,n,a,o,r,s)):(r=o,o=(o+s)/2,this._getCoincideLength(e,t,i,n,a,o,r,s))},_buildItem:function(e,t,i,n,a,o){var r=this.series,l=r[e],h=this.getCircle(e,t,i,n,a,o);if(s.pack(h,l,e,i,t,i.name),this.shapeList.push(h),l.itemStyle.normal.label.show){var m=this.getLabel(e,t,i,n,a,o);s.pack(m,l,e,l.data[t],t,l.data[t].name),this.shapeList.push(m)}},_buildCoincideItem:function(e,t,i,n,a,r,l,h,m,V){var U=this.series,d=U[e],p=[i,d],c=this.deepMerge(p,\"itemStyle.normal\")||{},u=this.deepMerge(p,\"itemStyle.emphasis\")||{},y=c.color||this.zr.getColor(t),g=u.color||this.zr.getColor(t),b=\"M\"+n+\",\"+a+\"A\"+l+\",\"+l+\",0,\"+m+\",1,\"+n+\",\"+r+\"A\"+h+\",\"+h+\",0,\"+V+\",1,\"+n+\",\"+a,f={color:y,path:b},k={zlevel:d.zlevel,z:d.z,style:f,highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};k=new o(k),k.buildPathArray&&(k.style.pathArray=k.buildPathArray(f.path)),s.pack(k,U[e],0,i,t,i.name),this.shapeList.push(k)},getCircle:function(e,t,i,n,o,r){var s=this.series[e],l=[i,s],h=this.deepMerge(l,\"itemStyle.normal\")||{},m=this.deepMerge(l,\"itemStyle.emphasis\")||{},V=h.color||this.zr.getColor(t),U=m.color||this.zr.getColor(t),d={zlevel:s.zlevel,z:s.z,clickable:!0,style:{x:n,y:o,r:r,brushType:\"fill\",opacity:1,color:V},highlightStyle:{color:U,lineWidth:m.borderWidth,strokeColor:m.borderColor}};return this.deepQuery([i,s,this.option],\"calculable\")&&(this.setCalculable(d),d.draggable=!0),new a(d)},getLabel:function(e,t,i,a,o,r){var s=this.series[e],l=s.itemStyle,h=[i,s],m=this.deepMerge(h,\"itemStyle.normal\")||{},V=\"normal\",U=l[V].label,d=U.textStyle||{},p=this.getLabelText(t,i,V),c=this.getFont(d),u=m.color||this.zr.getColor(t),y=d.fontSize||12,g={zlevel:s.zlevel,z:s.z,style:{x:a,y:o-r-y,color:d.color||u,text:p,textFont:c,textAlign:\"center\"}};return new n(g)},getLabelText:function(e,t,i){var n=this.series,a=n[0],o=this.deepQuery([t,a],\"itemStyle.\"+i+\".label.formatter\");return o?\"function\"==typeof o?o(a.name,t.name,t.value):\"string\"==typeof o?(o=o.replace(\"{a}\",\"{a0}\").replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\"),o=o.replace(\"{a0}\",a.name).replace(\"{b0}\",t.name).replace(\"{c0}\",t.value)):void 0:t.name},refresh:function(e){e&&(this.option=e,this.series=e.series),this._buildShape()}},l.inherits(t,i),e(\"../chart\").define(\"venn\",t),t}),i(\"echarts/chart/treemap\",[\"require\",\"./base\",\"zrender/tool/area\",\"zrender/shape/Rectangle\",\"zrender/shape/Text\",\"zrender/shape/Line\",\"../layout/TreeMap\",\"../data/Tree\",\"../config\",\"../util/ecData\",\"zrender/config\",\"zrender/tool/event\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a);var r=this;r._onclick=function(e){return r.__onclick(e)},r.zr.on(V.EVENT.CLICK,r._onclick)}var i=e(\"./base\"),n=e(\"zrender/tool/area\"),a=e(\"zrender/shape/Rectangle\"),o=e(\"zrender/shape/Text\"),r=e(\"zrender/shape/Line\"),s=e(\"../layout/TreeMap\"),l=e(\"../data/Tree\"),h=e(\"../config\");h.treemap={zlevel:0,z:1,calculable:!1,clickable:!0,center:[\"50%\",\"50%\"],size:[\"80%\",\"80%\"],root:\"\",itemStyle:{normal:{label:{\nshow:!0,x:5,y:12,textStyle:{align:\"left\",color:\"#000\",fontFamily:\"Arial\",fontSize:13,fontStyle:\"normal\",fontWeight:\"normal\"}},breadcrumb:{show:!0,textStyle:{}},borderWidth:1,borderColor:\"#ccc\",childBorderWidth:1,childBorderColor:\"#ccc\"},emphasis:{}}};var m=e(\"../util/ecData\"),V=e(\"zrender/config\"),U=(e(\"zrender/tool/event\"),e(\"zrender/tool/util\")),d=e(\"zrender/tool/color\");return t.prototype={type:h.CHART_TYPE_TREEMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=this.option.series),this._treesMap={};for(var t=this.series,i=this.component.legend,n=0;n<t.length;n++)if(t[n].type===h.CHART_TYPE_TREEMAP){t[n]=this.reformOption(t[n]);var a=t[n].name||\"\";if(this.selectedMap[a]=i?i.isSelected(a):!0,!this.selectedMap[a])continue;this._buildSeries(t[n],n)}},_buildSeries:function(e,t){var i=l.fromOptionData(e.name,e.data);this._treesMap[t]=i;var n=e.root&&i.getNodeById(e.root)||i.root;this._buildTreemap(n,t)},_buildTreemap:function(e,t){for(var i=this.shapeList,n=0;n<i.length;){var a=i[n];m.get(a,\"seriesIndex\")===t?(this.zr.delShape(i[n]),i.splice(n,1)):n++}for(var o=i.length,r=this.series[t],l=r.itemStyle,h=this.parsePercent(r.size[0],this.zr.getWidth())||400,V=this.parsePercent(r.size[1],this.zr.getHeight())||500,U=this.parseCenter(this.zr,r.center),d=U[0]-.5*h,p=U[1]-.5*V,c=h*V,u=0,y=[],g=e.children,n=0;n<g.length;n++)u+=g[n].data.value;for(var b=0;b<g.length;b++)y.push(g[b].data.value*c/u);for(var f=new s({x:d,y:p,width:h,height:V}),k=f.run(y),x=0;x<k.length;x++){var _=g[x].data,L=k[x],W=[_.itemStyle,l],X=this.deepMerge(W);X.normal.color||(X.normal.color=this.zr.getColor(x)),X.emphasis.color||(X.emphasis.color=X.normal.color),this._buildItem(_,X,L,t,x),_.children&&this._buildChildrenTreemap(_.children,X,L,t)}this.query(r,\"itemStyle.normal.breadcrumb.show\")&&this._buildBreadcrumb(e,t,d,p+V);for(var n=o;n<i.length;n++)this.zr.addShape(i[n])},_buildItem:function(e,t,i,n,a){var o=this.series,r=this.getRectangle(e,t,i);m.pack(r,o[n],n,e,a,e.name),this.shapeList.push(r)},getRectangle:function(e,t,i){var n=t.emphasis,o=t.normal,r=this.getLabel(t,i,e.name,e.value),s=this.option.hoverable,l={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:s,clickable:!0,style:U.merge({x:i.x,y:i.y,width:i.width,height:i.height,brushType:\"both\",color:o.color,lineWidth:o.borderWidth,strokeColor:o.borderColor},r.style,!0),highlightStyle:U.merge({color:n.color,lineWidth:n.borderWidth,strokeColor:n.borderColor},r.highlightStyle,!0)};return new a(l)},getLabel:function(e,t,i,a){var o=e.normal.label.textStyle,r=[e.emphasis.label.textStyle,o],s=this.deepMerge(r),l=e.normal.label.formatter,h=this.getLabelText(i,a,l),m=this.getFont(o),V=n.getTextWidth(h,m),U=n.getTextHeight(h,m),d=this.deepQuery([e.emphasis,e.normal],\"label.formatter\"),p=this.getLabelText(i,a,d),c=this.getFont(s),u=n.getTextWidth(h,c),y=n.getTextHeight(h,c);e.normal.label.show?(e.normal.label.x+V>t.width||e.normal.label.y+U>t.height)&&(h=\"\"):h=\"\",e.emphasis.label.show?(s.x+u>t.width||s.y+y>t.height)&&(p=\"\"):p=\"\";var g={style:{textX:t.x+e.normal.label.x,textY:t.y+e.normal.label.y,text:h,textPosition:\"specific\",textColor:o.color,textFont:m},highlightStyle:{textX:t.x+e.emphasis.label.x,textY:t.y+e.emphasis.label.y,text:p,textColor:s.color,textPosition:\"specific\"}};return g},getLabelText:function(e,t,i){return i?\"function\"==typeof i?i.call(this.myChart,e,t):\"string\"==typeof i?(i=i.replace(\"{b}\",\"{b0}\").replace(\"{c}\",\"{c0}\"),i=i.replace(\"{b0}\",e).replace(\"{c0}\",t)):void 0:e},_buildChildrenTreemap:function(e,t,i,n){for(var a=i.width*i.height,o=0,r=[],l=0;l<e.length;l++)o+=e[l].value;for(var h=0;h<e.length;h++)r.push(e[h].value*a/o);for(var V=new s({x:i.x,y:i.y,width:i.width,height:i.height}),U=V.run(r),d=t.normal.childBorderWidth,p=t.normal.childBorderColor,c=0;c<U.length;c++){var u=U[c],y=[];i.y.toFixed(2)!==u.y.toFixed(2)&&y.push(this._getLine(u.x,u.y,u.x+u.width,u.y,d,p)),i.x.toFixed(2)!==u.x.toFixed(2)&&y.push(this._getLine(u.x,u.y,u.x,u.y+u.height,d,p)),(i.y+i.height).toFixed(2)!==(u.y+u.height).toFixed(2)&&y.push(this._getLine(u.x,u.y+u.height,u.x+u.width,u.y+u.height,d,p)),(i.x+i.width).toFixed(2)!==(u.x+u.width).toFixed(2)&&y.push(this._getLine(u.x+u.width,u.y,u.x+u.width,u.y+u.height,d,p));for(var g=0;g<y.length;g++)m.set(y[g],\"seriesIndex\",n),this.shapeList.push(y[g])}},_getLine:function(e,t,i,n,a,o){var s={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:e,yStart:t,xEnd:i,yEnd:n,lineWidth:a,strokeColor:o}};return new r(s)},_buildBreadcrumb:function(e,t,i,n){for(var a=[],r=e;r;)a.unshift(r.data.name),r=r.parent;for(var s=this.series[t],l=this.query(s,\"itemStyle.normal.breadcrumb.textStyle\")||{},h=this.query(s,\"itemStyle.emphasis.breadcrumb.textStyle\")||{},V={y:n+10,textBaseline:\"top\",textAlign:\"left\",color:l.color,textFont:this.getFont(l)},p={brushType:\"fill\",color:h.color||d.lift(l.color,-.3),textFont:this.getFont(h)},c=0;c<a.length;c++){var u=new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:U.merge({x:i,text:a[c]+(a.length-1-c?\" > \":\"\")},V),clickable:!0,highlightStyle:p});m.set(u,\"seriesIndex\",t),m.set(u,\"name\",a[c]),i+=u.getRect(u.style).width,this.shapeList.push(u)}},__onclick:function(e){var t=e.target;if(t){var i=m.get(t,\"seriesIndex\"),n=m.get(t,\"name\"),a=this._treesMap[i],o=a.getNodeById(n);o&&o.children.length&&this._buildTreemap(o,i)}}},U.inherits(t,i),e(\"../chart\").define(\"treemap\",t),t}),i(\"echarts/layout/TreeMap\",[\"require\"],function(){function e(e){({x:e.x,y:e.y,width:e.width,height:e.height});this.x=e.x,this.y=e.y,this.width=e.width,this.height=e.height}return e.prototype.run=function(e){var t=[];return this._squarify(e,{x:this.x,y:this.y,width:this.width,height:this.height},t),t},e.prototype._squarify=function(e,t,i){var n=\"VERTICAL\",a=t.width,o=t.height;t.width<t.height&&(n=\"HORIZONTAL\",a=t.height,o=t.width);for(var r=this._getShapeListInAbstractRow(e,a,o),s=0;s<r.length;s++){r[s].x=0,r[s].y=0;for(var l=0;s>l;l++)r[s].y+=r[l].height}var h={};if(\"VERTICAL\"==n){for(var m=0;m<r.length;m++)i.push({x:r[m].x+t.x,y:r[m].y+t.y,width:r[m].width,height:r[m].height});h={x:r[0].width+t.x,y:t.y,width:t.width-r[0].width,height:t.height}}else{for(var V=0;V<r.length;V++)i.push({x:r[V].y+t.x,y:r[V].x+t.y,width:r[V].height,height:r[V].width});h={x:t.x,y:t.y+r[0].width,width:t.width,height:t.height-r[0].width}}var U=e.slice(r.length);0!==U.length&&this._squarify(U,h,i)},e.prototype._getShapeListInAbstractRow=function(e,t,i){if(1===e.length)return[{width:t,height:i}];for(var n=1;n<e.length;n++){var a=this._placeFixedNumberRectangles(e.slice(0,n),t,i),o=this._placeFixedNumberRectangles(e.slice(0,n+1),t,i);if(this._isFirstBetter(a,o))return a}},e.prototype._placeFixedNumberRectangles=function(e,t,i){for(var n=e.length,a=[],o=0,r=0;r<e.length;r++)o+=e[r];for(var s=o/i,l=0;n>l;l++){var h=i*e[l]/o;a.push({width:s,height:h})}return a},e.prototype._isFirstBetter=function(e,t){var i=e[0].height/e[0].width;i=i>1?1/i:i;var n=t[0].height/t[0].width;return n=n>1?1/n:n,Math.abs(i-1)<=Math.abs(n-1)?!0:!1},e}),i(\"echarts/data/Tree\",[\"require\",\"zrender/tool/util\"],function(e){function t(e,t){this.id=e,this.depth=0,this.height=0,this.children=[],this.parent=null,this.data=t||null}function i(e){this.root=new t(e)}var n=e(\"zrender/tool/util\");return t.prototype.add=function(e){var t=this.children;e.parent!==this&&(t.push(e),e.parent=this)},t.prototype.remove=function(e){var t=this.children,i=n.indexOf(t,e);i>=0&&(t.splice(i,1),e.parent=null)},t.prototype.traverse=function(e,t){e.call(t,this);for(var i=0;i<this.children.length;i++)this.children[i].traverse(e,t)},t.prototype.updateDepthAndHeight=function(e){var t=0;this.depth=e;for(var i=0;i<this.children.length;i++){var n=this.children[i];n.updateDepthAndHeight(e+1),n.height>t&&(t=n.height)}this.height=t+1},t.prototype.getNodeById=function(e){if(this.id===e)return this;for(var t=0;t<this.children.length;t++){var i=this.children[t].getNodeById(e);if(i)return i}},i.prototype.traverse=function(e,t){this.root.traverse(e,t)},i.prototype.getSubTree=function(e){var t=this.getNodeById(e);if(t){var n=new i(t.id);return n.root=t,n}},i.prototype.getNodeById=function(e){return this.root.getNodeById(e)},i.fromOptionData=function(e,n){function a(e,i){var n=new t(e.name,e);i.add(n);var o=e.children;if(o)for(var r=0;r<o.length;r++)a(o[r],n)}var o=new i(e),r=o.root;r.data={name:e,children:n};for(var s=0;s<n.length;s++)a(n[s],r);return o.root.updateDepthAndHeight(0),o},i.fromGraph=function(e){function n(t){for(var i=e.getNodeById(t.id),a=0;a<i.outEdges.length;a++){var r=i.outEdges[a],s=o[r.node2.id];t.children.push(s),n(s)}}for(var a={},o={},r=0;r<e.nodes.length;r++){var s,l=e.nodes[r];0===l.inDegree()?(a[l.id]=new i(l.id),s=a[l.id].root):s=new t(l.id),s.data=l.data,o[l.id]=s}var h=[];for(var m in a)n(a[m].root),a[m].root.updateDepthAndHeight(0),h.push(a[m]);return h},i}),i(\"echarts/chart/tree\",[\"require\",\"./base\",\"../util/shape/Icon\",\"zrender/shape/Image\",\"zrender/shape/Line\",\"zrender/shape/BezierCurve\",\"../layout/Tree\",\"../data/Tree\",\"../config\",\"../util/ecData\",\"zrender/config\",\"zrender/tool/event\",\"zrender/tool/util\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=.618,a=e(\"../util/shape/Icon\"),o=e(\"zrender/shape/Image\"),r=e(\"zrender/shape/Line\"),s=e(\"zrender/shape/BezierCurve\"),l=e(\"../layout/Tree\"),h=e(\"../data/Tree\"),m=e(\"../config\");m.tree={zlevel:1,z:2,calculable:!1,clickable:!0,rootLocation:{},orient:\"vertical\",symbol:\"circle\",symbolSize:20,nodePadding:30,layerPadding:100,itemStyle:{normal:{label:{show:!0},lineStyle:{width:1,color:\"#777\",type:\"curve\"}},emphasis:{}}};var V=e(\"../util/ecData\"),U=(e(\"zrender/config\"),e(\"zrender/tool/event\"),e(\"zrender/tool/util\"));return t.prototype={type:m.CHART_TYPE_TREE,_buildShape:function(e,t){var i=e.data[0];this.tree=h.fromOptionData(i.name,i.children),this.tree.root.data=i,this._setTreeShape(e),this.tree.traverse(function(i){this._buildItem(i,e,t),i.children.length>0&&this._buildLink(i,e)},this);var n=e.roam===!0||\"move\"===e.roam,a=e.roam===!0||\"scale\"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:n,zoomable:a}),(this.query(\"markPoint.effect.show\")||this.query(\"markLine.effect.show\"))&&this.zr.modLayer(m.EFFECT_ZLEVEL,{panable:n,zoomable:a}),this.addShapeList()},_buildItem:function(e,t,i){var n=[e.data,t],r=this.deepQuery(n,\"symbol\"),s=this.deepMerge(n,\"itemStyle.normal\")||{},l=this.deepMerge(n,\"itemStyle.emphasis\")||{},h=s.color||this.zr.getColor(),m=l.color||this.zr.getColor(),U=-e.layout.angle||0;e.id===this.tree.root.id&&(U=0);var d=\"right\";Math.abs(U)>=Math.PI/2&&Math.abs(U)<3*Math.PI/2&&(U+=Math.PI,d=\"left\");var p=[U,e.layout.position[0],e.layout.position[1]],c=new a({zlevel:this.getZlevelBase(),z:this.getZBase()+1,rotation:p,clickable:this.deepQuery(n,\"clickable\"),style:{x:e.layout.position[0]-.5*e.layout.width,y:e.layout.position[1]-.5*e.layout.height,width:e.layout.width,height:e.layout.height,iconType:r,color:h,brushType:\"both\",lineWidth:s.borderWidth,strokeColor:s.borderColor},highlightStyle:{color:m,lineWidth:l.borderWidth,strokeColor:l.borderColor}});c.style.iconType.match(\"image\")&&(c.style.image=c.style.iconType.replace(new RegExp(\"^image:\\\\/\\\\/\"),\"\"),c=new o({rotation:p,style:c.style,highlightStyle:c.highlightStyle,clickable:c.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(n,\"itemStyle.normal.label.show\")&&(c.style.text=null==e.data.label?e.id:e.data.label,c.style.textPosition=this.deepQuery(n,\"itemStyle.normal.label.position\"),\"radial\"===t.orient&&\"inside\"!==c.style.textPosition&&(c.style.textPosition=d),c.style.textColor=this.deepQuery(n,\"itemStyle.normal.label.textStyle.color\"),c.style.textFont=this.getFont(this.deepQuery(n,\"itemStyle.normal.label.textStyle\")||{})),this.deepQuery(n,\"itemStyle.emphasis.label.show\")&&(c.highlightStyle.textPosition=this.deepQuery(n,\"itemStyle.emphasis.label.position\"),c.highlightStyle.textColor=this.deepQuery(n,\"itemStyle.emphasis.label.textStyle.color\"),c.highlightStyle.textFont=this.getFont(this.deepQuery(n,\"itemStyle.emphasis.label.textStyle\")||{})),V.pack(c,t,i,e.data,0,e.id),this.shapeList.push(c)},_buildLink:function(e,t){var i=t.itemStyle.normal.lineStyle;if(\"broken\"===i.type)return void this._buildBrokenLine(e,i,t);for(var n=0;n<e.children.length;n++){var a=e.layout.position[0],o=e.layout.position[1],r=e.children[n].layout.position[0],s=e.children[n].layout.position[1];switch(i.type){case\"curve\":this._buildBezierCurve(e,e.children[n],i,t);break;case\"broken\":break;default:var l=this._getLine(a,o,r,s,i);this.shapeList.push(l)}}},_buildBrokenLine:function(e,t,i){var a=U.clone(t);a.type=\"solid\";var o=[],r=e.layout.position[0],s=e.layout.position[1],l=i.orient,h=e.children[0].layout.position[1],m=r,V=s+(h-s)*(1-n),d=e.children[0].layout.position[0],p=V,c=e.children[e.children.length-1].layout.position[0],u=V;if(\"horizontal\"===l){var y=e.children[0].layout.position[0];m=r+(y-r)*(1-n),V=s,d=m,p=e.children[0].layout.position[1],c=m,u=e.children[e.children.length-1].layout.position[1]}o.push(this._getLine(r,s,m,V,a)),o.push(this._getLine(d,p,c,u,a));for(var g=0;g<e.children.length;g++)y=e.children[g].layout.position[0],h=e.children[g].layout.position[1],\"horizontal\"===l?p=h:d=y,o.push(this._getLine(d,p,y,h,a));this.shapeList=this.shapeList.concat(o)},_getLine:function(e,t,i,n,a){return e===i&&(e=i=this.subPixelOptimize(e,a.width)),t===n&&(t=n=this.subPixelOptimize(t,a.width)),new r({zlevel:this.getZlevelBase(),hoverable:!1,style:U.merge({xStart:e,yStart:t,xEnd:i,yEnd:n,lineType:a.type,strokeColor:a.color,lineWidth:a.width},a,!0)})},_buildBezierCurve:function(e,t,i,a){var o=n,r=a.orient,l=e.layout.position[0],h=e.layout.position[1],m=t.layout.position[0],V=t.layout.position[1],d=l,p=(V-h)*o+h,c=m,u=(V-h)*(1-o)+h;if(\"horizontal\"===r)d=(m-l)*o+l,p=h,c=(m-l)*(1-o)+l,u=V;else if(\"radial\"===r)if(e.id===this.tree.root.id)d=(m-l)*o+l,p=(V-h)*o+h,c=(m-l)*(1-o)+l,u=(V-h)*(1-o)+h;else{var y=e.layout.originPosition[0],g=e.layout.originPosition[1],b=t.layout.originPosition[0],f=t.layout.originPosition[1],k=this.tree.root.layout.position[0],x=this.tree.root.layout.position[1];d=y,p=(f-g)*o+g,c=b,u=(f-g)*(1-o)+g;var _=(d-this.minX)/this.width*Math.PI*2;d=p*Math.cos(_)+k,p=p*Math.sin(_)+x,_=(c-this.minX)/this.width*Math.PI*2,c=u*Math.cos(_)+k,u=u*Math.sin(_)+x}var L=new s({zlevel:this.getZlevelBase(),hoverable:!1,style:U.merge({xStart:l,yStart:h,cpX1:d,cpY1:p,cpX2:c,cpY2:u,xEnd:m,yEnd:V,strokeColor:i.color,lineWidth:i.width},i,!0)});this.shapeList.push(L)},_setTreeShape:function(e){var t=new l({nodePadding:e.nodePadding,layerPadding:e.layerPadding});this.tree.traverse(function(t){var i=[t.data,e],n=this.deepQuery(i,\"symbolSize\");\"number\"==typeof n&&(n=[n,n]),t.layout={width:n[0],height:n[1]}},this),t.run(this.tree);var i=e.orient,n=e.rootLocation.x,a=e.rootLocation.y,o=this.zr.getWidth(),r=this.zr.getHeight();n=\"center\"===n?.5*o:this.parsePercent(n,o),a=\"center\"===a?.5*r:this.parsePercent(a,r),a=this.parsePercent(a,r),\"horizontal\"===i&&(n=isNaN(n)?10:n,a=isNaN(a)?.5*r:a),\"radial\"===i?(n=isNaN(n)?.5*o:n,a=isNaN(a)?.5*r:a):(n=isNaN(n)?.5*o:n,a=isNaN(a)?10:a);var s=this.tree.root.layout.position[0];if(\"radial\"===i){var h=1/0,m=0,V=0;this.tree.traverse(function(e){m=Math.max(m,e.layout.position[0]),h=Math.min(h,e.layout.position[0]),V=Math.max(V,e.layout.width)}),this.width=m-h+2*V,this.minX=h}this.tree.traverse(function(t){var o,r;if(\"vertical\"===i&&\"inverse\"===e.direction)o=t.layout.position[0]-s+n,r=a-t.layout.position[1];else if(\"vertical\"===i)o=t.layout.position[0]-s+n,r=t.layout.position[1]+a;else if(\"horizontal\"===i&&\"inverse\"===e.direction)r=t.layout.position[0]-s+a,o=n-t.layout.position[1];else if(\"horizontal\"===i)r=t.layout.position[0]-s+a,o=t.layout.position[1]+n;else{o=t.layout.position[0],r=t.layout.position[1],t.layout.originPosition=[o,r];var l=r,m=(o-h)/this.width*Math.PI*2;o=l*Math.cos(m)+n,r=l*Math.sin(m)+a,t.layout.angle=m}t.layout.position[0]=o,t.layout.position[1]=r},this)},refresh:function(e){this.clear(),e&&(this.option=e,this.series=this.option.series);for(var t=this.series,i=this.component.legend,n=0;n<t.length;n++)if(t[n].type===m.CHART_TYPE_TREE){t[n]=this.reformOption(t[n]);var a=t[n].name||\"\";if(this.selectedMap[a]=i?i.isSelected(a):!0,!this.selectedMap[a])continue;this._buildSeries(t[n],n)}},_buildSeries:function(e,t){this._buildShape(e,t)}},U.inherits(t,i),e(\"../chart\").define(\"tree\",t),t}),i(\"echarts/layout/Tree\",[\"require\",\"zrender/tool/vector\"],function(e){function t(e){e=e||{},this.nodePadding=e.nodePadding||30,this.layerPadding=e.layerPadding||100,this._layerOffsets=[],this._layers=[]}var i=e(\"zrender/tool/vector\");return t.prototype.run=function(e){this._layerOffsets.length=0;for(var t=0;t<e.root.height+1;t++)this._layerOffsets[t]=0,this._layers[t]=[];this._updateNodeXPosition(e.root);var i=e.root;this._updateNodeYPosition(i,0,i.layout.height)},t.prototype._updateNodeXPosition=function(e){var t=1/0,n=-(1/0);e.layout.position=e.layout.position||i.create();for(var a=0;a<e.children.length;a++){var o=e.children[a];this._updateNodeXPosition(o);var r=o.layout.position[0];t>r&&(t=r),r>n&&(n=r)}e.layout.position[0]=e.children.length>0?(t+n)/2:0;var s=this._layerOffsets[e.depth]||0;if(s>e.layout.position[0]){var l=s-e.layout.position[0];this._shiftSubtree(e,l);for(var a=e.depth+1;a<e.height+e.depth;a++)this._layerOffsets[a]+=l}this._layerOffsets[e.depth]=e.layout.position[0]+e.layout.width+this.nodePadding,this._layers[e.depth].push(e)},t.prototype._shiftSubtree=function(e,t){e.layout.position[0]+=t;for(var i=0;i<e.children.length;i++)this._shiftSubtree(e.children[i],t)},t.prototype._updateNodeYPosition=function(e,t,i){e.layout.position[1]=t;for(var n=0,a=0;a<e.children.length;a++)n=Math.max(e.children[a].layout.height,n);var o=this.layerPadding;\"function\"==typeof o&&(o=o(e.depth));for(var a=0;a<e.children.length;a++)this._updateNodeYPosition(e.children[a],t+o+i,n)},t}),i(\"echarts/chart/wordCloud\",[\"require\",\"./base\",\"zrender/shape/Text\",\"../layout/WordCloud\",\"../component/grid\",\"../component/dataRange\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"zrender/shape/Text\"),a=e(\"../layout/WordCloud\");e(\"../component/grid\"),e(\"../component/dataRange\");var o=e(\"../config\"),r=e(\"../util/ecData\"),s=e(\"zrender/tool/util\"),l=e(\"zrender/tool/color\");return o.wordCloud={zlevel:0,z:2,clickable:!0,center:[\"50%\",\"50%\"],size:[\"40%\",\"40%\"],textRotation:[0,90],textPadding:0,autoSize:{enable:!0,minSize:12},itemStyle:{normal:{textStyle:{fontSize:function(e){return e.value}}}}},t.prototype={type:o.CHART_TYPE_WORDCLOUD,refresh:function(e){e&&(this.option=e,this.series=e.series),this._init()},_init:function(){var e=this.series;this.backupShapeList();for(var t=this.component.legend,i=0;i<e.length;i++)if(e[i].type===o.CHART_TYPE_WORDCLOUD){e[i]=this.reformOption(e[i]);var n=e[i].name||\"\";if(this.selectedMap[n]=t?t.isSelected(n):!0,!this.selectedMap[n])continue;this.buildMark(i),this._initSerie(e[i])}},_initSerie:function(e){var t=e.itemStyle.normal.textStyle,i=[this.parsePercent(e.size[0],this.zr.getWidth())||200,this.parsePercent(e.size[1],this.zr.getHeight())||200],n=this.parseCenter(this.zr,e.center),o={size:i,wordletype:{autoSizeCal:e.autoSize},center:n,rotate:e.textRotation,padding:e.textPadding,font:t.fontFamily,fontSize:t.fontSize,fontWeight:t.fontWeight,fontStyle:t.fontStyle,text:function(e){return e.name},data:e.data},r=new a(o),s=this;r.end(function(e){s._buildShapes(e)}),r.start()},_buildShapes:function(e){for(var t=e.length,i=0;t>i;i++)this._buildTextShape(e[i],0,i);this.addShapeList()},_buildTextShape:function(e,t,i){var a=this.series,o=a[t],s=o.name||\"\",h=o.data[i],m=[h,o],V=this.component.legend,U=V?V.getColor(s):this.zr.getColor(t),d=this.deepMerge(m,\"itemStyle.normal\")||{},p=this.deepMerge(m,\"itemStyle.emphasis\")||{},c=this.getItemStyleColor(d.color,t,i,h)||U,u=this.getItemStyleColor(p.color,t,i,h)||(\"string\"==typeof c?l.lift(c,-.2):c),y=new n({zlevel:o.zlevel,z:o.z,hoverable:!0,clickable:this.deepQuery(m,\"clickable\"),style:{x:0,y:0,text:e.text,color:c,textFont:[e.style,e.weight,e.size+\"px\",e.font].join(\" \"),textBaseline:\"alphabetic\",textAlign:\"center\"},highlightStyle:{brushType:p.borderWidth?\"both\":\"fill\",color:u,lineWidth:p.borderWidth||0,strokeColor:p.borderColor},position:[e.x,e.y],rotation:[-e.rotate/180*Math.PI,0,0]});r.pack(y,o,t,h,i,h.name),this.shapeList.push(y)}},s.inherits(t,i),e(\"../chart\").define(\"wordCloud\",t),t}),i(\"echarts/layout/WordCloud\",[\"require\",\"../layout/WordCloudRectZero\",\"zrender/tool/util\"],function(e){function t(e){this._init(e)}var i=e(\"../layout/WordCloudRectZero\"),n=e(\"zrender/tool/util\");return t.prototype={start:function(){function e(){p.totalArea=r,U.autoSizeCal.enable&&p._autoCalTextSize(m,r,a,o,U.autoSizeCal.minSize),V.timer&&clearInterval(V.timer),V.timer=setInterval(t,0),t()}function t(){for(var e,t=+new Date,i=m.length;+new Date-t<V.timeInterval&&++s<i&&V.timer;)e=m[s],e.x=d[0]>>1,e.y=d[1]>>1,p._cloudSprite(e,m,s),e.hasText&&p._place(n,e,h)&&(l.push(e),e.x-=d[0]>>1,e.y-=d[1]>>1);s>=i&&(p.stop(),p._fixTagPosition(l),V.endcallback(l))}var n=null,a=0,o=0,r=0,s=-1,l=[],h=null,m=this.wordsdata,V=this.defaultOption,U=V.wordletype,d=V.size,p=this,c=new i({type:U.type,width:d[0],height:d[1]});return c.calculate(function(t){n=t.initarr,a=t.maxWit,o=t.maxHit,r=t.area,h=t.imgboard,e()},this),this},_fixTagPosition:function(e){for(var t=this.defaultOption.center,i=0,n=e.length;n>i;i++)e[i].x+=t[0],e[i].y+=t[1]},stop:function(){return this.defaultOption.timer&&(clearInterval(this.defaultOption.timer),this.defaultOption.timer=null),this},end:function(e){return e&&(this.defaultOption.endcallback=e),this},_init:function(e){this.defaultOption={},this._initProperty(e),this._initMethod(e),this._initCanvas(),this._initData(e.data)},_initData:function(e){var t=this,i=t.defaultOption;this.wordsdata=e.map(function(e,n){return e.text=i.text.call(t,e,n),e.font=i.font.call(t,e,n),e.style=i.fontStyle.call(t,e,n),e.weight=i.fontWeight.call(t,e,n),e.rotate=i.rotate.call(t,e,n),e.size=~~i.fontSize.call(t,e,n),e.padding=i.padding.call(t,e,n),e}).sort(function(e,t){return t.value-e.value})},_initMethod:function(e){function t(e){return e.name}function i(){return\"sans-serif\"}function n(){return\"normal\"}function a(e){return e.value}function o(){return 0}function r(e){return function(){return e[Math.round(Math.random()*(e.length-1))]}}function s(){return 0}function l(e){var t=e[0]/e[1];return function(e){return[t*(e*=.1)*Math.cos(e),e*Math.sin(e)]}}function h(e){var t=4,i=t*e[0]/e[1],n=0,a=0;return function(e){var o=0>e?-1:1;switch(Math.sqrt(1+4*o*e)-o&3){case 0:n+=i;break;case 1:a+=t;break;case 2:n-=i;break;default:a-=t}return[n,a]}}function m(e){return\"function\"==typeof e?e:function(){return e}}var V=this.defaultOption;V.text=e.text?m(e.text):t,V.font=e.font?m(e.font):i,V.fontSize=e.fontSize?m(e.fontSize):a,V.fontStyle=e.fontStyle?m(e.fontStyle):n,V.fontWeight=e.fontWeight?m(e.fontWeight):n,V.rotate=e.rotate?r(e.rotate):o,V.padding=e.padding?m(e.padding):s,V.center=e.center,V.spiral=l,V.endcallback=function(){},V.rectangularSpiral=h,V.archimedeanSpiral=l},_initProperty:function(e){var t=this.defaultOption;t.size=e.size||[256,256],t.wordletype=e.wordletype,t.words=e.words||[],t.timeInterval=1/0,t.timer=null,t.spirals={archimedean:t.archimedeanSpiral,rectangular:t.rectangularSpiral},n.merge(t,{size:[256,256],wordletype:{type:\"RECT\",areaPresent:.058,autoSizeCal:{enable:!0,minSize:12}}})},_initCanvas:function(){var e,t=Math.PI/180,i=64,n=2048,a=1;\"undefined\"!=typeof document?(e=document.createElement(\"canvas\"),e.width=1,e.height=1,a=Math.sqrt(e.getContext(\"2d\").getImageData(0,0,1,1).data.length>>2),e.width=(i<<5)/a,e.height=n/a):e=new Canvas(i<<5,n);var o=e.getContext(\"2d\");o.fillStyle=o.strokeStyle=\"red\",o.textAlign=\"center\",this.defaultOption.c=o,this.defaultOption.cw=i,this.defaultOption.ch=n,this.defaultOption.ratio=a,this.defaultOption.cloudRadians=t},_cloudSprite:function(e,t,i){if(!e.sprite){var n=this.defaultOption.cw,a=this.defaultOption.ch,o=this.defaultOption.c,r=this.defaultOption.ratio,s=this.defaultOption.cloudRadians;o.clearRect(0,0,(n<<5)/r,a/r);var l=0,h=0,m=0,V=t.length;for(--i;++i<V;){e=t[i],o.save(),o.font=e.style+\" \"+e.weight+\" \"+~~((e.size+1)/r)+\"px \"+e.font;var U=o.measureText(e.text+\"m\").width*r,d=e.size<<1;if(e.rotate){var p=Math.sin(e.rotate*s),c=Math.cos(e.rotate*s),u=U*c,y=U*p,g=d*c,b=d*p;U=Math.max(Math.abs(u+b),Math.abs(u-b))+31>>5<<5,d=~~Math.max(Math.abs(y+g),Math.abs(y-g))}else U=U+31>>5<<5;if(d>m&&(m=d),l+U>=n<<5&&(l=0,h+=m,m=0),h+d>=a)break;o.translate((l+(U>>1))/r,(h+(d>>1))/r),e.rotate&&o.rotate(e.rotate*s),o.fillText(e.text,0,0),e.padding&&(o.lineWidth=2*e.padding,o.strokeText(e.text,0,0)),o.restore(),e.width=U,e.height=d,e.xoff=l,e.yoff=h,e.x1=U>>1,e.y1=d>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,l+=U}for(var f=o.getImageData(0,0,(n<<5)/r,a/r).data,k=[];--i>=0;)if(e=t[i],e.hasText){for(var U=e.width,x=U>>5,d=e.y1-e.y0,_=0;d*x>_;_++)k[_]=0;if(l=e.xoff,null==l)return;h=e.yoff;for(var L=0,W=-1,X=0;d>X;X++){for(var _=0;U>_;_++){var v=x*X+(_>>5),w=f[(h+X)*(n<<5)+(l+_)<<2]?1<<31-_%32:0;k[v]|=w,L|=w}L?W=X:(e.y0++,d--,X--,h++)}e.y1=e.y0+W,e.sprite=k.slice(0,(e.y1-e.y0)*x)}}},_place:function(e,t,i){function n(e,t,i){i>>=5;for(var n,a=e.sprite,o=e.width>>5,r=e.x-(o<<4),s=127&r,l=32-s,h=e.y1-e.y0,m=(e.y+e.y0)*i+(r>>5),V=0;h>V;V++){n=0;for(var U=0;o>=U;U++)if((n<<l|(o>U?(n=a[V*o+U])>>>s:0))&t[m+U])return!0;m+=i}return!1}function a(e,t){return t.row[e.y]&&t.cloumn[e.x]&&e.x>=t.row[e.y].start&&e.x<=t.row[e.y].end&&e.y>=t.cloumn[e.x].start&&e.y<=t.cloumn[e.x].end}for(var o,r,s,l=this.defaultOption.size,h=([{x:0,y:0},{x:l[0],y:l[1]}],t.x),m=t.y,V=Math.sqrt(l[0]*l[0]+l[1]*l[1]),U=this.defaultOption.spiral(l),d=Math.random()<.5?1:-1,p=-d;(o=U(p+=d))&&(r=~~o[0],s=~~o[1],!(Math.min(r,s)>V));)if(t.x=h+r,t.y=m+s,!(t.x+t.x0<0||t.y+t.y0<0||t.x+t.x1>l[0]||t.y+t.y1>l[1])&&!n(t,e,l[0])&&a(t,i)){for(var c,u=t.sprite,y=t.width>>5,g=l[0]>>5,b=t.x-(y<<4),f=127&b,k=32-f,x=t.y1-t.y0,_=(t.y+t.y0)*g+(b>>5),L=0;x>L;L++){c=0;for(var W=0;y>=W;W++)e[_+W]|=c<<k|(y>W?(c=u[L*y+W])>>>f:0);_+=g}return delete t.sprite,!0}return!1},_autoCalTextSize:function(e,t,i,n,a){function o(e){c.clearRect(0,0,(d<<5)/u,p/u),c.save(),c.font=e.style+\" \"+e.weight+\" \"+~~((e.size+1)/u)+\"px \"+e.font;var t=c.measureText(e.text+\"m\").width*u,r=e.size<<1;t=t+31>>5<<5,c.restore(),e.aw=t,e.ah=r;var s,l,h;if(e.rotate){var m=Math.sin(e.rotate*y),V=Math.cos(e.rotate*y),g=t*V,b=t*m,f=r*V,k=r*m;l=Math.max(Math.abs(g+k),Math.abs(g-k))+31>>5<<5,h=~~Math.max(Math.abs(b+f),Math.abs(b-f))}return e.size<=U||e.rotate&&t*r<=e.area&&i>=l&&n>=h||t*r<=e.area&&i>=t&&n>=r?void(e.area=t*r):(s=e.rotate&&l>i&&h>n?Math.min(i/l,n/h):t>i||r>n?Math.min(i/t,n/r):Math.sqrt(e.area/(e.aw*e.ah)),e.size=~~(s*e.size),e.size<a?void(e.size=a):o(e))}function r(e,t){for(var i=e.length,n=0;i--;)n+=t(e[i]);return n}for(var s,l,h=r(e,function(e){return e.size}),m=e.length,V=.25,U=a,d=this.defaultOption.cw,p=this.defaultOption.ch,c=this.defaultOption.c,u=this.defaultOption.ratio,y=this.defaultOption.cloudRadians;m--;)s=e[m],l=s.size/h,s.areapre=V?V>l?l:V:l,s.area=t*s.areapre,s.totalarea=t,o(s)}},t}),i(\"echarts/layout/WordCloudRectZero\",[\"require\"],function(){function e(e){this.defaultOption={type:\"RECT\"},this._init(e)}return e.prototype={RECT:\"_calculateRect\",_init:function(e){this._initOption(e),this._initCanvas()},_initOption:function(e){for(k in e)this.defaultOption[k]=e[k]},_initCanvas:function(){var e=document.createElement(\"canvas\");e.width=1,e.height=1;var t=Math.sqrt(e.getContext(\"2d\").getImageData(0,0,1,1).data.length>>2);if(e.width=this.defaultOption.width,e.height=this.defaultOption.height,e.getContext)var i=e.getContext(\"2d\");this.canvas=e,this.ctx=i,this.ratio=t},calculate:function(e,t){var i=this.defaultOption.type,n=this[i];this[n].call(this,e,t)},_calculateReturn:function(e,t,i){t.call(i,e)},_calculateRect:function(e,t){var i={},n=this.defaultOption.width>>5<<5,a=this.defaultOption.height;i.initarr=this._rectZeroArray(n*a),i.area=n*a,i.maxHit=a,i.maxWit=n,i.imgboard=this._rectBoard(n,a),this._calculateReturn(i,e,t)},_rectBoard:function(e,t){for(var i=[],n=0;t>n;n++)i.push({y:n,start:0,end:e});for(var a=[],n=0;e>n;n++)a.push({x:n,start:0,end:t});return{row:i,cloumn:a}},_rectZeroArray:function(e){for(var t=[],i=e,n=-1;++n<i;)t[n]=0;return t}},e}),i(\"echarts/chart/heatmap\",[\"require\",\"./base\",\"../layer/heatmap\",\"../config\",\"../util/ecData\",\"zrender/tool/util\",\"zrender/tool/color\",\"zrender/shape/Image\",\"../chart\"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e(\"./base\"),n=e(\"../layer/heatmap\"),a=e(\"../config\"),o=(e(\"../util/ecData\"),e(\"zrender/tool/util\")),r=(e(\"zrender/tool/color\"),e(\"zrender/shape/Image\"));return a.heatmap={zlevel:0,z:2,clickable:!0},t.prototype={type:a.CHART_TYPE_HEATMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=e.series),this._init()},_init:function(){var e=this.series;this.backupShapeList();for(var t=e.length,i=0;t>i;++i)if(e[i].type===a.CHART_TYPE_HEATMAP){e[i]=this.reformOption(e[i]);var o=new n(e[i]),s=o.getCanvas(e[i].data,this.zr.getWidth(),this.zr.getHeight()),l=new r({position:[0,0],scale:[1,1],hoverable:this.option.hoverable,style:{x:0,y:0,image:s,width:s.width,height:s.height}});this.shapeList.push(l)}this.addShapeList()}},o.inherits(t,i),e(\"../chart\").define(\"heatmap\",t),t});var n=t(\"zrender\");n.tool={color:t(\"zrender/tool/color\"),math:t(\"zrender/tool/math\"),util:t(\"zrender/tool/util\"),vector:t(\"zrender/tool/vector\"),area:t(\"zrender/tool/area\"),event:t(\"zrender/tool/event\")},n.animation={Animation:t(\"zrender/animation/Animation\"),Cip:t(\"zrender/animation/Clip\"),easing:t(\"zrender/animation/easing\")};var a=t(\"echarts\");a.config=t(\"echarts/config\"),a.util={mapData:{params:t(\"echarts/util/mapData/params\")}},t(\"echarts/chart/line\"),t(\"echarts/chart/bar\"),t(\"echarts/chart/scatter\"),t(\"echarts/chart/k\"),t(\"echarts/chart/pie\"),t(\"echarts/chart/radar\"),t(\"echarts/chart/chord\"),t(\"echarts/chart/force\"),t(\"echarts/chart/map\"),t(\"echarts/chart/gauge\"),t(\"echarts/chart/funnel\"),t(\"echarts/chart/eventRiver\"),t(\"echarts/chart/venn\"),t(\"echarts/chart/treemap\"),t(\"echarts/chart/tree\"),t(\"echarts/chart/wordCloud\"),t(\"echarts/chart/heatmap\"),e.echarts=a,e.zrender=n}(window);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/fancybox/jquery.fancybox.css",
    "content": "/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */\n.fancybox-wrap,\n.fancybox-skin,\n.fancybox-outer,\n.fancybox-inner,\n.fancybox-image,\n.fancybox-wrap iframe,\n.fancybox-wrap object,\n.fancybox-nav,\n.fancybox-nav span,\n.fancybox-tmp\n{\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0;\n\toutline: none;\n\tvertical-align: top;\n}\n\n.fancybox-wrap {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tz-index: 8020;\n}\n\n.fancybox-skin {\n\tposition: relative;\n\tbackground: #f9f9f9;\n\tcolor: #444;\n\ttext-shadow: none;\n\t-webkit-border-radius: 4px;\n\t   -moz-border-radius: 4px;\n\t        border-radius: 4px;\n}\n\n.fancybox-opened {\n\tz-index: 8030;\n}\n\n.fancybox-opened .fancybox-skin {\n\t-webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);\n\t   -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);\n\t        box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);\n}\n\n.fancybox-outer, .fancybox-inner {\n\tposition: relative;\n}\n\n.fancybox-inner {\n\toverflow: hidden;\n}\n\n.fancybox-type-iframe .fancybox-inner {\n\t-webkit-overflow-scrolling: touch;\n}\n\n.fancybox-error {\n\tcolor: #444;\n\tfont: 14px/20px \"Helvetica Neue\",Helvetica,Arial,sans-serif;\n\tmargin: 0;\n\tpadding: 15px;\n\twhite-space: nowrap;\n}\n\n.fancybox-image, .fancybox-iframe {\n\tdisplay: block;\n\twidth: 100%;\n\theight: 100%;\n}\n\n.fancybox-image {\n\tmax-width: 100%;\n\tmax-height: 100%;\n}\n\n#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {\n\tbackground-image: url('fancybox_sprite.png');\n}\n\n#fancybox-loading {\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tmargin-top: -22px;\n\tmargin-left: -22px;\n\tbackground-position: 0 -108px;\n\topacity: 0.8;\n\tcursor: pointer;\n\tz-index: 8060;\n}\n\n#fancybox-loading div {\n\twidth: 44px;\n\theight: 44px;\n\tbackground: url('fancybox_loading.gif') center center no-repeat;\n}\n\n.fancybox-close {\n\tposition: absolute;\n\ttop: -18px;\n\tright: -18px;\n\twidth: 36px;\n\theight: 36px;\n\tcursor: pointer;\n\tz-index: 8040;\n}\n\n.fancybox-nav {\n\tposition: absolute;\n\ttop: 0;\n\twidth: 40%;\n\theight: 100%;\n\tcursor: pointer;\n\ttext-decoration: none;\n\tbackground: transparent url('blank.gif'); /* helps IE */\n\t-webkit-tap-highlight-color: rgba(0,0,0,0);\n\tz-index: 8040;\n}\n\n.fancybox-prev {\n\tleft: 0;\n}\n\n.fancybox-next {\n\tright: 0;\n}\n\n.fancybox-nav span {\n\tposition: absolute;\n\ttop: 50%;\n\twidth: 36px;\n\theight: 34px;\n\tmargin-top: -18px;\n\tcursor: pointer;\n\tz-index: 8040;\n\tvisibility: hidden;\n}\n\n.fancybox-prev span {\n\tleft: 10px;\n\tbackground-position: 0 -36px;\n}\n\n.fancybox-next span {\n\tright: 10px;\n\tbackground-position: 0 -72px;\n}\n\n.fancybox-nav:hover span {\n\tvisibility: visible;\n}\n\n.fancybox-tmp {\n\tposition: absolute;\n\ttop: -99999px;\n\tleft: -99999px;\n\tvisibility: hidden;\n\tmax-width: 99999px;\n\tmax-height: 99999px;\n\toverflow: visible !important;\n}\n\n/* Overlay helper */\n\n.fancybox-lock {\n    overflow: hidden !important;\n    width: auto;\n}\n\n.fancybox-lock body {\n    overflow: hidden !important;\n}\n\n.fancybox-lock-test {\n    overflow-y: hidden !important;\n}\n\n.fancybox-overlay {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\toverflow: hidden;\n\tdisplay: none;\n\tz-index: 8010;\n\tbackground: url('fancybox_overlay.png');\n}\n\n.fancybox-overlay-fixed {\n\tposition: fixed;\n\tbottom: 0;\n\tright: 0;\n}\n\n.fancybox-lock .fancybox-overlay {\n\toverflow: auto;\n\toverflow-y: scroll;\n}\n\n/* Title helper */\n\n.fancybox-title {\n\tvisibility: hidden;\n\tfont: normal 13px/20px \"Helvetica Neue\",Helvetica,Arial,sans-serif;\n\tposition: relative;\n\ttext-shadow: none;\n\tz-index: 8050;\n}\n\n.fancybox-opened .fancybox-title {\n\tvisibility: visible;\n}\n\n.fancybox-title-float-wrap {\n\tposition: absolute;\n\tbottom: 0;\n\tright: 50%;\n\tmargin-bottom: -35px;\n\tz-index: 8050;\n\ttext-align: center;\n}\n\n.fancybox-title-float-wrap .child {\n\tdisplay: inline-block;\n\tmargin-right: -100%;\n\tpadding: 2px 20px;\n\tbackground: transparent; /* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgba(0, 0, 0, 0.8);\n\t-webkit-border-radius: 15px;\n\t   -moz-border-radius: 15px;\n\t        border-radius: 15px;\n\ttext-shadow: 0 1px 2px #222;\n\tcolor: #FFF;\n\tfont-weight: bold;\n\tline-height: 24px;\n\twhite-space: nowrap;\n}\n\n.fancybox-title-outside-wrap {\n\tposition: relative;\n\tmargin-top: 10px;\n\tcolor: #fff;\n}\n\n.fancybox-title-inside-wrap {\n\tpadding-top: 10px;\n}\n\n.fancybox-title-over-wrap {\n\tposition: absolute;\n\tbottom: 0;\n\tleft: 0;\n\tcolor: #fff;\n\tpadding: 10px;\n\tbackground: #000;\n\tbackground: rgba(0, 0, 0, .8);\n}\n\n/*Retina graphics!*/\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n\t   only screen and (min--moz-device-pixel-ratio: 1.5),\n\t   only screen and (min-device-pixel-ratio: 1.5){\n\n\t#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {\n\t\tbackground-image: url('fancybox_sprite@2x.png');\n\t\tbackground-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/\n\t}\n\n\t#fancybox-loading div {\n\t\tbackground-image: url('fancybox_loading@2x.gif');\n\t\tbackground-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/fancybox/jquery.fancybox.js",
    "content": "/*!\n * fancyBox - jQuery Plugin\n * version: 2.1.5 (Fri, 14 Jun 2013)\n * @requires jQuery v1.6 or later\n *\n * Examples at http://fancyapps.com/fancybox/\n * License: www.fancyapps.com/fancybox/#license\n *\n * Copyright 2012 Janis Skarnelis - janis@fancyapps.com\n *\n */\n\n(function (window, document, $, undefined) {\n\t\"use strict\";\n\n\tvar H = $(\"html\"),\n\t\tW = $(window),\n\t\tD = $(document),\n\t\tF = $.fancybox = function () {\n\t\t\tF.open.apply( this, arguments );\n\t\t},\n\t\tIE =  navigator.userAgent.match(/msie/i),\n\t\tdidUpdate\t= null,\n\t\tisTouch\t\t= document.createTouch !== undefined,\n\n\t\tisQuery\t= function(obj) {\n\t\t\treturn obj && obj.hasOwnProperty && obj instanceof $;\n\t\t},\n\t\tisString = function(str) {\n\t\t\treturn str && $.type(str) === \"string\";\n\t\t},\n\t\tisPercentage = function(str) {\n\t\t\treturn isString(str) && str.indexOf('%') > 0;\n\t\t},\n\t\tisScrollable = function(el) {\n\t\t\treturn (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));\n\t\t},\n\t\tgetScalar = function(orig, dim) {\n\t\t\tvar value = parseInt(orig, 10) || 0;\n\n\t\t\tif (dim && isPercentage(orig)) {\n\t\t\t\tvalue = F.getViewport()[ dim ] / 100 * value;\n\t\t\t}\n\n\t\t\treturn Math.ceil(value);\n\t\t},\n\t\tgetValue = function(value, dim) {\n\t\t\treturn getScalar(value, dim) + 'px';\n\t\t};\n\n\t$.extend(F, {\n\t\t// The current version of fancyBox\n\t\tversion: '2.1.5',\n\n\t\tdefaults: {\n\t\t\tpadding : 15,\n\t\t\tmargin  : 20,\n\n\t\t\twidth     : 800,\n\t\t\theight    : 600,\n\t\t\tminWidth  : 100,\n\t\t\tminHeight : 100,\n\t\t\tmaxWidth  : 9999,\n\t\t\tmaxHeight : 9999,\n\t\t\tpixelRatio: 1, // Set to 2 for retina display support\n\n\t\t\tautoSize   : true,\n\t\t\tautoHeight : false,\n\t\t\tautoWidth  : false,\n\n\t\t\tautoResize  : true,\n\t\t\tautoCenter  : !isTouch,\n\t\t\tfitToView   : true,\n\t\t\taspectRatio : false,\n\t\t\ttopRatio    : 0.5,\n\t\t\tleftRatio   : 0.5,\n\n\t\t\tscrolling : 'auto', // 'auto', 'yes' or 'no'\n\t\t\twrapCSS   : '',\n\n\t\t\tarrows     : true,\n\t\t\tcloseBtn   : true,\n\t\t\tcloseClick : false,\n\t\t\tnextClick  : false,\n\t\t\tmouseWheel : true,\n\t\t\tautoPlay   : false,\n\t\t\tplaySpeed  : 3000,\n\t\t\tpreload    : 3,\n\t\t\tmodal      : false,\n\t\t\tloop       : true,\n\n\t\t\tajax  : {\n\t\t\t\tdataType : 'html',\n\t\t\t\theaders  : { 'X-fancyBox': true }\n\t\t\t},\n\t\t\tiframe : {\n\t\t\t\tscrolling : 'auto',\n\t\t\t\tpreload   : true\n\t\t\t},\n\t\t\tswf : {\n\t\t\t\twmode: 'transparent',\n\t\t\t\tallowfullscreen   : 'true',\n\t\t\t\tallowscriptaccess : 'always'\n\t\t\t},\n\n\t\t\tkeys  : {\n\t\t\t\tnext : {\n\t\t\t\t\t13 : 'left', // enter\n\t\t\t\t\t34 : 'up',   // page down\n\t\t\t\t\t39 : 'left', // right arrow\n\t\t\t\t\t40 : 'up'    // down arrow\n\t\t\t\t},\n\t\t\t\tprev : {\n\t\t\t\t\t8  : 'right',  // backspace\n\t\t\t\t\t33 : 'down',   // page up\n\t\t\t\t\t37 : 'right',  // left arrow\n\t\t\t\t\t38 : 'down'    // up arrow\n\t\t\t\t},\n\t\t\t\tclose  : [27], // escape key\n\t\t\t\tplay   : [32], // space - start/stop slideshow\n\t\t\t\ttoggle : [70]  // letter \"f\" - toggle fullscreen\n\t\t\t},\n\n\t\t\tdirection : {\n\t\t\t\tnext : 'left',\n\t\t\t\tprev : 'right'\n\t\t\t},\n\n\t\t\tscrollOutside  : true,\n\n\t\t\t// Override some properties\n\t\t\tindex   : 0,\n\t\t\ttype    : null,\n\t\t\thref    : null,\n\t\t\tcontent : null,\n\t\t\ttitle   : null,\n\n\t\t\t// HTML templates\n\t\t\ttpl: {\n\t\t\t\twrap     : '<div class=\"fancybox-wrap\" tabIndex=\"-1\"><div class=\"fancybox-skin\"><div class=\"fancybox-outer\"><div class=\"fancybox-inner\"></div></div></div></div>',\n\t\t\t\timage    : '<img class=\"fancybox-image\" src=\"{href}\" alt=\"\" />',\n\t\t\t\tiframe   : '<iframe id=\"fancybox-frame{rnd}\" name=\"fancybox-frame{rnd}\" class=\"fancybox-iframe\" frameborder=\"0\" vspace=\"0\" hspace=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency=\"true\"' : '') + '></iframe>',\n\t\t\t\terror    : '<p class=\"fancybox-error\">The requested content cannot be loaded.<br/>Please try again later.</p>',\n\t\t\t\tcloseBtn : '<a title=\"Close\" class=\"fancybox-item fancybox-close\" href=\"javascript:;\"></a>',\n\t\t\t\tnext     : '<a title=\"Next\" class=\"fancybox-nav fancybox-next\" href=\"javascript:;\"><span></span></a>',\n\t\t\t\tprev     : '<a title=\"Previous\" class=\"fancybox-nav fancybox-prev\" href=\"javascript:;\"><span></span></a>'\n\t\t\t},\n\n\t\t\t// Properties for each animation type\n\t\t\t// Opening fancyBox\n\t\t\topenEffect  : 'fade', // 'elastic', 'fade' or 'none'\n\t\t\topenSpeed   : 250,\n\t\t\topenEasing  : 'swing',\n\t\t\topenOpacity : true,\n\t\t\topenMethod  : 'zoomIn',\n\n\t\t\t// Closing fancyBox\n\t\t\tcloseEffect  : 'fade', // 'elastic', 'fade' or 'none'\n\t\t\tcloseSpeed   : 250,\n\t\t\tcloseEasing  : 'swing',\n\t\t\tcloseOpacity : true,\n\t\t\tcloseMethod  : 'zoomOut',\n\n\t\t\t// Changing next gallery item\n\t\t\tnextEffect : 'elastic', // 'elastic', 'fade' or 'none'\n\t\t\tnextSpeed  : 250,\n\t\t\tnextEasing : 'swing',\n\t\t\tnextMethod : 'changeIn',\n\n\t\t\t// Changing previous gallery item\n\t\t\tprevEffect : 'elastic', // 'elastic', 'fade' or 'none'\n\t\t\tprevSpeed  : 250,\n\t\t\tprevEasing : 'swing',\n\t\t\tprevMethod : 'changeOut',\n\n\t\t\t// Enable default helpers\n\t\t\thelpers : {\n\t\t\t\toverlay : true,\n\t\t\t\ttitle   : true\n\t\t\t},\n\n\t\t\t// Callbacks\n\t\t\tonCancel     : $.noop, // If canceling\n\t\t\tbeforeLoad   : $.noop, // Before loading\n\t\t\tafterLoad    : $.noop, // After loading\n\t\t\tbeforeShow   : $.noop, // Before changing in current item\n\t\t\tafterShow    : $.noop, // After opening\n\t\t\tbeforeChange : $.noop, // Before changing gallery item\n\t\t\tbeforeClose  : $.noop, // Before closing\n\t\t\tafterClose   : $.noop  // After closing\n\t\t},\n\n\t\t//Current state\n\t\tgroup    : {}, // Selected group\n\t\topts     : {}, // Group options\n\t\tprevious : null,  // Previous element\n\t\tcoming   : null,  // Element being loaded\n\t\tcurrent  : null,  // Currently loaded element\n\t\tisActive : false, // Is activated\n\t\tisOpen   : false, // Is currently open\n\t\tisOpened : false, // Have been fully opened at least once\n\n\t\twrap  : null,\n\t\tskin  : null,\n\t\touter : null,\n\t\tinner : null,\n\n\t\tplayer : {\n\t\t\ttimer    : null,\n\t\t\tisActive : false\n\t\t},\n\n\t\t// Loaders\n\t\tajaxLoad   : null,\n\t\timgPreload : null,\n\n\t\t// Some collections\n\t\ttransitions : {},\n\t\thelpers     : {},\n\n\t\t/*\n\t\t *\tStatic methods\n\t\t */\n\n\t\topen: function (group, opts) {\n\t\t\tif (!group) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!$.isPlainObject(opts)) {\n\t\t\t\topts = {};\n\t\t\t}\n\n\t\t\t// Close if already active\n\t\t\tif (false === F.close(true)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Normalize group\n\t\t\tif (!$.isArray(group)) {\n\t\t\t\tgroup = isQuery(group) ? $(group).get() : [group];\n\t\t\t}\n\n\t\t\t// Recheck if the type of each element is `object` and set content type (image, ajax, etc)\n\t\t\t$.each(group, function(i, element) {\n\t\t\t\tvar obj = {},\n\t\t\t\t\thref,\n\t\t\t\t\ttitle,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype,\n\t\t\t\t\trez,\n\t\t\t\t\threfParts,\n\t\t\t\t\tselector;\n\n\t\t\t\tif ($.type(element) === \"object\") {\n\t\t\t\t\t// Check if is DOM element\n\t\t\t\t\tif (element.nodeType) {\n\t\t\t\t\t\telement = $(element);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isQuery(element)) {\n\t\t\t\t\t\tobj = {\n\t\t\t\t\t\t\thref    : element.data('fancybox-href') || element.attr('href'),\n\t\t\t\t\t\t\ttitle   : element.data('fancybox-title') || element.attr('title'),\n\t\t\t\t\t\t\tisDom   : true,\n\t\t\t\t\t\t\telement : element\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tif ($.metadata) {\n\t\t\t\t\t\t\t$.extend(true, obj, element.metadata());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobj = element;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\thref  = opts.href  || obj.href || (isString(element) ? element : null);\n\t\t\t\ttitle = opts.title !== undefined ? opts.title : obj.title || '';\n\n\t\t\t\tcontent = opts.content || obj.content;\n\t\t\t\ttype    = content ? 'html' : (opts.type  || obj.type);\n\n\t\t\t\tif (!type && obj.isDom) {\n\t\t\t\t\ttype = element.data('fancybox-type');\n\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\trez  = element.prop('class').match(/fancybox\\.(\\w+)/);\n\t\t\t\t\t\ttype = rez ? rez[1] : null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isString(href)) {\n\t\t\t\t\t// Try to guess the content type\n\t\t\t\t\tif (!type) {\n\t\t\t\t\t\tif (F.isImage(href)) {\n\t\t\t\t\t\t\ttype = 'image';\n\n\t\t\t\t\t\t} else if (F.isSWF(href)) {\n\t\t\t\t\t\t\ttype = 'swf';\n\n\t\t\t\t\t\t} else if (href.charAt(0) === '#') {\n\t\t\t\t\t\t\ttype = 'inline';\n\n\t\t\t\t\t\t} else if (isString(element)) {\n\t\t\t\t\t\t\ttype    = 'html';\n\t\t\t\t\t\t\tcontent = element;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Split url into two pieces with source url and content selector, e.g,\n\t\t\t\t\t// \"/mypage.html #my_id\" will load \"/mypage.html\" and display element having id \"my_id\"\n\t\t\t\t\tif (type === 'ajax') {\n\t\t\t\t\t\threfParts = href.split(/\\s+/, 2);\n\t\t\t\t\t\thref      = hrefParts.shift();\n\t\t\t\t\t\tselector  = hrefParts.shift();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!content) {\n\t\t\t\t\tif (type === 'inline') {\n\t\t\t\t\t\tif (href) {\n\t\t\t\t\t\t\tcontent = $( isString(href) ? href.replace(/.*(?=#[^\\s]+$)/, '') : href ); //strip for ie7\n\n\t\t\t\t\t\t} else if (obj.isDom) {\n\t\t\t\t\t\t\tcontent = element;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if (type === 'html') {\n\t\t\t\t\t\tcontent = href;\n\n\t\t\t\t\t} else if (!type && !href && obj.isDom) {\n\t\t\t\t\t\ttype    = 'inline';\n\t\t\t\t\t\tcontent = element;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$.extend(obj, {\n\t\t\t\t\thref     : href,\n\t\t\t\t\ttype     : type,\n\t\t\t\t\tcontent  : content,\n\t\t\t\t\ttitle    : title,\n\t\t\t\t\tselector : selector\n\t\t\t\t});\n\n\t\t\t\tgroup[ i ] = obj;\n\t\t\t});\n\n\t\t\t// Extend the defaults\n\t\t\tF.opts = $.extend(true, {}, F.defaults, opts);\n\n\t\t\t// All options are merged recursive except keys\n\t\t\tif (opts.keys !== undefined) {\n\t\t\t\tF.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;\n\t\t\t}\n\n\t\t\tF.group = group;\n\n\t\t\treturn F._start(F.opts.index);\n\t\t},\n\n\t\t// Cancel image loading or abort ajax request\n\t\tcancel: function () {\n\t\t\tvar coming = F.coming;\n\n\t\t\tif (!coming || false === F.trigger('onCancel')) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tF.hideLoading();\n\n\t\t\tif (F.ajaxLoad) {\n\t\t\t\tF.ajaxLoad.abort();\n\t\t\t}\n\n\t\t\tF.ajaxLoad = null;\n\n\t\t\tif (F.imgPreload) {\n\t\t\t\tF.imgPreload.onload = F.imgPreload.onerror = null;\n\t\t\t}\n\n\t\t\tif (coming.wrap) {\n\t\t\t\tcoming.wrap.stop(true, true).trigger('onReset').remove();\n\t\t\t}\n\n\t\t\tF.coming = null;\n\n\t\t\t// If the first item has been canceled, then clear everything\n\t\t\tif (!F.current) {\n\t\t\t\tF._afterZoomOut( coming );\n\t\t\t}\n\t\t},\n\n\t\t// Start closing animation if is open; remove immediately if opening/closing\n\t\tclose: function (event) {\n\t\t\tF.cancel();\n\n\t\t\tif (false === F.trigger('beforeClose')) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tF.unbindEvents();\n\n\t\t\tif (!F.isActive) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!F.isOpen || event === true) {\n\t\t\t\t$('.fancybox-wrap').stop(true).trigger('onReset').remove();\n\n\t\t\t\tF._afterZoomOut();\n\n\t\t\t} else {\n\t\t\t\tF.isOpen = F.isOpened = false;\n\t\t\t\tF.isClosing = true;\n\n\t\t\t\t$('.fancybox-item, .fancybox-nav').remove();\n\n\t\t\t\tF.wrap.stop(true, true).removeClass('fancybox-opened');\n\n\t\t\t\tF.transitions[ F.current.closeMethod ]();\n\t\t\t}\n\t\t},\n\n\t\t// Manage slideshow:\n\t\t//   $.fancybox.play(); - toggle slideshow\n\t\t//   $.fancybox.play( true ); - start\n\t\t//   $.fancybox.play( false ); - stop\n\t\tplay: function ( action ) {\n\t\t\tvar clear = function () {\n\t\t\t\t\tclearTimeout(F.player.timer);\n\t\t\t\t},\n\t\t\t\tset = function () {\n\t\t\t\t\tclear();\n\n\t\t\t\t\tif (F.current && F.player.isActive) {\n\t\t\t\t\t\tF.player.timer = setTimeout(F.next, F.current.playSpeed);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstop = function () {\n\t\t\t\t\tclear();\n\n\t\t\t\t\tD.unbind('.player');\n\n\t\t\t\t\tF.player.isActive = false;\n\n\t\t\t\t\tF.trigger('onPlayEnd');\n\t\t\t\t},\n\t\t\t\tstart = function () {\n\t\t\t\t\tif (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {\n\t\t\t\t\t\tF.player.isActive = true;\n\n\t\t\t\t\t\tD.bind({\n\t\t\t\t\t\t\t'onCancel.player beforeClose.player' : stop,\n\t\t\t\t\t\t\t'onUpdate.player'   : set,\n\t\t\t\t\t\t\t'beforeLoad.player' : clear\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tset();\n\n\t\t\t\t\t\tF.trigger('onPlayStart');\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\tif (action === true || (!F.player.isActive && action !== false)) {\n\t\t\t\tstart();\n\t\t\t} else {\n\t\t\t\tstop();\n\t\t\t}\n\t\t},\n\n\t\t// Navigate to next gallery item\n\t\tnext: function ( direction ) {\n\t\t\tvar current = F.current;\n\n\t\t\tif (current) {\n\t\t\t\tif (!isString(direction)) {\n\t\t\t\t\tdirection = current.direction.next;\n\t\t\t\t}\n\n\t\t\t\tF.jumpto(current.index + 1, direction, 'next');\n\t\t\t}\n\t\t},\n\n\t\t// Navigate to previous gallery item\n\t\tprev: function ( direction ) {\n\t\t\tvar current = F.current;\n\n\t\t\tif (current) {\n\t\t\t\tif (!isString(direction)) {\n\t\t\t\t\tdirection = current.direction.prev;\n\t\t\t\t}\n\n\t\t\t\tF.jumpto(current.index - 1, direction, 'prev');\n\t\t\t}\n\t\t},\n\n\t\t// Navigate to gallery item by index\n\t\tjumpto: function ( index, direction, router ) {\n\t\t\tvar current = F.current;\n\n\t\t\tif (!current) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tindex = getScalar(index);\n\n\t\t\tF.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];\n\t\t\tF.router    = router || 'jumpto';\n\n\t\t\tif (current.loop) {\n\t\t\t\tif (index < 0) {\n\t\t\t\t\tindex = current.group.length + (index % current.group.length);\n\t\t\t\t}\n\n\t\t\t\tindex = index % current.group.length;\n\t\t\t}\n\n\t\t\tif (current.group[ index ] !== undefined) {\n\t\t\t\tF.cancel();\n\n\t\t\t\tF._start(index);\n\t\t\t}\n\t\t},\n\n\t\t// Center inside viewport and toggle position type to fixed or absolute if needed\n\t\treposition: function (e, onlyAbsolute) {\n\t\t\tvar current = F.current,\n\t\t\t\twrap    = current ? current.wrap : null,\n\t\t\t\tpos;\n\n\t\t\tif (wrap) {\n\t\t\t\tpos = F._getPosition(onlyAbsolute);\n\n\t\t\t\tif (e && e.type === 'scroll') {\n\t\t\t\t\tdelete pos.position;\n\n\t\t\t\t\twrap.stop(true, true).animate(pos, 200);\n\n\t\t\t\t} else {\n\t\t\t\t\twrap.css(pos);\n\n\t\t\t\t\tcurrent.pos = $.extend({}, current.dim, pos);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tupdate: function (e) {\n\t\t\tvar type = (e && e.type),\n\t\t\t\tanyway = !type || type === 'orientationchange';\n\n\t\t\tif (anyway) {\n\t\t\t\tclearTimeout(didUpdate);\n\n\t\t\t\tdidUpdate = null;\n\t\t\t}\n\n\t\t\tif (!F.isOpen || didUpdate) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdidUpdate = setTimeout(function() {\n\t\t\t\tvar current = F.current;\n\n\t\t\t\tif (!current || F.isClosing) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tF.wrap.removeClass('fancybox-tmp');\n\n\t\t\t\tif (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {\n\t\t\t\t\tF._setDimension();\n\t\t\t\t}\n\n\t\t\t\tif (!(type === 'scroll' && current.canShrink)) {\n\t\t\t\t\tF.reposition(e);\n\t\t\t\t}\n\n\t\t\t\tF.trigger('onUpdate');\n\n\t\t\t\tdidUpdate = null;\n\n\t\t\t}, (anyway && !isTouch ? 0 : 300));\n\t\t},\n\n\t\t// Shrink content to fit inside viewport or restore if resized\n\t\ttoggle: function ( action ) {\n\t\t\tif (F.isOpen) {\n\t\t\t\tF.current.fitToView = $.type(action) === \"boolean\" ? action : !F.current.fitToView;\n\n\t\t\t\t// Help browser to restore document dimensions\n\t\t\t\tif (isTouch) {\n\t\t\t\t\tF.wrap.removeAttr('style').addClass('fancybox-tmp');\n\n\t\t\t\t\tF.trigger('onUpdate');\n\t\t\t\t}\n\n\t\t\t\tF.update();\n\t\t\t}\n\t\t},\n\n\t\thideLoading: function () {\n\t\t\tD.unbind('.loading');\n\n\t\t\t$('#fancybox-loading').remove();\n\t\t},\n\n\t\tshowLoading: function () {\n\t\t\tvar el, viewport;\n\n\t\t\tF.hideLoading();\n\n\t\t\tel = $('<div id=\"fancybox-loading\"><div></div></div>').click(F.cancel).appendTo('body');\n\n\t\t\t// If user will press the escape-button, the request will be canceled\n\t\t\tD.bind('keydown.loading', function(e) {\n\t\t\t\tif ((e.which || e.keyCode) === 27) {\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\tF.cancel();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!F.defaults.fixed) {\n\t\t\t\tviewport = F.getViewport();\n\n\t\t\t\tel.css({\n\t\t\t\t\tposition : 'absolute',\n\t\t\t\t\ttop  : (viewport.h * 0.5) + viewport.y,\n\t\t\t\t\tleft : (viewport.w * 0.5) + viewport.x\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tgetViewport: function () {\n\t\t\tvar locked = (F.current && F.current.locked) || false,\n\t\t\t\trez    = {\n\t\t\t\t\tx: W.scrollLeft(),\n\t\t\t\t\ty: W.scrollTop()\n\t\t\t\t};\n\n\t\t\tif (locked) {\n\t\t\t\trez.w = locked[0].clientWidth;\n\t\t\t\trez.h = locked[0].clientHeight;\n\n\t\t\t} else {\n\t\t\t\t// See http://bugs.jquery.com/ticket/6724\n\t\t\t\trez.w = isTouch && window.innerWidth  ? window.innerWidth  : W.width();\n\t\t\t\trez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();\n\t\t\t}\n\n\t\t\treturn rez;\n\t\t},\n\n\t\t// Unbind the keyboard / clicking actions\n\t\tunbindEvents: function () {\n\t\t\tif (F.wrap && isQuery(F.wrap)) {\n\t\t\t\tF.wrap.unbind('.fb');\n\t\t\t}\n\n\t\t\tD.unbind('.fb');\n\t\t\tW.unbind('.fb');\n\t\t},\n\n\t\tbindEvents: function () {\n\t\t\tvar current = F.current,\n\t\t\t\tkeys;\n\n\t\t\tif (!current) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Changing document height on iOS devices triggers a 'resize' event,\n\t\t\t// that can change document height... repeating infinitely\n\t\t\tW.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);\n\n\t\t\tkeys = current.keys;\n\n\t\t\tif (keys) {\n\t\t\t\tD.bind('keydown.fb', function (e) {\n\t\t\t\t\tvar code   = e.which || e.keyCode,\n\t\t\t\t\t\ttarget = e.target || e.srcElement;\n\n\t\t\t\t\t// Skip esc key if loading, because showLoading will cancel preloading\n\t\t\t\t\tif (code === 27 && F.coming) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ignore key combinations and key events within form elements\n\t\t\t\t\tif (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {\n\t\t\t\t\t\t$.each(keys, function(i, val) {\n\t\t\t\t\t\t\tif (current.group.length > 1 && val[ code ] !== undefined) {\n\t\t\t\t\t\t\t\tF[ i ]( val[ code ] );\n\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ($.inArray(code, val) > -1) {\n\t\t\t\t\t\t\t\tF[ i ] ();\n\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ($.fn.mousewheel && current.mouseWheel) {\n\t\t\t\tF.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {\n\t\t\t\t\tvar target = e.target || null,\n\t\t\t\t\t\tparent = $(target),\n\t\t\t\t\t\tcanScroll = false;\n\n\t\t\t\t\twhile (parent.length) {\n\t\t\t\t\t\tif (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcanScroll = isScrollable( parent[0] );\n\t\t\t\t\t\tparent    = $(parent).parent();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (delta !== 0 && !canScroll) {\n\t\t\t\t\t\tif (F.group.length > 1 && !current.canShrink) {\n\t\t\t\t\t\t\tif (deltaY > 0 || deltaX > 0) {\n\t\t\t\t\t\t\t\tF.prev( deltaY > 0 ? 'down' : 'left' );\n\n\t\t\t\t\t\t\t} else if (deltaY < 0 || deltaX < 0) {\n\t\t\t\t\t\t\t\tF.next( deltaY < 0 ? 'up' : 'right' );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\ttrigger: function (event, o) {\n\t\t\tvar ret, obj = o || F.coming || F.current;\n\n\t\t\tif (!obj) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ($.isFunction( obj[event] )) {\n\t\t\t\tret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));\n\t\t\t}\n\n\t\t\tif (ret === false) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (obj.helpers) {\n\t\t\t\t$.each(obj.helpers, function (helper, opts) {\n\t\t\t\t\tif (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {\n\t\t\t\t\t\tF.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tD.trigger(event);\n\t\t},\n\n\t\tisImage: function (str) {\n\t\t\treturn isString(str) && str.match(/(^data:image\\/.*,)|(\\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\\?|#).*)?$)/i);\n\t\t},\n\n\t\tisSWF: function (str) {\n\t\t\treturn isString(str) && str.match(/\\.(swf)((\\?|#).*)?$/i);\n\t\t},\n\n\t\t_start: function (index) {\n\t\t\tvar coming = {},\n\t\t\t\tobj,\n\t\t\t\thref,\n\t\t\t\ttype,\n\t\t\t\tmargin,\n\t\t\t\tpadding;\n\n\t\t\tindex = getScalar( index );\n\t\t\tobj   = F.group[ index ] || null;\n\n\t\t\tif (!obj) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcoming = $.extend(true, {}, F.opts, obj);\n\n\t\t\t// Convert margin and padding properties to array - top, right, bottom, left\n\t\t\tmargin  = coming.margin;\n\t\t\tpadding = coming.padding;\n\n\t\t\tif ($.type(margin) === 'number') {\n\t\t\t\tcoming.margin = [margin, margin, margin, margin];\n\t\t\t}\n\n\t\t\tif ($.type(padding) === 'number') {\n\t\t\t\tcoming.padding = [padding, padding, padding, padding];\n\t\t\t}\n\n\t\t\t// 'modal' propery is just a shortcut\n\t\t\tif (coming.modal) {\n\t\t\t\t$.extend(true, coming, {\n\t\t\t\t\tcloseBtn   : false,\n\t\t\t\t\tcloseClick : false,\n\t\t\t\t\tnextClick  : false,\n\t\t\t\t\tarrows     : false,\n\t\t\t\t\tmouseWheel : false,\n\t\t\t\t\tkeys       : null,\n\t\t\t\t\thelpers: {\n\t\t\t\t\t\toverlay : {\n\t\t\t\t\t\t\tcloseClick : false\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// 'autoSize' property is a shortcut, too\n\t\t\tif (coming.autoSize) {\n\t\t\t\tcoming.autoWidth = coming.autoHeight = true;\n\t\t\t}\n\n\t\t\tif (coming.width === 'auto') {\n\t\t\t\tcoming.autoWidth = true;\n\t\t\t}\n\n\t\t\tif (coming.height === 'auto') {\n\t\t\t\tcoming.autoHeight = true;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Add reference to the group, so it`s possible to access from callbacks, example:\n\t\t\t * afterLoad : function() {\n\t\t\t *     this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');\n\t\t\t * }\n\t\t\t */\n\n\t\t\tcoming.group  = F.group;\n\t\t\tcoming.index  = index;\n\n\t\t\t// Give a chance for callback or helpers to update coming item (type, title, etc)\n\t\t\tF.coming = coming;\n\n\t\t\tif (false === F.trigger('beforeLoad')) {\n\t\t\t\tF.coming = null;\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttype = coming.type;\n\t\t\thref = coming.href;\n\n\t\t\tif (!type) {\n\t\t\t\tF.coming = null;\n\n\t\t\t\t//If we can not determine content type then drop silently or display next/prev item if looping through gallery\n\t\t\t\tif (F.current && F.router && F.router !== 'jumpto') {\n\t\t\t\t\tF.current.index = index;\n\n\t\t\t\t\treturn F[ F.router ]( F.direction );\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tF.isActive = true;\n\n\t\t\tif (type === 'image' || type === 'swf') {\n\t\t\t\tcoming.autoHeight = coming.autoWidth = false;\n\t\t\t\tcoming.scrolling  = 'visible';\n\t\t\t}\n\n\t\t\tif (type === 'image') {\n\t\t\t\tcoming.aspectRatio = true;\n\t\t\t}\n\n\t\t\tif (type === 'iframe' && isTouch) {\n\t\t\t\tcoming.scrolling = 'scroll';\n\t\t\t}\n\n\t\t\t// Build the neccessary markup\n\t\t\tcoming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );\n\n\t\t\t$.extend(coming, {\n\t\t\t\tskin  : $('.fancybox-skin',  coming.wrap),\n\t\t\t\touter : $('.fancybox-outer', coming.wrap),\n\t\t\t\tinner : $('.fancybox-inner', coming.wrap)\n\t\t\t});\n\n\t\t\t$.each([\"Top\", \"Right\", \"Bottom\", \"Left\"], function(i, v) {\n\t\t\t\tcoming.skin.css('padding' + v, getValue(coming.padding[ i ]));\n\t\t\t});\n\n\t\t\tF.trigger('onReady');\n\n\t\t\t// Check before try to load; 'inline' and 'html' types need content, others - href\n\t\t\tif (type === 'inline' || type === 'html') {\n\t\t\t\tif (!coming.content || !coming.content.length) {\n\t\t\t\t\treturn F._error( 'content' );\n\t\t\t\t}\n\n\t\t\t} else if (!href) {\n\t\t\t\treturn F._error( 'href' );\n\t\t\t}\n\n\t\t\tif (type === 'image') {\n\t\t\t\tF._loadImage();\n\n\t\t\t} else if (type === 'ajax') {\n\t\t\t\tF._loadAjax();\n\n\t\t\t} else if (type === 'iframe') {\n\t\t\t\tF._loadIframe();\n\n\t\t\t} else {\n\t\t\t\tF._afterLoad();\n\t\t\t}\n\t\t},\n\n\t\t_error: function ( type ) {\n\t\t\t$.extend(F.coming, {\n\t\t\t\ttype       : 'html',\n\t\t\t\tautoWidth  : true,\n\t\t\t\tautoHeight : true,\n\t\t\t\tminWidth   : 0,\n\t\t\t\tminHeight  : 0,\n\t\t\t\tscrolling  : 'no',\n\t\t\t\thasError   : type,\n\t\t\t\tcontent    : F.coming.tpl.error\n\t\t\t});\n\n\t\t\tF._afterLoad();\n\t\t},\n\n\t\t_loadImage: function () {\n\t\t\t// Reset preload image so it is later possible to check \"complete\" property\n\t\t\tvar img = F.imgPreload = new Image();\n\n\t\t\timg.onload = function () {\n\t\t\t\tthis.onload = this.onerror = null;\n\n\t\t\t\tF.coming.width  = this.width / F.opts.pixelRatio;\n\t\t\t\tF.coming.height = this.height / F.opts.pixelRatio;\n\n\t\t\t\tF._afterLoad();\n\t\t\t};\n\n\t\t\timg.onerror = function () {\n\t\t\t\tthis.onload = this.onerror = null;\n\n\t\t\t\tF._error( 'image' );\n\t\t\t};\n\n\t\t\timg.src = F.coming.href;\n\n\t\t\tif (img.complete !== true) {\n\t\t\t\tF.showLoading();\n\t\t\t}\n\t\t},\n\n\t\t_loadAjax: function () {\n\t\t\tvar coming = F.coming;\n\n\t\t\tF.showLoading();\n\n\t\t\tF.ajaxLoad = $.ajax($.extend({}, coming.ajax, {\n\t\t\t\turl: coming.href,\n\t\t\t\terror: function (jqXHR, textStatus) {\n\t\t\t\t\tif (F.coming && textStatus !== 'abort') {\n\t\t\t\t\t\tF._error( 'ajax', jqXHR );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tF.hideLoading();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsuccess: function (data, textStatus) {\n\t\t\t\t\tif (textStatus === 'success') {\n\t\t\t\t\t\tcoming.content = data;\n\n\t\t\t\t\t\tF._afterLoad();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}));\n\t\t},\n\n\t\t_loadIframe: function() {\n\t\t\tvar coming = F.coming,\n\t\t\t\tiframe = $(coming.tpl.iframe.replace(/\\{rnd\\}/g, new Date().getTime()))\n\t\t\t\t\t.attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)\n\t\t\t\t\t.attr('src', coming.href);\n\n\t\t\t// This helps IE\n\t\t\t$(coming.wrap).bind('onReset', function () {\n\t\t\t\ttry {\n\t\t\t\t\t$(this).find('iframe').hide().attr('src', '//about:blank').end().empty();\n\t\t\t\t} catch (e) {}\n\t\t\t});\n\n\t\t\tif (coming.iframe.preload) {\n\t\t\t\tF.showLoading();\n\n\t\t\t\tiframe.one('load', function() {\n\t\t\t\t\t$(this).data('ready', 1);\n\n\t\t\t\t\t// iOS will lose scrolling if we resize\n\t\t\t\t\tif (!isTouch) {\n\t\t\t\t\t\t$(this).bind('load.fb', F.update);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Without this trick:\n\t\t\t\t\t//   - iframe won't scroll on iOS devices\n\t\t\t\t\t//   - IE7 sometimes displays empty iframe\n\t\t\t\t\t$(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();\n\n\t\t\t\t\tF._afterLoad();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tcoming.content = iframe.appendTo( coming.inner );\n\n\t\t\tif (!coming.iframe.preload) {\n\t\t\t\tF._afterLoad();\n\t\t\t}\n\t\t},\n\n\t\t_preloadImages: function() {\n\t\t\tvar group   = F.group,\n\t\t\t\tcurrent = F.current,\n\t\t\t\tlen     = group.length,\n\t\t\t\tcnt     = current.preload ? Math.min(current.preload, len - 1) : 0,\n\t\t\t\titem,\n\t\t\t\ti;\n\n\t\t\tfor (i = 1; i <= cnt; i += 1) {\n\t\t\t\titem = group[ (current.index + i ) % len ];\n\n\t\t\t\tif (item.type === 'image' && item.href) {\n\t\t\t\t\tnew Image().src = item.href;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_afterLoad: function () {\n\t\t\tvar coming   = F.coming,\n\t\t\t\tprevious = F.current,\n\t\t\t\tplaceholder = 'fancybox-placeholder',\n\t\t\t\tcurrent,\n\t\t\t\tcontent,\n\t\t\t\ttype,\n\t\t\t\tscrolling,\n\t\t\t\thref,\n\t\t\t\tembed;\n\n\t\t\tF.hideLoading();\n\n\t\t\tif (!coming || F.isActive === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (false === F.trigger('afterLoad', coming, previous)) {\n\t\t\t\tcoming.wrap.stop(true).trigger('onReset').remove();\n\n\t\t\t\tF.coming = null;\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (previous) {\n\t\t\t\tF.trigger('beforeChange', previous);\n\n\t\t\t\tprevious.wrap.stop(true).removeClass('fancybox-opened')\n\t\t\t\t\t.find('.fancybox-item, .fancybox-nav')\n\t\t\t\t\t.remove();\n\t\t\t}\n\n\t\t\tF.unbindEvents();\n\n\t\t\tcurrent   = coming;\n\t\t\tcontent   = coming.content;\n\t\t\ttype      = coming.type;\n\t\t\tscrolling = coming.scrolling;\n\n\t\t\t$.extend(F, {\n\t\t\t\twrap  : current.wrap,\n\t\t\t\tskin  : current.skin,\n\t\t\t\touter : current.outer,\n\t\t\t\tinner : current.inner,\n\t\t\t\tcurrent  : current,\n\t\t\t\tprevious : previous\n\t\t\t});\n\n\t\t\thref = current.href;\n\n\t\t\tswitch (type) {\n\t\t\t\tcase 'inline':\n\t\t\t\tcase 'ajax':\n\t\t\t\tcase 'html':\n\t\t\t\t\tif (current.selector) {\n\t\t\t\t\t\tcontent = $('<div>').html(content).find(current.selector);\n\n\t\t\t\t\t} else if (isQuery(content)) {\n\t\t\t\t\t\tif (!content.data(placeholder)) {\n\t\t\t\t\t\t\tcontent.data(placeholder, $('<div class=\"' + placeholder + '\"></div>').insertAfter( content ).hide() );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontent = content.show().detach();\n\n\t\t\t\t\t\tcurrent.wrap.bind('onReset', function () {\n\t\t\t\t\t\t\tif ($(this).find(content).length) {\n\t\t\t\t\t\t\t\tcontent.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'image':\n\t\t\t\t\tcontent = current.tpl.image.replace('{href}', href);\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'swf':\n\t\t\t\t\tcontent = '<object id=\"fancybox-swf\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"100%\" height=\"100%\"><param name=\"movie\" value=\"' + href + '\"></param>';\n\t\t\t\t\tembed   = '';\n\n\t\t\t\t\t$.each(current.swf, function(name, val) {\n\t\t\t\t\t\tcontent += '<param name=\"' + name + '\" value=\"' + val + '\"></param>';\n\t\t\t\t\t\tembed   += ' ' + name + '=\"' + val + '\"';\n\t\t\t\t\t});\n\n\t\t\t\t\tcontent += '<embed src=\"' + href + '\" type=\"application/x-shockwave-flash\" width=\"100%\" height=\"100%\"' + embed + '></embed></object>';\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!(isQuery(content) && content.parent().is(current.inner))) {\n\t\t\t\tcurrent.inner.append( content );\n\t\t\t}\n\n\t\t\t// Give a chance for helpers or callbacks to update elements\n\t\t\tF.trigger('beforeShow');\n\n\t\t\t// Set scrolling before calculating dimensions\n\t\t\tcurrent.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));\n\n\t\t\t// Set initial dimensions and start position\n\t\t\tF._setDimension();\n\n\t\t\tF.reposition();\n\n\t\t\tF.isOpen = false;\n\t\t\tF.coming = null;\n\n\t\t\tF.bindEvents();\n\n\t\t\tif (!F.isOpened) {\n\t\t\t\t$('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();\n\n\t\t\t} else if (previous.prevMethod) {\n\t\t\t\tF.transitions[ previous.prevMethod ]();\n\t\t\t}\n\n\t\t\tF.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();\n\n\t\t\tF._preloadImages();\n\t\t},\n\n\t\t_setDimension: function () {\n\t\t\tvar viewport   = F.getViewport(),\n\t\t\t\tsteps      = 0,\n\t\t\t\tcanShrink  = false,\n\t\t\t\tcanExpand  = false,\n\t\t\t\twrap       = F.wrap,\n\t\t\t\tskin       = F.skin,\n\t\t\t\tinner      = F.inner,\n\t\t\t\tcurrent    = F.current,\n\t\t\t\twidth      = current.width,\n\t\t\t\theight     = current.height,\n\t\t\t\tminWidth   = current.minWidth,\n\t\t\t\tminHeight  = current.minHeight,\n\t\t\t\tmaxWidth   = current.maxWidth,\n\t\t\t\tmaxHeight  = current.maxHeight,\n\t\t\t\tscrolling  = current.scrolling,\n\t\t\t\tscrollOut  = current.scrollOutside ? current.scrollbarWidth : 0,\n\t\t\t\tmargin     = current.margin,\n\t\t\t\twMargin    = getScalar(margin[1] + margin[3]),\n\t\t\t\thMargin    = getScalar(margin[0] + margin[2]),\n\t\t\t\twPadding,\n\t\t\t\thPadding,\n\t\t\t\twSpace,\n\t\t\t\thSpace,\n\t\t\t\torigWidth,\n\t\t\t\torigHeight,\n\t\t\t\torigMaxWidth,\n\t\t\t\torigMaxHeight,\n\t\t\t\tratio,\n\t\t\t\twidth_,\n\t\t\t\theight_,\n\t\t\t\tmaxWidth_,\n\t\t\t\tmaxHeight_,\n\t\t\t\tiframe,\n\t\t\t\tbody;\n\n\t\t\t// Reset dimensions so we could re-check actual size\n\t\t\twrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');\n\n\t\t\twPadding = getScalar(skin.outerWidth(true)  - skin.width());\n\t\t\thPadding = getScalar(skin.outerHeight(true) - skin.height());\n\n\t\t\t// Any space between content and viewport (margin, padding, border, title)\n\t\t\twSpace = wMargin + wPadding;\n\t\t\thSpace = hMargin + hPadding;\n\n\t\t\torigWidth  = isPercentage(width)  ? (viewport.w - wSpace) * getScalar(width)  / 100 : width;\n\t\t\torigHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;\n\n\t\t\tif (current.type === 'iframe') {\n\t\t\t\tiframe = current.content;\n\n\t\t\t\tif (current.autoHeight && iframe.data('ready') === 1) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (iframe[0].contentWindow.document.location) {\n\t\t\t\t\t\t\tinner.width( origWidth ).height(9999);\n\n\t\t\t\t\t\t\tbody = iframe.contents().find('body');\n\n\t\t\t\t\t\t\tif (scrollOut) {\n\t\t\t\t\t\t\t\tbody.css('overflow-x', 'hidden');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\torigHeight = body.outerHeight(true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}\n\n\t\t\t} else if (current.autoWidth || current.autoHeight) {\n\t\t\t\tinner.addClass( 'fancybox-tmp' );\n\n\t\t\t\t// Set width or height in case we need to calculate only one dimension\n\t\t\t\tif (!current.autoWidth) {\n\t\t\t\t\tinner.width( origWidth );\n\t\t\t\t}\n\n\t\t\t\tif (!current.autoHeight) {\n\t\t\t\t\tinner.height( origHeight );\n\t\t\t\t}\n\n\t\t\t\tif (current.autoWidth) {\n\t\t\t\t\torigWidth = inner.width();\n\t\t\t\t}\n\n\t\t\t\tif (current.autoHeight) {\n\t\t\t\t\torigHeight = inner.height();\n\t\t\t\t}\n\n\t\t\t\tinner.removeClass( 'fancybox-tmp' );\n\t\t\t}\n\n\t\t\twidth  = getScalar( origWidth );\n\t\t\theight = getScalar( origHeight );\n\n\t\t\tratio  = origWidth / origHeight;\n\n\t\t\t// Calculations for the content\n\t\t\tminWidth  = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);\n\t\t\tmaxWidth  = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);\n\n\t\t\tminHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);\n\t\t\tmaxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);\n\n\t\t\t// These will be used to determine if wrap can fit in the viewport\n\t\t\torigMaxWidth  = maxWidth;\n\t\t\torigMaxHeight = maxHeight;\n\n\t\t\tif (current.fitToView) {\n\t\t\t\tmaxWidth  = Math.min(viewport.w - wSpace, maxWidth);\n\t\t\t\tmaxHeight = Math.min(viewport.h - hSpace, maxHeight);\n\t\t\t}\n\n\t\t\tmaxWidth_  = viewport.w - wMargin;\n\t\t\tmaxHeight_ = viewport.h - hMargin;\n\n\t\t\tif (current.aspectRatio) {\n\t\t\t\tif (width > maxWidth) {\n\t\t\t\t\twidth  = maxWidth;\n\t\t\t\t\theight = getScalar(width / ratio);\n\t\t\t\t}\n\n\t\t\t\tif (height > maxHeight) {\n\t\t\t\t\theight = maxHeight;\n\t\t\t\t\twidth  = getScalar(height * ratio);\n\t\t\t\t}\n\n\t\t\t\tif (width < minWidth) {\n\t\t\t\t\twidth  = minWidth;\n\t\t\t\t\theight = getScalar(width / ratio);\n\t\t\t\t}\n\n\t\t\t\tif (height < minHeight) {\n\t\t\t\t\theight = minHeight;\n\t\t\t\t\twidth  = getScalar(height * ratio);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\twidth = Math.max(minWidth, Math.min(width, maxWidth));\n\n\t\t\t\tif (current.autoHeight && current.type !== 'iframe') {\n\t\t\t\t\tinner.width( width );\n\n\t\t\t\t\theight = inner.height();\n\t\t\t\t}\n\n\t\t\t\theight = Math.max(minHeight, Math.min(height, maxHeight));\n\t\t\t}\n\n\t\t\t// Try to fit inside viewport (including the title)\n\t\t\tif (current.fitToView) {\n\t\t\t\tinner.width( width ).height( height );\n\n\t\t\t\twrap.width( width + wPadding );\n\n\t\t\t\t// Real wrap dimensions\n\t\t\t\twidth_  = wrap.width();\n\t\t\t\theight_ = wrap.height();\n\n\t\t\t\tif (current.aspectRatio) {\n\t\t\t\t\twhile ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {\n\t\t\t\t\t\tif (steps++ > 19) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\theight = Math.max(minHeight, Math.min(maxHeight, height - 10));\n\t\t\t\t\t\twidth  = getScalar(height * ratio);\n\n\t\t\t\t\t\tif (width < minWidth) {\n\t\t\t\t\t\t\twidth  = minWidth;\n\t\t\t\t\t\t\theight = getScalar(width / ratio);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (width > maxWidth) {\n\t\t\t\t\t\t\twidth  = maxWidth;\n\t\t\t\t\t\t\theight = getScalar(width / ratio);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tinner.width( width ).height( height );\n\n\t\t\t\t\t\twrap.width( width + wPadding );\n\n\t\t\t\t\t\twidth_  = wrap.width();\n\t\t\t\t\t\theight_ = wrap.height();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\twidth  = Math.max(minWidth,  Math.min(width,  width  - (width_  - maxWidth_)));\n\t\t\t\t\theight = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {\n\t\t\t\twidth += scrollOut;\n\t\t\t}\n\n\t\t\tinner.width( width ).height( height );\n\n\t\t\twrap.width( width + wPadding );\n\n\t\t\twidth_  = wrap.width();\n\t\t\theight_ = wrap.height();\n\n\t\t\tcanShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;\n\t\t\tcanExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));\n\n\t\t\t$.extend(current, {\n\t\t\t\tdim : {\n\t\t\t\t\twidth\t: getValue( width_ ),\n\t\t\t\t\theight\t: getValue( height_ )\n\t\t\t\t},\n\t\t\t\torigWidth  : origWidth,\n\t\t\t\torigHeight : origHeight,\n\t\t\t\tcanShrink  : canShrink,\n\t\t\t\tcanExpand  : canExpand,\n\t\t\t\twPadding   : wPadding,\n\t\t\t\thPadding   : hPadding,\n\t\t\t\twrapSpace  : height_ - skin.outerHeight(true),\n\t\t\t\tskinSpace  : skin.height() - height\n\t\t\t});\n\n\t\t\tif (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {\n\t\t\t\tinner.height('auto');\n\t\t\t}\n\t\t},\n\n\t\t_getPosition: function (onlyAbsolute) {\n\t\t\tvar current  = F.current,\n\t\t\t\tviewport = F.getViewport(),\n\t\t\t\tmargin   = current.margin,\n\t\t\t\twidth    = F.wrap.width()  + margin[1] + margin[3],\n\t\t\t\theight   = F.wrap.height() + margin[0] + margin[2],\n\t\t\t\trez      = {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop  : margin[0],\n\t\t\t\t\tleft : margin[3]\n\t\t\t\t};\n\n\t\t\tif (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {\n\t\t\t\trez.position = 'fixed';\n\n\t\t\t} else if (!current.locked) {\n\t\t\t\trez.top  += viewport.y;\n\t\t\t\trez.left += viewport.x;\n\t\t\t}\n\n\t\t\trez.top  = getValue(Math.max(rez.top,  rez.top  + ((viewport.h - height) * current.topRatio)));\n\t\t\trez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width)  * current.leftRatio)));\n\n\t\t\treturn rez;\n\t\t},\n\n\t\t_afterZoomIn: function () {\n\t\t\tvar current = F.current;\n\n\t\t\tif (!current) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tF.isOpen = F.isOpened = true;\n\n\t\t\tF.wrap.css('overflow', 'visible').addClass('fancybox-opened');\n\n\t\t\tF.update();\n\n\t\t\t// Assign a click event\n\t\t\tif ( current.closeClick || (current.nextClick && F.group.length > 1) ) {\n\t\t\t\tF.inner.css('cursor', 'pointer').bind('click.fb', function(e) {\n\t\t\t\t\tif (!$(e.target).is('a') && !$(e.target).parent().is('a')) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tF[ current.closeClick ? 'close' : 'next' ]();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Create a close button\n\t\t\tif (current.closeBtn) {\n\t\t\t\t$(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) {\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\tF.close();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Create navigation arrows\n\t\t\tif (current.arrows && F.group.length > 1) {\n\t\t\t\tif (current.loop || current.index > 0) {\n\t\t\t\t\t$(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);\n\t\t\t\t}\n\n\t\t\t\tif (current.loop || current.index < F.group.length - 1) {\n\t\t\t\t\t$(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tF.trigger('afterShow');\n\n\t\t\t// Stop the slideshow if this is the last item\n\t\t\tif (!current.loop && current.index === current.group.length - 1) {\n\t\t\t\tF.play( false );\n\n\t\t\t} else if (F.opts.autoPlay && !F.player.isActive) {\n\t\t\t\tF.opts.autoPlay = false;\n\n\t\t\t\tF.play();\n\t\t\t}\n\t\t},\n\n\t\t_afterZoomOut: function ( obj ) {\n\t\t\tobj = obj || F.current;\n\n\t\t\t$('.fancybox-wrap').trigger('onReset').remove();\n\n\t\t\t$.extend(F, {\n\t\t\t\tgroup  : {},\n\t\t\t\topts   : {},\n\t\t\t\trouter : false,\n\t\t\t\tcurrent   : null,\n\t\t\t\tisActive  : false,\n\t\t\t\tisOpened  : false,\n\t\t\t\tisOpen    : false,\n\t\t\t\tisClosing : false,\n\t\t\t\twrap   : null,\n\t\t\t\tskin   : null,\n\t\t\t\touter  : null,\n\t\t\t\tinner  : null\n\t\t\t});\n\n\t\t\tF.trigger('afterClose', obj);\n\t\t}\n\t});\n\n\t/*\n\t *\tDefault transitions\n\t */\n\n\tF.transitions = {\n\t\tgetOrigPosition: function () {\n\t\t\tvar current  = F.current,\n\t\t\t\telement  = current.element,\n\t\t\t\torig     = current.orig,\n\t\t\t\tpos      = {},\n\t\t\t\twidth    = 50,\n\t\t\t\theight   = 50,\n\t\t\t\thPadding = current.hPadding,\n\t\t\t\twPadding = current.wPadding,\n\t\t\t\tviewport = F.getViewport();\n\n\t\t\tif (!orig && current.isDom && element.is(':visible')) {\n\t\t\t\torig = element.find('img:first');\n\n\t\t\t\tif (!orig.length) {\n\t\t\t\t\torig = element;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isQuery(orig)) {\n\t\t\t\tpos = orig.offset();\n\n\t\t\t\tif (orig.is('img')) {\n\t\t\t\t\twidth  = orig.outerWidth();\n\t\t\t\t\theight = orig.outerHeight();\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tpos.top  = viewport.y + (viewport.h - height) * current.topRatio;\n\t\t\t\tpos.left = viewport.x + (viewport.w - width)  * current.leftRatio;\n\t\t\t}\n\n\t\t\tif (F.wrap.css('position') === 'fixed' || current.locked) {\n\t\t\t\tpos.top  -= viewport.y;\n\t\t\t\tpos.left -= viewport.x;\n\t\t\t}\n\n\t\t\tpos = {\n\t\t\t\ttop     : getValue(pos.top  - hPadding * current.topRatio),\n\t\t\t\tleft    : getValue(pos.left - wPadding * current.leftRatio),\n\t\t\t\twidth   : getValue(width  + wPadding),\n\t\t\t\theight  : getValue(height + hPadding)\n\t\t\t};\n\n\t\t\treturn pos;\n\t\t},\n\n\t\tstep: function (now, fx) {\n\t\t\tvar ratio,\n\t\t\t\tpadding,\n\t\t\t\tvalue,\n\t\t\t\tprop       = fx.prop,\n\t\t\t\tcurrent    = F.current,\n\t\t\t\twrapSpace  = current.wrapSpace,\n\t\t\t\tskinSpace  = current.skinSpace;\n\n\t\t\tif (prop === 'width' || prop === 'height') {\n\t\t\t\tratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);\n\n\t\t\t\tif (F.isClosing) {\n\t\t\t\t\tratio = 1 - ratio;\n\t\t\t\t}\n\n\t\t\t\tpadding = prop === 'width' ? current.wPadding : current.hPadding;\n\t\t\t\tvalue   = now - padding;\n\n\t\t\t\tF.skin[ prop ](  getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) ) );\n\t\t\t\tF.inner[ prop ]( getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );\n\t\t\t}\n\t\t},\n\n\t\tzoomIn: function () {\n\t\t\tvar current  = F.current,\n\t\t\t\tstartPos = current.pos,\n\t\t\t\teffect   = current.openEffect,\n\t\t\t\telastic  = effect === 'elastic',\n\t\t\t\tendPos   = $.extend({opacity : 1}, startPos);\n\n\t\t\t// Remove \"position\" property that breaks older IE\n\t\t\tdelete endPos.position;\n\n\t\t\tif (elastic) {\n\t\t\t\tstartPos = this.getOrigPosition();\n\n\t\t\t\tif (current.openOpacity) {\n\t\t\t\t\tstartPos.opacity = 0.1;\n\t\t\t\t}\n\n\t\t\t} else if (effect === 'fade') {\n\t\t\t\tstartPos.opacity = 0.1;\n\t\t\t}\n\n\t\t\tF.wrap.css(startPos).animate(endPos, {\n\t\t\t\tduration : effect === 'none' ? 0 : current.openSpeed,\n\t\t\t\teasing   : current.openEasing,\n\t\t\t\tstep     : elastic ? this.step : null,\n\t\t\t\tcomplete : F._afterZoomIn\n\t\t\t});\n\t\t},\n\n\t\tzoomOut: function () {\n\t\t\tvar current  = F.current,\n\t\t\t\teffect   = current.closeEffect,\n\t\t\t\telastic  = effect === 'elastic',\n\t\t\t\tendPos   = {opacity : 0.1};\n\n\t\t\tif (elastic) {\n\t\t\t\tendPos = this.getOrigPosition();\n\n\t\t\t\tif (current.closeOpacity) {\n\t\t\t\t\tendPos.opacity = 0.1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tF.wrap.animate(endPos, {\n\t\t\t\tduration : effect === 'none' ? 0 : current.closeSpeed,\n\t\t\t\teasing   : current.closeEasing,\n\t\t\t\tstep     : elastic ? this.step : null,\n\t\t\t\tcomplete : F._afterZoomOut\n\t\t\t});\n\t\t},\n\n\t\tchangeIn: function () {\n\t\t\tvar current   = F.current,\n\t\t\t\teffect    = current.nextEffect,\n\t\t\t\tstartPos  = current.pos,\n\t\t\t\tendPos    = { opacity : 1 },\n\t\t\t\tdirection = F.direction,\n\t\t\t\tdistance  = 200,\n\t\t\t\tfield;\n\n\t\t\tstartPos.opacity = 0.1;\n\n\t\t\tif (effect === 'elastic') {\n\t\t\t\tfield = direction === 'down' || direction === 'up' ? 'top' : 'left';\n\n\t\t\t\tif (direction === 'down' || direction === 'right') {\n\t\t\t\t\tstartPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);\n\t\t\t\t\tendPos[ field ]   = '+=' + distance + 'px';\n\n\t\t\t\t} else {\n\t\t\t\t\tstartPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);\n\t\t\t\t\tendPos[ field ]   = '-=' + distance + 'px';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Workaround for http://bugs.jquery.com/ticket/12273\n\t\t\tif (effect === 'none') {\n\t\t\t\tF._afterZoomIn();\n\n\t\t\t} else {\n\t\t\t\tF.wrap.css(startPos).animate(endPos, {\n\t\t\t\t\tduration : current.nextSpeed,\n\t\t\t\t\teasing   : current.nextEasing,\n\t\t\t\t\tcomplete : F._afterZoomIn\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tchangeOut: function () {\n\t\t\tvar previous  = F.previous,\n\t\t\t\teffect    = previous.prevEffect,\n\t\t\t\tendPos    = { opacity : 0.1 },\n\t\t\t\tdirection = F.direction,\n\t\t\t\tdistance  = 200;\n\n\t\t\tif (effect === 'elastic') {\n\t\t\t\tendPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';\n\t\t\t}\n\n\t\t\tprevious.wrap.animate(endPos, {\n\t\t\t\tduration : effect === 'none' ? 0 : previous.prevSpeed,\n\t\t\t\teasing   : previous.prevEasing,\n\t\t\t\tcomplete : function () {\n\t\t\t\t\t$(this).trigger('onReset').remove();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t/*\n\t *\tOverlay helper\n\t */\n\n\tF.helpers.overlay = {\n\t\tdefaults : {\n\t\t\tcloseClick : true,      // if true, fancyBox will be closed when user clicks on the overlay\n\t\t\tspeedOut   : 200,       // duration of fadeOut animation\n\t\t\tshowEarly  : true,      // indicates if should be opened immediately or wait until the content is ready\n\t\t\tcss        : {},        // custom CSS properties\n\t\t\tlocked     : !isTouch,  // if true, the content will be locked into overlay\n\t\t\tfixed      : true       // if false, the overlay CSS position property will not be set to \"fixed\"\n\t\t},\n\n\t\toverlay : null,      // current handle\n\t\tfixed   : false,     // indicates if the overlay has position \"fixed\"\n\t\tel      : $('html'), // element that contains \"the lock\"\n\n\t\t// Public methods\n\t\tcreate : function(opts) {\n\t\t\topts = $.extend({}, this.defaults, opts);\n\n\t\t\tif (this.overlay) {\n\t\t\t\tthis.close();\n\t\t\t}\n\n\t\t\tthis.overlay = $('<div class=\"fancybox-overlay\"></div>').appendTo( F.coming ? F.coming.parent : opts.parent );\n\t\t\tthis.fixed   = false;\n\n\t\t\tif (opts.fixed && F.defaults.fixed) {\n\t\t\t\tthis.overlay.addClass('fancybox-overlay-fixed');\n\n\t\t\t\tthis.fixed = true;\n\t\t\t}\n\t\t},\n\n\t\topen : function(opts) {\n\t\t\tvar that = this;\n\n\t\t\topts = $.extend({}, this.defaults, opts);\n\n\t\t\tif (this.overlay) {\n\t\t\t\tthis.overlay.unbind('.overlay').width('auto').height('auto');\n\n\t\t\t} else {\n\t\t\t\tthis.create(opts);\n\t\t\t}\n\n\t\t\tif (!this.fixed) {\n\t\t\t\tW.bind('resize.overlay', $.proxy( this.update, this) );\n\n\t\t\t\tthis.update();\n\t\t\t}\n\n\t\t\tif (opts.closeClick) {\n\t\t\t\tthis.overlay.bind('click.overlay', function(e) {\n\t\t\t\t\tif ($(e.target).hasClass('fancybox-overlay')) {\n\t\t\t\t\t\tif (F.isActive) {\n\t\t\t\t\t\t\tF.close();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthat.close();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.overlay.css( opts.css ).show();\n\t\t},\n\n\t\tclose : function() {\n\t\t\tvar scrollV, scrollH;\n\n\t\t\tW.unbind('resize.overlay');\n\n\t\t\tif (this.el.hasClass('fancybox-lock')) {\n\t\t\t\t$('.fancybox-margin').removeClass('fancybox-margin');\n\n\t\t\t\tscrollV = W.scrollTop();\n\t\t\t\tscrollH = W.scrollLeft();\n\n\t\t\t\tthis.el.removeClass('fancybox-lock');\n\n\t\t\t\tW.scrollTop( scrollV ).scrollLeft( scrollH );\n\t\t\t}\n\n\t\t\t$('.fancybox-overlay').remove().hide();\n\n\t\t\t$.extend(this, {\n\t\t\t\toverlay : null,\n\t\t\t\tfixed   : false\n\t\t\t});\n\t\t},\n\n\t\t// Private, callbacks\n\n\t\tupdate : function () {\n\t\t\tvar width = '100%', offsetWidth;\n\n\t\t\t// Reset width/height so it will not mess\n\t\t\tthis.overlay.width(width).height('100%');\n\n\t\t\t// jQuery does not return reliable result for IE\n\t\t\tif (IE) {\n\t\t\t\toffsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);\n\n\t\t\t\tif (D.width() > offsetWidth) {\n\t\t\t\t\twidth = D.width();\n\t\t\t\t}\n\n\t\t\t} else if (D.width() > W.width()) {\n\t\t\t\twidth = D.width();\n\t\t\t}\n\n\t\t\tthis.overlay.width(width).height(D.height());\n\t\t},\n\n\t\t// This is where we can manipulate DOM, because later it would cause iframes to reload\n\t\tonReady : function (opts, obj) {\n\t\t\tvar overlay = this.overlay;\n\n\t\t\t$('.fancybox-overlay').stop(true, true);\n\n\t\t\tif (!overlay) {\n\t\t\t\tthis.create(opts);\n\t\t\t}\n\n\t\t\tif (opts.locked && this.fixed && obj.fixed) {\n\t\t\t\tif (!overlay) {\n\t\t\t\t\tthis.margin = D.height() > W.height() ? $('html').css('margin-right').replace(\"px\", \"\") : false;\n\t\t\t\t}\n\n\t\t\t\tobj.locked = this.overlay.append( obj.wrap );\n\t\t\t\tobj.fixed  = false;\n\t\t\t}\n\n\t\t\tif (opts.showEarly === true) {\n\t\t\t\tthis.beforeShow.apply(this, arguments);\n\t\t\t}\n\t\t},\n\n\t\tbeforeShow : function(opts, obj) {\n\t\t\tvar scrollV, scrollH;\n\n\t\t\tif (obj.locked) {\n\t\t\t\tif (this.margin !== false) {\n\t\t\t\t\t$('*').filter(function(){\n\t\t\t\t\t\treturn ($(this).css('position') === 'fixed' && !$(this).hasClass(\"fancybox-overlay\") && !$(this).hasClass(\"fancybox-wrap\") );\n\t\t\t\t\t}).addClass('fancybox-margin');\n\n\t\t\t\t\tthis.el.addClass('fancybox-margin');\n\t\t\t\t}\n\n\t\t\t\tscrollV = W.scrollTop();\n\t\t\t\tscrollH = W.scrollLeft();\n\n\t\t\t\tthis.el.addClass('fancybox-lock');\n\n\t\t\t\tW.scrollTop( scrollV ).scrollLeft( scrollH );\n\t\t\t}\n\n\t\t\tthis.open(opts);\n\t\t},\n\n\t\tonUpdate : function() {\n\t\t\tif (!this.fixed) {\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t},\n\n\t\tafterClose: function (opts) {\n\t\t\t// Remove overlay if exists and fancyBox is not opening\n\t\t\t// (e.g., it is not being open using afterClose callback)\n\t\t\t//if (this.overlay && !F.isActive) {\n\t\t\tif (this.overlay && !F.coming) {\n\t\t\t\tthis.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));\n\t\t\t}\n\t\t}\n\t};\n\n\t/*\n\t *\tTitle helper\n\t */\n\n\tF.helpers.title = {\n\t\tdefaults : {\n\t\t\ttype     : 'float', // 'float', 'inside', 'outside' or 'over',\n\t\t\tposition : 'bottom' // 'top' or 'bottom'\n\t\t},\n\n\t\tbeforeShow: function (opts) {\n\t\t\tvar current = F.current,\n\t\t\t\ttext    = current.title,\n\t\t\t\ttype    = opts.type,\n\t\t\t\ttitle,\n\t\t\t\ttarget;\n\n\t\t\tif ($.isFunction(text)) {\n\t\t\t\ttext = text.call(current.element, current);\n\t\t\t}\n\n\t\t\tif (!isString(text) || $.trim(text) === '') {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttitle = $('<div class=\"fancybox-title fancybox-title-' + type + '-wrap\">' + text + '</div>');\n\n\t\t\tswitch (type) {\n\t\t\t\tcase 'inside':\n\t\t\t\t\ttarget = F.skin;\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'outside':\n\t\t\t\t\ttarget = F.wrap;\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'over':\n\t\t\t\t\ttarget = F.inner;\n\t\t\t\tbreak;\n\n\t\t\t\tdefault: // 'float'\n\t\t\t\t\ttarget = F.skin;\n\n\t\t\t\t\ttitle.appendTo('body');\n\n\t\t\t\t\tif (IE) {\n\t\t\t\t\t\ttitle.width( title.width() );\n\t\t\t\t\t}\n\n\t\t\t\t\ttitle.wrapInner('<span class=\"child\"></span>');\n\n\t\t\t\t\t//Increase bottom margin so this title will also fit into viewport\n\t\t\t\t\tF.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\ttitle[ (opts.position === 'top' ? 'prependTo'  : 'appendTo') ](target);\n\t\t}\n\t};\n\n\t// jQuery plugin initialization\n\t$.fn.fancybox = function (options) {\n\t\tvar index,\n\t\t\tthat     = $(this),\n\t\t\tselector = this.selector || '',\n\t\t\trun      = function(e) {\n\t\t\t\tvar what = $(this).blur(), idx = index, relType, relVal;\n\n\t\t\t\tif (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {\n\t\t\t\t\trelType = options.groupAttr || 'data-fancybox-group';\n\t\t\t\t\trelVal  = what.attr(relType);\n\n\t\t\t\t\tif (!relVal) {\n\t\t\t\t\t\trelType = 'rel';\n\t\t\t\t\t\trelVal  = what.get(0)[ relType ];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (relVal && relVal !== '' && relVal !== 'nofollow') {\n\t\t\t\t\t\twhat = selector.length ? $(selector) : that;\n\t\t\t\t\t\twhat = what.filter('[' + relType + '=\"' + relVal + '\"]');\n\t\t\t\t\t\tidx  = what.index(this);\n\t\t\t\t\t}\n\n\t\t\t\t\toptions.index = idx;\n\n\t\t\t\t\t// Stop an event from bubbling if everything is fine\n\t\t\t\t\tif (F.open(what, options) !== false) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\toptions = options || {};\n\t\tindex   = options.index || 0;\n\n\t\tif (!selector || options.live === false) {\n\t\t\tthat.unbind('click.fb-start').bind('click.fb-start', run);\n\n\t\t} else {\n\t\t\tD.undelegate(selector, 'click.fb-start').delegate(selector + \":not('.fancybox-item, .fancybox-nav')\", 'click.fb-start', run);\n\t\t}\n\n\t\tthis.filter('[data-fancybox-start=1]').trigger('click');\n\n\t\treturn this;\n\t};\n\n\t// Tests that need a body at doc ready\n\tD.ready(function() {\n\t\tvar w1, w2;\n\n\t\tif ( $.scrollbarWidth === undefined ) {\n\t\t\t// http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth\n\t\t\t$.scrollbarWidth = function() {\n\t\t\t\tvar parent = $('<div style=\"width:50px;height:50px;overflow:auto\"><div/></div>').appendTo('body'),\n\t\t\t\t\tchild  = parent.children(),\n\t\t\t\t\twidth  = child.innerWidth() - child.height( 99 ).innerWidth();\n\n\t\t\t\tparent.remove();\n\n\t\t\t\treturn width;\n\t\t\t};\n\t\t}\n\n\t\tif ( $.support.fixedPosition === undefined ) {\n\t\t\t$.support.fixedPosition = (function() {\n\t\t\t\tvar elem  = $('<div style=\"position:fixed;top:20px;\"></div>').appendTo('body'),\n\t\t\t\t\tfixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );\n\n\t\t\t\telem.remove();\n\n\t\t\t\treturn fixed;\n\t\t\t}());\n\t\t}\n\n\t\t$.extend(F.defaults, {\n\t\t\tscrollbarWidth : $.scrollbarWidth(),\n\t\t\tfixed  : $.support.fixedPosition,\n\t\t\tparent : $('body')\n\t\t});\n\n\t\t//Get real width of page scroll-bar\n\t\tw1 = $(window).width();\n\n\t\tH.addClass('fancybox-lock-test');\n\n\t\tw2 = $(window).width();\n\n\t\tH.removeClass('fancybox-lock-test');\n\n\t\t$(\"<style type='text/css'>.fancybox-margin{margin-right:\" + (w2 - w1) + \"px;}</style>\").appendTo(\"head\");\n\t});\n\n}(window, document, jQuery));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/curvedLines.js",
    "content": "/* The MIT License\n\n Copyright (c) 2011 by Michael Zinsmaier and nergal.dev\n Copyright (c) 2012 by Thomas Ritou\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n/*\n\n ____________________________________________________\n\n what it is:\n ____________________________________________________\n\n curvedLines is a plugin for flot, that tries to display lines in a smoother way.\n The plugin is based on nergal.dev's work https://code.google.com/p/flot/issues/detail?id=226\n and further extended with a mode that forces the min/max points of the curves to be on the\n points. Both modes are achieved through adding of more data points\n => 1) with large data sets you may get trouble\n => 2) if you want to display the points too, you have to plot them as 2nd data series over the lines\n\n && 3) consecutive x data points are not allowed to have the same value\n\n This is version 0.5 of curvedLines so it will probably not work in every case. However\n the basic form of use descirbed next works (:\n\n Feel free to further improve the code\n\n ____________________________________________________\n\n how to use it:\n ____________________________________________________\n\n var d1 = [[5,5],[7,3],[9,12]];\n\n var options = { series: { curvedLines: {  active: true }}};\n\n $.plot($(\"#placeholder\"), [{data = d1, lines: { show: true}, curvedLines: {apply: true}}], options);\n\n _____________________________________________________\n\n options:\n _____________________________________________________\n\n active:           bool true => plugin can be used\n apply:            bool true => series will be drawn as curved line\n fit:              bool true => forces the max,mins of the curve to be on the datapoints\n curvePointFactor  int  defines how many \"virtual\" points are used per \"real\" data point to\n emulate the curvedLines (points total = real points * curvePointFactor)\n fitPointDist:     int  defines the x axis distance of the additional two points that are used\n to enforce the min max condition.\n\n + line options (since v0.5 curved lines use flots line implementation for drawing\n => line options like fill, show ... are supported out of the box)\n\n */\n\n/*\n *  v0.1   initial commit\n *  v0.15  negative values should work now (outcommented a negative -> 0 hook hope it does no harm)\n *  v0.2   added fill option (thanks to monemihir) and multi axis support (thanks to soewono effendi)\n *  v0.3   improved saddle handling and added basic handling of Dates\n *  v0.4   rewritten fill option (thomas ritou) mostly from original flot code (now fill between points rather than to graph bottom), corrected fill Opacity bug\n *  v0.5   rewritten instead of implementing a own draw function CurvedLines is now based on the processDatapoints flot hook (credits go to thomas ritou).\n * \t\t   This change breakes existing code however CurvedLines are now just many tiny straight lines to flot and therefore all flot lines options (like gradient fill,\n * \t       shadow) are now supported out of the box\n *  v0.6   flot 0.8 compatibility and some bug fixes\n */\n\n(function($) {\n\n    var options = {\n        series : {\n            curvedLines : {\n                active : false,\n                apply: false,\n                fit : false,\n                curvePointFactor : 20,\n                fitPointDist : undefined\n            }\n        }\n    };\n\n    function init(plot) {\n\n        plot.hooks.processOptions.push(processOptions);\n\n        //if the plugin is active register processDatapoints method\n        function processOptions(plot, options) {\n            if (options.series.curvedLines.active) {\n                plot.hooks.processDatapoints.unshift(processDatapoints);\n            }\n        }\n\n        //only if the plugin is active\n        function processDatapoints(plot, series, datapoints) {\n            var nrPoints = datapoints.points.length / datapoints.pointsize;\n            var EPSILON = 0.5; //pretty large epsilon but save\n\n            if (series.curvedLines.apply == true && series.originSeries === undefined && nrPoints > (1 + EPSILON)) {\n                if (series.lines.fill) {\n\n                    var pointsTop = calculateCurvePoints(datapoints, series.curvedLines, 1)\n                        ,pointsBottom = calculateCurvePoints(datapoints, series.curvedLines, 2); //flot makes sure for us that we've got a second y point if fill is true !\n\n                    //Merge top and bottom curve\n                    datapoints.pointsize = 3;\n                    datapoints.points = [];\n                    var j = 0;\n                    var k = 0;\n                    var i = 0;\n                    var ps = 2;\n                    while (i < pointsTop.length || j < pointsBottom.length) {\n                        if (pointsTop[i] == pointsBottom[j]) {\n                            datapoints.points[k] = pointsTop[i];\n                            datapoints.points[k + 1] = pointsTop[i + 1];\n                            datapoints.points[k + 2] = pointsBottom[j + 1];\n                            j += ps;\n                            i += ps;\n\n                        } else if (pointsTop[i] < pointsBottom[j]) {\n                            datapoints.points[k] = pointsTop[i];\n                            datapoints.points[k + 1] = pointsTop[i + 1];\n                            datapoints.points[k + 2] = k > 0 ? datapoints.points[k-1] : null;\n                            i += ps;\n                        } else {\n                            datapoints.points[k] = pointsBottom[j];\n                            datapoints.points[k + 1] = k > 1 ? datapoints.points[k-2] : null;\n                            datapoints.points[k + 2] = pointsBottom[j + 1];\n                            j += ps;\n                        }\n                        k += 3;\n                    }\n                } else if (series.lines.lineWidth > 0) {\n                    datapoints.points = calculateCurvePoints(datapoints, series.curvedLines, 1);\n                    datapoints.pointsize = 2;\n                }\n            }\n        }\n\n        //no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226\n        //if fit option is selected additional datapoints get inserted before the curve calculations in nergal.dev s code.\n        function calculateCurvePoints(datapoints, curvedLinesOptions, yPos) {\n\n            var points = datapoints.points, ps = datapoints.pointsize;\n            var num = curvedLinesOptions.curvePointFactor * (points.length / ps);\n\n            var xdata = new Array;\n            var ydata = new Array;\n\n            var curX = -1;\n            var curY = -1;\n            var j = 0;\n\n            if (curvedLinesOptions.fit) {\n                //insert a point before and after the \"real\" data point to force the line\n                //to have a max,min at the data point.\n\n                var fpDist;\n                if(typeof curvedLinesOptions.fitPointDist == 'undefined') {\n                    //estimate it\n                    var minX = points[0];\n                    var maxX = points[points.length-ps];\n                    fpDist = (maxX - minX) / (500 * 100); //x range / (estimated pixel length of placeholder * factor)\n                } else {\n                    //use user defined value\n                    fpDist = curvedLinesOptions.fitPointDist;\n                }\n\n                for (var i = 0; i < points.length; i += ps) {\n\n                    var frontX;\n                    var backX;\n                    curX = i;\n                    curY = i + yPos;\n\n                    //add point X s\n                    frontX = points[curX] - fpDist;\n                    backX = points[curX] + fpDist;\n\n                    var factor = 2;\n                    while (frontX == points[curX] || backX == points[curX]) {\n                        //inside the ulp\n                        frontX = points[curX] - (fpDist * factor);\n                        backX = points[curX] + (fpDist * factor);\n                        factor++;\n                    }\n\n                    //add curve points\n                    xdata[j] = frontX;\n                    ydata[j] = points[curY];\n                    j++;\n\n                    xdata[j] = points[curX];\n                    ydata[j] = points[curY];\n                    j++;\n\n                    xdata[j] = backX;\n                    ydata[j] = points[curY];\n                    j++;\n                }\n            } else {\n                //just use the datapoints\n                for (var i = 0; i < points.length; i += ps) {\n                    curX = i;\n                    curY = i + yPos;\n\n                    xdata[j] = points[curX];\n                    ydata[j] = points[curY];\n                    j++;\n                }\n            }\n\n            var n = xdata.length;\n\n            var y2 = new Array();\n            var delta = new Array();\n            y2[0] = 0;\n            y2[n - 1] = 0;\n            delta[0] = 0;\n\n            for (var i = 1; i < n - 1; ++i) {\n                var d = (xdata[i + 1] - xdata[i - 1]);\n                if (d == 0) {\n                    //point before current point and after current point need some space in between\n                    return [];\n                }\n\n                var s = (xdata[i] - xdata[i - 1]) / d;\n                var p = s * y2[i - 1] + 2;\n                y2[i] = (s - 1) / p;\n                delta[i] = (ydata[i + 1] - ydata[i]) / (xdata[i + 1] - xdata[i]) - (ydata[i] - ydata[i - 1]) / (xdata[i] - xdata[i - 1]);\n                delta[i] = (6 * delta[i] / (xdata[i + 1] - xdata[i - 1]) - s * delta[i - 1]) / p;\n            }\n\n            for (var j = n - 2; j >= 0; --j) {\n                y2[j] = y2[j] * y2[j + 1] + delta[j];\n            }\n\n            //   xmax  - xmin  / #points\n            var step = (xdata[n - 1] - xdata[0]) / (num - 1);\n\n            var xnew = new Array;\n            var ynew = new Array;\n            var result = new Array;\n\n            xnew[0] = xdata[0];\n            ynew[0] = ydata[0];\n\n            result.push(xnew[0]);\n            result.push(ynew[0]);\n\n            for ( j = 1; j < num; ++j) {\n                //new x point (sampling point for the created curve)\n                xnew[j] = xnew[0] + j * step;\n\n                var max = n - 1;\n                var min = 0;\n\n                while (max - min > 1) {\n                    var k = Math.round((max + min) / 2);\n                    if (xdata[k] > xnew[j]) {\n                        max = k;\n                    } else {\n                        min = k;\n                    }\n                }\n\n                //found point one to the left and one to the right of generated new point\n                var h = (xdata[max] - xdata[min]);\n\n                if (h == 0) {\n                    //similar to above two points from original x data need some space between them\n                    return [];\n                }\n\n                var a = (xdata[max] - xnew[j]) / h;\n                var b = (xnew[j] - xdata[min]) / h;\n\n                ynew[j] = a * ydata[min] + b * ydata[max] + ((a * a * a - a) * y2[min] + (b * b * b - b) * y2[max]) * (h * h) / 6;\n\n                result.push(xnew[j]);\n                result.push(ynew[j]);\n            }\n\n            return result;\n        }\n\n    }//end init\n\n    $.plot.plugins.push({\n        init : init,\n        options : options,\n        name : 'curvedLines',\n        version : '0.5'\n    });\n\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/jquery.flot.js",
    "content": "/*! Javascript plotting library for jQuery, v. 0.7.\n *\n * Released under the MIT license by IOLA, December 2007.\n *\n */\n\n// first an inline dependency, jquery.colorhelpers.js, we inline it here\n// for convenience\n\n/* Plugin for jQuery for working with colors.\n *\n * Version 1.1.\n *\n * Inspiration from jQuery color animation plugin by John Resig.\n *\n * Released under the MIT license by Ole Laursen, October 2009.\n *\n * Examples:\n *\n *   $.color.parse(\"#fff\").scale('rgb', 0.25).add('a', -0.5).toString()\n *   var c = $.color.extract($(\"#mydiv\"), 'background-color');\n *   console.log(c.r, c.g, c.b, c.a);\n *   $.color.make(100, 50, 25, 0.4).toString() // returns \"rgba(100,50,25,0.4)\"\n *\n * Note that .scale() and .add() return the same modified object\n * instead of making a new one.\n *\n * V. 1.1: Fix error handling so e.g. parsing an empty string does\n * produce a color rather than just crashing.\n */\n(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return\"rgb(\"+[G.r,G.g,G.b].join(\",\")+\")\"}else{return\"rgba(\"+[G.r,G.g,G.b,G.a].join(\",\")+\")\"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=\"\"&&E!=\"transparent\"){break}D=D.parent()}while(!B.nodeName(D.get(0),\"body\"));if(E==\"rgba(0, 0, 0, 0)\"){E=\"transparent\"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/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(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*\\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\s*\\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D==\"transparent\"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);\n\n// the actual Flot code\n(function($) {\n    function Plot(placeholder, data_, options_, plugins) {\n        // data is on the form:\n        //   [ series1, series2 ... ]\n        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]\n        // or { data: [ [x1, y1], [x2, y2], ... ], label: \"some label\", ... }\n\n        var series = [],\n            options = {\n                // the color theme used for graphs\n                colors: [\"#edc240\", \"#afd8f8\", \"#cb4b4b\", \"#4da74d\", \"#9440ed\"],\n                legend: {\n                    show: true,\n                    noColumns: 1, // number of colums in legend table\n                    labelFormatter: null, // fn: string -> string\n                    labelBoxBorderColor: \"#ccc\", // border color for the little label boxes\n                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph\n                    position: \"ne\", // position of default legend container within plot\n                    margin: 5, // distance from grid edge to default legend container within plot\n                    backgroundColor: null, // null means auto-detect\n                    backgroundOpacity: 0.85 // set to 0 to avoid background\n                },\n                xaxis: {\n                    show: null, // null = auto-detect, true = always, false = never\n                    position: \"bottom\", // or \"top\"\n                    mode: null, // null or \"time\"\n                    color: null, // base color, labels, ticks\n                    tickColor: null, // possibly different color of ticks, e.g. \"rgba(0,0,0,0.15)\"\n                    transform: null, // null or f: number -> number to transform axis\n                    inverseTransform: null, // if transform is set, this should be the inverse function\n                    min: null, // min. value to show, null means set automatically\n                    max: null, // max. value to show, null means set automatically\n                    autoscaleMargin: null, // margin in % to add if auto-setting min/max\n                    ticks: null, // either [1, 3] or [[1, \"a\"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks\n                    tickFormatter: null, // fn: number -> string\n                    labelWidth: null, // size of tick labels in pixels\n                    labelHeight: null,\n                    reserveSpace: null, // whether to reserve space even if axis isn't shown\n                    tickLength: null, // size in pixels of ticks, or \"full\" for whole line\n                    alignTicksWithAxis: null, // axis number or null for no sync\n\n                    // mode specific options\n                    tickDecimals: null, // no. of decimals, null means auto\n                    tickSize: null, // number or [number, \"unit\"]\n                    minTickSize: null, // number or [number, \"unit\"]\n                    monthNames: null, // list of names of months\n                    timeformat: null, // format string to use\n                    twelveHourClock: false // 12 or 24 time in time mode\n                },\n                yaxis: {\n                    autoscaleMargin: 0.02,\n                    position: \"left\" // or \"right\"\n                },\n                xaxes: [],\n                yaxes: [],\n                series: {\n                    points: {\n                        show: false,\n                        radius: 3,\n                        lineWidth: 2, // in pixels\n                        fill: true,\n                        fillColor: \"#ffffff\",\n                        symbol: \"circle\" // or callback\n                    },\n                    lines: {\n                        // we don't put in show: false so we can see\n                        // whether lines were actively disabled\n                        lineWidth: 2, // in pixels\n                        fill: false,\n                        fillColor: null,\n                        steps: false\n                    },\n                    bars: {\n                        show: false,\n                        lineWidth: 2, // in pixels\n                        barWidth: 1, // in units of the x axis\n                        fill: true,\n                        fillColor: null,\n                        align: \"left\", // or \"center\"\n                        horizontal: false\n                    },\n                    shadowSize: 3\n                },\n                grid: {\n                    show: true,\n                    aboveData: false,\n                    color: \"#545454\", // primary color used for outline and labels\n                    backgroundColor: null, // null for transparent, else color\n                    borderColor: null, // set if different from the grid color\n                    tickColor: null, // color for the ticks, e.g. \"rgba(0,0,0,0.15)\"\n                    labelMargin: 5, // in pixels\n                    axisMargin: 8, // in pixels\n                    borderWidth: 2, // in pixels\n                    minBorderMargin: null, // in pixels, null means taken from points radius\n                    markings: null, // array of ranges or fn: axes -> array of ranges\n                    markingsColor: \"#f4f4f4\",\n                    markingsLineWidth: 2,\n                    // interactive stuff\n                    clickable: false,\n                    hoverable: false,\n                    autoHighlight: true, // highlight in case mouse is near\n                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item\n                },\n                hooks: {}\n            },\n        canvas = null,      // the canvas for the plot itself\n        overlay = null,     // canvas for interactive stuff on top of plot\n        eventHolder = null, // jQuery object that events should be bound to\n        ctx = null, octx = null,\n        xaxes = [], yaxes = [],\n        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},\n        canvasWidth = 0, canvasHeight = 0,\n        plotWidth = 0, plotHeight = 0,\n        hooks = {\n            processOptions: [],\n            processRawData: [],\n            processDatapoints: [],\n            drawSeries: [],\n            draw: [],\n            bindEvents: [],\n            drawOverlay: [],\n            shutdown: []\n        },\n        plot = this;\n\n        // public functions\n        plot.setData = setData;\n        plot.setupGrid = setupGrid;\n        plot.draw = draw;\n        plot.getPlaceholder = function() { return placeholder; };\n        plot.getCanvas = function() { return canvas; };\n        plot.getPlotOffset = function() { return plotOffset; };\n        plot.width = function () { return plotWidth; };\n        plot.height = function () { return plotHeight; };\n        plot.offset = function () {\n            var o = eventHolder.offset();\n            o.left += plotOffset.left;\n            o.top += plotOffset.top;\n            return o;\n        };\n        plot.getData = function () { return series; };\n        plot.getAxes = function () {\n            var res = {}, i;\n            $.each(xaxes.concat(yaxes), function (_, axis) {\n                if (axis)\n                    res[axis.direction + (axis.n != 1 ? axis.n : \"\") + \"axis\"] = axis;\n            });\n            return res;\n        };\n        plot.getXAxes = function () { return xaxes; };\n        plot.getYAxes = function () { return yaxes; };\n        plot.c2p = canvasToAxisCoords;\n        plot.p2c = axisToCanvasCoords;\n        plot.getOptions = function () { return options; };\n        plot.highlight = highlight;\n        plot.unhighlight = unhighlight;\n        plot.triggerRedrawOverlay = triggerRedrawOverlay;\n        plot.pointOffset = function(point) {\n            return {\n                left: parseInt(xaxes[axisNumber(point, \"x\") - 1].p2c(+point.x) + plotOffset.left),\n                top: parseInt(yaxes[axisNumber(point, \"y\") - 1].p2c(+point.y) + plotOffset.top)\n            };\n        };\n        plot.shutdown = shutdown;\n        plot.resize = function () {\n            getCanvasDimensions();\n            resizeCanvas(canvas);\n            resizeCanvas(overlay);\n        };\n\n        // public attributes\n        plot.hooks = hooks;\n\n        // initialize\n        initPlugins(plot);\n        parseOptions(options_);\n        setupCanvases();\n        setData(data_);\n        setupGrid();\n        draw();\n        bindEvents();\n\n\n        function executeHooks(hook, args) {\n            args = [plot].concat(args);\n            for (var i = 0; i < hook.length; ++i)\n                hook[i].apply(this, args);\n        }\n\n        function initPlugins() {\n            for (var i = 0; i < plugins.length; ++i) {\n                var p = plugins[i];\n                p.init(plot);\n                if (p.options)\n                    $.extend(true, options, p.options);\n            }\n        }\n\n        function parseOptions(opts) {\n            var i;\n\n            $.extend(true, options, opts);\n\n            if (options.xaxis.color == null)\n                options.xaxis.color = options.grid.color;\n            if (options.yaxis.color == null)\n                options.yaxis.color = options.grid.color;\n\n            if (options.xaxis.tickColor == null) // backwards-compatibility\n                options.xaxis.tickColor = options.grid.tickColor;\n            if (options.yaxis.tickColor == null) // backwards-compatibility\n                options.yaxis.tickColor = options.grid.tickColor;\n\n            if (options.grid.borderColor == null)\n                options.grid.borderColor = options.grid.color;\n            if (options.grid.tickColor == null)\n                options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();\n\n            // fill in defaults in axes, copy at least always the\n            // first as the rest of the code assumes it'll be there\n            for (i = 0; i < Math.max(1, options.xaxes.length); ++i)\n                options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);\n            for (i = 0; i < Math.max(1, options.yaxes.length); ++i)\n                options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);\n\n            // backwards compatibility, to be removed in future\n            if (options.xaxis.noTicks && options.xaxis.ticks == null)\n                options.xaxis.ticks = options.xaxis.noTicks;\n            if (options.yaxis.noTicks && options.yaxis.ticks == null)\n                options.yaxis.ticks = options.yaxis.noTicks;\n            if (options.x2axis) {\n                options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);\n                options.xaxes[1].position = \"top\";\n            }\n            if (options.y2axis) {\n                options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);\n                options.yaxes[1].position = \"right\";\n            }\n            if (options.grid.coloredAreas)\n                options.grid.markings = options.grid.coloredAreas;\n            if (options.grid.coloredAreasColor)\n                options.grid.markingsColor = options.grid.coloredAreasColor;\n            if (options.lines)\n                $.extend(true, options.series.lines, options.lines);\n            if (options.points)\n                $.extend(true, options.series.points, options.points);\n            if (options.bars)\n                $.extend(true, options.series.bars, options.bars);\n            if (options.shadowSize != null)\n                options.series.shadowSize = options.shadowSize;\n\n            // save options on axes for future reference\n            for (i = 0; i < options.xaxes.length; ++i)\n                getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];\n            for (i = 0; i < options.yaxes.length; ++i)\n                getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];\n\n            // add hooks from options\n            for (var n in hooks)\n                if (options.hooks[n] && options.hooks[n].length)\n                    hooks[n] = hooks[n].concat(options.hooks[n]);\n\n            executeHooks(hooks.processOptions, [options]);\n        }\n\n        function setData(d) {\n            series = parseData(d);\n            fillInSeriesOptions();\n            processData();\n        }\n\n        function parseData(d) {\n            var res = [];\n            for (var i = 0; i < d.length; ++i) {\n                var s = $.extend(true, {}, options.series);\n\n                if (d[i].data != null) {\n                    s.data = d[i].data; // move the data instead of deep-copy\n                    delete d[i].data;\n\n                    $.extend(true, s, d[i]);\n\n                    d[i].data = s.data;\n                }\n                else\n                    s.data = d[i];\n                res.push(s);\n            }\n\n            return res;\n        }\n\n        function axisNumber(obj, coord) {\n            var a = obj[coord + \"axis\"];\n            if (typeof a == \"object\") // if we got a real axis, extract number\n                a = a.n;\n            if (typeof a != \"number\")\n                a = 1; // default to first axis\n            return a;\n        }\n\n        function allAxes() {\n            // return flat array without annoying null entries\n            return $.grep(xaxes.concat(yaxes), function (a) { return a; });\n        }\n\n        function canvasToAxisCoords(pos) {\n            // return an object with x/y corresponding to all used axes\n            var res = {}, i, axis;\n            for (i = 0; i < xaxes.length; ++i) {\n                axis = xaxes[i];\n                if (axis && axis.used)\n                    res[\"x\" + axis.n] = axis.c2p(pos.left);\n            }\n\n            for (i = 0; i < yaxes.length; ++i) {\n                axis = yaxes[i];\n                if (axis && axis.used)\n                    res[\"y\" + axis.n] = axis.c2p(pos.top);\n            }\n\n            if (res.x1 !== undefined)\n                res.x = res.x1;\n            if (res.y1 !== undefined)\n                res.y = res.y1;\n\n            return res;\n        }\n\n        function axisToCanvasCoords(pos) {\n            // get canvas coords from the first pair of x/y found in pos\n            var res = {}, i, axis, key;\n\n            for (i = 0; i < xaxes.length; ++i) {\n                axis = xaxes[i];\n                if (axis && axis.used) {\n                    key = \"x\" + axis.n;\n                    if (pos[key] == null && axis.n == 1)\n                        key = \"x\";\n\n                    if (pos[key] != null) {\n                        res.left = axis.p2c(pos[key]);\n                        break;\n                    }\n                }\n            }\n\n            for (i = 0; i < yaxes.length; ++i) {\n                axis = yaxes[i];\n                if (axis && axis.used) {\n                    key = \"y\" + axis.n;\n                    if (pos[key] == null && axis.n == 1)\n                        key = \"y\";\n\n                    if (pos[key] != null) {\n                        res.top = axis.p2c(pos[key]);\n                        break;\n                    }\n                }\n            }\n\n            return res;\n        }\n\n        function getOrCreateAxis(axes, number) {\n            if (!axes[number - 1])\n                axes[number - 1] = {\n                    n: number, // save the number for future reference\n                    direction: axes == xaxes ? \"x\" : \"y\",\n                    options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)\n                };\n\n            return axes[number - 1];\n        }\n\n        function fillInSeriesOptions() {\n            var i;\n\n            // collect what we already got of colors\n            var neededColors = series.length,\n                usedColors = [],\n                assignedColors = [];\n            for (i = 0; i < series.length; ++i) {\n                var sc = series[i].color;\n                if (sc != null) {\n                    --neededColors;\n                    if (typeof sc == \"number\")\n                        assignedColors.push(sc);\n                    else\n                        usedColors.push($.color.parse(series[i].color));\n                }\n            }\n\n            // we might need to generate more colors if higher indices\n            // are assigned\n            for (i = 0; i < assignedColors.length; ++i) {\n                neededColors = Math.max(neededColors, assignedColors[i] + 1);\n            }\n\n            // produce colors as needed\n            var colors = [], variation = 0;\n            i = 0;\n            while (colors.length < neededColors) {\n                var c;\n                if (options.colors.length == i) // check degenerate case\n                    c = $.color.make(100, 100, 100);\n                else\n                    c = $.color.parse(options.colors[i]);\n\n                // vary color if needed\n                var sign = variation % 2 == 1 ? -1 : 1;\n                c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)\n\n                // FIXME: if we're getting to close to something else,\n                // we should probably skip this one\n                colors.push(c);\n\n                ++i;\n                if (i >= options.colors.length) {\n                    i = 0;\n                    ++variation;\n                }\n            }\n\n            // fill in the options\n            var colori = 0, s;\n            for (i = 0; i < series.length; ++i) {\n                s = series[i];\n\n                // assign colors\n                if (s.color == null) {\n                    s.color = colors[colori].toString();\n                    ++colori;\n                }\n                else if (typeof s.color == \"number\")\n                    s.color = colors[s.color].toString();\n\n                // turn on lines automatically in case nothing is set\n                if (s.lines.show == null) {\n                    var v, show = true;\n                    for (v in s)\n                        if (s[v] && s[v].show) {\n                            show = false;\n                            break;\n                        }\n                    if (show)\n                        s.lines.show = true;\n                }\n\n                // setup axes\n                s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, \"x\"));\n                s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, \"y\"));\n            }\n        }\n\n        function processData() {\n            var topSentry = Number.POSITIVE_INFINITY,\n                bottomSentry = Number.NEGATIVE_INFINITY,\n                fakeInfinity = Number.MAX_VALUE,\n                i, j, k, m, length,\n                s, points, ps, x, y, axis, val, f, p;\n\n            function updateAxis(axis, min, max) {\n                if (min < axis.datamin && min != -fakeInfinity)\n                    axis.datamin = min;\n                if (max > axis.datamax && max != fakeInfinity)\n                    axis.datamax = max;\n            }\n\n            $.each(allAxes(), function (_, axis) {\n                // init axis\n                axis.datamin = topSentry;\n                axis.datamax = bottomSentry;\n                axis.used = false;\n            });\n\n            for (i = 0; i < series.length; ++i) {\n                s = series[i];\n                s.datapoints = { points: [] };\n\n                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);\n            }\n\n            // first pass: clean and copy data\n            for (i = 0; i < series.length; ++i) {\n                s = series[i];\n\n                var data = s.data, format = s.datapoints.format;\n\n                if (!format) {\n                    format = [];\n                    // find out how to copy\n                    format.push({ x: true, number: true, required: true });\n                    format.push({ y: true, number: true, required: true });\n\n                    if (s.bars.show || (s.lines.show && s.lines.fill)) {\n                        format.push({ y: true, number: true, required: false, defaultValue: 0 });\n                        if (s.bars.horizontal) {\n                            delete format[format.length - 1].y;\n                            format[format.length - 1].x = true;\n                        }\n                    }\n\n                    s.datapoints.format = format;\n                }\n\n                if (s.datapoints.pointsize != null)\n                    continue; // already filled in\n\n                s.datapoints.pointsize = format.length;\n\n                ps = s.datapoints.pointsize;\n                points = s.datapoints.points;\n\n                insertSteps = s.lines.show && s.lines.steps;\n                s.xaxis.used = s.yaxis.used = true;\n\n                for (j = k = 0; j < data.length; ++j, k += ps) {\n                    p = data[j];\n\n                    var nullify = p == null;\n                    if (!nullify) {\n                        for (m = 0; m < ps; ++m) {\n                            val = p[m];\n                            f = format[m];\n\n                            if (f) {\n                                if (f.number && val != null) {\n                                    val = +val; // convert to number\n                                    if (isNaN(val))\n                                        val = null;\n                                    else if (val == Infinity)\n                                        val = fakeInfinity;\n                                    else if (val == -Infinity)\n                                        val = -fakeInfinity;\n                                }\n\n                                if (val == null) {\n                                    if (f.required)\n                                        nullify = true;\n\n                                    if (f.defaultValue != null)\n                                        val = f.defaultValue;\n                                }\n                            }\n\n                            points[k + m] = val;\n                        }\n                    }\n\n                    if (nullify) {\n                        for (m = 0; m < ps; ++m) {\n                            val = points[k + m];\n                            if (val != null) {\n                                f = format[m];\n                                // extract min/max info\n                                if (f.x)\n                                    updateAxis(s.xaxis, val, val);\n                                if (f.y)\n                                    updateAxis(s.yaxis, val, val);\n                            }\n                            points[k + m] = null;\n                        }\n                    }\n                    else {\n                        // a little bit of line specific stuff that\n                        // perhaps shouldn't be here, but lacking\n                        // better means...\n                        if (insertSteps && k > 0\n                            && points[k - ps] != null\n                            && points[k - ps] != points[k]\n                            && points[k - ps + 1] != points[k + 1]) {\n                            // copy the point to make room for a middle point\n                            for (m = 0; m < ps; ++m)\n                                points[k + ps + m] = points[k + m];\n\n                            // middle point has same y\n                            points[k + 1] = points[k - ps + 1];\n\n                            // we've added a point, better reflect that\n                            k += ps;\n                        }\n                    }\n                }\n            }\n\n            // give the hooks a chance to run\n            for (i = 0; i < series.length; ++i) {\n                s = series[i];\n\n                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);\n            }\n\n            // second pass: find datamax/datamin for auto-scaling\n            for (i = 0; i < series.length; ++i) {\n                s = series[i];\n                points = s.datapoints.points,\n                ps = s.datapoints.pointsize;\n\n                var xmin = topSentry, ymin = topSentry,\n                    xmax = bottomSentry, ymax = bottomSentry;\n\n                for (j = 0; j < points.length; j += ps) {\n                    if (points[j] == null)\n                        continue;\n\n                    for (m = 0; m < ps; ++m) {\n                        val = points[j + m];\n                        f = format[m];\n                        if (!f || val == fakeInfinity || val == -fakeInfinity)\n                            continue;\n\n                        if (f.x) {\n                            if (val < xmin)\n                                xmin = val;\n                            if (val > xmax)\n                                xmax = val;\n                        }\n                        if (f.y) {\n                            if (val < ymin)\n                                ymin = val;\n                            if (val > ymax)\n                                ymax = val;\n                        }\n                    }\n                }\n\n                if (s.bars.show) {\n                    // make sure we got room for the bar on the dancing floor\n                    var delta = s.bars.align == \"left\" ? 0 : -s.bars.barWidth/2;\n                    if (s.bars.horizontal) {\n                        ymin += delta;\n                        ymax += delta + s.bars.barWidth;\n                    }\n                    else {\n                        xmin += delta;\n                        xmax += delta + s.bars.barWidth;\n                    }\n                }\n\n                updateAxis(s.xaxis, xmin, xmax);\n                updateAxis(s.yaxis, ymin, ymax);\n            }\n\n            $.each(allAxes(), function (_, axis) {\n                if (axis.datamin == topSentry)\n                    axis.datamin = null;\n                if (axis.datamax == bottomSentry)\n                    axis.datamax = null;\n            });\n        }\n\n        function makeCanvas(skipPositioning, cls) {\n            var c = document.createElement('canvas');\n            c.className = cls;\n            c.width = canvasWidth;\n            c.height = canvasHeight;\n\n            if (!skipPositioning)\n                $(c).css({ position: 'absolute', left: 0, top: 0 });\n\n            $(c).appendTo(placeholder);\n\n            if (!c.getContext) // excanvas hack\n                c = window.G_vmlCanvasManager.initElement(c);\n\n            // used for resetting in case we get replotted\n            c.getContext(\"2d\").save();\n\n            return c;\n        }\n\n        function getCanvasDimensions() {\n            canvasWidth = placeholder.width();\n            canvasHeight = placeholder.height();\n\n            if (canvasWidth <= 0 || canvasHeight <= 0)\n                throw \"Invalid dimensions for plot, width = \" + canvasWidth + \", height = \" + canvasHeight;\n        }\n\n        function resizeCanvas(c) {\n            // resizing should reset the state (excanvas seems to be\n            // buggy though)\n            if (c.width != canvasWidth)\n                c.width = canvasWidth;\n\n            if (c.height != canvasHeight)\n                c.height = canvasHeight;\n\n            // so try to get back to the initial state (even if it's\n            // gone now, this should be safe according to the spec)\n            var cctx = c.getContext(\"2d\");\n            cctx.restore();\n\n            // and save again\n            cctx.save();\n        }\n\n        function setupCanvases() {\n            var reused,\n                existingCanvas = placeholder.children(\"canvas.base\"),\n                existingOverlay = placeholder.children(\"canvas.overlay\");\n\n            if (existingCanvas.length == 0 || existingOverlay == 0) {\n                // init everything\n\n                placeholder.html(\"\"); // make sure placeholder is clear\n\n                placeholder.css({ padding: 0 }); // padding messes up the positioning\n\n                if (placeholder.css(\"position\") == 'static')\n                    placeholder.css(\"position\", \"relative\"); // for positioning labels and overlay\n\n                getCanvasDimensions();\n\n                canvas = makeCanvas(true, \"base\");\n                overlay = makeCanvas(false, \"overlay\"); // overlay canvas for interactive features\n\n                reused = false;\n            }\n            else {\n                // reuse existing elements\n\n                canvas = existingCanvas.get(0);\n                overlay = existingOverlay.get(0);\n\n                reused = true;\n            }\n\n            ctx = canvas.getContext(\"2d\");\n            octx = overlay.getContext(\"2d\");\n\n            // we include the canvas in the event holder too, because IE 7\n            // sometimes has trouble with the stacking order\n            eventHolder = $([overlay, canvas]);\n\n            if (reused) {\n                // run shutdown in the old plot object\n                placeholder.data(\"plot\").shutdown();\n\n                // reset reused canvases\n                plot.resize();\n\n                // make sure overlay pixels are cleared (canvas is cleared when we redraw)\n                octx.clearRect(0, 0, canvasWidth, canvasHeight);\n\n                // then whack any remaining obvious garbage left\n                eventHolder.unbind();\n                placeholder.children().not([canvas, overlay]).remove();\n            }\n\n            // save in case we get replotted\n            placeholder.data(\"plot\", plot);\n        }\n\n        function bindEvents() {\n            // bind events\n            if (options.grid.hoverable) {\n                eventHolder.mousemove(onMouseMove);\n                eventHolder.mouseleave(onMouseLeave);\n            }\n\n            if (options.grid.clickable)\n                eventHolder.click(onClick);\n\n            executeHooks(hooks.bindEvents, [eventHolder]);\n        }\n\n        function shutdown() {\n            if (redrawTimeout)\n                clearTimeout(redrawTimeout);\n\n            eventHolder.unbind(\"mousemove\", onMouseMove);\n            eventHolder.unbind(\"mouseleave\", onMouseLeave);\n            eventHolder.unbind(\"click\", onClick);\n\n            executeHooks(hooks.shutdown, [eventHolder]);\n        }\n\n        function setTransformationHelpers(axis) {\n            // set helper functions on the axis, assumes plot area\n            // has been computed already\n\n            function identity(x) { return x; }\n\n            var s, m, t = axis.options.transform || identity,\n                it = axis.options.inverseTransform;\n\n            // precompute how much the axis is scaling a point\n            // in canvas space\n            if (axis.direction == \"x\") {\n                s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));\n                m = Math.min(t(axis.max), t(axis.min));\n            }\n            else {\n                s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));\n                s = -s;\n                m = Math.max(t(axis.max), t(axis.min));\n            }\n\n            // data point to canvas coordinate\n            if (t == identity) // slight optimization\n                axis.p2c = function (p) { return (p - m) * s; };\n            else\n                axis.p2c = function (p) { return (t(p) - m) * s; };\n            // canvas coordinate to data point\n            if (!it)\n                axis.c2p = function (c) { return m + c / s; };\n            else\n                axis.c2p = function (c) { return it(m + c / s); };\n        }\n\n        function measureTickLabels(axis) {\n            var opts = axis.options, i, ticks = axis.ticks || [], labels = [],\n                l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv;\n\n            function makeDummyDiv(labels, width) {\n                return $('<div style=\"position:absolute;top:-10000px;' + width + 'font-size:smaller\">' +\n                         '<div class=\"' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis\">'\n                         + labels.join(\"\") + '</div></div>')\n                    .appendTo(placeholder);\n            }\n\n            if (axis.direction == \"x\") {\n                // to avoid measuring the widths of the labels (it's slow), we\n                // construct fixed-size boxes and put the labels inside\n                // them, we don't need the exact figures and the\n                // fixed-size box content is easy to center\n                if (w == null)\n                    w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1));\n\n                // measure x label heights\n                if (h == null) {\n                    labels = [];\n                    for (i = 0; i < ticks.length; ++i) {\n                        l = ticks[i].label;\n                        if (l)\n                            labels.push('<div class=\"tickLabel\" style=\"float:left;width:' + w + 'px\">' + l + '</div>');\n                    }\n\n                    if (labels.length > 0) {\n                        // stick them all in the same div and measure\n                        // collective height\n                        labels.push('<div style=\"clear:left\"></div>');\n                        dummyDiv = makeDummyDiv(labels, \"width:10000px;\");\n                        h = dummyDiv.height();\n                        dummyDiv.remove();\n                    }\n                }\n            }\n            else if (w == null || h == null) {\n                // calculate y label dimensions\n                for (i = 0; i < ticks.length; ++i) {\n                    l = ticks[i].label;\n                    if (l)\n                        labels.push('<div class=\"tickLabel\">' + l + '</div>');\n                }\n\n                if (labels.length > 0) {\n                    dummyDiv = makeDummyDiv(labels, \"\");\n                    if (w == null)\n                        w = dummyDiv.children().width();\n                    if (h == null)\n                        h = dummyDiv.find(\"div.tickLabel\").height();\n                    dummyDiv.remove();\n                }\n            }\n\n            if (w == null)\n                w = 0;\n            if (h == null)\n                h = 0;\n\n            axis.labelWidth = w;\n            axis.labelHeight = h;\n        }\n\n        function allocateAxisBoxFirstPhase(axis) {\n            // find the bounding box of the axis by looking at label\n            // widths/heights and ticks, make room by diminishing the\n            // plotOffset\n\n            var lw = axis.labelWidth,\n                lh = axis.labelHeight,\n                pos = axis.options.position,\n                tickLength = axis.options.tickLength,\n                axismargin = options.grid.axisMargin,\n                padding = options.grid.labelMargin,\n                all = axis.direction == \"x\" ? xaxes : yaxes,\n                index;\n\n            // determine axis margin\n            var samePosition = $.grep(all, function (a) {\n                return a && a.options.position == pos && a.reserveSpace;\n            });\n            if ($.inArray(axis, samePosition) == samePosition.length - 1)\n                axismargin = 0; // outermost\n\n            // determine tick length - if we're innermost, we can use \"full\"\n            if (tickLength == null)\n                tickLength = \"full\";\n\n            var sameDirection = $.grep(all, function (a) {\n                return a && a.reserveSpace;\n            });\n\n            var innermost = $.inArray(axis, sameDirection) == 0;\n            if (!innermost && tickLength == \"full\")\n                tickLength = 5;\n\n            if (!isNaN(+tickLength))\n                padding += +tickLength;\n\n            // compute box\n            if (axis.direction == \"x\") {\n                lh += padding;\n\n                if (pos == \"bottom\") {\n                    plotOffset.bottom += lh + axismargin;\n                    axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };\n                }\n                else {\n                    axis.box = { top: plotOffset.top + axismargin, height: lh };\n                    plotOffset.top += lh + axismargin;\n                }\n            }\n            else {\n                lw += padding;\n\n                if (pos == \"left\") {\n                    axis.box = { left: plotOffset.left + axismargin, width: lw };\n                    plotOffset.left += lw + axismargin;\n                }\n                else {\n                    plotOffset.right += lw + axismargin;\n                    axis.box = { left: canvasWidth - plotOffset.right, width: lw };\n                }\n            }\n\n             // save for future reference\n            axis.position = pos;\n            axis.tickLength = tickLength;\n            axis.box.padding = padding;\n            axis.innermost = innermost;\n        }\n\n        function allocateAxisBoxSecondPhase(axis) {\n            // set remaining bounding box coordinates\n            if (axis.direction == \"x\") {\n                axis.box.left = plotOffset.left;\n                axis.box.width = plotWidth;\n            }\n            else {\n                axis.box.top = plotOffset.top;\n                axis.box.height = plotHeight;\n            }\n        }\n\n        function setupGrid() {\n            var i, axes = allAxes();\n\n            // first calculate the plot and axis box dimensions\n\n            $.each(axes, function (_, axis) {\n                axis.show = axis.options.show;\n                if (axis.show == null)\n                    axis.show = axis.used; // by default an axis is visible if it's got data\n\n                axis.reserveSpace = axis.show || axis.options.reserveSpace;\n\n                setRange(axis);\n            });\n\n            allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });\n\n            plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;\n            if (options.grid.show) {\n                $.each(allocatedAxes, function (_, axis) {\n                    // make the ticks\n                    setupTickGeneration(axis);\n                    setTicks(axis);\n                    snapRangeToTicks(axis, axis.ticks);\n\n                    // find labelWidth/Height for axis\n                    measureTickLabels(axis);\n                });\n\n                // with all dimensions in house, we can compute the\n                // axis boxes, start from the outside (reverse order)\n                for (i = allocatedAxes.length - 1; i >= 0; --i)\n                    allocateAxisBoxFirstPhase(allocatedAxes[i]);\n\n                // make sure we've got enough space for things that\n                // might stick out\n                var minMargin = options.grid.minBorderMargin;\n                if (minMargin == null) {\n                    minMargin = 0;\n                    for (i = 0; i < series.length; ++i)\n                        minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2);\n                }\n\n                for (var a in plotOffset) {\n                    plotOffset[a] += options.grid.borderWidth;\n                    plotOffset[a] = Math.max(minMargin, plotOffset[a]);\n                }\n            }\n\n            plotWidth = canvasWidth - plotOffset.left - plotOffset.right;\n            plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;\n\n            // now we got the proper plotWidth/Height, we can compute the scaling\n            $.each(axes, function (_, axis) {\n                setTransformationHelpers(axis);\n            });\n\n            if (options.grid.show) {\n                $.each(allocatedAxes, function (_, axis) {\n                    allocateAxisBoxSecondPhase(axis);\n                });\n\n                insertAxisLabels();\n            }\n\n            insertLegend();\n        }\n\n        function setRange(axis) {\n            var opts = axis.options,\n                min = +(opts.min != null ? opts.min : axis.datamin),\n                max = +(opts.max != null ? opts.max : axis.datamax),\n                delta = max - min;\n\n            if (delta == 0.0) {\n                // degenerate case\n                var widen = max == 0 ? 1 : 0.01;\n\n                if (opts.min == null)\n                    min -= widen;\n                // always widen max if we couldn't widen min to ensure we\n                // don't fall into min == max which doesn't work\n                if (opts.max == null || opts.min != null)\n                    max += widen;\n            }\n            else {\n                // consider autoscaling\n                var margin = opts.autoscaleMargin;\n                if (margin != null) {\n                    if (opts.min == null) {\n                        min -= delta * margin;\n                        // make sure we don't go below zero if all values\n                        // are positive\n                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)\n                            min = 0;\n                    }\n                    if (opts.max == null) {\n                        max += delta * margin;\n                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)\n                            max = 0;\n                    }\n                }\n            }\n            axis.min = min;\n            axis.max = max;\n        }\n\n        function setupTickGeneration(axis) {\n            var opts = axis.options;\n\n            // estimate number of ticks\n            var noTicks;\n            if (typeof opts.ticks == \"number\" && opts.ticks > 0)\n                noTicks = opts.ticks;\n            else\n                // heuristic based on the model a*sqrt(x) fitted to\n                // some data points that seemed reasonable\n                noTicks = 0.3 * Math.sqrt(axis.direction == \"x\" ? canvasWidth : canvasHeight);\n\n            var delta = (axis.max - axis.min) / noTicks,\n                size, generator, unit, formatter, i, magn, norm;\n\n            if (opts.mode == \"time\") {\n                // pretty handling of time\n\n                // map of app. size of time units in milliseconds\n                var timeUnitSize = {\n                    \"second\": 1000,\n                    \"minute\": 60 * 1000,\n                    \"hour\": 60 * 60 * 1000,\n                    \"day\": 24 * 60 * 60 * 1000,\n                    \"month\": 30 * 24 * 60 * 60 * 1000,\n                    \"year\": 365.2425 * 24 * 60 * 60 * 1000\n                };\n\n\n                // the allowed tick sizes, after 1 year we use\n                // an integer algorithm\n                var spec = [\n                    [1, \"second\"], [2, \"second\"], [5, \"second\"], [10, \"second\"],\n                    [30, \"second\"],\n                    [1, \"minute\"], [2, \"minute\"], [5, \"minute\"], [10, \"minute\"],\n                    [30, \"minute\"],\n                    [1, \"hour\"], [2, \"hour\"], [4, \"hour\"],\n                    [8, \"hour\"], [12, \"hour\"],\n                    [1, \"day\"], [2, \"day\"], [3, \"day\"],\n                    [0.25, \"month\"], [0.5, \"month\"], [1, \"month\"],\n                    [2, \"month\"], [3, \"month\"], [6, \"month\"],\n                    [1, \"year\"]\n                ];\n\n                var minSize = 0;\n                if (opts.minTickSize != null) {\n                    if (typeof opts.tickSize == \"number\")\n                        minSize = opts.tickSize;\n                    else\n                        minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];\n                }\n\n                for (var i = 0; i < spec.length - 1; ++i)\n                    if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]\n                                 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2\n                       && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)\n                        break;\n                size = spec[i][0];\n                unit = spec[i][1];\n\n                // special-case the possibility of several years\n                if (unit == \"year\") {\n                    magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));\n                    norm = (delta / timeUnitSize.year) / magn;\n                    if (norm < 1.5)\n                        size = 1;\n                    else if (norm < 3)\n                        size = 2;\n                    else if (norm < 7.5)\n                        size = 5;\n                    else\n                        size = 10;\n\n                    size *= magn;\n                }\n\n                axis.tickSize = opts.tickSize || [size, unit];\n\n                generator = function(axis) {\n                    var ticks = [],\n                        tickSize = axis.tickSize[0], unit = axis.tickSize[1],\n                        d = new Date(axis.min);\n\n                    var step = tickSize * timeUnitSize[unit];\n\n                    if (unit == \"second\")\n                        d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));\n                    if (unit == \"minute\")\n                        d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));\n                    if (unit == \"hour\")\n                        d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));\n                    if (unit == \"month\")\n                        d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));\n                    if (unit == \"year\")\n                        d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));\n\n                    // reset smaller components\n                    d.setUTCMilliseconds(0);\n                    if (step >= timeUnitSize.minute)\n                        d.setUTCSeconds(0);\n                    if (step >= timeUnitSize.hour)\n                        d.setUTCMinutes(0);\n                    if (step >= timeUnitSize.day)\n                        d.setUTCHours(0);\n                    if (step >= timeUnitSize.day * 4)\n                        d.setUTCDate(1);\n                    if (step >= timeUnitSize.year)\n                        d.setUTCMonth(0);\n\n\n                    var carry = 0, v = Number.NaN, prev;\n                    do {\n                        prev = v;\n                        v = d.getTime();\n                        ticks.push(v);\n                        if (unit == \"month\") {\n                            if (tickSize < 1) {\n                                // a bit complicated - we'll divide the month\n                                // up but we need to take care of fractions\n                                // so we don't end up in the middle of a day\n                                d.setUTCDate(1);\n                                var start = d.getTime();\n                                d.setUTCMonth(d.getUTCMonth() + 1);\n                                var end = d.getTime();\n                                d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);\n                                carry = d.getUTCHours();\n                                d.setUTCHours(0);\n                            }\n                            else\n                                d.setUTCMonth(d.getUTCMonth() + tickSize);\n                        }\n                        else if (unit == \"year\") {\n                            d.setUTCFullYear(d.getUTCFullYear() + tickSize);\n                        }\n                        else\n                            d.setTime(v + step);\n                    } while (v < axis.max && v != prev);\n\n                    return ticks;\n                };\n\n                formatter = function (v, axis) {\n                    var d = new Date(v);\n\n                    // first check global format\n                    if (opts.timeformat != null)\n                        return $.plot.formatDate(d, opts.timeformat, opts.monthNames);\n\n                    var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];\n                    var span = axis.max - axis.min;\n                    var suffix = (opts.twelveHourClock) ? \" %p\" : \"\";\n\n                    if (t < timeUnitSize.minute)\n                        fmt = \"%h:%M:%S\" + suffix;\n                    else if (t < timeUnitSize.day) {\n                        if (span < 2 * timeUnitSize.day)\n                            fmt = \"%h:%M\" + suffix;\n                        else\n                            fmt = \"%b %d %h:%M\" + suffix;\n                    }\n                    else if (t < timeUnitSize.month)\n                        fmt = \"%b %d\";\n                    else if (t < timeUnitSize.year) {\n                        if (span < timeUnitSize.year)\n                            fmt = \"%b\";\n                        else\n                            fmt = \"%b %y\";\n                    }\n                    else\n                        fmt = \"%y\";\n\n                    return $.plot.formatDate(d, fmt, opts.monthNames);\n                };\n            }\n            else {\n                // pretty rounding of base-10 numbers\n                var maxDec = opts.tickDecimals;\n                var dec = -Math.floor(Math.log(delta) / Math.LN10);\n                if (maxDec != null && dec > maxDec)\n                    dec = maxDec;\n\n                magn = Math.pow(10, -dec);\n                norm = delta / magn; // norm is between 1.0 and 10.0\n\n                if (norm < 1.5)\n                    size = 1;\n                else if (norm < 3) {\n                    size = 2;\n                    // special case for 2.5, requires an extra decimal\n                    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {\n                        size = 2.5;\n                        ++dec;\n                    }\n                }\n                else if (norm < 7.5)\n                    size = 5;\n                else\n                    size = 10;\n\n                size *= magn;\n\n                if (opts.minTickSize != null && size < opts.minTickSize)\n                    size = opts.minTickSize;\n\n                axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);\n                axis.tickSize = opts.tickSize || size;\n\n                generator = function (axis) {\n                    var ticks = [];\n\n                    // spew out all possible ticks\n                    var start = floorInBase(axis.min, axis.tickSize),\n                        i = 0, v = Number.NaN, prev;\n                    do {\n                        prev = v;\n                        v = start + i * axis.tickSize;\n                        ticks.push(v);\n                        ++i;\n                    } while (v < axis.max && v != prev);\n                    return ticks;\n                };\n\n                formatter = function (v, axis) {\n                    return v.toFixed(axis.tickDecimals);\n                };\n            }\n\n            if (opts.alignTicksWithAxis != null) {\n                var otherAxis = (axis.direction == \"x\" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];\n                if (otherAxis && otherAxis.used && otherAxis != axis) {\n                    // consider snapping min/max to outermost nice ticks\n                    var niceTicks = generator(axis);\n                    if (niceTicks.length > 0) {\n                        if (opts.min == null)\n                            axis.min = Math.min(axis.min, niceTicks[0]);\n                        if (opts.max == null && niceTicks.length > 1)\n                            axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);\n                    }\n\n                    generator = function (axis) {\n                        // copy ticks, scaled to this axis\n                        var ticks = [], v, i;\n                        for (i = 0; i < otherAxis.ticks.length; ++i) {\n                            v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);\n                            v = axis.min + v * (axis.max - axis.min);\n                            ticks.push(v);\n                        }\n                        return ticks;\n                    };\n\n                    // we might need an extra decimal since forced\n                    // ticks don't necessarily fit naturally\n                    if (axis.mode != \"time\" && opts.tickDecimals == null) {\n                        var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),\n                            ts = generator(axis);\n\n                        // only proceed if the tick interval rounded\n                        // with an extra decimal doesn't give us a\n                        // zero at end\n                        if (!(ts.length > 1 && /\\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))\n                            axis.tickDecimals = extraDec;\n                    }\n                }\n            }\n\n            axis.tickGenerator = generator;\n            if ($.isFunction(opts.tickFormatter))\n                axis.tickFormatter = function (v, axis) { return \"\" + opts.tickFormatter(v, axis); };\n            else\n                axis.tickFormatter = formatter;\n        }\n\n        function setTicks(axis) {\n            var oticks = axis.options.ticks, ticks = [];\n            if (oticks == null || (typeof oticks == \"number\" && oticks > 0))\n                ticks = axis.tickGenerator(axis);\n            else if (oticks) {\n                if ($.isFunction(oticks))\n                    // generate the ticks\n                    ticks = oticks({ min: axis.min, max: axis.max });\n                else\n                    ticks = oticks;\n            }\n\n            // clean up/labelify the supplied ticks, copy them over\n            var i, v;\n            axis.ticks = [];\n            for (i = 0; i < ticks.length; ++i) {\n                var label = null;\n                var t = ticks[i];\n                if (typeof t == \"object\") {\n                    v = +t[0];\n                    if (t.length > 1)\n                        label = t[1];\n                }\n                else\n                    v = +t;\n                if (label == null)\n                    label = axis.tickFormatter(v, axis);\n                if (!isNaN(v))\n                    axis.ticks.push({ v: v, label: label });\n            }\n        }\n\n        function snapRangeToTicks(axis, ticks) {\n            if (axis.options.autoscaleMargin && ticks.length > 0) {\n                // snap to ticks\n                if (axis.options.min == null)\n                    axis.min = Math.min(axis.min, ticks[0].v);\n                if (axis.options.max == null && ticks.length > 1)\n                    axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);\n            }\n        }\n\n        function draw() {\n            ctx.clearRect(0, 0, canvasWidth, canvasHeight);\n\n            var grid = options.grid;\n\n            // draw background, if any\n            if (grid.show && grid.backgroundColor)\n                drawBackground();\n\n            if (grid.show && !grid.aboveData)\n                drawGrid();\n\n            for (var i = 0; i < series.length; ++i) {\n                executeHooks(hooks.drawSeries, [ctx, series[i]]);\n                drawSeries(series[i]);\n            }\n\n            executeHooks(hooks.draw, [ctx]);\n\n            if (grid.show && grid.aboveData)\n                drawGrid();\n        }\n\n        function extractRange(ranges, coord) {\n            var axis, from, to, key, axes = allAxes();\n\n            for (i = 0; i < axes.length; ++i) {\n                axis = axes[i];\n                if (axis.direction == coord) {\n                    key = coord + axis.n + \"axis\";\n                    if (!ranges[key] && axis.n == 1)\n                        key = coord + \"axis\"; // support x1axis as xaxis\n                    if (ranges[key]) {\n                        from = ranges[key].from;\n                        to = ranges[key].to;\n                        break;\n                    }\n                }\n            }\n\n            // backwards-compat stuff - to be removed in future\n            if (!ranges[key]) {\n                axis = coord == \"x\" ? xaxes[0] : yaxes[0];\n                from = ranges[coord + \"1\"];\n                to = ranges[coord + \"2\"];\n            }\n\n            // auto-reverse as an added bonus\n            if (from != null && to != null && from > to) {\n                var tmp = from;\n                from = to;\n                to = tmp;\n            }\n\n            return { from: from, to: to, axis: axis };\n        }\n\n        function drawBackground() {\n            ctx.save();\n            ctx.translate(plotOffset.left, plotOffset.top);\n\n            ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, \"rgba(255, 255, 255, 0)\");\n            ctx.fillRect(0, 0, plotWidth, plotHeight);\n            ctx.restore();\n        }\n\n        function drawGrid() {\n            var i;\n\n            ctx.save();\n            ctx.translate(plotOffset.left, plotOffset.top);\n\n            // draw markings\n            var markings = options.grid.markings;\n            if (markings) {\n                if ($.isFunction(markings)) {\n                    var axes = plot.getAxes();\n                    // xmin etc. is backwards compatibility, to be\n                    // removed in the future\n                    axes.xmin = axes.xaxis.min;\n                    axes.xmax = axes.xaxis.max;\n                    axes.ymin = axes.yaxis.min;\n                    axes.ymax = axes.yaxis.max;\n\n                    markings = markings(axes);\n                }\n\n                for (i = 0; i < markings.length; ++i) {\n                    var m = markings[i],\n                        xrange = extractRange(m, \"x\"),\n                        yrange = extractRange(m, \"y\");\n\n                    // fill in missing\n                    if (xrange.from == null)\n                        xrange.from = xrange.axis.min;\n                    if (xrange.to == null)\n                        xrange.to = xrange.axis.max;\n                    if (yrange.from == null)\n                        yrange.from = yrange.axis.min;\n                    if (yrange.to == null)\n                        yrange.to = yrange.axis.max;\n\n                    // clip\n                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||\n                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)\n                        continue;\n\n                    xrange.from = Math.max(xrange.from, xrange.axis.min);\n                    xrange.to = Math.min(xrange.to, xrange.axis.max);\n                    yrange.from = Math.max(yrange.from, yrange.axis.min);\n                    yrange.to = Math.min(yrange.to, yrange.axis.max);\n\n                    if (xrange.from == xrange.to && yrange.from == yrange.to)\n                        continue;\n\n                    // then draw\n                    xrange.from = xrange.axis.p2c(xrange.from);\n                    xrange.to = xrange.axis.p2c(xrange.to);\n                    yrange.from = yrange.axis.p2c(yrange.from);\n                    yrange.to = yrange.axis.p2c(yrange.to);\n\n                    if (xrange.from == xrange.to || yrange.from == yrange.to) {\n                        // draw line\n                        ctx.beginPath();\n                        ctx.strokeStyle = m.color || options.grid.markingsColor;\n                        ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;\n                        ctx.moveTo(xrange.from, yrange.from);\n                        ctx.lineTo(xrange.to, yrange.to);\n                        ctx.stroke();\n                    }\n                    else {\n                        // fill area\n                        ctx.fillStyle = m.color || options.grid.markingsColor;\n                        ctx.fillRect(xrange.from, yrange.to,\n                                     xrange.to - xrange.from,\n                                     yrange.from - yrange.to);\n                    }\n                }\n            }\n\n            // draw the ticks\n            var axes = allAxes(), bw = options.grid.borderWidth;\n\n            for (var j = 0; j < axes.length; ++j) {\n                var axis = axes[j], box = axis.box,\n                    t = axis.tickLength, x, y, xoff, yoff;\n                if (!axis.show || axis.ticks.length == 0)\n                    continue\n\n                ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString();\n                ctx.lineWidth = 1;\n\n                // find the edges\n                if (axis.direction == \"x\") {\n                    x = 0;\n                    if (t == \"full\")\n                        y = (axis.position == \"top\" ? 0 : plotHeight);\n                    else\n                        y = box.top - plotOffset.top + (axis.position == \"top\" ? box.height : 0);\n                }\n                else {\n                    y = 0;\n                    if (t == \"full\")\n                        x = (axis.position == \"left\" ? 0 : plotWidth);\n                    else\n                        x = box.left - plotOffset.left + (axis.position == \"left\" ? box.width : 0);\n                }\n\n                // draw tick bar\n                if (!axis.innermost) {\n                    ctx.beginPath();\n                    xoff = yoff = 0;\n                    if (axis.direction == \"x\")\n                        xoff = plotWidth;\n                    else\n                        yoff = plotHeight;\n\n                    if (ctx.lineWidth == 1) {\n                        x = Math.floor(x) + 0.5;\n                        y = Math.floor(y) + 0.5;\n                    }\n\n                    ctx.moveTo(x, y);\n                    ctx.lineTo(x + xoff, y + yoff);\n                    ctx.stroke();\n                }\n\n                // draw ticks\n                ctx.beginPath();\n                for (i = 0; i < axis.ticks.length; ++i) {\n                    var v = axis.ticks[i].v;\n\n                    xoff = yoff = 0;\n\n                    if (v < axis.min || v > axis.max\n                        // skip those lying on the axes if we got a border\n                        || (t == \"full\" && bw > 0\n                            && (v == axis.min || v == axis.max)))\n                        continue;\n\n                    if (axis.direction == \"x\") {\n                        x = axis.p2c(v);\n                        yoff = t == \"full\" ? -plotHeight : t;\n\n                        if (axis.position == \"top\")\n                            yoff = -yoff;\n                    }\n                    else {\n                        y = axis.p2c(v);\n                        xoff = t == \"full\" ? -plotWidth : t;\n\n                        if (axis.position == \"left\")\n                            xoff = -xoff;\n                    }\n\n                    if (ctx.lineWidth == 1) {\n                        if (axis.direction == \"x\")\n                            x = Math.floor(x) + 0.5;\n                        else\n                            y = Math.floor(y) + 0.5;\n                    }\n\n                    ctx.moveTo(x, y);\n                    ctx.lineTo(x + xoff, y + yoff);\n                }\n\n                ctx.stroke();\n            }\n\n\n            // draw border\n            if (bw) {\n                ctx.lineWidth = bw;\n                ctx.strokeStyle = options.grid.borderColor;\n                ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);\n            }\n\n            ctx.restore();\n        }\n\n        function insertAxisLabels() {\n            placeholder.find(\".tickLabels\").remove();\n\n            var html = ['<div class=\"tickLabels\" style=\"font-size:smaller\">'];\n\n            var axes = allAxes();\n            for (var j = 0; j < axes.length; ++j) {\n                var axis = axes[j], box = axis.box;\n                if (!axis.show)\n                    continue;\n                //debug: html.push('<div style=\"position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width +  'px;height:' + box.height + 'px\"></div>')\n                html.push('<div class=\"' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis\" style=\"color:' + axis.options.color + '\">');\n                for (var i = 0; i < axis.ticks.length; ++i) {\n                    var tick = axis.ticks[i];\n                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)\n                        continue;\n\n                    var pos = {}, align;\n\n                    if (axis.direction == \"x\") {\n                        align = \"center\";\n                        pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2);\n                        if (axis.position == \"bottom\")\n                            pos.top = box.top + box.padding;\n                        else\n                            pos.bottom = canvasHeight - (box.top + box.height - box.padding);\n                    }\n                    else {\n                        pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2);\n                        if (axis.position == \"left\") {\n                            pos.right = canvasWidth - (box.left + box.width - box.padding)\n                            align = \"right\";\n                        }\n                        else {\n                            pos.left = box.left + box.padding;\n                            align = \"left\";\n                        }\n                    }\n\n                    pos.width = axis.labelWidth;\n\n                    var style = [\"position:absolute\", \"text-align:\" + align ];\n                    for (var a in pos)\n                        style.push(a + \":\" + pos[a] + \"px\")\n\n                    html.push('<div class=\"tickLabel\" style=\"' + style.join(';') + '\">' + tick.label + '</div>');\n                }\n                html.push('</div>');\n            }\n\n            html.push('</div>');\n\n            placeholder.append(html.join(\"\"));\n        }\n\n        function drawSeries(series) {\n            if (series.lines.show)\n                drawSeriesLines(series);\n            if (series.bars.show)\n                drawSeriesBars(series);\n            if (series.points.show)\n                drawSeriesPoints(series);\n        }\n\n        function drawSeriesLines(series) {\n            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {\n                var points = datapoints.points,\n                    ps = datapoints.pointsize,\n                    prevx = null, prevy = null;\n\n                ctx.beginPath();\n                for (var i = ps; i < points.length; i += ps) {\n                    var x1 = points[i - ps], y1 = points[i - ps + 1],\n                        x2 = points[i], y2 = points[i + 1];\n\n                    if (x1 == null || x2 == null)\n                        continue;\n\n                    // clip with ymin\n                    if (y1 <= y2 && y1 < axisy.min) {\n                        if (y2 < axisy.min)\n                            continue;   // line segment is outside\n                        // compute new intersection point\n                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y1 = axisy.min;\n                    }\n                    else if (y2 <= y1 && y2 < axisy.min) {\n                        if (y1 < axisy.min)\n                            continue;\n                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y2 = axisy.min;\n                    }\n\n                    // clip with ymax\n                    if (y1 >= y2 && y1 > axisy.max) {\n                        if (y2 > axisy.max)\n                            continue;\n                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y1 = axisy.max;\n                    }\n                    else if (y2 >= y1 && y2 > axisy.max) {\n                        if (y1 > axisy.max)\n                            continue;\n                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y2 = axisy.max;\n                    }\n\n                    // clip with xmin\n                    if (x1 <= x2 && x1 < axisx.min) {\n                        if (x2 < axisx.min)\n                            continue;\n                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x1 = axisx.min;\n                    }\n                    else if (x2 <= x1 && x2 < axisx.min) {\n                        if (x1 < axisx.min)\n                            continue;\n                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x2 = axisx.min;\n                    }\n\n                    // clip with xmax\n                    if (x1 >= x2 && x1 > axisx.max) {\n                        if (x2 > axisx.max)\n                            continue;\n                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x1 = axisx.max;\n                    }\n                    else if (x2 >= x1 && x2 > axisx.max) {\n                        if (x1 > axisx.max)\n                            continue;\n                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x2 = axisx.max;\n                    }\n\n                    if (x1 != prevx || y1 != prevy)\n                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);\n\n                    prevx = x2;\n                    prevy = y2;\n                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);\n                }\n                ctx.stroke();\n            }\n\n            function plotLineArea(datapoints, axisx, axisy) {\n                var points = datapoints.points,\n                    ps = datapoints.pointsize,\n                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),\n                    i = 0, top, areaOpen = false,\n                    ypos = 1, segmentStart = 0, segmentEnd = 0;\n\n                // we process each segment in two turns, first forward\n                // direction to sketch out top, then once we hit the\n                // end we go backwards to sketch the bottom\n                while (true) {\n                    if (ps > 0 && i > points.length + ps)\n                        break;\n\n                    i += ps; // ps is negative if going backwards\n\n                    var x1 = points[i - ps],\n                        y1 = points[i - ps + ypos],\n                        x2 = points[i], y2 = points[i + ypos];\n\n                    if (areaOpen) {\n                        if (ps > 0 && x1 != null && x2 == null) {\n                            // at turning point\n                            segmentEnd = i;\n                            ps = -ps;\n                            ypos = 2;\n                            continue;\n                        }\n\n                        if (ps < 0 && i == segmentStart + ps) {\n                            // done with the reverse sweep\n                            ctx.fill();\n                            areaOpen = false;\n                            ps = -ps;\n                            ypos = 1;\n                            i = segmentStart = segmentEnd + ps;\n                            continue;\n                        }\n                    }\n\n                    if (x1 == null || x2 == null)\n                        continue;\n\n                    // clip x values\n\n                    // clip with xmin\n                    if (x1 <= x2 && x1 < axisx.min) {\n                        if (x2 < axisx.min)\n                            continue;\n                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x1 = axisx.min;\n                    }\n                    else if (x2 <= x1 && x2 < axisx.min) {\n                        if (x1 < axisx.min)\n                            continue;\n                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x2 = axisx.min;\n                    }\n\n                    // clip with xmax\n                    if (x1 >= x2 && x1 > axisx.max) {\n                        if (x2 > axisx.max)\n                            continue;\n                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x1 = axisx.max;\n                    }\n                    else if (x2 >= x1 && x2 > axisx.max) {\n                        if (x1 > axisx.max)\n                            continue;\n                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n                        x2 = axisx.max;\n                    }\n\n                    if (!areaOpen) {\n                        // open area\n                        ctx.beginPath();\n                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));\n                        areaOpen = true;\n                    }\n\n                    // now first check the case where both is outside\n                    if (y1 >= axisy.max && y2 >= axisy.max) {\n                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));\n                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));\n                        continue;\n                    }\n                    else if (y1 <= axisy.min && y2 <= axisy.min) {\n                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));\n                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));\n                        continue;\n                    }\n\n                    // else it's a bit more complicated, there might\n                    // be a flat maxed out rectangle first, then a\n                    // triangular cutout or reverse; to find these\n                    // keep track of the current x values\n                    var x1old = x1, x2old = x2;\n\n                    // clip the y values, without shortcutting, we\n                    // go through all cases in turn\n\n                    // clip with ymin\n                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {\n                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y1 = axisy.min;\n                    }\n                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {\n                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y2 = axisy.min;\n                    }\n\n                    // clip with ymax\n                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {\n                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y1 = axisy.max;\n                    }\n                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {\n                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n                        y2 = axisy.max;\n                    }\n\n                    // if the x value was changed we got a rectangle\n                    // to fill\n                    if (x1 != x1old) {\n                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));\n                        // it goes to (x1, y1), but we fill that below\n                    }\n\n                    // fill triangular section, this sometimes result\n                    // in redundant points if (x1, y1) hasn't changed\n                    // from previous line to, but we just ignore that\n                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));\n                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));\n\n                    // fill the other rectangle if it's there\n                    if (x2 != x2old) {\n                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));\n                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));\n                    }\n                }\n            }\n\n            ctx.save();\n            ctx.translate(plotOffset.left, plotOffset.top);\n            ctx.lineJoin = \"round\";\n\n            var lw = series.lines.lineWidth,\n                sw = series.shadowSize;\n            // FIXME: consider another form of shadow when filling is turned on\n            if (lw > 0 && sw > 0) {\n                // draw shadow as a thick and thin line with transparency\n                ctx.lineWidth = sw;\n                ctx.strokeStyle = \"rgba(0,0,0,0.1)\";\n                // position shadow at angle from the mid of line\n                var angle = Math.PI/18;\n                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);\n                ctx.lineWidth = sw/2;\n                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);\n            }\n\n            ctx.lineWidth = lw;\n            ctx.strokeStyle = series.color;\n            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);\n            if (fillStyle) {\n                ctx.fillStyle = fillStyle;\n                plotLineArea(series.datapoints, series.xaxis, series.yaxis);\n            }\n\n            if (lw > 0)\n                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);\n            ctx.restore();\n        }\n\n        function drawSeriesPoints(series) {\n            function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {\n                var points = datapoints.points, ps = datapoints.pointsize;\n\n                for (var i = 0; i < points.length; i += ps) {\n                    var x = points[i], y = points[i + 1];\n                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)\n                        continue;\n\n                    ctx.beginPath();\n                    x = axisx.p2c(x);\n                    y = axisy.p2c(y) + offset;\n                    if (symbol == \"circle\")\n                        ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);\n                    else\n                        symbol(ctx, x, y, radius, shadow);\n                    ctx.closePath();\n\n                    if (fillStyle) {\n                        ctx.fillStyle = fillStyle;\n                        ctx.fill();\n                    }\n                    ctx.stroke();\n                }\n            }\n\n            ctx.save();\n            ctx.translate(plotOffset.left, plotOffset.top);\n\n            var lw = series.points.lineWidth,\n                sw = series.shadowSize,\n                radius = series.points.radius,\n                symbol = series.points.symbol;\n            if (lw > 0 && sw > 0) {\n                // draw shadow in two steps\n                var w = sw / 2;\n                ctx.lineWidth = w;\n                ctx.strokeStyle = \"rgba(0,0,0,0.1)\";\n                plotPoints(series.datapoints, radius, null, w + w/2, true,\n                           series.xaxis, series.yaxis, symbol);\n\n                ctx.strokeStyle = \"rgba(0,0,0,0.2)\";\n                plotPoints(series.datapoints, radius, null, w/2, true,\n                           series.xaxis, series.yaxis, symbol);\n            }\n\n            ctx.lineWidth = lw;\n            ctx.strokeStyle = series.color;\n            plotPoints(series.datapoints, radius,\n                       getFillStyle(series.points, series.color), 0, false,\n                       series.xaxis, series.yaxis, symbol);\n            ctx.restore();\n        }\n\n        function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {\n            var left, right, bottom, top,\n                drawLeft, drawRight, drawTop, drawBottom,\n                tmp;\n\n            // in horizontal mode, we start the bar from the left\n            // instead of from the bottom so it appears to be\n            // horizontal rather than vertical\n            if (horizontal) {\n                drawBottom = drawRight = drawTop = true;\n                drawLeft = false;\n                left = b;\n                right = x;\n                top = y + barLeft;\n                bottom = y + barRight;\n\n                // account for negative bars\n                if (right < left) {\n                    tmp = right;\n                    right = left;\n                    left = tmp;\n                    drawLeft = true;\n                    drawRight = false;\n                }\n            }\n            else {\n                drawLeft = drawRight = drawTop = true;\n                drawBottom = false;\n                left = x + barLeft;\n                right = x + barRight;\n                bottom = b;\n                top = y;\n\n                // account for negative bars\n                if (top < bottom) {\n                    tmp = top;\n                    top = bottom;\n                    bottom = tmp;\n                    drawBottom = true;\n                    drawTop = false;\n                }\n            }\n\n            // clip\n            if (right < axisx.min || left > axisx.max ||\n                top < axisy.min || bottom > axisy.max)\n                return;\n\n            if (left < axisx.min) {\n                left = axisx.min;\n                drawLeft = false;\n            }\n\n            if (right > axisx.max) {\n                right = axisx.max;\n                drawRight = false;\n            }\n\n            if (bottom < axisy.min) {\n                bottom = axisy.min;\n                drawBottom = false;\n            }\n\n            if (top > axisy.max) {\n                top = axisy.max;\n                drawTop = false;\n            }\n\n            left = axisx.p2c(left);\n            bottom = axisy.p2c(bottom);\n            right = axisx.p2c(right);\n            top = axisy.p2c(top);\n\n            // fill the bar\n            if (fillStyleCallback) {\n                c.beginPath();\n                c.moveTo(left, bottom);\n                c.lineTo(left, top);\n                c.lineTo(right, top);\n                c.lineTo(right, bottom);\n                c.fillStyle = fillStyleCallback(bottom, top);\n                c.fill();\n            }\n\n            // draw outline\n            if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {\n                c.beginPath();\n\n                // FIXME: inline moveTo is buggy with excanvas\n                c.moveTo(left, bottom + offset);\n                if (drawLeft)\n                    c.lineTo(left, top + offset);\n                else\n                    c.moveTo(left, top + offset);\n                if (drawTop)\n                    c.lineTo(right, top + offset);\n                else\n                    c.moveTo(right, top + offset);\n                if (drawRight)\n                    c.lineTo(right, bottom + offset);\n                else\n                    c.moveTo(right, bottom + offset);\n                if (drawBottom)\n                    c.lineTo(left, bottom + offset);\n                else\n                    c.moveTo(left, bottom + offset);\n                c.stroke();\n            }\n        }\n\n        function drawSeriesBars(series) {\n            function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {\n                var points = datapoints.points, ps = datapoints.pointsize;\n\n                for (var i = 0; i < points.length; i += ps) {\n                    if (points[i] == null)\n                        continue;\n                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);\n                }\n            }\n\n            ctx.save();\n            ctx.translate(plotOffset.left, plotOffset.top);\n\n            // FIXME: figure out a way to add shadows (for instance along the right edge)\n            ctx.lineWidth = series.bars.lineWidth;\n            ctx.strokeStyle = series.color;\n            var barLeft = series.bars.align == \"left\" ? 0 : -series.bars.barWidth/2;\n            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;\n            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);\n            ctx.restore();\n        }\n\n        function getFillStyle(filloptions, seriesColor, bottom, top) {\n            var fill = filloptions.fill;\n            if (!fill)\n                return null;\n\n            if (filloptions.fillColor)\n                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);\n\n            var c = $.color.parse(seriesColor);\n            c.a = typeof fill == \"number\" ? fill : 0.4;\n            c.normalize();\n            return c.toString();\n        }\n\n        function insertLegend() {\n            placeholder.find(\".legend\").remove();\n\n            if (!options.legend.show)\n                return;\n\n            var fragments = [], rowStarted = false,\n                lf = options.legend.labelFormatter, s, label;\n            for (var i = 0; i < series.length; ++i) {\n                s = series[i];\n                label = s.label;\n                if (!label)\n                    continue;\n\n                if (i % options.legend.noColumns == 0) {\n                    if (rowStarted)\n                        fragments.push('</tr>');\n                    fragments.push('<tr>');\n                    rowStarted = true;\n                }\n\n                if (lf)\n                    label = lf(label, s);\n\n                fragments.push(\n                    '<td class=\"legendColorBox\"><div style=\"border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px\"><div style=\"width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden\"></div></div></td>' +\n                    '<td class=\"legendLabel\">' + label + '</td>');\n            }\n            if (rowStarted)\n                fragments.push('</tr>');\n\n            if (fragments.length == 0)\n                return;\n\n            var table = '<table style=\"font-size:smaller;color:' + options.grid.color + '\">' + fragments.join(\"\") + '</table>';\n            if (options.legend.container != null)\n                $(options.legend.container).html(table);\n            else {\n                var pos = \"\",\n                    p = options.legend.position,\n                    m = options.legend.margin;\n                if (m[0] == null)\n                    m = [m, m];\n                if (p.charAt(0) == \"n\")\n                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';\n                else if (p.charAt(0) == \"s\")\n                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';\n                if (p.charAt(1) == \"e\")\n                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';\n                else if (p.charAt(1) == \"w\")\n                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';\n                var legend = $('<div class=\"legend\">' + table.replace('style=\"', 'style=\"position:absolute;' + pos +';') + '</div>').appendTo(placeholder);\n                if (options.legend.backgroundOpacity != 0.0) {\n                    // put in the transparent background\n                    // separately to avoid blended labels and\n                    // label boxes\n                    var c = options.legend.backgroundColor;\n                    if (c == null) {\n                        c = options.grid.backgroundColor;\n                        if (c && typeof c == \"string\")\n                            c = $.color.parse(c);\n                        else\n                            c = $.color.extract(legend, 'background-color');\n                        c.a = 1;\n                        c = c.toString();\n                    }\n                    var div = legend.children();\n                    $('<div style=\"position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';\"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);\n                }\n            }\n        }\n\n\n        // interactive features\n\n        var highlights = [],\n            redrawTimeout = null;\n\n        // returns the data item the mouse is over, or null if none is found\n        function findNearbyItem(mouseX, mouseY, seriesFilter) {\n            var maxDistance = options.grid.mouseActiveRadius,\n                smallestDistance = maxDistance * maxDistance + 1,\n                item = null, foundPoint = false, i, j;\n\n            for (i = series.length - 1; i >= 0; --i) {\n                if (!seriesFilter(series[i]))\n                    continue;\n\n                var s = series[i],\n                    axisx = s.xaxis,\n                    axisy = s.yaxis,\n                    points = s.datapoints.points,\n                    ps = s.datapoints.pointsize,\n                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster\n                    my = axisy.c2p(mouseY),\n                    maxx = maxDistance / axisx.scale,\n                    maxy = maxDistance / axisy.scale;\n\n                // with inverse transforms, we can't use the maxx/maxy\n                // optimization, sadly\n                if (axisx.options.inverseTransform)\n                    maxx = Number.MAX_VALUE;\n                if (axisy.options.inverseTransform)\n                    maxy = Number.MAX_VALUE;\n\n                if (s.lines.show || s.points.show) {\n                    for (j = 0; j < points.length; j += ps) {\n                        var x = points[j], y = points[j + 1];\n                        if (x == null)\n                            continue;\n\n                        // For points and lines, the cursor must be within a\n                        // certain distance to the data point\n                        if (x - mx > maxx || x - mx < -maxx ||\n                            y - my > maxy || y - my < -maxy)\n                            continue;\n\n                        // We have to calculate distances in pixels, not in\n                        // data units, because the scales of the axes may be different\n                        var dx = Math.abs(axisx.p2c(x) - mouseX),\n                            dy = Math.abs(axisy.p2c(y) - mouseY),\n                            dist = dx * dx + dy * dy; // we save the sqrt\n\n                        // use <= to ensure last point takes precedence\n                        // (last generally means on top of)\n                        if (dist < smallestDistance) {\n                            smallestDistance = dist;\n                            item = [i, j / ps];\n                        }\n                    }\n                }\n\n                if (s.bars.show && !item) { // no other point can be nearby\n                    var barLeft = s.bars.align == \"left\" ? 0 : -s.bars.barWidth/2,\n                        barRight = barLeft + s.bars.barWidth;\n\n                    for (j = 0; j < points.length; j += ps) {\n                        var x = points[j], y = points[j + 1], b = points[j + 2];\n                        if (x == null)\n                            continue;\n\n                        // for a bar graph, the cursor must be inside the bar\n                        if (series[i].bars.horizontal ?\n                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&\n                             my >= y + barLeft && my <= y + barRight) :\n                            (mx >= x + barLeft && mx <= x + barRight &&\n                             my >= Math.min(b, y) && my <= Math.max(b, y)))\n                                item = [i, j / ps];\n                    }\n                }\n            }\n\n            if (item) {\n                i = item[0];\n                j = item[1];\n                ps = series[i].datapoints.pointsize;\n\n                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),\n                         dataIndex: j,\n                         series: series[i],\n                         seriesIndex: i };\n            }\n\n            return null;\n        }\n\n        function onMouseMove(e) {\n            if (options.grid.hoverable)\n                triggerClickHoverEvent(\"plothover\", e,\n                                       function (s) { return s[\"hoverable\"] != false; });\n        }\n\n        function onMouseLeave(e) {\n            if (options.grid.hoverable)\n                triggerClickHoverEvent(\"plothover\", e,\n                                       function (s) { return false; });\n        }\n\n        function onClick(e) {\n            triggerClickHoverEvent(\"plotclick\", e,\n                                   function (s) { return s[\"clickable\"] != false; });\n        }\n\n        // trigger click or hover event (they send the same parameters\n        // so we share their code)\n        function triggerClickHoverEvent(eventname, event, seriesFilter) {\n            var offset = eventHolder.offset(),\n                canvasX = event.pageX - offset.left - plotOffset.left,\n                canvasY = event.pageY - offset.top - plotOffset.top,\n            pos = canvasToAxisCoords({ left: canvasX, top: canvasY });\n\n            pos.pageX = event.pageX;\n            pos.pageY = event.pageY;\n\n            var item = findNearbyItem(canvasX, canvasY, seriesFilter);\n\n            if (item) {\n                // fill in mouse pos for any listeners out there\n                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);\n                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);\n            }\n\n            if (options.grid.autoHighlight) {\n                // clear auto-highlights\n                for (var i = 0; i < highlights.length; ++i) {\n                    var h = highlights[i];\n                    if (h.auto == eventname &&\n                        !(item && h.series == item.series &&\n                          h.point[0] == item.datapoint[0] &&\n                          h.point[1] == item.datapoint[1]))\n                        unhighlight(h.series, h.point);\n                }\n\n                if (item)\n                    highlight(item.series, item.datapoint, eventname);\n            }\n\n            placeholder.trigger(eventname, [ pos, item ]);\n        }\n\n        function triggerRedrawOverlay() {\n            if (!redrawTimeout)\n                redrawTimeout = setTimeout(drawOverlay, 30);\n        }\n\n        function drawOverlay() {\n            redrawTimeout = null;\n\n            // draw highlights\n            octx.save();\n            octx.clearRect(0, 0, canvasWidth, canvasHeight);\n            octx.translate(plotOffset.left, plotOffset.top);\n\n            var i, hi;\n            for (i = 0; i < highlights.length; ++i) {\n                hi = highlights[i];\n\n                if (hi.series.bars.show)\n                    drawBarHighlight(hi.series, hi.point);\n                else\n                    drawPointHighlight(hi.series, hi.point);\n            }\n            octx.restore();\n\n            executeHooks(hooks.drawOverlay, [octx]);\n        }\n\n        function highlight(s, point, auto) {\n            if (typeof s == \"number\")\n                s = series[s];\n\n            if (typeof point == \"number\") {\n                var ps = s.datapoints.pointsize;\n                point = s.datapoints.points.slice(ps * point, ps * (point + 1));\n            }\n\n            var i = indexOfHighlight(s, point);\n            if (i == -1) {\n                highlights.push({ series: s, point: point, auto: auto });\n\n                triggerRedrawOverlay();\n            }\n            else if (!auto)\n                highlights[i].auto = false;\n        }\n\n        function unhighlight(s, point) {\n            if (s == null && point == null) {\n                highlights = [];\n                triggerRedrawOverlay();\n            }\n\n            if (typeof s == \"number\")\n                s = series[s];\n\n            if (typeof point == \"number\")\n                point = s.data[point];\n\n            var i = indexOfHighlight(s, point);\n            if (i != -1) {\n                highlights.splice(i, 1);\n\n                triggerRedrawOverlay();\n            }\n        }\n\n        function indexOfHighlight(s, p) {\n            for (var i = 0; i < highlights.length; ++i) {\n                var h = highlights[i];\n                if (h.series == s && h.point[0] == p[0]\n                    && h.point[1] == p[1])\n                    return i;\n            }\n            return -1;\n        }\n\n        function drawPointHighlight(series, point) {\n            var x = point[0], y = point[1],\n                axisx = series.xaxis, axisy = series.yaxis;\n\n            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)\n                return;\n\n            var pointRadius = series.points.radius + series.points.lineWidth / 2;\n            octx.lineWidth = pointRadius;\n            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();\n            var radius = 1.5 * pointRadius,\n                x = axisx.p2c(x),\n                y = axisy.p2c(y);\n\n            octx.beginPath();\n            if (series.points.symbol == \"circle\")\n                octx.arc(x, y, radius, 0, 2 * Math.PI, false);\n            else\n                series.points.symbol(octx, x, y, radius, false);\n            octx.closePath();\n            octx.stroke();\n        }\n\n        function drawBarHighlight(series, point) {\n            octx.lineWidth = series.bars.lineWidth;\n            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();\n            var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();\n            var barLeft = series.bars.align == \"left\" ? 0 : -series.bars.barWidth/2;\n            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,\n                    0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);\n        }\n\n        function getColorOrGradient(spec, bottom, top, defaultColor) {\n            if (typeof spec == \"string\")\n                return spec;\n            else {\n                // assume this is a gradient spec; IE currently only\n                // supports a simple vertical gradient properly, so that's\n                // what we support too\n                var gradient = ctx.createLinearGradient(0, top, 0, bottom);\n\n                for (var i = 0, l = spec.colors.length; i < l; ++i) {\n                    var c = spec.colors[i];\n                    if (typeof c != \"string\") {\n                        var co = $.color.parse(defaultColor);\n                        if (c.brightness != null)\n                            co = co.scale('rgb', c.brightness)\n                        if (c.opacity != null)\n                            co.a *= c.opacity;\n                        c = co.toString();\n                    }\n                    gradient.addColorStop(i / (l - 1), c);\n                }\n\n                return gradient;\n            }\n        }\n    }\n\n    $.plot = function(placeholder, data, options) {\n        //var t0 = new Date();\n        var plot = new Plot($(placeholder), data, options, $.plot.plugins);\n        //(window.console ? console.log : alert)(\"time used (msecs): \" + ((new Date()).getTime() - t0.getTime()));\n        return plot;\n    };\n\n    $.plot.version = \"0.7\";\n\n    $.plot.plugins = [];\n\n    // returns a string with the date d formatted according to fmt\n    $.plot.formatDate = function(d, fmt, monthNames) {\n        var leftPad = function(n) {\n            n = \"\" + n;\n            return n.length == 1 ? \"0\" + n : n;\n        };\n\n        var r = [];\n        var escape = false, padNext = false;\n        var hours = d.getUTCHours();\n        var isAM = hours < 12;\n        if (monthNames == null)\n            monthNames = [\"1月\", \"2月\", \"3月\", \"4月\", \"5月\", \"6月\", \"7月\", \"8月\", \"9月\", \"10月\", \"11月\", \"12月\"];\n\n        if (fmt.search(/%p|%P/) != -1) {\n            if (hours > 12) {\n                hours = hours - 12;\n            } else if (hours == 0) {\n                hours = 12;\n            }\n        }\n        for (var i = 0; i < fmt.length; ++i) {\n            var c = fmt.charAt(i);\n\n            if (escape) {\n                switch (c) {\n                case 'h': c = \"\" + hours; break;\n                case 'H': c = leftPad(hours); break;\n                case 'M': c = leftPad(d.getUTCMinutes()); break;\n                case 'S': c = leftPad(d.getUTCSeconds()); break;\n                case 'd': c = \"\" + d.getUTCDate(); break;\n                case 'm': c = \"\" + (d.getUTCMonth() + 1); break;\n                case 'y': c = \"\" + d.getUTCFullYear(); break;\n                case 'b': c = \"\" + monthNames[d.getUTCMonth()]; break;\n                case 'p': c = (isAM) ? (\"\" + \"am\") : (\"\" + \"pm\"); break;\n                case 'P': c = (isAM) ? (\"\" + \"AM\") : (\"\" + \"PM\"); break;\n                case '0': c = \"\"; padNext = true; break;\n                }\n                if (c && padNext) {\n                    c = leftPad(c);\n                    padNext = false;\n                }\n                r.push(c);\n                if (!padNext)\n                    escape = false;\n            }\n            else {\n                if (c == \"%\")\n                    escape = true;\n                else\n                    r.push(c);\n            }\n        }\n        return r.join(\"\");\n    };\n\n    // round to nearby lower multiple of base\n    function floorInBase(n, base) {\n        return base * Math.floor(n / base);\n    }\n\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/jquery.flot.pie.js",
    "content": "/*\nFlot plugin for rendering pie charts. The plugin assumes the data is\ncoming is as a single data value for each series, and each of those\nvalues is a positive value or zero (negative numbers don't make\nany sense and will cause strange effects). The data values do\nNOT need to be passed in as percentage values because it\ninternally calculates the total and percentages.\n\n* Created by Brian Medendorp, June 2009\n* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars\n\n* Changes:\n\t2009-10-22: lineJoin set to round\n\t2009-10-23: IE full circle fix, donut\n\t2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera\n\t2009-11-17: Added IE hover capability submitted by Anthony Aragues\n\t2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)\n\n\nAvailable options are:\nseries: {\n\tpie: {\n\t\tshow: true/false\n\t\tradius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'\n\t\tinnerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect\n\t\tstartAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result\n\t\ttilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)\n\t\toffset: {\n\t\t\ttop: integer value to move the pie up or down\n\t\t\tleft: integer value to move the pie left or right, or 'auto'\n\t\t},\n\t\tstroke: {\n\t\t\tcolor: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')\n\t\t\twidth: integer pixel width of the stroke\n\t\t},\n\t\tlabel: {\n\t\t\tshow: true/false, or 'auto'\n\t\t\tformatter:  a user-defined function that modifies the text/style of the label text\n\t\t\tradius: 0-1 for percentage of fullsize, or a specified pixel length\n\t\t\tbackground: {\n\t\t\t\tcolor: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')\n\t\t\t\topacity: 0-1\n\t\t\t},\n\t\t\tthreshold: 0-1 for the percentage value at which to hide labels (if they're too small)\n\t\t},\n\t\tcombine: {\n\t\t\tthreshold: 0-1 for the percentage value at which to combine slices (if they're too small)\n\t\t\tcolor: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined\n\t\t\tlabel: any text value of what the combined slice should be labeled\n\t\t}\n\t\thighlight: {\n\t\t\topacity: 0-1\n\t\t}\n\t}\n}\n\nMore detail and specific examples can be found in the included HTML file.\n\n*/\n\n(function ($)\n{\n\tfunction init(plot) // this is the \"body\" of the plugin\n\t{\n\t\tvar canvas = null;\n\t\tvar target = null;\n\t\tvar maxRadius = null;\n\t\tvar centerLeft = null;\n\t\tvar centerTop = null;\n\t\tvar total = 0;\n\t\tvar redraw = true;\n\t\tvar redrawAttempts = 10;\n\t\tvar shrink = 0.95;\n\t\tvar legendWidth = 0;\n\t\tvar processed = false;\n\t\tvar raw = false;\n\n\t\t// interactive variables\n\t\tvar highlights = [];\n\n\t\t// add hook to determine if pie plugin in enabled, and then perform necessary operations\n\t\tplot.hooks.processOptions.push(checkPieEnabled);\n\t\tplot.hooks.bindEvents.push(bindEvents);\n\n\t\t// check to see if the pie plugin is enabled\n\t\tfunction checkPieEnabled(plot, options)\n\t\t{\n\t\t\tif (options.series.pie.show)\n\t\t\t{\n\t\t\t\t//disable grid\n\t\t\t\toptions.grid.show = false;\n\n\t\t\t\t// set labels.show\n\t\t\t\tif (options.series.pie.label.show=='auto')\n\t\t\t\t\tif (options.legend.show)\n\t\t\t\t\t\toptions.series.pie.label.show = false;\n\t\t\t\t\telse\n\t\t\t\t\t\toptions.series.pie.label.show = true;\n\n\t\t\t\t// set radius\n\t\t\t\tif (options.series.pie.radius=='auto')\n\t\t\t\t\tif (options.series.pie.label.show)\n\t\t\t\t\t\toptions.series.pie.radius = 3/4;\n\t\t\t\t\telse\n\t\t\t\t\t\toptions.series.pie.radius = 1;\n\n\t\t\t\t// ensure sane tilt\n\t\t\t\tif (options.series.pie.tilt>1)\n\t\t\t\t\toptions.series.pie.tilt=1;\n\t\t\t\tif (options.series.pie.tilt<0)\n\t\t\t\t\toptions.series.pie.tilt=0;\n\n\t\t\t\t// add processData hook to do transformations on the data\n\t\t\t\tplot.hooks.processDatapoints.push(processDatapoints);\n\t\t\t\tplot.hooks.drawOverlay.push(drawOverlay);\n\n\t\t\t\t// add draw hook\n\t\t\t\tplot.hooks.draw.push(draw);\n\t\t\t}\n\t\t}\n\n\t\t// bind hoverable events\n\t\tfunction bindEvents(plot, eventHolder)\n\t\t{\n\t\t\tvar options = plot.getOptions();\n\n\t\t\tif (options.series.pie.show && options.grid.hoverable)\n\t\t\t\teventHolder.unbind('mousemove').mousemove(onMouseMove);\n\n\t\t\tif (options.series.pie.show && options.grid.clickable)\n\t\t\t\teventHolder.unbind('click').click(onClick);\n\t\t}\n\n\n\t\t// debugging function that prints out an object\n\t\tfunction alertObject(obj)\n\t\t{\n\t\t\tvar msg = '';\n\t\t\tfunction traverse(obj, depth)\n\t\t\t{\n\t\t\t\tif (!depth)\n\t\t\t\t\tdepth = 0;\n\t\t\t\tfor (var i = 0; i < obj.length; ++i)\n\t\t\t\t{\n\t\t\t\t\tfor (var j=0; j<depth; j++)\n\t\t\t\t\t\tmsg += '\\t';\n\n\t\t\t\t\tif( typeof obj[i] == \"object\")\n\t\t\t\t\t{\t// its an object\n\t\t\t\t\t\tmsg += ''+i+':\\n';\n\t\t\t\t\t\ttraverse(obj[i], depth+1);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\t// its a value\n\t\t\t\t\t\tmsg += ''+i+': '+obj[i]+'\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttraverse(obj);\n\t\t\talert(msg);\n\t\t}\n\n\t\tfunction calcTotal(data)\n\t\t{\n\t\t\tfor (var i = 0; i < data.length; ++i)\n\t\t\t{\n\t\t\t\tvar item = parseFloat(data[i].data[0][1]);\n\t\t\t\tif (item)\n\t\t\t\t\ttotal += item;\n\t\t\t}\n\t\t}\n\n\t\tfunction processDatapoints(plot, series, data, datapoints)\n\t\t{\n\t\t\tif (!processed)\n\t\t\t{\n\t\t\t\tprocessed = true;\n\n\t\t\t\tcanvas = plot.getCanvas();\n\t\t\t\ttarget = $(canvas).parent();\n\t\t\t\toptions = plot.getOptions();\n\n\t\t\t\tplot.setData(combine(plot.getData()));\n\t\t\t}\n\t\t}\n\n\t\tfunction setupPie()\n\t\t{\n\t\t\tlegendWidth = target.children().filter('.legend').children().width();\n\n\t\t\t// calculate maximum radius and center point\n\t\t\tmaxRadius =  Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;\n\t\t\tcenterTop = (canvas.height/2)+options.series.pie.offset.top;\n\t\t\tcenterLeft = (canvas.width/2);\n\n\t\t\tif (options.series.pie.offset.left=='auto')\n\t\t\t\tif (options.legend.position.match('w'))\n\t\t\t\t\tcenterLeft += legendWidth/2;\n\t\t\t\telse\n\t\t\t\t\tcenterLeft -= legendWidth/2;\n\t\t\telse\n\t\t\t\tcenterLeft += options.series.pie.offset.left;\n\n\t\t\tif (centerLeft<maxRadius)\n\t\t\t\tcenterLeft = maxRadius;\n\t\t\telse if (centerLeft>canvas.width-maxRadius)\n\t\t\t\tcenterLeft = canvas.width-maxRadius;\n\t\t}\n\n\t\tfunction fixData(data)\n\t\t{\n\t\t\tfor (var i = 0; i < data.length; ++i)\n\t\t\t{\n\t\t\t\tif (typeof(data[i].data)=='number')\n\t\t\t\t\tdata[i].data = [[1,data[i].data]];\n\t\t\t\telse if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')\n\t\t\t\t{\n\t\t\t\t\tif (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')\n\t\t\t\t\t\tdata[i].label = data[i].data.label; // fix weirdness coming from flot\n\t\t\t\t\tdata[i].data = [[1,0]];\n\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn data;\n\t\t}\n\n\t\tfunction combine(data)\n\t\t{\n\t\t\tdata = fixData(data);\n\t\t\tcalcTotal(data);\n\t\t\tvar combined = 0;\n\t\t\tvar numCombined = 0;\n\t\t\tvar color = options.series.pie.combine.color;\n\n\t\t\tvar newdata = [];\n\t\t\tfor (var i = 0; i < data.length; ++i)\n\t\t\t{\n\t\t\t\t// make sure its a number\n\t\t\t\tdata[i].data[0][1] = parseFloat(data[i].data[0][1]);\n\t\t\t\tif (!data[i].data[0][1])\n\t\t\t\t\tdata[i].data[0][1] = 0;\n\n\t\t\t\tif (data[i].data[0][1]/total<=options.series.pie.combine.threshold)\n\t\t\t\t{\n\t\t\t\t\tcombined += data[i].data[0][1];\n\t\t\t\t\tnumCombined++;\n\t\t\t\t\tif (!color)\n\t\t\t\t\t\tcolor = data[i].color;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnewdata.push({\n\t\t\t\t\t\tdata: [[1,data[i].data[0][1]]],\n\t\t\t\t\t\tcolor: data[i].color,\n\t\t\t\t\t\tlabel: data[i].label,\n\t\t\t\t\t\tangle: (data[i].data[0][1]*(Math.PI*2))/total,\n\t\t\t\t\t\tpercent: (data[i].data[0][1]/total*100)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (numCombined>0)\n\t\t\t\tnewdata.push({\n\t\t\t\t\tdata: [[1,combined]],\n\t\t\t\t\tcolor: color,\n\t\t\t\t\tlabel: options.series.pie.combine.label,\n\t\t\t\t\tangle: (combined*(Math.PI*2))/total,\n\t\t\t\t\tpercent: (combined/total*100)\n\t\t\t\t});\n\t\t\treturn newdata;\n\t\t}\n\n\t\tfunction draw(plot, newCtx)\n\t\t{\n\t\t\tif (!target) return; // if no series were passed\n\t\t\tctx = newCtx;\n\n\t\t\tsetupPie();\n\t\t\tvar slices = plot.getData();\n\n\t\t\tvar attempts = 0;\n\t\t\twhile (redraw && attempts<redrawAttempts)\n\t\t\t{\n\t\t\t\tredraw = false;\n\t\t\t\tif (attempts>0)\n\t\t\t\t\tmaxRadius *= shrink;\n\t\t\t\tattempts += 1;\n\t\t\t\tclear();\n\t\t\t\tif (options.series.pie.tilt<=0.8)\n\t\t\t\t\tdrawShadow();\n\t\t\t\tdrawPie();\n\t\t\t}\n\t\t\tif (attempts >= redrawAttempts) {\n\t\t\t\tclear();\n\t\t\t\ttarget.prepend('<div class=\"error\">Could not draw pie with labels contained inside canvas</div>');\n\t\t\t}\n\n\t\t\tif ( plot.setSeries && plot.insertLegend )\n\t\t\t{\n\t\t\t\tplot.setSeries(slices);\n\t\t\t\tplot.insertLegend();\n\t\t\t}\n\n\t\t\t// we're actually done at this point, just defining internal functions at this point\n\n\t\t\tfunction clear()\n\t\t\t{\n\t\t\t\tctx.clearRect(0,0,canvas.width,canvas.height);\n\t\t\t\ttarget.children().filter('.pieLabel, .pieLabelBackground').remove();\n\t\t\t}\n\n\t\t\tfunction drawShadow()\n\t\t\t{\n\t\t\t\tvar shadowLeft = 5;\n\t\t\t\tvar shadowTop = 15;\n\t\t\t\tvar edge = 10;\n\t\t\t\tvar alpha = 0.02;\n\n\t\t\t\t// set radius\n\t\t\t\tif (options.series.pie.radius>1)\n\t\t\t\t\tvar radius = options.series.pie.radius;\n\t\t\t\telse\n\t\t\t\t\tvar radius = maxRadius * options.series.pie.radius;\n\n\t\t\t\tif (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)\n\t\t\t\t\treturn;\t// shadow would be outside canvas, so don't draw it\n\n\t\t\t\tctx.save();\n\t\t\t\tctx.translate(shadowLeft,shadowTop);\n\t\t\t\tctx.globalAlpha = alpha;\n\t\t\t\tctx.fillStyle = '#000';\n\n\t\t\t\t// center and rotate to starting position\n\t\t\t\tctx.translate(centerLeft,centerTop);\n\t\t\t\tctx.scale(1, options.series.pie.tilt);\n\n\t\t\t\t//radius -= edge;\n\t\t\t\tfor (var i=1; i<=edge; i++)\n\t\t\t\t{\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.arc(0,0,radius,0,Math.PI*2,false);\n\t\t\t\t\tctx.fill();\n\t\t\t\t\tradius -= i;\n\t\t\t\t}\n\n\t\t\t\tctx.restore();\n\t\t\t}\n\n\t\t\tfunction drawPie()\n\t\t\t{\n\t\t\t\tstartAngle = Math.PI*options.series.pie.startAngle;\n\n\t\t\t\t// set radius\n\t\t\t\tif (options.series.pie.radius>1)\n\t\t\t\t\tvar radius = options.series.pie.radius;\n\t\t\t\telse\n\t\t\t\t\tvar radius = maxRadius * options.series.pie.radius;\n\n\t\t\t\t// center and rotate to starting position\n\t\t\t\tctx.save();\n\t\t\t\tctx.translate(centerLeft,centerTop);\n\t\t\t\tctx.scale(1, options.series.pie.tilt);\n\t\t\t\t//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera\n\n\t\t\t\t// draw slices\n\t\t\t\tctx.save();\n\t\t\t\tvar currentAngle = startAngle;\n\t\t\t\tfor (var i = 0; i < slices.length; ++i)\n\t\t\t\t{\n\t\t\t\t\tslices[i].startAngle = currentAngle;\n\t\t\t\t\tdrawSlice(slices[i].angle, slices[i].color, true);\n\t\t\t\t}\n\t\t\t\tctx.restore();\n\n\t\t\t\t// draw slice outlines\n\t\t\t\tctx.save();\n\t\t\t\tctx.lineWidth = options.series.pie.stroke.width;\n\t\t\t\tcurrentAngle = startAngle;\n\t\t\t\tfor (var i = 0; i < slices.length; ++i)\n\t\t\t\t\tdrawSlice(slices[i].angle, options.series.pie.stroke.color, false);\n\t\t\t\tctx.restore();\n\n\t\t\t\t// draw donut hole\n\t\t\t\tdrawDonutHole(ctx);\n\n\t\t\t\t// draw labels\n\t\t\t\tif (options.series.pie.label.show)\n\t\t\t\t\tdrawLabels();\n\n\t\t\t\t// restore to original state\n\t\t\t\tctx.restore();\n\n\t\t\t\tfunction drawSlice(angle, color, fill)\n\t\t\t\t{\n\t\t\t\t\tif (angle<=0)\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\tif (fill)\n\t\t\t\t\t\tctx.fillStyle = color;\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tctx.strokeStyle = color;\n\t\t\t\t\t\tctx.lineJoin = 'round';\n\t\t\t\t\t}\n\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tif (Math.abs(angle - Math.PI*2) > 0.000000001)\n\t\t\t\t\t\tctx.moveTo(0,0); // Center of the pie\n\t\t\t\t\telse if ($.browser.msie)\n\t\t\t\t\t\tangle -= 0.0001;\n\t\t\t\t\t//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera\n\t\t\t\t\tctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\t//ctx.rotate(angle); // This doesn't work properly in Opera\n\t\t\t\t\tcurrentAngle += angle;\n\n\t\t\t\t\tif (fill)\n\t\t\t\t\t\tctx.fill();\n\t\t\t\t\telse\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\n\t\t\t\tfunction drawLabels()\n\t\t\t\t{\n\t\t\t\t\tvar currentAngle = startAngle;\n\n\t\t\t\t\t// set radius\n\t\t\t\t\tif (options.series.pie.label.radius>1)\n\t\t\t\t\t\tvar radius = options.series.pie.label.radius;\n\t\t\t\t\telse\n\t\t\t\t\t\tvar radius = maxRadius * options.series.pie.label.radius;\n\n\t\t\t\t\tfor (var i = 0; i < slices.length; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (slices[i].percent >= options.series.pie.label.threshold*100)\n\t\t\t\t\t\t\tdrawLabel(slices[i], currentAngle, i);\n\t\t\t\t\t\tcurrentAngle += slices[i].angle;\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction drawLabel(slice, startAngle, index)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (slice.data[0][1]==0)\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t// format label text\n\t\t\t\t\t\tvar lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;\n\t\t\t\t\t\tif (lf)\n\t\t\t\t\t\t\ttext = lf(slice.label, slice);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\ttext = slice.label;\n\t\t\t\t\t\tif (plf)\n\t\t\t\t\t\t\ttext = plf(text, slice);\n\n\t\t\t\t\t\tvar halfAngle = ((startAngle+slice.angle) + startAngle)/2;\n\t\t\t\t\t\tvar x = centerLeft + Math.round(Math.cos(halfAngle) * radius);\n\t\t\t\t\t\tvar y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;\n\n\t\t\t\t\t\tvar html = '<span class=\"pieLabel\" id=\"pieLabel'+index+'\" style=\"position:absolute;top:' + y + 'px;left:' + x + 'px;\">' + text + \"</span>\";\n\t\t\t\t\t\ttarget.append(html);\n\t\t\t\t\t\tvar label = target.children('#pieLabel'+index);\n\t\t\t\t\t\tvar labelTop = (y - label.height()/2);\n\t\t\t\t\t\tvar labelLeft = (x - label.width()/2);\n\t\t\t\t\t\tlabel.css('top', labelTop);\n\t\t\t\t\t\tlabel.css('left', labelLeft);\n\n\t\t\t\t\t\t// check to make sure that the label is not outside the canvas\n\t\t\t\t\t\tif (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)\n\t\t\t\t\t\t\tredraw = true;\n\n\t\t\t\t\t\tif (options.series.pie.label.background.opacity != 0) {\n\t\t\t\t\t\t\t// put in the transparent background separately to avoid blended labels and label boxes\n\t\t\t\t\t\t\tvar c = options.series.pie.label.background.color;\n\t\t\t\t\t\t\tif (c == null) {\n\t\t\t\t\t\t\t\tc = slice.color;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';\n\t\t\t\t\t\t\t$('<div class=\"pieLabelBackground\" style=\"position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';\"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);\n\t\t\t\t\t\t}\n\t\t\t\t\t} // end individual label function\n\t\t\t\t} // end drawLabels function\n\t\t\t} // end drawPie function\n\t\t} // end draw function\n\n\t\t// Placed here because it needs to be accessed from multiple locations\n\t\tfunction drawDonutHole(layer)\n\t\t{\n\t\t\t// draw donut hole\n\t\t\tif(options.series.pie.innerRadius > 0)\n\t\t\t{\n\t\t\t\t// subtract the center\n\t\t\t\tlayer.save();\n\t\t\t\tinnerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;\n\t\t\t\tlayer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color\n\t\t\t\tlayer.beginPath();\n\t\t\t\tlayer.fillStyle = options.series.pie.stroke.color;\n\t\t\t\tlayer.arc(0,0,innerRadius,0,Math.PI*2,false);\n\t\t\t\tlayer.fill();\n\t\t\t\tlayer.closePath();\n\t\t\t\tlayer.restore();\n\n\t\t\t\t// add inner stroke\n\t\t\t\tlayer.save();\n\t\t\t\tlayer.beginPath();\n\t\t\t\tlayer.strokeStyle = options.series.pie.stroke.color;\n\t\t\t\tlayer.arc(0,0,innerRadius,0,Math.PI*2,false);\n\t\t\t\tlayer.stroke();\n\t\t\t\tlayer.closePath();\n\t\t\t\tlayer.restore();\n\t\t\t\t// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.\n\t\t\t}\n\t\t}\n\n\t\t//-- Additional Interactive related functions --\n\n\t\tfunction isPointInPoly(poly, pt)\n\t\t{\n\t\t\tfor(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)\n\t\t\t\t((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))\n\t\t\t\t&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])\n\t\t\t\t&& (c = !c);\n\t\t\treturn c;\n\t\t}\n\n\t\tfunction findNearbySlice(mouseX, mouseY)\n\t\t{\n\t\t\tvar slices = plot.getData(),\n\t\t\t\toptions = plot.getOptions(),\n\t\t\t\tradius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;\n\n\t\t\tfor (var i = 0; i < slices.length; ++i)\n\t\t\t{\n\t\t\t\tvar s = slices[i];\n\n\t\t\t\tif(s.pie.show)\n\t\t\t\t{\n\t\t\t\t\tctx.save();\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(0,0); // Center of the pie\n\t\t\t\t\t//ctx.scale(1, options.series.pie.tilt);\t// this actually seems to break everything when here.\n\t\t\t\t\tctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tx = mouseX-centerLeft;\n\t\t\t\t\ty = mouseY-centerTop;\n\t\t\t\t\tif(ctx.isPointInPath)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//alert('found slice!');\n\t\t\t\t\t\t\tctx.restore();\n\t\t\t\t\t\t\treturn {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};\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// excanvas for IE doesn;t support isPointInPath, this is a workaround.\n\t\t\t\t\t\tp1X = (radius * Math.cos(s.startAngle));\n\t\t\t\t\t\tp1Y = (radius * Math.sin(s.startAngle));\n\t\t\t\t\t\tp2X = (radius * Math.cos(s.startAngle+(s.angle/4)));\n\t\t\t\t\t\tp2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));\n\t\t\t\t\t\tp3X = (radius * Math.cos(s.startAngle+(s.angle/2)));\n\t\t\t\t\t\tp3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));\n\t\t\t\t\t\tp4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));\n\t\t\t\t\t\tp4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));\n\t\t\t\t\t\tp5X = (radius * Math.cos(s.startAngle+s.angle));\n\t\t\t\t\t\tp5Y = (radius * Math.sin(s.startAngle+s.angle));\n\t\t\t\t\t\tarrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];\n\t\t\t\t\t\tarrPoint = [x,y];\n\t\t\t\t\t\t// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?\n\t\t\t\t\t\tif(isPointInPoly(arrPoly, arrPoint))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tctx.restore();\n\t\t\t\t\t\t\treturn {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tctx.restore();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tfunction onMouseMove(e)\n\t\t{\n\t\t\ttriggerClickHoverEvent('plothover', e);\n\t\t}\n\n        function onClick(e)\n\t\t{\n\t\t\ttriggerClickHoverEvent('plotclick', e);\n        }\n\n\t\t// trigger click or hover event (they send the same parameters so we share their code)\n\t\tfunction triggerClickHoverEvent(eventname, e)\n\t\t{\n\t\t\tvar offset = plot.offset(),\n\t\t\t\tcanvasX = parseInt(e.pageX - offset.left),\n\t\t\t\tcanvasY =  parseInt(e.pageY - offset.top),\n\t\t\t\titem = findNearbySlice(canvasX, canvasY);\n\n\t\t\tif (options.grid.autoHighlight)\n\t\t\t{\n\t\t\t\t// clear auto-highlights\n\t\t\t\tfor (var i = 0; i < highlights.length; ++i)\n\t\t\t\t{\n\t\t\t\t\tvar h = highlights[i];\n\t\t\t\t\tif (h.auto == eventname && !(item && h.series == item.series))\n\t\t\t\t\t\tunhighlight(h.series);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// highlight the slice\n\t\t\tif (item)\n\t\t\t    highlight(item.series, eventname);\n\n\t\t\t// trigger any hover bind events\n\t\t\tvar pos = { pageX: e.pageX, pageY: e.pageY };\n\t\t\ttarget.trigger(eventname, [ pos, item ]);\n\t\t}\n\n\t\tfunction highlight(s, auto)\n\t\t{\n\t\t\tif (typeof s == \"number\")\n\t\t\t\ts = series[s];\n\n\t\t\tvar i = indexOfHighlight(s);\n\t\t\tif (i == -1)\n\t\t\t{\n\t\t\t\thighlights.push({ series: s, auto: auto });\n\t\t\t\tplot.triggerRedrawOverlay();\n\t\t\t}\n\t\t\telse if (!auto)\n\t\t\t\thighlights[i].auto = false;\n\t\t}\n\n\t\tfunction unhighlight(s)\n\t\t{\n\t\t\tif (s == null)\n\t\t\t{\n\t\t\t\thighlights = [];\n\t\t\t\tplot.triggerRedrawOverlay();\n\t\t\t}\n\n\t\t\tif (typeof s == \"number\")\n\t\t\t\ts = series[s];\n\n\t\t\tvar i = indexOfHighlight(s);\n\t\t\tif (i != -1)\n\t\t\t{\n\t\t\t\thighlights.splice(i, 1);\n\t\t\t\tplot.triggerRedrawOverlay();\n\t\t\t}\n\t\t}\n\n\t\tfunction indexOfHighlight(s)\n\t\t{\n\t\t\tfor (var i = 0; i < highlights.length; ++i)\n\t\t\t{\n\t\t\t\tvar h = highlights[i];\n\t\t\t\tif (h.series == s)\n\t\t\t\t\treturn i;\n\t\t\t}\n\t\t\treturn -1;\n\t\t}\n\n\t\tfunction drawOverlay(plot, octx)\n\t\t{\n\t\t\t//alert(options.series.pie.radius);\n\t\t\tvar options = plot.getOptions();\n\t\t\t//alert(options.series.pie.radius);\n\n\t\t\tvar radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;\n\n\t\t\toctx.save();\n\t\t\toctx.translate(centerLeft, centerTop);\n\t\t\toctx.scale(1, options.series.pie.tilt);\n\n\t\t\tfor (i = 0; i < highlights.length; ++i)\n\t\t\t\tdrawHighlight(highlights[i].series);\n\n\t\t\tdrawDonutHole(octx);\n\n\t\t\toctx.restore();\n\n\t\t\tfunction drawHighlight(series)\n\t\t\t{\n\t\t\t\tif (series.angle < 0) return;\n\n\t\t\t\t//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();\n\t\t\t\toctx.fillStyle = \"rgba(255, 255, 255, \"+options.series.pie.highlight.opacity+\")\"; // this is temporary until we have access to parseColor\n\n\t\t\t\toctx.beginPath();\n\t\t\t\tif (Math.abs(series.angle - Math.PI*2) > 0.000000001)\n\t\t\t\t\toctx.moveTo(0,0); // Center of the pie\n\t\t\t\toctx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);\n\t\t\t\toctx.closePath();\n\t\t\t\toctx.fill();\n\t\t\t}\n\n\t\t}\n\n\t} // end init (plugin body)\n\n\t// define pie specific options and their default values\n\tvar options = {\n\t\tseries: {\n\t\t\tpie: {\n\t\t\t\tshow: false,\n\t\t\t\tradius: 'auto',\t// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)\n\t\t\t\tinnerRadius:0, /* for donut */\n\t\t\t\tstartAngle: 3/2,\n\t\t\t\ttilt: 1,\n\t\t\t\toffset: {\n\t\t\t\t\ttop: 0,\n\t\t\t\t\tleft: 'auto'\n\t\t\t\t},\n\t\t\t\tstroke: {\n\t\t\t\t\tcolor: '#FFF',\n\t\t\t\t\twidth: 1\n\t\t\t\t},\n\t\t\t\tlabel: {\n\t\t\t\t\tshow: 'auto',\n\t\t\t\t\tformatter: function(label, slice){\n\t\t\t\t\t\treturn '<div style=\"font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';\">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';\n\t\t\t\t\t},\t// formatter function\n\t\t\t\t\tradius: 1,\t// radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)\n\t\t\t\t\tbackground: {\n\t\t\t\t\t\tcolor: null,\n\t\t\t\t\t\topacity: 0\n\t\t\t\t\t},\n\t\t\t\t\tthreshold: 0\t// percentage at which to hide the label (i.e. the slice is too narrow)\n\t\t\t\t},\n\t\t\t\tcombine: {\n\t\t\t\t\tthreshold: -1,\t// percentage at which to combine little slices into one larger slice\n\t\t\t\t\tcolor: null,\t// color to give the new slice (auto-generated if null)\n\t\t\t\t\tlabel: 'Other'\t// label to give the new slice\n\t\t\t\t},\n\t\t\t\thighlight: {\n\t\t\t\t\t//color: '#FFF',\t\t// will add this functionality once parseColor is available\n\t\t\t\t\topacity: 0.5\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t$.plot.plugins.push({\n\t\tinit: init,\n\t\toptions: options,\n\t\tname: \"pie\",\n\t\tversion: \"1.0\"\n\t});\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/jquery.flot.resize.js",
    "content": "/* Flot plugin for automatically redrawing plots as the placeholder resizes.\n\nCopyright (c) 2007-2013 IOLA and Ole Laursen.\nLicensed under the MIT license.\n\nIt works by listening for changes on the placeholder div (through the jQuery\nresize event plugin) - if the size changes, it will redraw the plot.\n\nThere are no options. If you need to disable the plugin for some plots, you\ncan just fix the size of their placeholders.\n\n*/\n\n/* Inline dependency:\n * jQuery resize event - v1.1 - 3/14/2010\n * http://benalman.com/projects/jquery-resize-plugin/\n *\n * Copyright (c) 2010 \"Cowboy\" Ben Alman\n * Dual licensed under the MIT and GPL licenses.\n * http://benalman.com/about/license/\n */\n\n(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k=\"setTimeout\",j=\"resize\",d=j+\"-special-event\",b=\"delay\",f=\"throttleWindow\";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);\n\n(function ($) {\n    var options = { }; // no options\n\n    function init(plot) {\n        function onResize() {\n            var placeholder = plot.getPlaceholder();\n\n            // somebody might have hidden us and we can't plot\n            // when we don't have the dimensions\n            if (placeholder.width() == 0 || placeholder.height() == 0)\n                return;\n\n            plot.resize();\n            plot.setupGrid();\n            plot.draw();\n        }\n\n        function bindEvents(plot, eventHolder) {\n            plot.getPlaceholder().resize(onResize);\n        }\n\n        function shutdown(plot, eventHolder) {\n            plot.getPlaceholder().unbind(\"resize\", onResize);\n        }\n\n        plot.hooks.bindEvents.push(bindEvents);\n        plot.hooks.shutdown.push(shutdown);\n    }\n\n    $.plot.plugins.push({\n        init: init,\n        options: options,\n        name: 'resize',\n        version: '1.0'\n    });\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/jquery.flot.spline.js",
    "content": "/**\n * Flot plugin that provides spline interpolation for line graphs\n * author: Alex Bardas < alex.bardas@gmail.com >\n * modified by: Avi Kohn https://github.com/AMKohn\n * based on the spline interpolation described at:\n *\t\t http://scaledinnovation.com/analytics/splines/aboutSplines.html\n *\n * Example usage: (add in plot options series object)\n *\t\tfor linespline:\n *\t\t\tseries: {\n *\t\t\t\t...\n *\t\t\t\tlines: {\n *\t\t\t\t\tshow: false\n *\t\t\t\t},\n *\t\t\t\tsplines: {\n *\t\t\t\t\tshow: true,\n *\t\t\t\t\ttension: x, (float between 0 and 1, defaults to 0.5),\n *\t\t\t\t\tlineWidth: y (number, defaults to 2),\n *\t\t\t\t\tfill: z (float between 0 .. 1 or false, as in flot documentation)\n *\t\t\t\t},\n *\t\t\t\t...\n *\t\t\t}\n *\t\tareaspline:\n *\t\t\tseries: {\n *\t\t\t\t...\n *\t\t\t\tlines: {\n *\t\t\t\t\tshow: true,\n *\t\t\t\t\tlineWidth: 0, (line drawing will not execute)\n *\t\t\t\t\tfill: x, (float between 0 .. 1, as in flot documentation)\n *\t\t\t\t\t...\n *\t\t\t\t},\n *\t\t\t\tsplines: {\n *\t\t\t\t\tshow: true,\n *\t\t\t\t\ttension: 0.5 (float between 0 and 1)\n *\t\t\t\t},\n *\t\t\t\t...\n *\t\t\t}\n *\n */\n\n(function($) {\n    'use strict'\n\n    /**\n     * @param {Number} x0, y0, x1, y1: coordinates of the end (knot) points of the segment\n     * @param {Number} x2, y2: the next knot (not connected, but needed to calculate p2)\n     * @param {Number} tension: control how far the control points spread\n     * @return {Array}: p1 -> control point, from x1 back toward x0\n     * \t\t\t\t\tp2 -> the next control point, returned to become the next segment's p1\n     *\n     * @api private\n     */\n    function getControlPoints(x0, y0, x1, y1, x2, y2, tension) {\n\n        var pow = Math.pow,\n            sqrt = Math.sqrt,\n            d01, d12, fa, fb, p1x, p1y, p2x, p2y;\n\n        //  Scaling factors: distances from this knot to the previous and following knots.\n        d01 = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2));\n        d12 = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));\n\n        fa = tension * d01 / (d01 + d12);\n        fb = tension - fa;\n\n        p1x = x1 + fa * (x0 - x2);\n        p1y = y1 + fa * (y0 - y2);\n\n        p2x = x1 - fb * (x0 - x2);\n        p2y = y1 - fb * (y0 - y2);\n\n        return [p1x, p1y, p2x, p2y];\n    }\n\n    var line = [];\n\n    function drawLine(points, ctx, height, fill, seriesColor) {\n        var c = $.color.parse(seriesColor);\n\n        c.a = typeof fill == \"number\" ? fill : .3;\n        c.normalize();\n        c = c.toString();\n\n        ctx.beginPath();\n        ctx.moveTo(points[0][0], points[0][1]);\n\n        var plength = points.length;\n\n        for (var i = 0; i < plength; i++) {\n            ctx[points[i][3]].apply(ctx, points[i][2]);\n        }\n\n        ctx.stroke();\n\n        ctx.lineWidth = 0;\n        ctx.lineTo(points[plength - 1][0], height);\n        ctx.lineTo(points[0][0], height);\n\n        ctx.closePath();\n\n        if (fill !== false) {\n            ctx.fillStyle = c;\n            ctx.fill();\n        }\n    }\n\n    /**\n     * @param {Object} ctx: canvas context\n     * @param {String} type: accepted strings: 'bezier' or 'quadratic' (defaults to quadratic)\n     * @param {Array} points: 2 points for which to draw the interpolation\n     * @param {Array} cpoints: control points for those segment points\n     *\n     * @api private\n     */\n    function queue(ctx, type, points, cpoints) {\n        if (type === void 0 || (type !== 'bezier' && type !== 'quadratic')) {\n            type = 'quadratic';\n        }\n        type = type + 'CurveTo';\n\n        if (line.length == 0) line.push([points[0], points[1], cpoints.concat(points.slice(2)), type]);\n        else if (type == \"quadraticCurveTo\" && points.length == 2) {\n            cpoints = cpoints.slice(0, 2).concat(points);\n\n            line.push([points[0], points[1], cpoints, type]);\n        }\n        else line.push([points[2], points[3], cpoints.concat(points.slice(2)), type]);\n    }\n\n    /**\n     * @param {Object} plot\n     * @param {Object} ctx: canvas context\n     * @param {Object} series\n     *\n     * @api private\n     */\n\n    function drawSpline(plot, ctx, series) {\n        // Not interested if spline is not requested\n        if (series.splines.show !== true) {\n            return;\n        }\n\n        var cp = [],\n        // array of control points\n            tension = series.splines.tension || 0.5,\n            idx, x, y, points = series.datapoints.points,\n            ps = series.datapoints.pointsize,\n            plotOffset = plot.getPlotOffset(),\n            len = points.length,\n            pts = [];\n\n        line = [];\n\n        // Cannot display a linespline/areaspline if there are less than 3 points\n        if (len / ps < 4) {\n            $.extend(series.lines, series.splines);\n            return;\n        }\n\n        for (idx = 0; idx < len; idx += ps) {\n            x = points[idx];\n            y = points[idx + 1];\n            if (x == null || x < series.xaxis.min || x > series.xaxis.max || y < series.yaxis.min || y > series.yaxis.max) {\n                continue;\n            }\n\n            pts.push(series.xaxis.p2c(x) + plotOffset.left, series.yaxis.p2c(y) + plotOffset.top);\n        }\n\n        len = pts.length;\n\n        // Draw an open curve, not connected at the ends\n        for (idx = 0; idx < len - 2; idx += 2) {\n            cp = cp.concat(getControlPoints.apply(this, pts.slice(idx, idx + 6).concat([tension])));\n        }\n\n        ctx.save();\n        ctx.strokeStyle = series.color;\n        ctx.lineWidth = series.splines.lineWidth;\n\n        queue(ctx, 'quadratic', pts.slice(0, 4), cp.slice(0, 2));\n\n        for (idx = 2; idx < len - 3; idx += 2) {\n            queue(ctx, 'bezier', pts.slice(idx, idx + 4), cp.slice(2 * idx - 2, 2 * idx + 2));\n        }\n\n        queue(ctx, 'quadratic', pts.slice(len - 2, len), [cp[2 * len - 10], cp[2 * len - 9], pts[len - 4], pts[len - 3]]);\n\n        drawLine(line, ctx, plot.height() + 10, series.splines.fill, series.color);\n\n        ctx.restore();\n    }\n\n    $.plot.plugins.push({\n        init: function(plot) {\n            plot.hooks.drawSeries.push(drawSpline);\n        },\n        options: {\n            series: {\n                splines: {\n                    show: false,\n                    lineWidth: 2,\n                    tension: 0.5,\n                    fill: false\n                }\n            }\n        },\n        name: 'spline',\n        version: '0.8.2'\n    });\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/flot/jquery.flot.symbol.js",
    "content": "/* Flot plugin that adds some extra symbols for plotting points.\n\n Copyright (c) 2007-2014 IOLA and Ole Laursen.\n Licensed under the MIT license.\n\n The symbols are accessed as strings through the standard symbol options:\n\n series: {\n points: {\n symbol: \"square\" // or \"diamond\", \"triangle\", \"cross\"\n }\n }\n\n */\n\n(function ($) {\n    function processRawData(plot, series, datapoints) {\n        // we normalize the area of each symbol so it is approximately the\n        // same as a circle of the given radius\n\n        var handlers = {\n            square: function (ctx, x, y, radius, shadow) {\n                // pi * r^2 = (2s)^2  =>  s = r * sqrt(pi)/2\n                var size = radius * Math.sqrt(Math.PI) / 2;\n                ctx.rect(x - size, y - size, size + size, size + size);\n            },\n            diamond: function (ctx, x, y, radius, shadow) {\n                // pi * r^2 = 2s^2  =>  s = r * sqrt(pi/2)\n                var size = radius * Math.sqrt(Math.PI / 2);\n                ctx.moveTo(x - size, y);\n                ctx.lineTo(x, y - size);\n                ctx.lineTo(x + size, y);\n                ctx.lineTo(x, y + size);\n                ctx.lineTo(x - size, y);\n            },\n            triangle: function (ctx, x, y, radius, shadow) {\n                // pi * r^2 = 1/2 * s^2 * sin (pi / 3)  =>  s = r * sqrt(2 * pi / sin(pi / 3))\n                var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));\n                var height = size * Math.sin(Math.PI / 3);\n                ctx.moveTo(x - size/2, y + height/2);\n                ctx.lineTo(x + size/2, y + height/2);\n                if (!shadow) {\n                    ctx.lineTo(x, y - height/2);\n                    ctx.lineTo(x - size/2, y + height/2);\n                }\n            },\n            cross: function (ctx, x, y, radius, shadow) {\n                // pi * r^2 = (2s)^2  =>  s = r * sqrt(pi)/2\n                var size = radius * Math.sqrt(Math.PI) / 2;\n                ctx.moveTo(x - size, y - size);\n                ctx.lineTo(x + size, y + size);\n                ctx.moveTo(x - size, y + size);\n                ctx.lineTo(x + size, y - size);\n            }\n        };\n\n        var s = series.points.symbol;\n        if (handlers[s])\n            series.points.symbol = handlers[s];\n    }\n\n    function init(plot) {\n        plot.hooks.processDatapoints.push(processRawData);\n    }\n\n    $.plot.plugins.push({\n        init: init,\n        name: 'symbols',\n        version: '1.0'\n    });\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/gritter/jquery.gritter.css",
    "content": "/* the norm */\n#gritter-notice-wrapper {\n\tposition:fixed;\n\ttop:40px;\n\tright:20px;\n\twidth:301px;\n\tz-index:9999;\n\n    -webkit-animation-duration: 1s;\n    animation-duration: 1s;\n    -webkit-animation-fill-mode: both;\n    animation-fill-mode: both;\n\n    -webkit-animation-name: bounceIn;\n    animation-name: bounceIn;\n}\n@keyframes bounceIn {\n    0% {\n        opacity: 0;\n        -webkit-transform: scale(.3);\n        -ms-transform: scale(.3);\n        transform: scale(.3);\n    }\n\n    50% {\n        opacity: 1;\n        -webkit-transform: scale(1.05);\n        -ms-transform: scale(1.05);\n        transform: scale(1.05);\n    }\n\n    70% {\n        -webkit-transform: scale(.9);\n        -ms-transform: scale(.9);\n        transform: scale(.9);\n    }\n\n    100% {\n        opacity: 1;\n        -webkit-transform: scale(1);\n        -ms-transform: scale(1);\n        transform: scale(1);\n    }\n}\n#gritter-notice-wrapper.top-left {\n    left: 20px;\n    right: auto;\n}\n#gritter-notice-wrapper.bottom-right {\n    top: auto;\n    left: auto;\n    bottom: 20px;\n    right: 20px;\n}\n#gritter-notice-wrapper.bottom-left {\n    top: auto;\n    right: auto;\n    bottom: 20px;\n    left: 20px;\n}\n.gritter-item-wrapper {\n\tposition:relative;\n\tmargin:0 0 10px 0;\n\tbackground:url('images/ie-spacer.gif'); /* ie7/8 fix */\n}\n\n.hover .gritter-top {\n\t/*background-position:right -30px;*/\n}\n.gritter-bottom {\n\theight:8px;\n\tmargin:0;\n}\n\n.gritter-item {\n\tdisplay:block;\n\tbackground-color: rgba(39,58,75,0.8);\n    border-radius: 4px;\n\tcolor:#eee;\n\tpadding:10px 11px 10px 11px;\n\tfont-size: 11px;\n\tfont-family:verdana;\n}\n.hover .gritter-item {\n\tbackground-position:right -40px;\n}\n.gritter-item p {\n\tpadding:0;\n\tmargin:0;\n\tword-wrap:break-word;\n}\n\n.gritter-item a:hover {\n    color: #f8ac59;\n    text-decoration: underline;\n}\n.gritter-close {\n\tdisplay:none;\n\tposition:absolute;\n\ttop:5px;\n\tright:3px;\n\tbackground:url(images/gritter.png) no-repeat left top;\n\tcursor:pointer;\n\twidth:30px;\n\theight:30px;\n\ttext-indent:-9999em;\n}\n.gritter-title {\n\tfont-size:12px;\n\tfont-weight:bold;\n\tpadding:0 0 7px 0;\n\tdisplay:block;\n    text-transform: uppercase;\n}\n.gritter-image {\n\twidth:48px;\n\theight:48px;\n\tfloat:left;\n}\n.gritter-with-image,\n.gritter-without-image {\n\tpadding:0;\n}\n.gritter-with-image {\n\twidth:220px;\n\tfloat:right;\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(images/gritter-light.png);\n    color: #222;\n}\n.gritter-light .gritter-title {\n    text-shadow: none;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jeditable/jquery.jeditable.js",
    "content": "/*\n * Jeditable - jQuery in place edit plugin\n *\n * Copyright (c) 2006-2009 Mika Tuupola, Dylan Verheul\n *\n * Licensed under the MIT license:\n *   http://www.opensource.org/licenses/mit-license.php\n *\n * Project home:\n *   http://www.appelsiini.net/projects/jeditable\n *\n * Based on editable by Dylan Verheul <dylan_at_dyve.net>:\n *    http://www.dyve.net/jquery/?editable\n *\n */\n\n/**\n * Version 1.7.1\n *\n * ** means there is basic unit tests for this parameter.\n *\n * @name  Jeditable\n * @type  jQuery\n * @param String  target             (POST) URL or function to send edited content to **\n * @param Hash    options            additional options\n * @param String  options[method]    method to use to send edited content (POST or PUT) **\n * @param Function options[callback] Function to run after submitting edited content **\n * @param String  options[name]      POST parameter name of edited content\n * @param String  options[id]        POST parameter name of edited div id\n * @param Hash    options[submitdata] Extra parameters to send when submitting edited content.\n * @param String  options[type]      text, textarea or select (or any 3rd party input type) **\n * @param Integer options[rows]      number of rows if using textarea **\n * @param Integer options[cols]      number of columns if using textarea **\n * @param Mixed   options[height]    'auto', 'none' or height in pixels **\n * @param Mixed   options[width]     'auto', 'none' or width in pixels **\n * @param String  options[loadurl]   URL to fetch input content before editing **\n * @param String  options[loadtype]  Request type for load url. Should be GET or POST.\n * @param String  options[loadtext]  Text to display while loading external content.\n * @param Mixed   options[loaddata]  Extra parameters to pass when fetching content before editing.\n * @param Mixed   options[data]      Or content given as paramameter. String or function.**\n * @param String  options[indicator] indicator html to show when saving\n * @param String  options[tooltip]   optional tooltip text via title attribute **\n * @param String  options[event]     jQuery event such as 'click' of 'dblclick' **\n * @param String  options[submit]    submit button value, empty means no button **\n * @param String  options[cancel]    cancel button value, empty means no button **\n * @param String  options[cssclass]  CSS class to apply to input form. 'inherit' to copy from parent. **\n * @param String  options[style]     Style to apply to input form 'inherit' to copy from parent. **\n * @param String  options[select]    true or false, when true text is highlighted ??\n * @param String  options[placeholder] Placeholder text or html to insert when element is empty. **\n * @param String  options[onblur]    'cancel', 'submit', 'ignore' or function ??\n *\n * @param Function options[onsubmit] function(settings, original) { ... } called before submit\n * @param Function options[onreset]  function(settings, original) { ... } called before reset\n * @param Function options[onerror]  function(settings, original, xhr) { ... } called on error\n *\n * @param Hash    options[ajaxoptions]  jQuery Ajax options. See docs.jquery.com.\n *\n */\n\n(function($) {\n\n    $.fn.editable = function(target, options) {\n\n        if ('disable' == target) {\n            $(this).data('disabled.editable', true);\n            return;\n        }\n        if ('enable' == target) {\n            $(this).data('disabled.editable', false);\n            return;\n        }\n        if ('destroy' == target) {\n            $(this)\n                .unbind($(this).data('event.editable'))\n                .removeData('disabled.editable')\n                .removeData('event.editable');\n            return;\n        }\n\n        var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);\n\n        /* setup some functions */\n        var plugin   = $.editable.types[settings.type].plugin || function() { };\n        var submit   = $.editable.types[settings.type].submit || function() { };\n        var buttons  = $.editable.types[settings.type].buttons\n            || $.editable.types['defaults'].buttons;\n        var content  = $.editable.types[settings.type].content\n            || $.editable.types['defaults'].content;\n        var element  = $.editable.types[settings.type].element\n            || $.editable.types['defaults'].element;\n        var reset    = $.editable.types[settings.type].reset\n            || $.editable.types['defaults'].reset;\n        var callback = settings.callback || function() { };\n        var onedit   = settings.onedit   || function() { };\n        var onsubmit = settings.onsubmit || function() { };\n        var onreset  = settings.onreset  || function() { };\n        var onerror  = settings.onerror  || reset;\n\n        /* show tooltip */\n        if (settings.tooltip) {\n            $(this).attr('title', settings.tooltip);\n        }\n\n        settings.autowidth  = 'auto' == settings.width;\n        settings.autoheight = 'auto' == settings.height;\n\n        return this.each(function() {\n\n            /* save this to self because this changes when scope changes */\n            var self = this;\n\n            /* inlined block elements lose their width and height after first edit */\n            /* save them for later use as workaround */\n            var savedwidth  = $(self).width();\n            var savedheight = $(self).height();\n\n            /* save so it can be later used by $.editable('destroy') */\n            $(this).data('event.editable', settings.event);\n\n            /* if element is empty add something clickable (if requested) */\n            if (!$.trim($(this).html())) {\n                $(this).html(settings.placeholder);\n            }\n\n            $(this).bind(settings.event, function(e) {\n\n                /* abort if disabled for this element */\n                if (true === $(this).data('disabled.editable')) {\n                    return;\n                }\n\n                /* prevent throwing an exeption if edit field is clicked again */\n                if (self.editing) {\n                    return;\n                }\n\n                /* abort if onedit hook returns false */\n                if (false === onedit.apply(this, [settings, self])) {\n                    return;\n                }\n\n                /* prevent default action and bubbling */\n                e.preventDefault();\n                e.stopPropagation();\n\n                /* remove tooltip */\n                if (settings.tooltip) {\n                    $(self).removeAttr('title');\n                }\n\n                /* figure out how wide and tall we are, saved width and height */\n                /* are workaround for http://dev.jquery.com/ticket/2190 */\n                if (0 == $(self).width()) {\n                    //$(self).css('visibility', 'hidden');\n                    settings.width  = savedwidth;\n                    settings.height = savedheight;\n                } else {\n                    if (settings.width != 'none') {\n                        settings.width =\n                            settings.autowidth ? $(self).width()  : settings.width;\n                    }\n                    if (settings.height != 'none') {\n                        settings.height =\n                            settings.autoheight ? $(self).height() : settings.height;\n                    }\n                }\n                //$(this).css('visibility', '');\n\n                /* remove placeholder text, replace is here because of IE */\n                if ($(this).html().toLowerCase().replace(/(;|\")/g, '') ==\n                    settings.placeholder.toLowerCase().replace(/(;|\")/g, '')) {\n                    $(this).html('');\n                }\n\n                self.editing    = true;\n                self.revert     = $(self).html();\n                $(self).html('');\n\n                /* create the form object */\n                var form = $('<form />');\n\n                /* apply css or style or both */\n                if (settings.cssclass) {\n                    if ('inherit' == settings.cssclass) {\n                        form.attr('class', $(self).attr('class'));\n                    } else {\n                        form.attr('class', settings.cssclass);\n                    }\n                }\n\n                if (settings.style) {\n                    if ('inherit' == settings.style) {\n                        form.attr('style', $(self).attr('style'));\n                        /* IE needs the second line or display wont be inherited */\n                        form.css('display', $(self).css('display'));\n                    } else {\n                        form.attr('style', settings.style);\n                    }\n                }\n\n                /* add main input element to form and store it in input */\n                var input = element.apply(form, [settings, self]);\n\n                /* set input content via POST, GET, given data or existing value */\n                var input_content;\n\n                if (settings.loadurl) {\n                    var t = setTimeout(function() {\n                        input.disabled = true;\n                        content.apply(form, [settings.loadtext, settings, self]);\n                    }, 100);\n\n                    var loaddata = {};\n                    loaddata[settings.id] = self.id;\n                    if ($.isFunction(settings.loaddata)) {\n                        $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));\n                    } else {\n                        $.extend(loaddata, settings.loaddata);\n                    }\n                    $.ajax({\n                        type : settings.loadtype,\n                        url  : settings.loadurl,\n                        data : loaddata,\n                        async : false,\n                        success: function(result) {\n                            window.clearTimeout(t);\n                            input_content = result;\n                            input.disabled = false;\n                        }\n                    });\n                } else if (settings.data) {\n                    input_content = settings.data;\n                    if ($.isFunction(settings.data)) {\n                        input_content = settings.data.apply(self, [self.revert, settings]);\n                    }\n                } else {\n                    input_content = self.revert;\n                }\n                content.apply(form, [input_content, settings, self]);\n\n                input.attr('name', settings.name);\n\n                /* add buttons to the form */\n                buttons.apply(form, [settings, self]);\n\n                /* add created form to self */\n                $(self).append(form);\n\n                /* attach 3rd party plugin if requested */\n                plugin.apply(form, [settings, self]);\n\n                /* focus to first visible form element */\n                $(':input:visible:enabled:first', form).focus();\n\n                /* highlight input contents when requested */\n                if (settings.select) {\n                    input.select();\n                }\n\n                /* discard changes if pressing esc */\n                input.keydown(function(e) {\n                    if (e.keyCode == 27) {\n                        e.preventDefault();\n                        //self.reset();\n                        reset.apply(form, [settings, self]);\n                    }\n                });\n\n                /* discard, submit or nothing with changes when clicking outside */\n                /* do nothing is usable when navigating with tab */\n                var t;\n                if ('cancel' == settings.onblur) {\n                    input.blur(function(e) {\n                        /* prevent canceling if submit was clicked */\n                        t = setTimeout(function() {\n                            reset.apply(form, [settings, self]);\n                        }, 500);\n                    });\n                } else if ('submit' == settings.onblur) {\n                    input.blur(function(e) {\n                        /* prevent double submit if submit was clicked */\n                        t = setTimeout(function() {\n                            form.submit();\n                        }, 200);\n                    });\n                } else if ($.isFunction(settings.onblur)) {\n                    input.blur(function(e) {\n                        settings.onblur.apply(self, [input.val(), settings]);\n                    });\n                } else {\n                    input.blur(function(e) {\n                        /* TODO: maybe something here */\n                    });\n                }\n\n                form.submit(function(e) {\n\n                    if (t) {\n                        clearTimeout(t);\n                    }\n\n                    /* do no submit */\n                    e.preventDefault();\n\n                    /* call before submit hook. */\n                    /* if it returns false abort submitting */\n                    if (false !== onsubmit.apply(form, [settings, self])) {\n                        /* custom inputs call before submit hook. */\n                        /* if it returns false abort submitting */\n                        if (false !== submit.apply(form, [settings, self])) {\n\n                            /* check if given target is function */\n                            if ($.isFunction(settings.target)) {\n                                var str = settings.target.apply(self, [input.val(), settings]);\n                                $(self).html(str);\n                                self.editing = false;\n                                callback.apply(self, [self.innerHTML, settings]);\n                                /* TODO: this is not dry */\n                                if (!$.trim($(self).html())) {\n                                    $(self).html(settings.placeholder);\n                                }\n                            } else {\n                                /* add edited content and id of edited element to POST */\n                                var submitdata = {};\n                                submitdata[settings.name] = input.val();\n                                submitdata[settings.id] = self.id;\n                                /* add extra data to be POST:ed */\n                                if ($.isFunction(settings.submitdata)) {\n                                    $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));\n                                } else {\n                                    $.extend(submitdata, settings.submitdata);\n                                }\n\n                                /* quick and dirty PUT support */\n                                if ('PUT' == settings.method) {\n                                    submitdata['_method'] = 'put';\n                                }\n\n                                /* show the saving indicator */\n                                $(self).html(settings.indicator);\n\n                                /* defaults for ajaxoptions */\n                                var ajaxoptions = {\n                                    type    : 'POST',\n                                    data    : submitdata,\n                                    dataType: 'html',\n                                    url     : settings.target,\n                                    success : function(result, status) {\n                                        if (ajaxoptions.dataType == 'html') {\n                                            $(self).html(result);\n                                        }\n                                        self.editing = false;\n                                        callback.apply(self, [result, settings]);\n                                        if (!$.trim($(self).html())) {\n                                            $(self).html(settings.placeholder);\n                                        }\n                                    },\n                                    error   : function(xhr, status, error) {\n                                        onerror.apply(form, [settings, self, xhr]);\n                                    }\n                                };\n\n                                /* override with what is given in settings.ajaxoptions */\n                                $.extend(ajaxoptions, settings.ajaxoptions);\n                                $.ajax(ajaxoptions);\n\n                            }\n                        }\n                    }\n\n                    /* show tooltip again */\n                    $(self).attr('title', settings.tooltip);\n\n                    return false;\n                });\n            });\n\n            /* privileged methods */\n            this.reset = function(form) {\n                /* prevent calling reset twice when blurring */\n                if (this.editing) {\n                    /* before reset hook, if it returns false abort reseting */\n                    if (false !== onreset.apply(form, [settings, self])) {\n                        $(self).html(self.revert);\n                        self.editing   = false;\n                        if (!$.trim($(self).html())) {\n                            $(self).html(settings.placeholder);\n                        }\n                        /* show tooltip again */\n                        if (settings.tooltip) {\n                            $(self).attr('title', settings.tooltip);\n                        }\n                    }\n                }\n            };\n        });\n\n    };\n\n\n    $.editable = {\n        types: {\n            defaults: {\n                element : function(settings, original) {\n                    var input = $('<input type=\"hidden\"></input>');\n                    $(this).append(input);\n                    return(input);\n                },\n                content : function(string, settings, original) {\n                    $(':input:first', this).val(string);\n                },\n                reset : function(settings, original) {\n                    original.reset(this);\n                },\n                buttons : function(settings, original) {\n                    var form = this;\n                    if (settings.submit) {\n                        /* if given html string use that */\n                        if (settings.submit.match(/>$/)) {\n                            var submit = $(settings.submit).click(function() {\n                                if (submit.attr(\"type\") != \"submit\") {\n                                    form.submit();\n                                }\n                            });\n                            /* otherwise use button with given string as text */\n                        } else {\n                            var submit = $('<button type=\"submit\" />');\n                            submit.html(settings.submit);\n                        }\n                        $(this).append(submit);\n                    }\n                    if (settings.cancel) {\n                        /* if given html string use that */\n                        if (settings.cancel.match(/>$/)) {\n                            var cancel = $(settings.cancel);\n                            /* otherwise use button with given string as text */\n                        } else {\n                            var cancel = $('<button type=\"cancel\" />');\n                            cancel.html(settings.cancel);\n                        }\n                        $(this).append(cancel);\n\n                        $(cancel).click(function(event) {\n                            //original.reset();\n                            if ($.isFunction($.editable.types[settings.type].reset)) {\n                                var reset = $.editable.types[settings.type].reset;\n                            } else {\n                                var reset = $.editable.types['defaults'].reset;\n                            }\n                            reset.apply(form, [settings, original]);\n                            return false;\n                        });\n                    }\n                }\n            },\n            text: {\n                element : function(settings, original) {\n                    var input = $('<input />');\n                    if (settings.width  != 'none') { input.width(settings.width);  }\n                    if (settings.height != 'none') { input.height(settings.height); }\n                    /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */\n                    //input[0].setAttribute('autocomplete','off');\n                    input.attr('autocomplete','off');\n                    $(this).append(input);\n                    return(input);\n                }\n            },\n            textarea: {\n                element : function(settings, original) {\n                    var textarea = $('<textarea />');\n                    if (settings.rows) {\n                        textarea.attr('rows', settings.rows);\n                    } else if (settings.height != \"none\") {\n                        textarea.height(settings.height);\n                    }\n                    if (settings.cols) {\n                        textarea.attr('cols', settings.cols);\n                    } else if (settings.width != \"none\") {\n                        textarea.width(settings.width);\n                    }\n                    $(this).append(textarea);\n                    return(textarea);\n                }\n            },\n            select: {\n                element : function(settings, original) {\n                    var select = $('<select />');\n                    $(this).append(select);\n                    return(select);\n                },\n                content : function(data, settings, original) {\n                    /* If it is string assume it is json. */\n                    if (String == data.constructor) {\n                        eval ('var json = ' + data);\n                    } else {\n                        /* Otherwise assume it is a hash already. */\n                        var json = data;\n                    }\n                    for (var key in json) {\n                        if (!json.hasOwnProperty(key)) {\n                            continue;\n                        }\n                        if ('selected' == key) {\n                            continue;\n                        }\n                        var option = $('<option />').val(key).append(json[key]);\n                        $('select', this).append(option);\n                    }\n                    /* Loop option again to set selected. IE needed this... */\n                    $('select', this).children().each(function() {\n                        if ($(this).val() == json['selected'] ||\n                            $(this).text() == $.trim(original.revert)) {\n                            $(this).attr('selected', 'selected');\n                        }\n                    });\n                }\n            }\n        },\n\n        /* Add new input type */\n        addInputType: function(name, input) {\n            $.editable.types[name] = input;\n        }\n    };\n\n    // publicly accessible defaults\n    $.fn.editable.defaults = {\n        name       : 'value',\n        id         : 'id',\n        type       : 'text',\n        width      : 'auto',\n        height     : 'auto',\n        event      : 'click.editable',\n        onblur     : 'cancel',\n        loadtype   : 'GET',\n        loadtext   : 'Loading...',\n        placeholder: 'Click to edit',\n        loaddata   : {},\n        submitdata : {},\n        ajaxoptions: {}\n    };\n\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqTreeGrid/jquery.treegrid.bootstrap3.js",
    "content": "$.extend($.fn.treegrid.defaults, {\n    expanderExpandedClass: 'glyphicon glyphicon-chevron-down',\n    expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqTreeGrid/jquery.treegrid.css",
    "content": ".treegrid-indent {width:16px; height: 16px; display: inline-block; position: relative;}\n\n.treegrid-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}\n\n.treegrid-expander-expanded{background-image: url(img/collapse.png); }\n.treegrid-expander-collapsed{background-image: url(img/expand.png);}\n.treegrid-selected{background: #f5f5f5 !important;}\n.treegrid-table{border:0 !important;margin-bottom:0}\n.treegrid-table tbody {display:block;height:auto;overflow-y:auto;}\n.treegrid-table thead, .treegrid-table tbody tr {display:table;width:100%;table-layout:fixed;}\n.treegrid-thead th{line-height:40px;border: 0 !important;background:#fff !important;border-radius: 4px;border-left:1px solid #e7eaec !important;border-bottom:2px solid #e7eaec !important;text-align: center;}\n.treegrid-thead tr :first-child{border-left:0 !important}\n.treegrid-tbody td{border: 0 !important;border-left:1px solid #e7eaec !important;border-bottom:1px solid #e7eaec !important;overflow: hidden;\n    white-space: nowrap;\n    text-overflow: ellipsis;}\n.treegrid-tbody tr :first-child{border-left:0 !important}\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqTreeGrid/jquery.treegrid.extension.js",
    "content": "(function($) {\n    \"use strict\";\n\n    $.fn.bootstrapTreeTable = function(options, param) {\n        // 如果是调用方法\n        if (typeof options == 'string') {\n            return $.fn.bootstrapTreeTable.methods[options](this, param);\n        }\n\n        // 如果是初始化组件\n        options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});\n        // 是否有radio或checkbox\n        var hasSelectItem = false;\n        var target = $(this);\n        // 在外层包装一下div，样式用的bootstrap-table的\n        var _main_div = $(\"<div class='fixed-table-container'></div>\");\n        target.before(_main_div);\n        _main_div.append(target);\n        target.addClass(\"table table-hover treegrid-table table-bordered\");\n        if (options.striped) {\n            target.addClass('table-striped');\n        }\n        // 工具条在外层包装一下div，样式用的bootstrap-table的\n        if(options.toolbar){\n            var _tool_div = $(\"<div class='fixed-table-toolbar' style='display:none;'></div>\");\n            var _tool_left_div = $(\"<div class='bs-bars pull-left'></div>\");\n            _tool_left_div.append($(options.toolbar));\n            _tool_div.append(_tool_left_div);\n            _main_div.before(_tool_div);\n        }\n        // 得到根节点\n        target.getRootNodes = function(data) {\n            // 指定Root节点值\n            var _root = options.rootCodeValue?options.rootCodeValue:null\n            var result = [];\n            $.each(data, function(index, item) {\n                // 这里兼容几种常见Root节点写法\n                // 默认的几种判断\n                var _defaultRootFlag = item[options.parentCode] == '0'\n                    || item[options.parentCode] == 0\n                    || item[options.parentCode] == null\n                    || item[options.parentCode] == '';\n                if (!item[options.parentCode] || (_root?(item[options.parentCode] == options.rootCodeValue):_defaultRootFlag)){\n                    result.push(item);\n                }\n                // 添加一个默认属性，用来判断当前节点有没有被显示\n                item.isShow = false;\n            });\n            return result;\n        };\n        var j = 0;\n        // 递归获取子节点并且设置子节点\n        target.getChildNodes = function(data, parentNode, parentIndex, tbody) {\n            $.each(data, function(i, item) {\n                if (item[options.parentCode] == parentNode[options.code]) {\n                    var tr = $('<tr></tr>');\n                    var nowParentIndex = (parentIndex + (j++) + 1);\n                    tr.addClass('treegrid-' + nowParentIndex);\n                    tr.addClass('treegrid-parent-' + parentIndex);\n                    target.renderRow(tr,item);\n                    item.isShow = true;\n                    tbody.append(tr);\n                    target.getChildNodes(data, item, nowParentIndex, tbody)\n\n                }\n            });\n        };\n        // 绘制行\n        target.renderRow = function(tr,item){\n            $.each(options.columns, function(index, column) {\n                // 判断有没有选择列\n                if(index==0&&column.field=='selectItem'){\n                    hasSelectItem = true;\n                    var td = $('<td style=\"text-align:center;width:36px\"></td>');\n                    if(column.radio){\n                        var _ipt = $('<input name=\"select_item\" type=\"radio\" value=\"'+item[options.id]+'\"></input>');\n                        td.append(_ipt);\n                    }\n                    if(column.checkbox){\n                        var _ipt = $('<input name=\"select_item\" type=\"checkbox\" value=\"'+item[options.id]+'\"></input>');\n                        td.append(_ipt);\n                    }\n                    tr.append(td);\n                }else{\n                    var td = $('<td style=\"text-align:'+column.align+';'+((column.width)?('width:'+column.width):'')+'\"></td>');\n                    // 增加formatter渲染\n                    if (column.formatter) {\n                        td.html(column.formatter.call(this, item, index));\n                    } else {\n                        td.text(item[column.field]);\n                    }\n                    tr.append(td);\n                }\n            });\n        }\n        // 加载数据\n        target.load = function(parms){\n            // 加载数据前先清空\n            target.html(\"\");\n            // 构造表头\n            var thr = $('<tr></tr>');\n            $.each(options.columns, function(i, item) {\n                var th = null;\n                // 判断有没有选择列\n                if(i==0&&item.field=='selectItem'){\n                    hasSelectItem = true;\n                    th = $('<th style=\"text-align:'+item.valign+';width:36px\"></th>');\n                }else{\n                    th = $('<th style=\"text-align:'+item.valign+';padding:10px;'+((item.width)?('width:'+item.width):'')+'\"></th>');\n                }\n                th.text(item.title);\n                thr.append(th);\n            });\n            var thead = $('<thead class=\"treegrid-thead\"></thead>');\n            thead.append(thr);\n            target.append(thead);\n            // 构造表体\n            var tbody = $('<tbody class=\"treegrid-tbody\"></tbody>');\n            target.append(tbody);\n            // 添加加载loading\n            var _loading = '<tr><td colspan=\"'+options.columns.length+'\"><div style=\"display: block;text-align: center;\">正在努力地加载数据中，请稍候……</div></td></tr>'\n            tbody.html(_loading);\n            // 默认高度\n            if(options.height){\n                tbody.css(\"height\",options.height);\n            }\n            $.ajax({\n                type : options.type,\n                url : options.url,\n                data : parms?parms:options.ajaxParams,\n                dataType : \"JSON\",\n                success : function(data, textStatus, jqXHR) {\n                    // 加载完数据先清空\n                    tbody.html(\"\");\n                    if(!data||data.length<=0){\n                        var _empty = '<tr><td colspan=\"'+options.columns.length+'\"><div style=\"display: block;text-align: center;\">没有记录</div></td></tr>'\n                        tbody.html(_empty);\n                        return;\n                    }\n                    var rootNode = target.getRootNodes(data);\n                    $.each(rootNode, function(i, item) {\n                        var tr = $('<tr></tr>');\n                        tr.addClass('treegrid-' + (j + \"_\" + i));\n                        target.renderRow(tr,item);\n                        item.isShow = true;\n                        tbody.append(tr);\n                        target.getChildNodes(data, item, (j + \"_\" + i), tbody);\n                    });\n                    // 下边的操作主要是为了查询时让一些没有根节点的节点显示\n                    $.each(data, function(i, item) {\n                        if(!item.isShow){\n                            var tr = $('<tr></tr>');\n                            tr.addClass('treegrid-' + (j + \"_\" + i));\n                            target.renderRow(tr,item);\n                            tbody.append(tr);\n                        }\n                    });\n                    target.append(tbody);\n                    // 初始化treegrid\n                    target.treegrid({\n                        treeColumn: options.expandColumn?options.expandColumn:(hasSelectItem?1:0),//如果有radio或checkbox默认第二列层级显示，当前是在用户未设置的提前下\n                        expanderExpandedClass : options.expanderExpandedClass,\n                        expanderCollapsedClass : options.expanderCollapsedClass\n                    });\n                    if (!options.expandAll) {\n                        target.treegrid('collapseAll');\n                    }\n                    //动态设置表头宽度\n                    //thead.css(\"width\", tbody.children(\":first\").css(\"width\"));\n                    // 行点击选中事件\n                    target.find(\"tbody\").find(\"tr\").click(function(){\n                        if(hasSelectItem){\n                            var _ipt = $(this).find(\"input[name='select_item']\");\n                            if(_ipt.attr(\"type\")==\"radio\"){\n                                _ipt.prop('checked',true);\n                                target.find(\"tbody\").find(\"tr\").removeClass(\"treegrid-selected\");\n                                $(this).addClass(\"treegrid-selected\");\n                            }else{\n                                if(_ipt.prop('checked')){\n                                    _ipt.prop('checked',false);\n                                    $(this).removeClass(\"treegrid-selected\");\n                                }else{\n                                    _ipt.prop('checked',true);\n                                    $(this).addClass(\"treegrid-selected\");\n                                }\n                            }\n                        }\n                    });\n                },\n                error:function(xhr,textStatus){\n                    var _errorMsg = '<tr><td colspan=\"'+options.columns.length+'\"><div style=\"display: block;text-align: center;\">'+xhr.responseText+'</div></td></tr>'\n                    tbody.html(_errorMsg);\n                    debugger;\n                },\n            });\n        }\n        if (options.url) {\n            target.load();\n        } else {\n            // 也可以通过defaults里面的data属性通过传递一个数据集合进来对组件进行初始化....有兴趣可以自己实现，思路和上述类似\n        }\n\n        return target;\n    };\n\n    // 组件方法封装........\n    $.fn.bootstrapTreeTable.methods = {\n        // 返回选中记录的id（返回的id由配置中的id属性指定）\n        // 为了兼容bootstrap-table的写法，统一返回数组，这里只返回了指定的id\n        getSelections : function(target, data) {\n            // 所有被选中的记录input\n            var _ipt = target.find(\"tbody\").find(\"tr\").find(\"input[name='select_item']:checked\");\n            var chk_value =[];\n            // 如果是radio\n            if(_ipt.attr(\"type\")==\"radio\"){\n                chk_value.push({id:_ipt.val()});\n            }else{\n                _ipt.each(function(_i,_item){\n                    chk_value.push({id:$(_item).val()});\n                });\n            }\n            return chk_value;\n        },\n        // 刷新记录\n        refresh : function(target, parms) {\n            if(parms){\n                target.load(parms);\n            }else{\n                target.load();\n            }\n        },\n        // 重置表格视图\n        resetHeight : function(target, height) {\n        \ttarget.find(\"tbody\").css(\"height\", height + 'px');\n        }\n        // 组件的其他方法也可以进行类似封装........\n    };\n\n    $.fn.bootstrapTreeTable.defaults = {\n        id : 'menuId',// 选取记录返回的值\n        code : 'menuId',// 用于设置父子关系\n        parentCode : 'parentId',// 用于设置父子关系\n        rootCodeValue: null,//设置根节点code值----可指定根节点，默认为null,\"\",0,\"0\"\n        data : [], // 构造table的数据集合\n        type : \"GET\", // 请求数据的ajax类型\n        url : null, // 请求数据的ajax的url\n        ajaxParams : {}, // 请求数据的ajax的data属性\n        expandColumn : null,// 在哪一列上面显示展开按钮\n        expandAll : true, // 是否全部展开\n        striped : false, // 是否各行渐变色\n        columns : [],\n        toolbar: null,//顶部工具条\n        height: 0,\n        expanderExpandedClass : 'glyphicon glyphicon-chevron-down',// 展开的按钮的图标\n        expanderCollapsedClass : 'glyphicon glyphicon-chevron-right'// 缩起的按钮的图标\n\n    };\n})(jQuery);"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqTreeGrid/jquery.treegrid.js",
    "content": "/*\n * jQuery treegrid Plugin 0.2.0\n * https://github.com/maxazan/jquery-treegrid\n * \n * Copyright 2013, Pomazan Max\n * Licensed under the MIT licenses.\n */\n(function($) {\n\n    var methods = {\n        /**\n         * Initialize tree\n         * \n         * @param {Object} options\n         * @returns {Object[]}\n         */\n        initTree: function(options) {\n            var settings = $.extend({}, this.treegrid.defaults, options);\n            return this.each(function() {\n                var $this = $(this);\n                $this.treegrid('setTreeContainer', $(this));\n                $this.treegrid('setSettings', settings);\n                settings.getRootNodes.apply(this, [$(this)]).treegrid('initNode', settings);\n            });\n        },\n        /**\n         * Initialize node\n         * \n         * @param {Object} settings\n         * @returns {Object[]}\n         */\n        initNode: function(settings) {\n            return this.each(function() {\n                var $this = $(this);\n                $this.treegrid('setTreeContainer', settings.getTreeGridContainer.apply(this));\n                $this.treegrid('getChildNodes').treegrid('initNode', settings);\n                $this.treegrid('initExpander').treegrid('initIndent').treegrid('initEvents').treegrid('initState').treegrid(\"initSettingsEvents\");\n            });\n        },\n        /**\n         * Initialize node events\n         * \n         * @returns {Node}\n         */\n        initEvents: function() {\n            var $this = $(this);\n            //Save state on change\n            $this.on(\"change\", function() {\n                var $this = $(this);\n                $this.treegrid('render');\n                if ($this.treegrid('getSetting', 'saveState')) {\n                    $this.treegrid('saveState');\n                }\n            });\n            //Default behavior on collapse\n            $this.on(\"collapse\", function() {\n                var $this = $(this);\n                $this.removeClass('treegrid-expanded');\n                $this.addClass('treegrid-collapsed');\n            });\n            //Default behavior on expand\n            $this.on(\"expand\", function() {\n                var $this = $(this);\n                $this.removeClass('treegrid-collapsed');\n                $this.addClass('treegrid-expanded');\n            });\n\n            return $this;\n        },\n        /**\n         * Initialize events from settings\n         * \n         * @returns {Node}\n         */\n        initSettingsEvents: function() {\n            var $this = $(this);\n            //Save state on change\n            $this.on(\"change\", function() {\n                var $this = $(this);\n                if (typeof ($this.treegrid('getSetting', 'onChange')) === \"function\") {\n                    $this.treegrid('getSetting', 'onChange').apply($this);\n                }\n            });\n            //Default behavior on collapse\n            $this.on(\"collapse\", function() {\n                var $this = $(this);\n                if (typeof ($this.treegrid('getSetting', 'onCollapse')) === \"function\") {\n                    $this.treegrid('getSetting', 'onCollapse').apply($this);\n                }\n            });\n            //Default behavior on expand\n            $this.on(\"expand\", function() {\n                var $this = $(this);\n                if (typeof ($this.treegrid('getSetting', 'onExpand')) === \"function\") {\n                    $this.treegrid('getSetting', 'onExpand').apply($this);\n                }\n\n            });\n\n            return $this;\n        },\n        /**\n         * Initialize expander for node\n         * \n         * @returns {Node}\n         */\n        initExpander: function() {\n            var $this = $(this);\n            var cell = $this.find('td').get($this.treegrid('getSetting', 'treeColumn'));\n            var tpl = $this.treegrid('getSetting', 'expanderTemplate');\n            var expander = $this.treegrid('getSetting', 'getExpander').apply(this);\n            if (expander) {\n                expander.remove();\n            }\n            $(tpl).prependTo(cell).click(function() {\n                $($(this).closest('tr')).treegrid('toggle');\n            });\n            return $this;\n        },\n        /**\n         * Initialize indent for node\n         * \n         * @returns {Node}\n         */\n        initIndent: function() {\n            var $this = $(this);\n            $this.find('.treegrid-indent').remove();\n            for (var i = 0; i < $(this).treegrid('getDepth'); i++) {\n                $($this.treegrid('getSetting', 'indentTemplate')).insertBefore($this.find('.treegrid-expander'));\n            }\n            return $this;\n        },\n        /**\n         * Initialise state of node\n         * \n         * @returns {Node}\n         */\n        initState: function() {\n            var $this = $(this);\n            if ($this.treegrid('getSetting', 'saveState') && !$this.treegrid('isFirstInit')) {\n                $this.treegrid('restoreState');\n            } else {\n                if ($this.treegrid('getSetting', 'initialState') === \"expanded\") {\n                    $this.treegrid('expand');\n                } else {\n                    $this.treegrid('collapse');\n                }\n            }\n            return $this;\n        },\n        /**\n         * Return true if this tree was never been initialised\n         * \n         * @returns {Boolean}\n         */\n        isFirstInit: function() {\n            var tree = $(this).treegrid('getTreeContainer');\n            if (tree.data('first_init') === undefined) {\n                tree.data('first_init', $.cookie(tree.treegrid('getSetting', 'saveStateName')) === undefined);\n            }\n            return tree.data('first_init');\n        },\n        /**\n         * Save state of current node\n         * \n         * @returns {Node}\n         */\n        saveState: function() {\n            var $this = $(this);\n            if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {\n\n                var stateArrayString = $.cookie($this.treegrid('getSetting', 'saveStateName')) || '';\n                var stateArray = (stateArrayString === '' ? [] : stateArrayString.split(','));\n                var nodeId = $this.treegrid('getNodeId');\n\n                if ($this.treegrid('isExpanded')) {\n                    if ($.inArray(nodeId, stateArray) === -1) {\n                        stateArray.push(nodeId);\n                    }\n                } else if ($this.treegrid('isCollapsed')) {\n                    if ($.inArray(nodeId, stateArray) !== -1) {\n                        stateArray.splice($.inArray(nodeId, stateArray), 1);\n                    }\n                }\n                $.cookie($this.treegrid('getSetting', 'saveStateName'), stateArray.join(','));\n            }\n            return $this;\n        },\n        /**\n         * Restore state of current node.\n         * \n         * @returns {Node}\n         */\n        restoreState: function() {\n            var $this = $(this);\n            if ($this.treegrid('getSetting', 'saveStateMethod') === 'cookie') {\n                var stateArray = $.cookie($this.treegrid('getSetting', 'saveStateName')).split(',');\n                if ($.inArray($this.treegrid('getNodeId'), stateArray) !== -1) {\n                    $this.treegrid('expand');\n                } else {\n                    $this.treegrid('collapse');\n                }\n\n            }\n            return $this;\n        },\n        /**\n         * Method return setting by name\n         * \n         * @param {type} name\n         * @returns {unresolved}\n         */\n        getSetting: function(name) {\n            if (!$(this).treegrid('getTreeContainer')) {\n                return null;\n            }\n            return $(this).treegrid('getTreeContainer').data('settings')[name];\n        },\n        /**\n         * Add new settings\n         * \n         * @param {Object} settings\n         */\n        setSettings: function(settings) {\n            $(this).treegrid('getTreeContainer').data('settings', settings);\n        },\n        /**\n         * Return tree container\n         * \n         * @returns {HtmlElement}\n         */\n        getTreeContainer: function() {\n            return $(this).data('treegrid');\n        },\n        /**\n         * Set tree container\n         * \n         * @param {HtmlE;ement} container\n         */\n        setTreeContainer: function(container) {\n            return $(this).data('treegrid', container);\n        },\n        /**\n         * Method return all root nodes of tree. \n         * \n         * Start init all child nodes from it.\n         * \n         * @returns {Array}\n         */\n        getRootNodes: function() {\n            return $(this).treegrid('getSetting', 'getRootNodes').apply(this, [$(this).treegrid('getTreeContainer')]);\n        },\n        /**\n         * Method return all nodes of tree. \n         * \n         * @returns {Array}\n         */\n        getAllNodes: function() {\n            return $(this).treegrid('getSetting', 'getAllNodes').apply(this, [$(this).treegrid('getTreeContainer')]);\n        },\n        /**\n         * Mthod return true if element is Node\n         * \n         * @returns {String}\n         */\n        isNode: function() {\n            return $(this).treegrid('getNodeId') !== null;\n        },\n        /**\n         * Mthod return id of node\n         * \n         * @returns {String}\n         */\n        getNodeId: function() {\n            if ($(this).treegrid('getSetting', 'getNodeId') === null) {\n                return null;\n            } else {\n                return $(this).treegrid('getSetting', 'getNodeId').apply(this);\n            }\n        },\n        /**\n         * Method return parent id of node or null if root node\n         * \n         * @returns {String}\n         */\n        getParentNodeId: function() {\n            return $(this).treegrid('getSetting', 'getParentNodeId').apply(this);\n        },\n        /**\n         * Method return parent node or null if root node\n         * \n         * @returns {Object[]}\n         */\n        getParentNode: function() {\n            if ($(this).treegrid('getParentNodeId') === null) {\n                return null;\n            } else {\n                return $(this).treegrid('getSetting', 'getNodeById').apply(this, [$(this).treegrid('getParentNodeId'), $(this).treegrid('getTreeContainer')]);\n            }\n        },\n        /**\n         * Method return array of child nodes or null if node is leaf\n         * \n         * @returns {Object[]}\n         */\n        getChildNodes: function() {\n            return $(this).treegrid('getSetting', 'getChildNodes').apply(this, [$(this).treegrid('getNodeId'), $(this).treegrid('getTreeContainer')]);\n        },\n        /**\n         * Method return depth of tree.\n         * \n         * This method is needs for calculate indent\n         * \n         * @returns {Number}\n         */\n        getDepth: function() {\n            if ($(this).treegrid('getParentNode') === null) {\n                return 0;\n            }\n            return $(this).treegrid('getParentNode').treegrid('getDepth') + 1;\n        },\n        /**\n         * Method return true if node is root\n         * \n         * @returns {Boolean}\n         */\n        isRoot: function() {\n            return $(this).treegrid('getDepth') === 0;\n        },\n        /**\n         * Method return true if node has no child nodes\n         * \n         * @returns {Boolean}\n         */\n        isLeaf: function() {\n            return $(this).treegrid('getChildNodes').length === 0;\n        },\n        /**\n         * Method return true if node last in branch\n         * \n         * @returns {Boolean}\n         */\n        isLast: function() {\n            if ($(this).treegrid('isNode')) {\n                var parentNode = $(this).treegrid('getParentNode');\n                if (parentNode === null) {\n                    if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').last().treegrid('getNodeId')) {\n                        return true;\n                    }\n                } else {\n                    if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').last().treegrid('getNodeId')) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        },\n        /**\n         * Method return true if node first in branch\n         * \n         * @returns {Boolean}\n         */\n        isFirst: function() {\n            if ($(this).treegrid('isNode')) {\n                var parentNode = $(this).treegrid('getParentNode');\n                if (parentNode === null) {\n                    if ($(this).treegrid('getNodeId') === $(this).treegrid('getRootNodes').first().treegrid('getNodeId')) {\n                        return true;\n                    }\n                } else {\n                    if ($(this).treegrid('getNodeId') === parentNode.treegrid('getChildNodes').first().treegrid('getNodeId')) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        },\n        /**\n         * Return true if node expanded\n         * \n         * @returns {Boolean}\n         */\n        isExpanded: function() {\n            return $(this).hasClass('treegrid-expanded');\n        },\n        /**\n         * Return true if node collapsed\n         * \n         * @returns {Boolean}\n         */\n        isCollapsed: function() {\n            return $(this).hasClass('treegrid-collapsed');\n        },\n        /**\n         * Return true if at least one of parent node is collapsed\n         * \n         * @returns {Boolean}\n         */\n        isOneOfParentsCollapsed: function() {\n            var $this = $(this);\n            if ($this.treegrid('isRoot')) {\n                return false;\n            } else {\n                if ($this.treegrid('getParentNode').treegrid('isCollapsed')) {\n                    return true;\n                } else {\n                    return $this.treegrid('getParentNode').treegrid('isOneOfParentsCollapsed');\n                }\n            }\n        },\n        /**\n         * Expand node\n         * \n         * @returns {Node}\n         */\n        expand: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n                if (!$this.treegrid('isLeaf') && !$this.treegrid(\"isExpanded\")) {\n                    $this.trigger(\"expand\");\n                    $this.trigger(\"change\");\n                }\n            });\n        },\n        /**\n         * Expand all nodes\n         * \n         * @returns {Node}\n         */\n        expandAll: function() {\n            var $this = $(this);\n            $this.treegrid('getRootNodes').treegrid('expandRecursive');\n            return $this;\n        },\n        /**\n         * Expand current node and all child nodes begin from current\n         * \n         * @returns {Node}\n         */\n        expandRecursive: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n                $this.treegrid('expand');\n                if (!$this.treegrid('isLeaf')) {\n                    $this.treegrid('getChildNodes').treegrid('expandRecursive');\n                }\n            });\n        },\n        /**\n         * Collapse node\n         * \n         * @returns {Node}\n         */\n        collapse: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n                if (!$this.treegrid('isLeaf') && !$this.treegrid(\"isCollapsed\")) {\n                    $this.trigger(\"collapse\");\n                    $this.trigger(\"change\");\n                }\n            });\n        },\n        /**\n         * Collapse all nodes\n         * \n         * @returns {Node}\n         */\n        collapseAll: function() {\n            var $this = $(this);\n            $this.treegrid('getRootNodes').treegrid('collapseRecursive');\n            return $this;\n        },\n        /**\n         * Collapse current node and all child nodes begin from current\n         * \n         * @returns {Node}\n         */\n        collapseRecursive: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n                $this.treegrid('collapse');\n                if (!$this.treegrid('isLeaf')) {\n                    $this.treegrid('getChildNodes').treegrid('collapseRecursive');\n                }\n            });\n        },\n        /**\n         * Expand if collapsed, Collapse if expanded\n         * \n         * @returns {Node}\n         */\n        toggle: function() {\n            var $this = $(this);\n            if ($this.treegrid('isExpanded')) {\n                $this.treegrid('collapse');\n            } else {\n                $this.treegrid('expand');\n            }\n            return $this;\n        },\n        /**\n         * Rendering node\n         * \n         * @returns {Node}\n         */\n        render: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n\n                if ($this.treegrid('isOneOfParentsCollapsed')) {\n                    $this.hide();\n                } else {\n                    $this.show();\n                }\n                if (!$this.treegrid('isLeaf')) {\n                    $this.treegrid('renderExpander');\n                    $this.treegrid('getChildNodes').treegrid('render');\n                }\n            });\n        },\n        /**\n         * Rendering expander depends on node state\n         * \n         * @returns {Node}\n         */\n        renderExpander: function() {\n            return $(this).each(function() {\n                var $this = $(this);\n                var expander = $this.treegrid('getSetting', 'getExpander').apply(this);\n                if (expander) {\n\n                    if (!$this.treegrid('isCollapsed')) {\n                        expander.removeClass($this.treegrid('getSetting', 'expanderCollapsedClass'));\n                        expander.addClass($this.treegrid('getSetting', 'expanderExpandedClass'));\n                    } else {\n                        expander.removeClass($this.treegrid('getSetting', 'expanderExpandedClass'));\n                        expander.addClass($this.treegrid('getSetting', 'expanderCollapsedClass'));\n                    }\n                } else {\n                    $this.treegrid('initExpander');\n                    $this.treegrid('renderExpander');\n                }\n            });\n        }\n    };\n    $.fn.treegrid = 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.initTree.apply(this, arguments);\n        } else {\n            $.error('Method with name ' + method + ' does not exists for jQuery.treegrid');\n        }\n    };\n    /**\n     *  Plugin's default options\n     */\n    $.fn.treegrid.defaults = {\n        initialState: 'expanded',\n        saveState: false,\n        saveStateMethod: 'cookie',\n        saveStateName: 'tree-grid-state',\n        expanderTemplate: '<span class=\"treegrid-expander\"></span>',\n        indentTemplate: '<span class=\"treegrid-indent\"></span>',\n        expanderExpandedClass: 'treegrid-expander-expanded',\n        expanderCollapsedClass: 'treegrid-expander-collapsed',\n        treeColumn: 0,\n        getExpander: function() {\n            return $(this).find('.treegrid-expander');\n        },\n        getNodeId: function() {\n            var template = /treegrid-([A-Za-z0-9_-]+)/;\n            if (template.test($(this).attr('class'))) {\n                return template.exec($(this).attr('class'))[1];\n            }\n            return null;\n        },\n        getParentNodeId: function() {\n            var template = /treegrid-parent-([A-Za-z0-9_-]+)/;\n            if (template.test($(this).attr('class'))) {\n                return template.exec($(this).attr('class'))[1];\n            }\n            return null;\n        },\n        getNodeById: function(id, treegridContainer) {\n            var templateClass = \"treegrid-\" + id;\n            return treegridContainer.find('tr.' + templateClass);\n        },\n        getChildNodes: function(id, treegridContainer) {\n            var templateClass = \"treegrid-parent-\" + id;\n            return treegridContainer.find('tr.' + templateClass);\n        },\n        getTreeGridContainer: function() {\n            return $(this).closest('table');\n        },\n        getRootNodes: function(treegridContainer) {\n            var result = $.grep(treegridContainer.find('tr'), function(element) {\n                var classNames = $(element).attr('class');\n                var templateClass = /treegrid-([A-Za-z0-9_-]+)/;\n                var templateParentClass = /treegrid-parent-([A-Za-z0-9_-]+)/;\n                return templateClass.test(classNames) && !templateParentClass.test(classNames);\n            });\n            return $(result);\n        },\n        getAllNodes: function(treegridContainer) {\n            var result = $.grep(treegridContainer.find('tr'), function(element) {\n                var classNames = $(element).attr('class');\n                var templateClass = /treegrid-([A-Za-z0-9_-]+)/;\n                return templateClass.test(classNames);\n            });\n            return $(result);\n        },\n        //Events\n        onCollapse: null,\n        onExpand: null,\n        onChange: null\n\n    };\n})(jQuery);"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqTreeGrid/tree.table.js",
    "content": "/**\n * 初始化 Tree Table 的封装\n *\n * @author 郑保乐\n */\n(function () {\n    var TreeTable = function (tableId, url, columns) {\n        this.btInstance = null;\t\t\t\t\t//jquery和bootstrapTreeTable绑定的对象\n        this.bstableId = tableId;\n        this.url = url;\n        this.method = \"GET\";\n        this.columns = columns;\n        this.data = {};// ajax的参数\n        this.expandColumn = null;// 展开显示的列 \n        this.id = 'menuId';// 选取记录返回的值\n        this.code = 'menuId';// 用于设置父子关系\n        this.parentCode = 'parentId';// 用于设置父子关系\n        this.expandAll = false;// 是否默认全部展开\n        this.toolbarId = tableId + \"Toolbar\";\n        this.height = 430;\n    };\n\n    TreeTable.prototype = {\n        /**\n         * 初始化bootstrap table\n         */\n        init: function () {\n            var tableId = this.bstableId;\n            this.btInstance =\n                $('#'+tableId).bootstrapTreeTable({\n                    id: this.id,// 选取记录返回的值\n                    code: this.code,// 用于设置父子关系\n                    parentCode: this.parentCode,// 用于设置父子关系\n                    rootCodeValue: this.rootCodeValue,//设置根节点code值----可指定根节点，默认为null,\"\",0,\"0\"\n                    type: this.method, //请求数据的ajax类型\n                    url: this.url,   //请求数据的ajax的url\n                    ajaxParams: this.data, //请求数据的ajax的data属性\n                    expandColumn: this.expandColumn,//在哪一列上面显示展开按钮,从0开始\n                    striped: true,   //是否各行渐变色\n                    expandAll: this.expandAll,  //是否全部展开\n                    columns: this.columns,\t\t//列数组\n                    toolbar: \"#\" + this.toolbarId,//顶部工具条\n                    height: this.height,\n                });\n            return this;\n        },\n\n        /**\n         * 设置在哪一列上面显示展开按钮,从0开始\n         */\n        setExpandColumn: function (expandColumn) {\n            this.expandColumn = expandColumn;\n        },\n        /**\n         * 设置记录返回的id值\n         */\n        setIdField: function (id) {\n            this.id = id;\n        },\n        /**\n         * 设置记录分级的字段\n         */\n        setCodeField: function (code) {\n            this.code = code;\n        },\n        /**\n         * 设置记录分级的父级字段\n         */\n        setParentCodeField: function (parentCode) {\n            this.parentCode = parentCode;\n        },\n        /**\n         * 设置根节点code值----可指定根节点，默认为null,\"\",0,\"0\"\n         */\n        setRootCodeValue: function (rootCodeValue) {\n            this.rootCodeValue = rootCodeValue;\n        },\n        /**\n         * 设置是否默认全部展开\n         */\n        setExpandAll: function (expandAll) {\n        \tthis.expandAll = expandAll;\n        },\n        /**\n         * 设置表格高度\n         */\n        setHeight: function (height) {\n        \tthis.height = height;\n        },\n        /**\n         * 设置ajax post请求时候附带的参数\n         */\n        set: function (key, value) {\n            if (typeof key == \"object\") {\n                for (var i in key) {\n                    if (typeof i == \"function\")\n                        continue;\n                    this.data[i] = key[i];\n                }\n            } else {\n                this.data[key] = (typeof value == \"undefined\") ? $(\"#\" + key).val() : value;\n            }\n            return this;\n        },\n\n        /**\n         * 设置ajax get请求时候附带的参数\n         */\n        setData: function (data) {\n            this.data = data;\n            return this;\n        },\n\n        /**\n         * 清空ajax post请求参数\n         */\n        clear: function () {\n            this.data = {};\n            return this;\n        },\n\n        /**\n         * 刷新表格\n         */\n        refresh: function (parms) {\n            if (typeof parms != \"undefined\") {\n                this.btInstance.bootstrapTreeTable('refresh', parms.query);// 为了兼容bootstrap-table的写法\n            } else {\n                this.btInstance.bootstrapTreeTable('refresh');\n            }\n        },\n        \n        /**\n         * 设置高度\n         */\n        resetHeight: function(parms) {\n        \tif (typeof parms != \"undefined\") {\n                this.btInstance.bootstrapTreeTable('resetHeight', parms.height);// 为了兼容bootstrap-table的写法\n            } else {\n                this.btInstance.bootstrapTreeTable('resetHeight');\n            }\n        },\n        \n        /**\n         * 获取选中行\n         */\n        getSelectedRow: function() {\n            return this.btInstance.bootstrapTreeTable('getSelections');\n        }\n    };\n\n    window.TreeTable = TreeTable;\n\n}());"
  },
  {
    "path": "src/main/resources/static/js/plugins/jqgrid/i18n/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:'存在'}],\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};\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jsKnob/jquery.knob.js",
    "content": "/*!jQuery Knob*/\n/**\n * Downward compatible, touchable dial\n *\n * Version: 1.2.8\n * Requires: jQuery v1.7+\n *\n * Copyright (c) 2012 Anthony Terrien\n * Under MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Thanks to vor, eskimoblood, spiffistan, FabrizioC\n */\n(function($) {\n\n    /**\n     * Kontrol library\n     */\n    \"use strict\";\n\n    /**\n     * Definition of globals and core\n     */\n    var k = {}, // kontrol\n        max = Math.max,\n        min = Math.min;\n\n    k.c = {};\n    k.c.d = $(document);\n    k.c.t = function (e) {\n        return e.originalEvent.touches.length - 1;\n    };\n\n    /**\n     * Kontrol Object\n     *\n     * Definition of an abstract UI control\n     *\n     * Each concrete component must call this one.\n     * <code>\n     * k.o.call(this);\n     * </code>\n     */\n    k.o = function () {\n        var s = this;\n\n        this.o = null; // array of options\n        this.$ = null; // jQuery wrapped element\n        this.i = null; // mixed HTMLInputElement or array of HTMLInputElement\n        this.g = null; // deprecated 2D graphics context for 'pre-rendering'\n        this.v = null; // value ; mixed array or integer\n        this.cv = null; // change value ; not commited value\n        this.x = 0; // canvas x position\n        this.y = 0; // canvas y position\n        this.w = 0; // canvas width\n        this.h = 0; // canvas height\n        this.$c = null; // jQuery canvas element\n        this.c = null; // rendered canvas context\n        this.t = 0; // touches index\n        this.isInit = false;\n        this.fgColor = null; // main color\n        this.pColor = null; // previous color\n        this.dH = null; // draw hook\n        this.cH = null; // change hook\n        this.eH = null; // cancel hook\n        this.rH = null; // release hook\n        this.scale = 1; // scale factor\n        this.relative = false;\n        this.relativeWidth = false;\n        this.relativeHeight = false;\n        this.$div = null; // component div\n\n        this.run = function () {\n            var cf = function (e, conf) {\n                var k;\n                for (k in conf) {\n                    s.o[k] = conf[k];\n                }\n                s._carve().init();\n                s._configure()\n                    ._draw();\n            };\n\n            if(this.$.data('kontroled')) return;\n            this.$.data('kontroled', true);\n\n            this.extend();\n            this.o = $.extend(\n                {\n                    // Config\n                    min : this.$.data('min') !== undefined ? this.$.data('min') : 0,\n                    max : this.$.data('max') !== undefined ? this.$.data('max') : 100,\n                    stopper : true,\n                    readOnly : this.$.data('readonly') || (this.$.attr('readonly') === 'readonly'),\n\n                    // UI\n                    cursor : (this.$.data('cursor') === true && 30) ||\n                        this.$.data('cursor') || 0,\n                    thickness : (\n                        this.$.data('thickness') &&\n                            Math.max(Math.min(this.$.data('thickness'), 1), 0.01)\n                        ) || 0.35,\n                    lineCap : this.$.data('linecap') || 'butt',\n                    width : this.$.data('width') || 200,\n                    height : this.$.data('height') || 200,\n                    displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'),\n                    displayPrevious : this.$.data('displayprevious'),\n                    fgColor : this.$.data('fgcolor') || '#87CEEB',\n                    inputColor: this.$.data('inputcolor'),\n                    font: this.$.data('font') || 'Arial',\n                    fontWeight: this.$.data('font-weight') || 'bold',\n                    inline : false,\n                    step : this.$.data('step') || 1,\n                    rotation: this.$.data('rotation'),\n\n                    // Hooks\n                    draw : null, // function () {}\n                    change : null, // function (value) {}\n                    cancel : null, // function () {}\n                    release : null, // function (value) {}\n\n                    // Output formatting, allows to add unit: %, ms ...\n                    format: function(v) {\n                        return v;\n                    },\n                    parse: function (v) {\n                        return parseFloat(v);\n                    }\n                }, this.o\n            );\n\n            // finalize options\n            this.o.flip = this.o.rotation === 'anticlockwise' || this.o.rotation === 'acw';\n            if(!this.o.inputColor) {\n                this.o.inputColor = this.o.fgColor;\n            }\n\n            // routing value\n            if(this.$.is('fieldset')) {\n\n                // fieldset = array of integer\n                this.v = {};\n                this.i = this.$.find('input');\n                this.i.each(function(k) {\n                    var $this = $(this);\n                    s.i[k] = $this;\n                    s.v[k] = s.o.parse($this.val());\n\n                    $this.bind(\n                        'change blur'\n                        , function () {\n                            var val = {};\n                            val[k] = $this.val();\n                            s.val(val);\n                        }\n                    );\n                });\n                this.$.find('legend').remove();\n\n            } else {\n\n                // input = integer\n                this.i = this.$;\n                this.v = this.o.parse(this.$.val());\n                (this.v === '') && (this.v = this.o.min);\n\n                this.$.bind(\n                    'change blur'\n                    , function () {\n                        s.val(s._validate(s.o.parse(s.$.val())));\n                    }\n                );\n\n            }\n\n            (!this.o.displayInput) && this.$.hide();\n\n            // adds needed DOM elements (canvas, div)\n            this.$c = $(document.createElement('canvas')).attr({\n                width: this.o.width,\n                height: this.o.height\n            });\n\n            // wraps all elements in a div\n            // add to DOM before Canvas init is triggered\n            this.$div = $('<div style=\"'\n                + (this.o.inline ? 'display:inline;' : '')\n                + 'width:' + this.o.width + 'px;height:' + this.o.height + 'px;'\n                + '\"></div>');\n\n            this.$.wrap(this.$div).before(this.$c);\n            this.$div = this.$.parent();\n\n            if (typeof G_vmlCanvasManager !== 'undefined') {\n                G_vmlCanvasManager.initElement(this.$c[0]);\n            }\n\n            this.c = this.$c[0].getContext ? this.$c[0].getContext('2d') : null;\n\n            if (!this.c) {\n                throw {\n                    name:        \"CanvasNotSupportedException\",\n                    message:     \"Canvas not supported. Please use excanvas on IE8.0.\",\n                    toString:    function(){return this.name + \": \" + this.message}\n                }\n            }\n\n            // hdpi support\n            this.scale = (window.devicePixelRatio || 1) /\n                (\n                    this.c.webkitBackingStorePixelRatio ||\n                        this.c.mozBackingStorePixelRatio ||\n                        this.c.msBackingStorePixelRatio ||\n                        this.c.oBackingStorePixelRatio ||\n                        this.c.backingStorePixelRatio || 1\n                    );\n\n            // detects relative width / height\n            this.relativeWidth = ((this.o.width % 1 !== 0) &&\n                this.o.width.indexOf('%'));\n            this.relativeHeight = ((this.o.height % 1 !== 0) &&\n                this.o.height.indexOf('%'));\n            this.relative = (this.relativeWidth || this.relativeHeight);\n\n            // computes size and carves the component\n            this._carve();\n\n            // prepares props for transaction\n            if (this.v instanceof Object) {\n                this.cv = {};\n                this.copy(this.v, this.cv);\n            } else {\n                this.cv = this.v;\n            }\n\n            // binds configure event\n            this.$\n                .bind(\"configure\", cf)\n                .parent()\n                .bind(\"configure\", cf);\n\n            // finalize init\n            this._listen()\n                ._configure()\n                ._xy()\n                .init();\n\n            this.isInit = true;\n\n            this.$.val(this.o.format(this.v));\n            this._draw();\n\n            return this;\n        };\n\n        this._carve = function() {\n            if(this.relative) {\n                var w = this.relativeWidth ?\n                        this.$div.parent().width() *\n                            parseInt(this.o.width) / 100 :\n                        this.$div.parent().width(),\n                    h = this.relativeHeight ?\n                        this.$div.parent().height() *\n                            parseInt(this.o.height) / 100 :\n                        this.$div.parent().height();\n\n                // apply relative\n                this.w = this.h = Math.min(w, h);\n            } else {\n                this.w = this.o.width;\n                this.h = this.o.height;\n            }\n\n            // finalize div\n            this.$div.css({\n                'width': this.w + 'px',\n                'height': this.h + 'px'\n            });\n\n            // finalize canvas with computed width\n            this.$c.attr({\n                width: this.w,\n                height: this.h\n            });\n\n            // scaling\n            if (this.scale !== 1) {\n                this.$c[0].width = this.$c[0].width * this.scale;\n                this.$c[0].height = this.$c[0].height * this.scale;\n                this.$c.width(this.w);\n                this.$c.height(this.h);\n            }\n\n            return this;\n        }\n\n        this._draw = function () {\n\n            // canvas pre-rendering\n            var d = true;\n\n            s.g = s.c;\n\n            s.clear();\n\n            s.dH\n            && (d = s.dH());\n\n            (d !== false) && s.draw();\n\n        };\n\n        this._touch = function (e) {\n\n            var touchMove = function (e) {\n\n                var v = s.xy2val(\n                    e.originalEvent.touches[s.t].pageX,\n                    e.originalEvent.touches[s.t].pageY\n                );\n\n                if (v == s.cv) return;\n\n                if (s.cH && (s.cH(v) === false)) return;\n\n                s.change(s._validate(v));\n                s._draw();\n            };\n\n            // get touches index\n            this.t = k.c.t(e);\n\n            // First touch\n            touchMove(e);\n\n            // Touch events listeners\n            k.c.d\n                .bind(\"touchmove.k\", touchMove)\n                .bind(\n                \"touchend.k\"\n                , function () {\n                    k.c.d.unbind('touchmove.k touchend.k');\n                    s.val(s.cv);\n                }\n            );\n\n            return this;\n        };\n\n        this._mouse = function (e) {\n\n            var mouseMove = function (e) {\n                var v = s.xy2val(e.pageX, e.pageY);\n\n                if (v == s.cv) return;\n\n                if (s.cH && (s.cH(v) === false)) return;\n\n                s.change(s._validate(v));\n                s._draw();\n            };\n\n            // First click\n            mouseMove(e);\n\n            // Mouse events listeners\n            k.c.d\n                .bind(\"mousemove.k\", mouseMove)\n                .bind(\n                // Escape key cancel current change\n                \"keyup.k\"\n                , function (e) {\n                    if (e.keyCode === 27) {\n                        k.c.d.unbind(\"mouseup.k mousemove.k keyup.k\");\n\n                        if (\n                            s.eH\n                                && (s.eH() === false)\n                            ) return;\n\n                        s.cancel();\n                    }\n                }\n            )\n                .bind(\n                \"mouseup.k\"\n                , function (e) {\n                    k.c.d.unbind('mousemove.k mouseup.k keyup.k');\n                    s.val(s.cv);\n                }\n            );\n\n            return this;\n        };\n\n        this._xy = function () {\n            var o = this.$c.offset();\n            this.x = o.left;\n            this.y = o.top;\n            return this;\n        };\n\n        this._listen = function () {\n\n            if (!this.o.readOnly) {\n                this.$c\n                    .bind(\n                    \"mousedown\"\n                    , function (e) {\n                        e.preventDefault();\n                        s._xy()._mouse(e);\n                    }\n                )\n                    .bind(\n                    \"touchstart\"\n                    , function (e) {\n                        e.preventDefault();\n                        s._xy()._touch(e);\n                    }\n                );\n\n                this.listen();\n            } else {\n                this.$.attr('readonly', 'readonly');\n            }\n\n            if(this.relative) {\n                $(window).resize(function() {\n                    s._carve()\n                        .init();\n                    s._draw();\n                });\n            }\n\n            return this;\n        };\n\n        this._configure = function () {\n\n            // Hooks\n            if (this.o.draw) this.dH = this.o.draw;\n            if (this.o.change) this.cH = this.o.change;\n            if (this.o.cancel) this.eH = this.o.cancel;\n            if (this.o.release) this.rH = this.o.release;\n\n            if (this.o.displayPrevious) {\n                this.pColor = this.h2rgba(this.o.fgColor, \"0.4\");\n                this.fgColor = this.h2rgba(this.o.fgColor, \"0.6\");\n            } else {\n                this.fgColor = this.o.fgColor;\n            }\n\n            return this;\n        };\n\n        this._clear = function () {\n            this.$c[0].width = this.$c[0].width;\n        };\n\n        this._validate = function(v) {\n            return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;\n        };\n\n        // Abstract methods\n        this.listen = function () {}; // on start, one time\n        this.extend = function () {}; // each time configure triggered\n        this.init = function () {}; // each time configure triggered\n        this.change = function (v) {}; // on change\n        this.val = function (v) {}; // on release\n        this.xy2val = function (x, y) {}; //\n        this.draw = function () {}; // on change / on release\n        this.clear = function () { this._clear(); };\n\n        // Utils\n        this.h2rgba = function (h, a) {\n            var rgb;\n            h = h.substring(1,7)\n            rgb = [parseInt(h.substring(0,2),16)\n                ,parseInt(h.substring(2,4),16)\n                ,parseInt(h.substring(4,6),16)];\n            return \"rgba(\" + rgb[0] + \",\" + rgb[1] + \",\" + rgb[2] + \",\" + a + \")\";\n        };\n\n        this.copy = function (f, t) {\n            for (var i in f) { t[i] = f[i]; }\n        };\n    };\n\n\n    /**\n     * k.Dial\n     */\n    k.Dial = function () {\n        k.o.call(this);\n\n        this.startAngle = null;\n        this.xy = null;\n        this.radius = null;\n        this.lineWidth = null;\n        this.cursorExt = null;\n        this.w2 = null;\n        this.PI2 = 2*Math.PI;\n\n        this.extend = function () {\n            this.o = $.extend(\n                {\n                    bgColor : this.$.data('bgcolor') || '#EEEEEE',\n                    angleOffset : this.$.data('angleoffset') || 0,\n                    angleArc : this.$.data('anglearc') || 360,\n                    inline : true\n                }, this.o\n            );\n        };\n\n        this.val = function (v, triggerRelease) {\n            if (null != v) {\n\n                // reverse format\n                v = this.o.parse(v);\n\n                if (\n                    triggerRelease !== false && (v != this.v) && this.rH &&\n                        (this.rH(v) === false)\n                    ) return;\n\n                this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;\n                this.v = this.cv;\n                this.$.val(this.o.format(this.v));\n                this._draw();\n            } else {\n                return this.v;\n            }\n        };\n\n        this.xy2val = function (x, y) {\n            var a, ret;\n\n            a = Math.atan2(\n                x - (this.x + this.w2)\n                , - (y - this.y - this.w2)\n            ) - this.angleOffset;\n\n            if (this.o.flip) {\n                a = this.angleArc - a - this.PI2;\n            }\n\n            if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {\n                // if isset angleArc option, set to min if .5 under min\n                a = 0;\n            } else if (a < 0) {\n                a += this.PI2;\n            }\n\n            ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc))\n                + this.o.min;\n\n            this.o.stopper && (ret = max(min(ret, this.o.max), this.o.min));\n\n            return ret;\n        };\n\n        this.listen = function () {\n            // bind MouseWheel\n            var s = this, mwTimerStop, mwTimerRelease,\n                mw = function (e) {\n                    e.preventDefault();\n\n                    var ori = e.originalEvent\n                        ,deltaX = ori.detail || ori.wheelDeltaX\n                        ,deltaY = ori.detail || ori.wheelDeltaY\n                        ,v = s._validate(s.o.parse(s.$.val()))\n                            + (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0);\n\n                    v = max(min(v, s.o.max), s.o.min);\n\n                    s.val(v, false);\n\n                    if(s.rH) {\n                        // Handle mousewheel stop\n                        clearTimeout(mwTimerStop);\n                        mwTimerStop = setTimeout(function() {\n                            s.rH(v);\n                            mwTimerStop = null;\n                        }, 100);\n\n                        // Handle mousewheel releases\n                        if(!mwTimerRelease) {\n                            mwTimerRelease = setTimeout(function() {\n                                if(mwTimerStop) s.rH(v);\n                                mwTimerRelease = null;\n                            }, 200);\n                        }\n                    }\n                }\n                , kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step};\n\n            this.$\n                .bind(\n                \"keydown\"\n                ,function (e) {\n                    var kc = e.keyCode;\n\n                    // numpad support\n                    if(kc >= 96 && kc <= 105) {\n                        kc = e.keyCode = kc - 48;\n                    }\n\n                    kval = parseInt(String.fromCharCode(kc));\n\n                    if (isNaN(kval)) {\n\n                        (kc !== 13)         // enter\n                            && (kc !== 8)       // bs\n                            && (kc !== 9)       // tab\n                            && (kc !== 189)     // -\n                            && (kc !== 190 || s.$.val().match(/\\./))     // . only allowed once\n                        && e.preventDefault();\n\n                        // arrows\n                        if ($.inArray(kc,[37,38,39,40]) > -1) {\n                            e.preventDefault();\n\n                            var v = s.o.parse(s.$.val()) + kv[kc] * m;\n                            s.o.stopper && (v = max(min(v, s.o.max), s.o.min));\n\n                            s.change(v);\n                            s._draw();\n\n                            // long time keydown speed-up\n                            to = window.setTimeout(\n                                function () { m *= 2; }, 30\n                            );\n                        }\n                    }\n                }\n            )\n                .bind(\n                \"keyup\"\n                ,function (e) {\n                    if (isNaN(kval)) {\n                        if (to) {\n                            window.clearTimeout(to);\n                            to = null;\n                            m = 1;\n                            s.val(s.$.val());\n                        }\n                    } else {\n                        // kval postcond\n                        (s.$.val() > s.o.max && s.$.val(s.o.max))\n                        || (s.$.val() < s.o.min && s.$.val(s.o.min));\n                    }\n\n                }\n            );\n\n            this.$c.bind(\"mousewheel DOMMouseScroll\", mw);\n            this.$.bind(\"mousewheel DOMMouseScroll\", mw)\n        };\n\n        this.init = function () {\n\n            if (\n                this.v < this.o.min\n                    || this.v > this.o.max\n                ) this.v = this.o.min;\n\n            this.$.val(this.v);\n            this.w2 = this.w / 2;\n            this.cursorExt = this.o.cursor / 100;\n            this.xy = this.w2 * this.scale;\n            this.lineWidth = this.xy * this.o.thickness;\n            this.lineCap = this.o.lineCap;\n            this.radius = this.xy - this.lineWidth / 2;\n\n            this.o.angleOffset\n            && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);\n\n            this.o.angleArc\n            && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);\n\n            // deg to rad\n            this.angleOffset = this.o.angleOffset * Math.PI / 180;\n            this.angleArc = this.o.angleArc * Math.PI / 180;\n\n            // compute start and end angles\n            this.startAngle = 1.5 * Math.PI + this.angleOffset;\n            this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;\n\n            var s = max(\n                String(Math.abs(this.o.max)).length\n                , String(Math.abs(this.o.min)).length\n                , 2\n            ) + 2;\n\n            this.o.displayInput\n                && this.i.css({\n                'width' : ((this.w / 2 + 4) >> 0) + 'px'\n                ,'height' : ((this.w / 3) >> 0) + 'px'\n                ,'position' : 'absolute'\n                ,'vertical-align' : 'middle'\n                ,'margin-top' : ((this.w / 3) >> 0) + 'px'\n                ,'margin-left' : '-' + ((this.w * 3 / 4 + 2) >> 0) + 'px'\n                ,'border' : 0\n                ,'background' : 'none'\n                ,'font' : this.o.fontWeight + ' ' + ((this.w / s) >> 0) + 'px ' + this.o.font\n                ,'text-align' : 'center'\n                ,'color' : this.o.inputColor || this.o.fgColor\n                ,'padding' : '0px'\n                ,'-webkit-appearance': 'none'\n            })\n            || this.i.css({\n                'width' : '0px'\n                ,'visibility' : 'hidden'\n            });\n        };\n\n        this.change = function (v) {\n            this.cv = v;\n            this.$.val(this.o.format(v));\n        };\n\n        this.angle = function (v) {\n            return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);\n        };\n\n        this.arc = function (v) {\n            var sa, ea;\n            v = this.angle(v);\n            if (this.o.flip) {\n                sa = this.endAngle + 0.00001;\n                ea = sa - v - 0.00001;\n            } else {\n                sa = this.startAngle - 0.00001;\n                ea = sa + v + 0.00001;\n            }\n            this.o.cursor\n                && (sa = ea - this.cursorExt)\n            && (ea = ea + this.cursorExt);\n            return {\n                s: sa,\n                e: ea,\n                d: this.o.flip && !this.o.cursor\n            };\n        };\n\n        this.draw = function () {\n\n            var c = this.g,                 // context\n                a = this.arc(this.cv)       // Arc\n                , pa                        // Previous arc\n                , r = 1;\n\n            c.lineWidth = this.lineWidth;\n            c.lineCap = this.lineCap;\n\n            c.beginPath();\n            c.strokeStyle = this.o.bgColor;\n            c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);\n            c.stroke();\n\n            if (this.o.displayPrevious) {\n                pa = this.arc(this.v);\n                c.beginPath();\n                c.strokeStyle = this.pColor;\n                c.arc(this.xy, this.xy, this.radius, pa.s, pa.e, pa.d);\n                c.stroke();\n                r = (this.cv == this.v);\n            }\n\n            c.beginPath();\n            c.strokeStyle = r ? this.o.fgColor : this.fgColor ;\n            c.arc(this.xy, this.xy, this.radius, a.s, a.e, a.d);\n            c.stroke();\n        };\n\n        this.cancel = function () {\n            this.val(this.v);\n        };\n    };\n\n    $.fn.dial = $.fn.knob = function (o) {\n        return this.each(\n            function () {\n                var d = new k.Dial();\n                d.o = o;\n                d.$ = $(this);\n                d.run();\n            }\n        ).parent();\n    };\n\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jsTree/jstree.js",
    "content": "/*!\n * jsTree {{VERSION}}\n * http://jstree.com/\n *\n * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)\n *\n * Licensed same as jquery - under the terms of the MIT License\n *   http://www.opensource.org/licenses/mit-license.php\n */\n/*!\n * if using jslint please allow for the jQuery global and use following options:\n * jslint: loopfunc: true, browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true\n */\n/*jshint -W083 */\n/*globals jQuery, define, module, exports, require, window, document, postMessage */\n(function (factory) {\n\t\"use strict\";\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(['jquery'], factory);\n\t}\n\telse if(typeof module !== 'undefined' && module.exports) {\n\t\tmodule.exports = factory(require('jquery'));\n\t}\n\telse {\n\t\tfactory(jQuery);\n\t}\n}(function ($, undefined) {\n\t\"use strict\";\n\n\t// prevent another load? maybe there is a better way?\n\tif($.jstree) {\n\t\treturn;\n\t}\n\n\t/**\n\t * ### jsTree core functionality\n\t */\n\n\t// internal variables\n\tvar instance_counter = 0,\n\t\tccp_node = false,\n\t\tccp_mode = false,\n\t\tccp_inst = false,\n\t\tthemes_loaded = [],\n\t\tsrc = $('script:last').attr('src'),\n\t\tdocument = window.document; // local variable is always faster to access then a global\n\n\t/**\n\t * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances.\n\t * @name $.jstree\n\t */\n\t$.jstree = {\n\t\t/**\n\t\t * specifies the jstree version in use\n\t\t * @name $.jstree.version\n\t\t */\n\t\tversion : '{{VERSION}}',\n\t\t/**\n\t\t * holds all the default options used when creating new instances\n\t\t * @name $.jstree.defaults\n\t\t */\n\t\tdefaults : {\n\t\t\t/**\n\t\t\t * configure which plugins will be active on an instance. Should be an array of strings, where each element is a plugin name. The default is `[]`\n\t\t\t * @name $.jstree.defaults.plugins\n\t\t\t */\n\t\t\tplugins : []\n\t\t},\n\t\t/**\n\t\t * stores all loaded jstree plugins (used internally)\n\t\t * @name $.jstree.plugins\n\t\t */\n\t\tplugins : {},\n\t\tpath : src && src.indexOf('/') !== -1 ? src.replace(/\\/[^\\/]+$/,'') : '',\n\t\tidregex : /[\\\\:&!^|()\\[\\]<>@*'+~#\";.,=\\- \\/${}%?`]/g,\n\t\troot : '#'\n\t};\n\t\n\t/**\n\t * creates a jstree instance\n\t * @name $.jstree.create(el [, options])\n\t * @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector\n\t * @param {Object} options options for this instance (extends `$.jstree.defaults`)\n\t * @return {jsTree} the new instance\n\t */\n\t$.jstree.create = function (el, options) {\n\t\tvar tmp = new $.jstree.core(++instance_counter),\n\t\t\topt = options;\n\t\toptions = $.extend(true, {}, $.jstree.defaults, options);\n\t\tif(opt && opt.plugins) {\n\t\t\toptions.plugins = opt.plugins;\n\t\t}\n\t\t$.each(options.plugins, function (i, k) {\n\t\t\tif(i !== 'core') {\n\t\t\t\ttmp = tmp.plugin(k, options[k]);\n\t\t\t}\n\t\t});\n\t\t$(el).data('jstree', tmp);\n\t\ttmp.init(el, options);\n\t\treturn tmp;\n\t};\n\t/**\n\t * remove all traces of jstree from the DOM and destroy all instances\n\t * @name $.jstree.destroy()\n\t */\n\t$.jstree.destroy = function () {\n\t\t$('.jstree:jstree').jstree('destroy');\n\t\t$(document).off('.jstree');\n\t};\n\t/**\n\t * the jstree class constructor, used only internally\n\t * @private\n\t * @name $.jstree.core(id)\n\t * @param {Number} id this instance's index\n\t */\n\t$.jstree.core = function (id) {\n\t\tthis._id = id;\n\t\tthis._cnt = 0;\n\t\tthis._wrk = null;\n\t\tthis._data = {\n\t\t\tcore : {\n\t\t\t\tthemes : {\n\t\t\t\t\tname : false,\n\t\t\t\t\tdots : false,\n\t\t\t\t\ticons : false,\n\t\t\t\t\tellipsis : false\n\t\t\t\t},\n\t\t\t\tselected : [],\n\t\t\t\tlast_error : {},\n\t\t\t\tworking : false,\n\t\t\t\tworker_queue : [],\n\t\t\t\tfocused : null\n\t\t\t}\n\t\t};\n\t};\n\t/**\n\t * get a reference to an existing instance\n\t *\n\t * __Examples__\n\t *\n\t *\t// provided a container with an ID of \"tree\", and a nested node with an ID of \"branch\"\n\t *\t// all of there will return the same instance\n\t *\t$.jstree.reference('tree');\n\t *\t$.jstree.reference('#tree');\n\t *\t$.jstree.reference($('#tree'));\n\t *\t$.jstree.reference(document.getElementByID('tree'));\n\t *\t$.jstree.reference('branch');\n\t *\t$.jstree.reference('#branch');\n\t *\t$.jstree.reference($('#branch'));\n\t *\t$.jstree.reference(document.getElementByID('branch'));\n\t *\n\t * @name $.jstree.reference(needle)\n\t * @param {DOMElement|jQuery|String} needle\n\t * @return {jsTree|null} the instance or `null` if not found\n\t */\n\t$.jstree.reference = function (needle) {\n\t\tvar tmp = null,\n\t\t\tobj = null;\n\t\tif(needle && needle.id && (!needle.tagName || !needle.nodeType)) { needle = needle.id; }\n\n\t\tif(!obj || !obj.length) {\n\t\t\ttry { obj = $(needle); } catch (ignore) { }\n\t\t}\n\t\tif(!obj || !obj.length) {\n\t\t\ttry { obj = $('#' + needle.replace($.jstree.idregex,'\\\\$&')); } catch (ignore) { }\n\t\t}\n\t\tif(obj && obj.length && (obj = obj.closest('.jstree')).length && (obj = obj.data('jstree'))) {\n\t\t\ttmp = obj;\n\t\t}\n\t\telse {\n\t\t\t$('.jstree').each(function () {\n\t\t\t\tvar inst = $(this).data('jstree');\n\t\t\t\tif(inst && inst._model.data[needle]) {\n\t\t\t\t\ttmp = inst;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn tmp;\n\t};\n\t/**\n\t * Create an instance, get an instance or invoke a command on a instance.\n\t *\n\t * If there is no instance associated with the current node a new one is created and `arg` is used to extend `$.jstree.defaults` for this new instance. There would be no return value (chaining is not broken).\n\t *\n\t * If there is an existing instance and `arg` is a string the command specified by `arg` is executed on the instance, with any additional arguments passed to the function. If the function returns a value it will be returned (chaining could break depending on function).\n\t *\n\t * If there is an existing instance and `arg` is not a string the instance itself is returned (similar to `$.jstree.reference`).\n\t *\n\t * In any other case - nothing is returned and chaining is not broken.\n\t *\n\t * __Examples__\n\t *\n\t *\t$('#tree1').jstree(); // creates an instance\n\t *\t$('#tree2').jstree({ plugins : [] }); // create an instance with some options\n\t *\t$('#tree1').jstree('open_node', '#branch_1'); // call a method on an existing instance, passing additional arguments\n\t *\t$('#tree2').jstree(); // get an existing instance (or create an instance)\n\t *\t$('#tree2').jstree(true); // get an existing instance (will not create new instance)\n\t *\t$('#branch_1').jstree().select_node('#branch_1'); // get an instance (using a nested element and call a method)\n\t *\n\t * @name $().jstree([arg])\n\t * @param {String|Object} arg\n\t * @return {Mixed}\n\t */\n\t$.fn.jstree = function (arg) {\n\t\t// check for string argument\n\t\tvar is_method\t= (typeof arg === 'string'),\n\t\t\targs\t\t= Array.prototype.slice.call(arguments, 1),\n\t\t\tresult\t\t= null;\n\t\tif(arg === true && !this.length) { return false; }\n\t\tthis.each(function () {\n\t\t\t// get the instance (if there is one) and method (if it exists)\n\t\t\tvar instance = $.jstree.reference(this),\n\t\t\t\tmethod = is_method && instance ? instance[arg] : null;\n\t\t\t// if calling a method, and method is available - execute on the instance\n\t\t\tresult = is_method && method ?\n\t\t\t\tmethod.apply(instance, args) :\n\t\t\t\tnull;\n\t\t\t// if there is no instance and no method is being called - create one\n\t\t\tif(!instance && !is_method && (arg === undefined || $.isPlainObject(arg))) {\n\t\t\t\t$.jstree.create(this, arg);\n\t\t\t}\n\t\t\t// if there is an instance and no method is called - return the instance\n\t\t\tif( (instance && !is_method) || arg === true ) {\n\t\t\t\tresult = instance || false;\n\t\t\t}\n\t\t\t// if there was a method call which returned a result - break and return the value\n\t\t\tif(result !== null && result !== undefined) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\t// if there was a method call with a valid return value - return that, otherwise continue the chain\n\t\treturn result !== null && result !== undefined ?\n\t\t\tresult : this;\n\t};\n\t/**\n\t * used to find elements containing an instance\n\t *\n\t * __Examples__\n\t *\n\t *\t$('div:jstree').each(function () {\n\t *\t\t$(this).jstree('destroy');\n\t *\t});\n\t *\n\t * @name $(':jstree')\n\t * @return {jQuery}\n\t */\n\t$.expr.pseudos.jstree = $.expr.createPseudo(function(search) {\n\t\treturn function(a) {\n\t\t\treturn $(a).hasClass('jstree') &&\n\t\t\t\t$(a).data('jstree') !== undefined;\n\t\t};\n\t});\n\n\t/**\n\t * stores all defaults for the core\n\t * @name $.jstree.defaults.core\n\t */\n\t$.jstree.defaults.core = {\n\t\t/**\n\t\t * data configuration\n\t\t *\n\t\t * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items).\n\t\t *\n\t\t * You can also pass in a HTML string or a JSON array here.\n\t\t *\n\t\t * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree.\n\t\t * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used.\n\t\t *\n\t\t * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result.\n\t\t *\n\t\t * __Examples__\n\t\t *\n\t\t *\t// AJAX\n\t\t *\t$('#tree').jstree({\n\t\t *\t\t'core' : {\n\t\t *\t\t\t'data' : {\n\t\t *\t\t\t\t'url' : '/get/children/',\n\t\t *\t\t\t\t'data' : function (node) {\n\t\t *\t\t\t\t\treturn { 'id' : node.id };\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// direct data\n\t\t *\t$('#tree').jstree({\n\t\t *\t\t'core' : {\n\t\t *\t\t\t'data' : [\n\t\t *\t\t\t\t'Simple root node',\n\t\t *\t\t\t\t{\n\t\t *\t\t\t\t\t'id' : 'node_2',\n\t\t *\t\t\t\t\t'text' : 'Root node with options',\n\t\t *\t\t\t\t\t'state' : { 'opened' : true, 'selected' : true },\n\t\t *\t\t\t\t\t'children' : [ { 'text' : 'Child 1' }, 'Child 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\t *\t// function\n\t\t *\t$('#tree').jstree({\n\t\t *\t\t'core' : {\n\t\t *\t\t\t'data' : function (obj, callback) {\n\t\t *\t\t\t\tcallback.call(this, ['Root 1', 'Root 2']);\n\t\t *\t\t\t}\n\t\t *\t\t});\n\t\t *\n\t\t * @name $.jstree.defaults.core.data\n\t\t */\n\t\tdata\t\t\t: false,\n\t\t/**\n\t\t * configure the various strings used throughout the tree\n\t\t *\n\t\t * You can use an object where the key is the string you need to replace and the value is your replacement.\n\t\t * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement.\n\t\t * If left as `false` no replacement is made.\n\t\t *\n\t\t * __Examples__\n\t\t *\n\t\t *\t$('#tree').jstree({\n\t\t *\t\t'core' : {\n\t\t *\t\t\t'strings' : {\n\t\t *\t\t\t\t'Loading ...' : 'Please wait ...'\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\t});\n\t\t *\n\t\t * @name $.jstree.defaults.core.strings\n\t\t */\n\t\tstrings\t\t\t: false,\n\t\t/**\n\t\t * determines what happens when a user tries to modify the structure of the tree\n\t\t * If left as `false` all operations like create, rename, delete, move or copy are prevented.\n\t\t * You can set this to `true` to allow all interactions or use a function to have better control.\n\t\t *\n\t\t * __Examples__\n\t\t *\n\t\t *\t$('#tree').jstree({\n\t\t *\t\t'core' : {\n\t\t *\t\t\t'check_callback' : function (operation, node, node_parent, node_position, more) {\n\t\t *\t\t\t\t// operation can be 'create_node', 'rename_node', 'delete_node', 'move_node', 'copy_node' or 'edit'\n\t\t *\t\t\t\t// in case of 'rename_node' node_position is filled with the new node name\n\t\t *\t\t\t\treturn operation === 'rename_node' ? true : false;\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\t});\n\t\t *\n\t\t * @name $.jstree.defaults.core.check_callback\n\t\t */\n\t\tcheck_callback\t: false,\n\t\t/**\n\t\t * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc)\n\t\t * @name $.jstree.defaults.core.error\n\t\t */\n\t\terror\t\t\t: $.noop,\n\t\t/**\n\t\t * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`)\n\t\t * @name $.jstree.defaults.core.animation\n\t\t */\n\t\tanimation\t\t: 200,\n\t\t/**\n\t\t * a boolean indicating if multiple nodes can be selected\n\t\t * @name $.jstree.defaults.core.multiple\n\t\t */\n\t\tmultiple\t\t: true,\n\t\t/**\n\t\t * theme configuration object\n\t\t * @name $.jstree.defaults.core.themes\n\t\t */\n\t\tthemes\t\t\t: {\n\t\t\t/**\n\t\t\t * the name of the theme to use (if left as `false` the default theme is used)\n\t\t\t * @name $.jstree.defaults.core.themes.name\n\t\t\t */\n\t\t\tname\t\t\t: false,\n\t\t\t/**\n\t\t\t * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme.\n\t\t\t * @name $.jstree.defaults.core.themes.url\n\t\t\t */\n\t\t\turl\t\t\t\t: false,\n\t\t\t/**\n\t\t\t * the location of all jstree themes - only used if `url` is set to `true`\n\t\t\t * @name $.jstree.defaults.core.themes.dir\n\t\t\t */\n\t\t\tdir\t\t\t\t: false,\n\t\t\t/**\n\t\t\t * a boolean indicating if connecting dots are shown\n\t\t\t * @name $.jstree.defaults.core.themes.dots\n\t\t\t */\n\t\t\tdots\t\t\t: true,\n\t\t\t/**\n\t\t\t * a boolean indicating if node icons are shown\n\t\t\t * @name $.jstree.defaults.core.themes.icons\n\t\t\t */\n\t\t\ticons\t\t\t: true,\n\t\t\t/**\n\t\t\t * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container\n\t\t\t * @name $.jstree.defaults.core.themes.ellipsis\n\t\t\t */\n\t\t\tellipsis\t\t: false,\n\t\t\t/**\n\t\t\t * a boolean indicating if the tree background is striped\n\t\t\t * @name $.jstree.defaults.core.themes.stripes\n\t\t\t */\n\t\t\tstripes\t\t\t: false,\n\t\t\t/**\n\t\t\t * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants)\n\t\t\t * @name $.jstree.defaults.core.themes.variant\n\t\t\t */\n\t\t\tvariant\t\t\t: false,\n\t\t\t/**\n\t\t\t * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `false`.\n\t\t\t * @name $.jstree.defaults.core.themes.responsive\n\t\t\t */\n\t\t\tresponsive\t\t: false\n\t\t},\n\t\t/**\n\t\t * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user)\n\t\t * @name $.jstree.defaults.core.expand_selected_onload\n\t\t */\n\t\texpand_selected_onload : true,\n\t\t/**\n\t\t * if left as `true` web workers will be used to parse incoming JSON data where possible, so that the UI will not be blocked by large requests. Workers are however about 30% slower. Defaults to `true`\n\t\t * @name $.jstree.defaults.core.worker\n\t\t */\n\t\tworker : true,\n\t\t/**\n\t\t * Force node text to plain text (and escape HTML). Defaults to `false`\n\t\t * @name $.jstree.defaults.core.force_text\n\t\t */\n\t\tforce_text : false,\n\t\t/**\n\t\t * Should the node should be toggled if the text is double clicked . Defaults to `true`\n\t\t * @name $.jstree.defaults.core.dblclick_toggle\n\t\t */\n\t\tdblclick_toggle : true\n\t};\n\t$.jstree.core.prototype = {\n\t\t/**\n\t\t * used to decorate an instance with a plugin. Used internally.\n\t\t * @private\n\t\t * @name plugin(deco [, opts])\n\t\t * @param  {String} deco the plugin to decorate with\n\t\t * @param  {Object} opts options for the plugin\n\t\t * @return {jsTree}\n\t\t */\n\t\tplugin : function (deco, opts) {\n\t\t\tvar Child = $.jstree.plugins[deco];\n\t\t\tif(Child) {\n\t\t\t\tthis._data[deco] = {};\n\t\t\t\tChild.prototype = this;\n\t\t\t\treturn new Child(opts, this);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\t/**\n\t\t * initialize the instance. Used internally.\n\t\t * @private\n\t\t * @name init(el, optons)\n\t\t * @param {DOMElement|jQuery|String} el the element we are transforming\n\t\t * @param {Object} options options for this instance\n\t\t * @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree\n\t\t */\n\t\tinit : function (el, options) {\n\t\t\tthis._model = {\n\t\t\t\tdata : {},\n\t\t\t\tchanged : [],\n\t\t\t\tforce_full_redraw : false,\n\t\t\t\tredraw_timeout : false,\n\t\t\t\tdefault_state : {\n\t\t\t\t\tloaded : true,\n\t\t\t\t\topened : false,\n\t\t\t\t\tselected : false,\n\t\t\t\t\tdisabled : false\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis._model.data[$.jstree.root] = {\n\t\t\t\tid : $.jstree.root,\n\t\t\t\tparent : null,\n\t\t\t\tparents : [],\n\t\t\t\tchildren : [],\n\t\t\t\tchildren_d : [],\n\t\t\t\tstate : { loaded : false }\n\t\t\t};\n\n\t\t\tthis.element = $(el).addClass('jstree jstree-' + this._id);\n\t\t\tthis.settings = options;\n\n\t\t\tthis._data.core.ready = false;\n\t\t\tthis._data.core.loaded = false;\n\t\t\tthis._data.core.rtl = (this.element.css(\"direction\") === \"rtl\");\n\t\t\tthis.element[this._data.core.rtl ? 'addClass' : 'removeClass'](\"jstree-rtl\");\n\t\t\tthis.element.attr('role','tree');\n\t\t\tif(this.settings.core.multiple) {\n\t\t\t\tthis.element.attr('aria-multiselectable', true);\n\t\t\t}\n\t\t\tif(!this.element.attr('tabindex')) {\n\t\t\t\tthis.element.attr('tabindex','0');\n\t\t\t}\n\n\t\t\tthis.bind();\n\t\t\t/**\n\t\t\t * triggered after all events are bound\n\t\t\t * @event\n\t\t\t * @name init.jstree\n\t\t\t */\n\t\t\tthis.trigger(\"init\");\n\n\t\t\tthis._data.core.original_container_html = this.element.find(\" > ul > li\").clone(true);\n\t\t\tthis._data.core.original_container_html\n\t\t\t\t.find(\"li\").addBack()\n\t\t\t\t.contents().filter(function() {\n\t\t\t\t\treturn this.nodeType === 3 && (!this.nodeValue || /^\\s+$/.test(this.nodeValue));\n\t\t\t\t})\n\t\t\t\t.remove();\n\t\t\tthis.element.html(\"<\"+\"ul class='jstree-container-ul jstree-children' role='group'><\"+\"li id='j\"+this._id+\"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><i class='jstree-icon jstree-ocl'></i><\"+\"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>\" + this.get_string(\"Loading ...\") + \"</a></li></ul>\");\n\t\t\tthis.element.attr('aria-activedescendant','j' + this._id + '_loading');\n\t\t\tthis._data.core.li_height = this.get_container_ul().children(\"li\").first().outerHeight() || 24;\n\t\t\tthis._data.core.node = this._create_prototype_node();\n\t\t\t/**\n\t\t\t * triggered after the loading text is shown and before loading starts\n\t\t\t * @event\n\t\t\t * @name loading.jstree\n\t\t\t */\n\t\t\tthis.trigger(\"loading\");\n\t\t\tthis.load_node($.jstree.root);\n\t\t},\n\t\t/**\n\t\t * destroy an instance\n\t\t * @name destroy()\n\t\t * @param  {Boolean} keep_html if not set to `true` the container will be emptied, otherwise the current DOM elements will be kept intact\n\t\t */\n\t\tdestroy : function (keep_html) {\n\t\t\t/**\n\t\t\t * triggered before the tree is destroyed\n\t\t\t * @event\n\t\t\t * @name destroy.jstree\n\t\t\t */\n\t\t\tthis.trigger(\"destroy\");\n\t\t\tif(this._wrk) {\n\t\t\t\ttry {\n\t\t\t\t\twindow.URL.revokeObjectURL(this._wrk);\n\t\t\t\t\tthis._wrk = null;\n\t\t\t\t}\n\t\t\t\tcatch (ignore) { }\n\t\t\t}\n\t\t\tif(!keep_html) { this.element.empty(); }\n\t\t\tthis.teardown();\n\t\t},\n\t\t/**\n\t\t * Create prototype node\n\t\t */\n\t\t_create_prototype_node : function () {\n\t\t\tvar _node = document.createElement('LI'), _temp1, _temp2;\n\t\t\t_node.setAttribute('role', 'treeitem');\n\t\t\t_temp1 = document.createElement('I');\n\t\t\t_temp1.className = 'jstree-icon jstree-ocl';\n\t\t\t_temp1.setAttribute('role', 'presentation');\n\t\t\t_node.appendChild(_temp1);\n\t\t\t_temp1 = document.createElement('A');\n\t\t\t_temp1.className = 'jstree-anchor';\n\t\t\t_temp1.setAttribute('href','#');\n\t\t\t_temp1.setAttribute('tabindex','-1');\n\t\t\t_temp2 = document.createElement('I');\n\t\t\t_temp2.className = 'jstree-icon jstree-themeicon';\n\t\t\t_temp2.setAttribute('role', 'presentation');\n\t\t\t_temp1.appendChild(_temp2);\n\t\t\t_node.appendChild(_temp1);\n\t\t\t_temp1 = _temp2 = null;\n\n\t\t\treturn _node;\n\t\t},\n\t\t/**\n\t\t * part of the destroying of an instance. Used internally.\n\t\t * @private\n\t\t * @name teardown()\n\t\t */\n\t\tteardown : function () {\n\t\t\tthis.unbind();\n\t\t\tthis.element\n\t\t\t\t.removeClass('jstree')\n\t\t\t\t.removeData('jstree')\n\t\t\t\t.find(\"[class^='jstree']\")\n\t\t\t\t\t.addBack()\n\t\t\t\t\t.attr(\"class\", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });\n\t\t\tthis.element = null;\n\t\t},\n\t\t/**\n\t\t * bind all events. Used internally.\n\t\t * @private\n\t\t * @name bind()\n\t\t */\n\t\tbind : function () {\n\t\t\tvar word = '',\n\t\t\t\ttout = null,\n\t\t\t\twas_click = 0;\n\t\t\tthis.element\n\t\t\t\t.on(\"dblclick.jstree\", function (e) {\n\t\t\t\t\t\tif(e.target.tagName && e.target.tagName.toLowerCase() === \"input\") { return true; }\n\t\t\t\t\t\tif(document.selection && document.selection.empty) {\n\t\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif(window.getSelection) {\n\t\t\t\t\t\t\t\tvar sel = window.getSelection();\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t\t\t\t\tsel.collapse();\n\t\t\t\t\t\t\t\t} catch (ignore) { }\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.on(\"mousedown.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif(e.target === this.element[0]) {\n\t\t\t\t\t\t\te.preventDefault(); // prevent losing focus when clicking scroll arrows (FF, Chrome)\n\t\t\t\t\t\t\twas_click = +(new Date()); // ie does not allow to prevent losing focus\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.on(\"mousedown.jstree\", \".jstree-ocl\", function (e) {\n\t\t\t\t\t\te.preventDefault(); // prevent any node inside from losing focus when clicking the open/close icon\n\t\t\t\t\t})\n\t\t\t\t.on(\"click.jstree\", \".jstree-ocl\", $.proxy(function (e) {\n\t\t\t\t\t\tthis.toggle_node(e.target);\n\t\t\t\t\t}, this))\n\t\t\t\t.on(\"dblclick.jstree\", \".jstree-anchor\", $.proxy(function (e) {\n\t\t\t\t\t\tif(e.target.tagName && e.target.tagName.toLowerCase() === \"input\") { return true; }\n\t\t\t\t\t\tif(this.settings.core.dblclick_toggle) {\n\t\t\t\t\t\t\tthis.toggle_node(e.target);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.on(\"click.jstree\", \".jstree-anchor\", $.proxy(function (e) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tif(e.currentTarget !== document.activeElement) { $(e.currentTarget).focus(); }\n\t\t\t\t\t\tthis.activate_node(e.currentTarget, e);\n\t\t\t\t\t}, this))\n\t\t\t\t.on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) {\n\t\t\t\t\t\tif(e.target.tagName && e.target.tagName.toLowerCase() === \"input\") { return true; }\n\t\t\t\t\t\tif(e.which !== 32 && e.which !== 13 && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) { return true; }\n\t\t\t\t\t\tvar o = null;\n\t\t\t\t\t\tif(this._data.core.rtl) {\n\t\t\t\t\t\t\tif(e.which === 37) { e.which = 39; }\n\t\t\t\t\t\t\telse if(e.which === 39) { e.which = 37; }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tswitch(e.which) {\n\t\t\t\t\t\t\tcase 32: // aria defines space only with Ctrl\n\t\t\t\t\t\t\t\tif(e.ctrlKey) {\n\t\t\t\t\t\t\t\t\te.type = \"click\";\n\t\t\t\t\t\t\t\t\t$(e.currentTarget).trigger(e);\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\tcase 13: // enter\n\t\t\t\t\t\t\t\te.type = \"click\";\n\t\t\t\t\t\t\t\t$(e.currentTarget).trigger(e);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 37: // left\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tif(this.is_open(e.currentTarget)) {\n\t\t\t\t\t\t\t\t\tthis.close_node(e.currentTarget);\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\to = this.get_parent(e.currentTarget);\n\t\t\t\t\t\t\t\t\tif(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); }\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\tcase 38: // up\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\to = this.get_prev_dom(e.currentTarget);\n\t\t\t\t\t\t\t\tif(o && o.length) { o.children('.jstree-anchor').focus(); }\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 39: // right\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tif(this.is_closed(e.currentTarget)) {\n\t\t\t\t\t\t\t\t\tthis.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (this.is_open(e.currentTarget)) {\n\t\t\t\t\t\t\t\t\to = this.get_node(e.currentTarget, true).children('.jstree-children')[0];\n\t\t\t\t\t\t\t\t\tif(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); }\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\tcase 40: // down\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\to = this.get_next_dom(e.currentTarget);\n\t\t\t\t\t\t\t\tif(o && o.length) { o.children('.jstree-anchor').focus(); }\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 106: // aria defines * on numpad as open_all - not very common\n\t\t\t\t\t\t\t\tthis.open_all();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 36: // home\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\to = this._firstChild(this.get_container_ul()[0]);\n\t\t\t\t\t\t\t\tif(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); }\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 35: // end\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tthis.element.find('.jstree-anchor').filter(':visible').last().focus();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 113: // f2 - safe to include - if check_callback is false it will fail\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tthis.edit(e.currentTarget);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t/*!\n\t\t\t\t\t\t\t// delete\n\t\t\t\t\t\t\tcase 46:\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\to = this.get_node(e.currentTarget);\n\t\t\t\t\t\t\t\tif(o && o.id && o.id !== $.jstree.root) {\n\t\t\t\t\t\t\t\t\to = this.is_selected(o) ? this.get_selected() : o;\n\t\t\t\t\t\t\t\t\tthis.delete_node(o);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.on(\"load_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tif(data.status) {\n\t\t\t\t\t\t\tif(data.node.id === $.jstree.root && !this._data.core.loaded) {\n\t\t\t\t\t\t\t\tthis._data.core.loaded = true;\n\t\t\t\t\t\t\t\tif(this._firstChild(this.get_container_ul()[0])) {\n\t\t\t\t\t\t\t\t\tthis.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).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\t * triggered after the root node is loaded for the first time\n\t\t\t\t\t\t\t\t * @event\n\t\t\t\t\t\t\t\t * @name loaded.jstree\n\t\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t\tthis.trigger(\"loaded\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(!this._data.core.ready) {\n\t\t\t\t\t\t\t\tsetTimeout($.proxy(function() {\n\t\t\t\t\t\t\t\t\tif(this.element && !this.get_container_ul().find('.jstree-loading').length) {\n\t\t\t\t\t\t\t\t\t\tthis._data.core.ready = true;\n\t\t\t\t\t\t\t\t\t\tif(this._data.core.selected.length) {\n\t\t\t\t\t\t\t\t\t\t\tif(this.settings.core.expand_selected_onload) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar tmp = [], i, j;\n\t\t\t\t\t\t\t\t\t\t\t\tfor(i = 0, j = this._data.core.selected.length; i < j; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents);\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\ttmp = $.vakata.array_unique(tmp);\n\t\t\t\t\t\t\t\t\t\t\t\tfor(i = 0, j = tmp.length; i < j; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.open_node(tmp[i], false, 0);\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\tthis.trigger('changed', { 'action' : 'ready', 'selected' : this._data.core.selected });\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\t * triggered after all nodes are finished loading\n\t\t\t\t\t\t\t\t\t\t * @event\n\t\t\t\t\t\t\t\t\t\t * @name ready.jstree\n\t\t\t\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t\t\t\tthis.trigger(\"ready\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, this), 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t// quick searching when the tree is focused\n\t\t\t\t.on('keypress.jstree', $.proxy(function (e) {\n\t\t\t\t\t\tif(e.target.tagName && e.target.tagName.toLowerCase() === \"input\") { return true; }\n\t\t\t\t\t\tif(tout) { clearTimeout(tout); }\n\t\t\t\t\t\ttout = setTimeout(function () {\n\t\t\t\t\t\t\tword = '';\n\t\t\t\t\t\t}, 500);\n\n\t\t\t\t\t\tvar chr = String.fromCharCode(e.which).toLowerCase(),\n\t\t\t\t\t\t\tcol = this.element.find('.jstree-anchor').filter(':visible'),\n\t\t\t\t\t\t\tind = col.index(document.activeElement) || 0,\n\t\t\t\t\t\t\tend = false;\n\t\t\t\t\t\tword += chr;\n\n\t\t\t\t\t\t// match for whole word from current node down (including the current node)\n\t\t\t\t\t\tif(word.length > 1) {\n\t\t\t\t\t\t\tcol.slice(ind).each($.proxy(function (i, v) {\n\t\t\t\t\t\t\t\tif($(v).text().toLowerCase().indexOf(word) === 0) {\n\t\t\t\t\t\t\t\t\t$(v).focus();\n\t\t\t\t\t\t\t\t\tend = true;\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t\tif(end) { return; }\n\n\t\t\t\t\t\t\t// match for whole word from the beginning of the tree\n\t\t\t\t\t\t\tcol.slice(0, ind).each($.proxy(function (i, v) {\n\t\t\t\t\t\t\t\tif($(v).text().toLowerCase().indexOf(word) === 0) {\n\t\t\t\t\t\t\t\t\t$(v).focus();\n\t\t\t\t\t\t\t\t\tend = true;\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t\tif(end) { return; }\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// list nodes that start with that letter (only if word consists of a single char)\n\t\t\t\t\t\tif(new RegExp('^' + chr.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&') + '+$').test(word)) {\n\t\t\t\t\t\t\t// search for the next node starting with that letter\n\t\t\t\t\t\t\tcol.slice(ind + 1).each($.proxy(function (i, v) {\n\t\t\t\t\t\t\t\tif($(v).text().toLowerCase().charAt(0) === chr) {\n\t\t\t\t\t\t\t\t\t$(v).focus();\n\t\t\t\t\t\t\t\t\tend = true;\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t\tif(end) { return; }\n\n\t\t\t\t\t\t\t// search from the beginning\n\t\t\t\t\t\t\tcol.slice(0, ind + 1).each($.proxy(function (i, v) {\n\t\t\t\t\t\t\t\tif($(v).text().toLowerCase().charAt(0) === chr) {\n\t\t\t\t\t\t\t\t\t$(v).focus();\n\t\t\t\t\t\t\t\t\tend = true;\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t\tif(end) { return; }\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t// THEME RELATED\n\t\t\t\t.on(\"init.jstree\", $.proxy(function () {\n\t\t\t\t\t\tvar s = this.settings.core.themes;\n\t\t\t\t\t\tthis._data.core.themes.dots\t\t\t= s.dots;\n\t\t\t\t\t\tthis._data.core.themes.stripes\t\t= s.stripes;\n\t\t\t\t\t\tthis._data.core.themes.icons\t\t= s.icons;\n\t\t\t\t\t\tthis._data.core.themes.ellipsis\t\t= s.ellipsis;\n\t\t\t\t\t\tthis.set_theme(s.name || \"default\", s.url);\n\t\t\t\t\t\tthis.set_theme_variant(s.variant);\n\t\t\t\t\t}, this))\n\t\t\t\t.on(\"loading.jstree\", $.proxy(function () {\n\t\t\t\t\t\tthis[ this._data.core.themes.dots ? \"show_dots\" : \"hide_dots\" ]();\n\t\t\t\t\t\tthis[ this._data.core.themes.icons ? \"show_icons\" : \"hide_icons\" ]();\n\t\t\t\t\t\tthis[ this._data.core.themes.stripes ? \"show_stripes\" : \"hide_stripes\" ]();\n\t\t\t\t\t\tthis[ this._data.core.themes.ellipsis ? \"show_ellipsis\" : \"hide_ellipsis\" ]();\n\t\t\t\t\t}, this))\n\t\t\t\t.on('blur.jstree', '.jstree-anchor', $.proxy(function (e) {\n\t\t\t\t\t\tthis._data.core.focused = null;\n\t\t\t\t\t\t$(e.currentTarget).filter('.jstree-hovered').mouseleave();\n\t\t\t\t\t\tthis.element.attr('tabindex', '0');\n\t\t\t\t\t}, this))\n\t\t\t\t.on('focus.jstree', '.jstree-anchor', $.proxy(function (e) {\n\t\t\t\t\t\tvar tmp = this.get_node(e.currentTarget);\n\t\t\t\t\t\tif(tmp && tmp.id) {\n\t\t\t\t\t\t\tthis._data.core.focused = tmp.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.element.find('.jstree-hovered').not(e.currentTarget).mouseleave();\n\t\t\t\t\t\t$(e.currentTarget).mouseenter();\n\t\t\t\t\t\tthis.element.attr('tabindex', '-1');\n\t\t\t\t\t}, this))\n\t\t\t\t.on('focus.jstree', $.proxy(function () {\n\t\t\t\t\t\tif(+(new Date()) - was_click > 500 && !this._data.core.focused) {\n\t\t\t\t\t\t\twas_click = 0;\n\t\t\t\t\t\t\tvar act = this.get_node(this.element.attr('aria-activedescendant'), true);\n\t\t\t\t\t\t\tif(act) {\n\t\t\t\t\t\t\t\tact.find('> .jstree-anchor').focus();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) {\n\t\t\t\t\t\tthis.hover_node(e.currentTarget);\n\t\t\t\t\t}, this))\n\t\t\t\t.on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) {\n\t\t\t\t\t\tthis.dehover_node(e.currentTarget);\n\t\t\t\t\t}, this));\n\t\t},\n\t\t/**\n\t\t * part of the destroying of an instance. Used internally.\n\t\t * @private\n\t\t * @name unbind()\n\t\t */\n\t\tunbind : function () {\n\t\t\tthis.element.off('.jstree');\n\t\t\t$(document).off('.jstree-' + this._id);\n\t\t},\n\t\t/**\n\t\t * trigger an event. Used internally.\n\t\t * @private\n\t\t * @name trigger(ev [, data])\n\t\t * @param  {String} ev the name of the event to trigger\n\t\t * @param  {Object} data additional data to pass with the event\n\t\t */\n\t\ttrigger : function (ev, data) {\n\t\t\tif(!data) {\n\t\t\t\tdata = {};\n\t\t\t}\n\t\t\tdata.instance = this;\n\t\t\tthis.element.triggerHandler(ev.replace('.jstree','') + '.jstree', data);\n\t\t},\n\t\t/**\n\t\t * returns the jQuery extended instance container\n\t\t * @name get_container()\n\t\t * @return {jQuery}\n\t\t */\n\t\tget_container : function () {\n\t\t\treturn this.element;\n\t\t},\n\t\t/**\n\t\t * returns the jQuery extended main UL node inside the instance container. Used internally.\n\t\t * @private\n\t\t * @name get_container_ul()\n\t\t * @return {jQuery}\n\t\t */\n\t\tget_container_ul : function () {\n\t\t\treturn this.element.children(\".jstree-children\").first();\n\t\t},\n\t\t/**\n\t\t * gets string replacements (localization). Used internally.\n\t\t * @private\n\t\t * @name get_string(key)\n\t\t * @param  {String} key\n\t\t * @return {String}\n\t\t */\n\t\tget_string : function (key) {\n\t\t\tvar a = this.settings.core.strings;\n\t\t\tif($.isFunction(a)) { return a.call(this, key); }\n\t\t\tif(a && a[key]) { return a[key]; }\n\t\t\treturn key;\n\t\t},\n\t\t/**\n\t\t * gets the first child of a DOM node. Used internally.\n\t\t * @private\n\t\t * @name _firstChild(dom)\n\t\t * @param  {DOMElement} dom\n\t\t * @return {DOMElement}\n\t\t */\n\t\t_firstChild : function (dom) {\n\t\t\tdom = dom ? dom.firstChild : null;\n\t\t\twhile(dom !== null && dom.nodeType !== 1) {\n\t\t\t\tdom = dom.nextSibling;\n\t\t\t}\n\t\t\treturn dom;\n\t\t},\n\t\t/**\n\t\t * gets the next sibling of a DOM node. Used internally.\n\t\t * @private\n\t\t * @name _nextSibling(dom)\n\t\t * @param  {DOMElement} dom\n\t\t * @return {DOMElement}\n\t\t */\n\t\t_nextSibling : function (dom) {\n\t\t\tdom = dom ? dom.nextSibling : null;\n\t\t\twhile(dom !== null && dom.nodeType !== 1) {\n\t\t\t\tdom = dom.nextSibling;\n\t\t\t}\n\t\t\treturn dom;\n\t\t},\n\t\t/**\n\t\t * gets the previous sibling of a DOM node. Used internally.\n\t\t * @private\n\t\t * @name _previousSibling(dom)\n\t\t * @param  {DOMElement} dom\n\t\t * @return {DOMElement}\n\t\t */\n\t\t_previousSibling : function (dom) {\n\t\t\tdom = dom ? dom.previousSibling : null;\n\t\t\twhile(dom !== null && dom.nodeType !== 1) {\n\t\t\t\tdom = dom.previousSibling;\n\t\t\t}\n\t\t\treturn dom;\n\t\t},\n\t\t/**\n\t\t * get the JSON representation of a node (or the actual jQuery extended DOM node) by using any input (child DOM element, ID string, selector, etc)\n\t\t * @name get_node(obj [, as_dom])\n\t\t * @param  {mixed} obj\n\t\t * @param  {Boolean} as_dom\n\t\t * @return {Object|jQuery}\n\t\t */\n\t\tget_node : function (obj, as_dom) {\n\t\t\tif(obj && obj.id) {\n\t\t\t\tobj = obj.id;\n\t\t\t}\n\t\t\tvar dom;\n\t\t\ttry {\n\t\t\t\tif(this._model.data[obj]) {\n\t\t\t\t\tobj = this._model.data[obj];\n\t\t\t\t}\n\t\t\t\telse if(typeof obj === \"string\" && this._model.data[obj.replace(/^#/, '')]) {\n\t\t\t\t\tobj = this._model.data[obj.replace(/^#/, '')];\n\t\t\t\t}\n\t\t\t\telse if(typeof obj === \"string\" && (dom = $('#' + obj.replace($.jstree.idregex,'\\\\$&'), this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) {\n\t\t\t\t\tobj = this._model.data[dom.closest('.jstree-node').attr('id')];\n\t\t\t\t}\n\t\t\t\telse if((dom = $(obj, this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) {\n\t\t\t\t\tobj = this._model.data[dom.closest('.jstree-node').attr('id')];\n\t\t\t\t}\n\t\t\t\telse if((dom = $(obj, this.element)).length && dom.hasClass('jstree')) {\n\t\t\t\t\tobj = this._model.data[$.jstree.root];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif(as_dom) {\n\t\t\t\t\tobj = obj.id === $.jstree.root ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\\\$&'), this.element);\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t} catch (ex) { return false; }\n\t\t},\n\t\t/**\n\t\t * get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array)\n\t\t * @name get_path(obj [, glue, ids])\n\t\t * @param  {mixed} obj the node\n\t\t * @param  {String} glue if you want the path as a string - pass the glue here (for example '/'), if a falsy value is supplied here, an array is returned\n\t\t * @param  {Boolean} ids if set to true build the path using ID, otherwise node text is used\n\t\t * @return {mixed}\n\t\t */\n\t\tget_path : function (obj, glue, ids) {\n\t\t\tobj = obj.parents ? obj : this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root || !obj.parents) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar i, j, p = [];\n\t\t\tp.push(ids ? obj.id : obj.text);\n\t\t\tfor(i = 0, j = obj.parents.length; i < j; i++) {\n\t\t\t\tp.push(ids ? obj.parents[i] : this.get_text(obj.parents[i]));\n\t\t\t}\n\t\t\tp = p.reverse().slice(1);\n\t\t\treturn glue ? p.join(glue) : p;\n\t\t},\n\t\t/**\n\t\t * get the next visible node that is below the `obj` node. If `strict` is set to `true` only sibling nodes are returned.\n\t\t * @name get_next_dom(obj [, strict])\n\t\t * @param  {mixed} obj\n\t\t * @param  {Boolean} strict\n\t\t * @return {jQuery}\n\t\t */\n\t\tget_next_dom : function (obj, strict) {\n\t\t\tvar tmp;\n\t\t\tobj = this.get_node(obj, true);\n\t\t\tif(obj[0] === this.element[0]) {\n\t\t\t\ttmp = this._firstChild(this.get_container_ul()[0]);\n\t\t\t\twhile (tmp && tmp.offsetHeight === 0) {\n\t\t\t\t\ttmp = this._nextSibling(tmp);\n\t\t\t\t}\n\t\t\t\treturn tmp ? $(tmp) : false;\n\t\t\t}\n\t\t\tif(!obj || !obj.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(strict) {\n\t\t\t\ttmp = obj[0];\n\t\t\t\tdo {\n\t\t\t\t\ttmp = this._nextSibling(tmp);\n\t\t\t\t} while (tmp && tmp.offsetHeight === 0);\n\t\t\t\treturn tmp ? $(tmp) : false;\n\t\t\t}\n\t\t\tif(obj.hasClass(\"jstree-open\")) {\n\t\t\t\ttmp = this._firstChild(obj.children('.jstree-children')[0]);\n\t\t\t\twhile (tmp && tmp.offsetHeight === 0) {\n\t\t\t\t\ttmp = this._nextSibling(tmp);\n\t\t\t\t}\n\t\t\t\tif(tmp !== null) {\n\t\t\t\t\treturn $(tmp);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmp = obj[0];\n\t\t\tdo {\n\t\t\t\ttmp = this._nextSibling(tmp);\n\t\t\t} while (tmp && tmp.offsetHeight === 0);\n\t\t\tif(tmp !== null) {\n\t\t\t\treturn $(tmp);\n\t\t\t}\n\t\t\treturn obj.parentsUntil(\".jstree\",\".jstree-node\").nextAll(\".jstree-node:visible\").first();\n\t\t},\n\t\t/**\n\t\t * get the previous visible node that is above the `obj` node. If `strict` is set to `true` only sibling nodes are returned.\n\t\t * @name get_prev_dom(obj [, strict])\n\t\t * @param  {mixed} obj\n\t\t * @param  {Boolean} strict\n\t\t * @return {jQuery}\n\t\t */\n\t\tget_prev_dom : function (obj, strict) {\n\t\t\tvar tmp;\n\t\t\tobj = this.get_node(obj, true);\n\t\t\tif(obj[0] === this.element[0]) {\n\t\t\t\ttmp = this.get_container_ul()[0].lastChild;\n\t\t\t\twhile (tmp && tmp.offsetHeight === 0) {\n\t\t\t\t\ttmp = this._previousSibling(tmp);\n\t\t\t\t}\n\t\t\t\treturn tmp ? $(tmp) : false;\n\t\t\t}\n\t\t\tif(!obj || !obj.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(strict) {\n\t\t\t\ttmp = obj[0];\n\t\t\t\tdo {\n\t\t\t\t\ttmp = this._previousSibling(tmp);\n\t\t\t\t} while (tmp && tmp.offsetHeight === 0);\n\t\t\t\treturn tmp ? $(tmp) : false;\n\t\t\t}\n\t\t\ttmp = obj[0];\n\t\t\tdo {\n\t\t\t\ttmp = this._previousSibling(tmp);\n\t\t\t} while (tmp && tmp.offsetHeight === 0);\n\t\t\tif(tmp !== null) {\n\t\t\t\tobj = $(tmp);\n\t\t\t\twhile(obj.hasClass(\"jstree-open\")) {\n\t\t\t\t\tobj = obj.children(\".jstree-children\").first().children(\".jstree-node:visible:last\");\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t\ttmp = obj[0].parentNode.parentNode;\n\t\t\treturn tmp && tmp.className && tmp.className.indexOf('jstree-node') !== -1 ? $(tmp) : false;\n\t\t},\n\t\t/**\n\t\t * get the parent ID of a node\n\t\t * @name get_parent(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {String}\n\t\t */\n\t\tget_parent : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn obj.parent;\n\t\t},\n\t\t/**\n\t\t * get a jQuery collection of all the children of a node (node must be rendered)\n\t\t * @name get_children_dom(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {jQuery}\n\t\t */\n\t\tget_children_dom : function (obj) {\n\t\t\tobj = this.get_node(obj, true);\n\t\t\tif(obj[0] === this.element[0]) {\n\t\t\t\treturn this.get_container_ul().children(\".jstree-node\");\n\t\t\t}\n\t\t\tif(!obj || !obj.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn obj.children(\".jstree-children\").children(\".jstree-node\");\n\t\t},\n\t\t/**\n\t\t * checks if a node has children\n\t\t * @name is_parent(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_parent : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && (obj.state.loaded === false || obj.children.length > 0);\n\t\t},\n\t\t/**\n\t\t * checks if a node is loaded (its children are available)\n\t\t * @name is_loaded(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_loaded : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && obj.state.loaded;\n\t\t},\n\t\t/**\n\t\t * check if a node is currently loading (fetching children)\n\t\t * @name is_loading(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_loading : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && obj.state && obj.state.loading;\n\t\t},\n\t\t/**\n\t\t * check if a node is opened\n\t\t * @name is_open(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_open : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && obj.state.opened;\n\t\t},\n\t\t/**\n\t\t * check if a node is in a closed state\n\t\t * @name is_closed(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_closed : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && this.is_parent(obj) && !obj.state.opened;\n\t\t},\n\t\t/**\n\t\t * check if a node has no children\n\t\t * @name is_leaf(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_leaf : function (obj) {\n\t\t\treturn !this.is_parent(obj);\n\t\t},\n\t\t/**\n\t\t * loads a node (fetches its children using the `core.data` setting). Multiple nodes can be passed to by using an array.\n\t\t * @name load_node(obj [, callback])\n\t\t * @param  {mixed} obj\n\t\t * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives two arguments - the node and a boolean status\n\t\t * @return {Boolean}\n\t\t * @trigger load_node.jstree\n\t\t */\n\t\tload_node : function (obj, callback) {\n\t\t\tvar k, l, i, j, c;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tthis._load_nodes(obj.slice(), callback);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj) {\n\t\t\t\tif(callback) { callback.call(this, obj, false); }\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// if(obj.state.loading) { } // the node is already loading - just wait for it to load and invoke callback? but if called implicitly it should be loaded again?\n\t\t\tif(obj.state.loaded) {\n\t\t\t\tobj.state.loaded = false;\n\t\t\t\tfor(i = 0, j = obj.parents.length; i < j; i++) {\n\t\t\t\t\tthis._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {\n\t\t\t\t\t\treturn $.inArray(v, obj.children_d) === -1;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor(k = 0, l = obj.children_d.length; k < l; k++) {\n\t\t\t\t\tif(this._model.data[obj.children_d[k]].state.selected) {\n\t\t\t\t\t\tc = true;\n\t\t\t\t\t}\n\t\t\t\t\tdelete this._model.data[obj.children_d[k]];\n\t\t\t\t}\n\t\t\t\tif (c) {\n\t\t\t\t\tthis._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {\n\t\t\t\t\t\treturn $.inArray(v, obj.children_d) === -1;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tobj.children = [];\n\t\t\t\tobj.children_d = [];\n\t\t\t\tif(c) {\n\t\t\t\t\tthis.trigger('changed', { 'action' : 'load_node', 'node' : obj, 'selected' : this._data.core.selected });\n\t\t\t\t}\n\t\t\t}\n\t\t\tobj.state.failed = false;\n\t\t\tobj.state.loading = true;\n\t\t\tthis.get_node(obj, true).addClass(\"jstree-loading\").attr('aria-busy',true);\n\t\t\tthis._load_node(obj, $.proxy(function (status) {\n\t\t\t\tobj = this._model.data[obj.id];\n\t\t\t\tobj.state.loading = false;\n\t\t\t\tobj.state.loaded = status;\n\t\t\t\tobj.state.failed = !obj.state.loaded;\n\t\t\t\tvar dom = this.get_node(obj, true), i = 0, j = 0, m = this._model.data, has_children = false;\n\t\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\t\tif(m[obj.children[i]] && !m[obj.children[i]].state.hidden) {\n\t\t\t\t\t\thas_children = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(obj.state.loaded && dom && dom.length) {\n\t\t\t\t\tdom.removeClass('jstree-closed jstree-open jstree-leaf');\n\t\t\t\t\tif (!has_children) {\n\t\t\t\t\t\tdom.addClass('jstree-leaf');\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (obj.id !== '#') {\n\t\t\t\t\t\t\tdom.addClass(obj.state.opened ? 'jstree-open' : 'jstree-closed');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdom.removeClass(\"jstree-loading\").attr('aria-busy',false);\n\t\t\t\t/**\n\t\t\t\t * triggered after a node is loaded\n\t\t\t\t * @event\n\t\t\t\t * @name load_node.jstree\n\t\t\t\t * @param {Object} node the node that was loading\n\t\t\t\t * @param {Boolean} status was the node loaded successfully\n\t\t\t\t */\n\t\t\t\tthis.trigger('load_node', { \"node\" : obj, \"status\" : status });\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback.call(this, obj, status);\n\t\t\t\t}\n\t\t\t}, this));\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * load an array of nodes (will also load unavailable nodes as soon as the appear in the structure). Used internally.\n\t\t * @private\n\t\t * @name _load_nodes(nodes [, callback])\n\t\t * @param  {array} nodes\n\t\t * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - the array passed to _load_nodes\n\t\t */\n\t\t_load_nodes : function (nodes, callback, is_callback, force_reload) {\n\t\t\tvar r = true,\n\t\t\t\tc = function () { this._load_nodes(nodes, callback, true); },\n\t\t\t\tm = this._model.data, i, j, tmp = [];\n\t\t\tfor(i = 0, j = nodes.length; i < j; i++) {\n\t\t\t\tif(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || (!is_callback && force_reload) )) {\n\t\t\t\t\tif(!this.is_loading(nodes[i])) {\n\t\t\t\t\t\tthis.load_node(nodes[i], c);\n\t\t\t\t\t}\n\t\t\t\t\tr = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(r) {\n\t\t\t\tfor(i = 0, j = nodes.length; i < j; i++) {\n\t\t\t\t\tif(m[nodes[i]] && m[nodes[i]].state.loaded) {\n\t\t\t\t\t\ttmp.push(nodes[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(callback && !callback.done) {\n\t\t\t\t\tcallback.call(this, tmp);\n\t\t\t\t\tcallback.done = true;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * loads all unloaded nodes\n\t\t * @name load_all([obj, callback])\n\t\t * @param {mixed} obj the node to load recursively, omit to load all nodes in the tree\n\t\t * @param {function} callback a function to be executed once loading all the nodes is complete,\n\t\t * @trigger load_all.jstree\n\t\t */\n\t\tload_all : function (obj, callback) {\n\t\t\tif(!obj) { obj = $.jstree.root; }\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj) { return false; }\n\t\t\tvar to_load = [],\n\t\t\t\tm = this._model.data,\n\t\t\t\tc = m[obj.id].children_d,\n\t\t\t\ti, j;\n\t\t\tif(obj.state && !obj.state.loaded) {\n\t\t\t\tto_load.push(obj.id);\n\t\t\t}\n\t\t\tfor(i = 0, j = c.length; i < j; i++) {\n\t\t\t\tif(m[c[i]] && m[c[i]].state && !m[c[i]].state.loaded) {\n\t\t\t\t\tto_load.push(c[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(to_load.length) {\n\t\t\t\tthis._load_nodes(to_load, function () {\n\t\t\t\t\tthis.load_all(obj, callback);\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\t/**\n\t\t\t\t * triggered after a load_all call completes\n\t\t\t\t * @event\n\t\t\t\t * @name load_all.jstree\n\t\t\t\t * @param {Object} node the recursively loaded node\n\t\t\t\t */\n\t\t\t\tif(callback) { callback.call(this, obj); }\n\t\t\t\tthis.trigger('load_all', { \"node\" : obj });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * handles the actual loading of a node. Used only internally.\n\t\t * @private\n\t\t * @name _load_node(obj [, callback])\n\t\t * @param  {mixed} obj\n\t\t * @param  {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - a boolean status\n\t\t * @return {Boolean}\n\t\t */\n\t\t_load_node : function (obj, callback) {\n\t\t\tvar s = this.settings.core.data, t;\n\t\t\tvar notTextOrCommentNode = function notTextOrCommentNode () {\n\t\t\t\treturn this.nodeType !== 3 && this.nodeType !== 8;\n\t\t\t};\n\t\t\t// use original HTML\n\t\t\tif(!s) {\n\t\t\t\tif(obj.id === $.jstree.root) {\n\t\t\t\t\treturn this._append_html_data(obj, this._data.core.original_container_html.clone(true), function (status) {\n\t\t\t\t\t\tcallback.call(this, status);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn callback.call(this, false);\n\t\t\t\t}\n\t\t\t\t// return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false);\n\t\t\t}\n\t\t\tif($.isFunction(s)) {\n\t\t\t\treturn s.call(this, obj, $.proxy(function (d) {\n\t\t\t\t\tif(d === false) {\n\t\t\t\t\t\tcallback.call(this, false);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(notTextOrCommentNode) : d, function (status) {\n\t\t\t\t\t\t\tcallback.call(this, status);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d));\n\t\t\t\t}, this));\n\t\t\t}\n\t\t\tif(typeof s === 'object') {\n\t\t\t\tif(s.url) {\n\t\t\t\t\ts = $.extend(true, {}, s);\n\t\t\t\t\tif($.isFunction(s.url)) {\n\t\t\t\t\t\ts.url = s.url.call(this, obj);\n\t\t\t\t\t}\n\t\t\t\t\tif($.isFunction(s.data)) {\n\t\t\t\t\t\ts.data = s.data.call(this, obj);\n\t\t\t\t\t}\n\t\t\t\t\treturn $.ajax(s)\n\t\t\t\t\t\t.done($.proxy(function (d,t,x) {\n\t\t\t\t\t\t\t\tvar type = x.getResponseHeader('Content-Type');\n\t\t\t\t\t\t\t\tif((type && type.indexOf('json') !== -1) || typeof d === \"object\") {\n\t\t\t\t\t\t\t\t\treturn this._append_json_data(obj, d, function (status) { callback.call(this, status); });\n\t\t\t\t\t\t\t\t\t//return callback.call(this, this._append_json_data(obj, d));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif((type && type.indexOf('html') !== -1) || typeof d === \"string\") {\n\t\t\t\t\t\t\t\t\treturn this._append_html_data(obj, $($.parseHTML(d)).filter(notTextOrCommentNode), function (status) { callback.call(this, status); });\n\t\t\t\t\t\t\t\t\t// return callback.call(this, this._append_html_data(obj, $(d)));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) };\n\t\t\t\t\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\t\t\t\t\treturn callback.call(this, false);\n\t\t\t\t\t\t\t}, this))\n\t\t\t\t\t\t.fail($.proxy(function (f) {\n\t\t\t\t\t\t\t\tthis._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) };\n\t\t\t\t\t\t\t\tcallback.call(this, false);\n\t\t\t\t\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t}\n\t\t\t\tif ($.isArray(s)) {\n\t\t\t\t\tt = $.extend(true, [], s);\n\t\t\t\t} else if ($.isPlainObject(s)) {\n\t\t\t\t\tt = $.extend(true, {}, s);\n\t\t\t\t} else {\n\t\t\t\t\tt = s;\n\t\t\t\t}\n\t\t\t\tif(obj.id === $.jstree.root) {\n\t\t\t\t\treturn this._append_json_data(obj, t, function (status) {\n\t\t\t\t\t\tcallback.call(this, status);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_05', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };\n\t\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\t\treturn callback.call(this, false);\n\t\t\t\t}\n\t\t\t\t//return callback.call(this, (obj.id === $.jstree.root ? this._append_json_data(obj, t) : false) );\n\t\t\t}\n\t\t\tif(typeof s === 'string') {\n\t\t\t\tif(obj.id === $.jstree.root) {\n\t\t\t\t\treturn this._append_html_data(obj, $($.parseHTML(s)).filter(notTextOrCommentNode), function (status) {\n\t\t\t\t\t\tcallback.call(this, status);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_06', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };\n\t\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\t\treturn callback.call(this, false);\n\t\t\t\t}\n\t\t\t\t//return callback.call(this, (obj.id === $.jstree.root ? this._append_html_data(obj, $(s)) : false) );\n\t\t\t}\n\t\t\treturn callback.call(this, false);\n\t\t},\n\t\t/**\n\t\t * adds a node to the list of nodes to redraw. Used only internally.\n\t\t * @private\n\t\t * @name _node_changed(obj [, callback])\n\t\t * @param  {mixed} obj\n\t\t */\n\t\t_node_changed : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(obj) {\n\t\t\t\tthis._model.changed.push(obj.id);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * appends HTML content to the tree. Used internally.\n\t\t * @private\n\t\t * @name _append_html_data(obj, data)\n\t\t * @param  {mixed} obj the node to append to\n\t\t * @param  {String} data the HTML string to parse and append\n\t\t * @trigger model.jstree, changed.jstree\n\t\t */\n\t\t_append_html_data : function (dom, data, cb) {\n\t\t\tdom = this.get_node(dom);\n\t\t\tdom.children = [];\n\t\t\tdom.children_d = [];\n\t\t\tvar dat = data.is('ul') ? data.children() : data,\n\t\t\t\tpar = dom.id,\n\t\t\t\tchd = [],\n\t\t\t\tdpc = [],\n\t\t\t\tm = this._model.data,\n\t\t\t\tp = m[par],\n\t\t\t\ts = this._data.core.selected.length,\n\t\t\t\ttmp, i, j;\n\t\t\tdat.each($.proxy(function (i, v) {\n\t\t\t\ttmp = this._parse_model_from_html($(v), par, p.parents.concat());\n\t\t\t\tif(tmp) {\n\t\t\t\t\tchd.push(tmp);\n\t\t\t\t\tdpc.push(tmp);\n\t\t\t\t\tif(m[tmp].children_d.length) {\n\t\t\t\t\t\tdpc = dpc.concat(m[tmp].children_d);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, this));\n\t\t\tp.children = chd;\n\t\t\tp.children_d = dpc;\n\t\t\tfor(i = 0, j = p.parents.length; i < j; i++) {\n\t\t\t\tm[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when new data is inserted to the tree model\n\t\t\t * @event\n\t\t\t * @name model.jstree\n\t\t\t * @param {Array} nodes an array of node IDs\n\t\t\t * @param {String} parent the parent ID of the nodes\n\t\t\t */\n\t\t\tthis.trigger('model', { \"nodes\" : dpc, 'parent' : par });\n\t\t\tif(par !== $.jstree.root) {\n\t\t\t\tthis._node_changed(par);\n\t\t\t\tthis.redraw();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.get_container_ul().children('.jstree-initial-node').remove();\n\t\t\t\tthis.redraw(true);\n\t\t\t}\n\t\t\tif(this._data.core.selected.length !== s) {\n\t\t\t\tthis.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected });\n\t\t\t}\n\t\t\tcb.call(this, true);\n\t\t},\n\t\t/**\n\t\t * appends JSON content to the tree. Used internally.\n\t\t * @private\n\t\t * @name _append_json_data(obj, data)\n\t\t * @param  {mixed} obj the node to append to\n\t\t * @param  {String} data the JSON object to parse and append\n\t\t * @param  {Boolean} force_processing internal param - do not set\n\t\t * @trigger model.jstree, changed.jstree\n\t\t */\n\t\t_append_json_data : function (dom, data, cb, force_processing) {\n\t\t\tif(this.element === null) { return; }\n\t\t\tdom = this.get_node(dom);\n\t\t\tdom.children = [];\n\t\t\tdom.children_d = [];\n\t\t\t// *%$@!!!\n\t\t\tif(data.d) {\n\t\t\t\tdata = data.d;\n\t\t\t\tif(typeof data === \"string\") {\n\t\t\t\t\tdata = JSON.parse(data);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!$.isArray(data)) { data = [data]; }\n\t\t\tvar w = null,\n\t\t\t\targs = {\n\t\t\t\t\t'df'\t: this._model.default_state,\n\t\t\t\t\t'dat'\t: data,\n\t\t\t\t\t'par'\t: dom.id,\n\t\t\t\t\t'm'\t\t: this._model.data,\n\t\t\t\t\t't_id'\t: this._id,\n\t\t\t\t\t't_cnt'\t: this._cnt,\n\t\t\t\t\t'sel'\t: this._data.core.selected\n\t\t\t\t},\n\t\t\t\tfunc = function (data, undefined) {\n\t\t\t\t\tif(data.data) { data = data.data; }\n\t\t\t\t\tvar dat = data.dat,\n\t\t\t\t\t\tpar = data.par,\n\t\t\t\t\t\tchd = [],\n\t\t\t\t\t\tdpc = [],\n\t\t\t\t\t\tadd = [],\n\t\t\t\t\t\tdf = data.df,\n\t\t\t\t\t\tt_id = data.t_id,\n\t\t\t\t\t\tt_cnt = data.t_cnt,\n\t\t\t\t\t\tm = data.m,\n\t\t\t\t\t\tp = m[par],\n\t\t\t\t\t\tsel = data.sel,\n\t\t\t\t\t\ttmp, i, j, rslt,\n\t\t\t\t\t\tparse_flat = function (d, p, ps) {\n\t\t\t\t\t\t\tif(!ps) { ps = []; }\n\t\t\t\t\t\t\telse { ps = ps.concat(); }\n\t\t\t\t\t\t\tif(p) { ps.unshift(p); }\n\t\t\t\t\t\t\tvar tid = d.id.toString(),\n\t\t\t\t\t\t\t\ti, j, c, e,\n\t\t\t\t\t\t\t\ttmp = {\n\t\t\t\t\t\t\t\t\tid\t\t\t: tid,\n\t\t\t\t\t\t\t\t\ttext\t\t: d.text || '',\n\t\t\t\t\t\t\t\t\ticon\t\t: d.icon !== undefined ? d.icon : true,\n\t\t\t\t\t\t\t\t\tparent\t\t: p,\n\t\t\t\t\t\t\t\t\tparents\t\t: ps,\n\t\t\t\t\t\t\t\t\tchildren\t: d.children || [],\n\t\t\t\t\t\t\t\t\tchildren_d\t: d.children_d || [],\n\t\t\t\t\t\t\t\t\tdata\t\t: d.data,\n\t\t\t\t\t\t\t\t\tstate\t\t: { },\n\t\t\t\t\t\t\t\t\tli_attr\t\t: { id : false },\n\t\t\t\t\t\t\t\t\ta_attr\t\t: { href : '#' },\n\t\t\t\t\t\t\t\t\toriginal\t: false\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfor(i in df) {\n\t\t\t\t\t\t\t\tif(df.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\ttmp.state[i] = df[i];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && d.data && d.data.jstree && d.data.jstree.icon) {\n\t\t\t\t\t\t\t\ttmp.icon = d.data.jstree.icon;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(tmp.icon === undefined || tmp.icon === null || tmp.icon === \"\") {\n\t\t\t\t\t\t\t\ttmp.icon = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && d.data) {\n\t\t\t\t\t\t\t\ttmp.data = d.data;\n\t\t\t\t\t\t\t\tif(d.data.jstree) {\n\t\t\t\t\t\t\t\t\tfor(i in d.data.jstree) {\n\t\t\t\t\t\t\t\t\t\tif(d.data.jstree.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\t\ttmp.state[i] = d.data.jstree[i];\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\tif(d && typeof d.state === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.state) {\n\t\t\t\t\t\t\t\t\tif(d.state.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.state[i] = d.state[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\tif(d && typeof d.li_attr === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.li_attr) {\n\t\t\t\t\t\t\t\t\tif(d.li_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.li_attr[i] = d.li_attr[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\tif(!tmp.li_attr.id) {\n\t\t\t\t\t\t\t\ttmp.li_attr.id = tid;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && typeof d.a_attr === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.a_attr) {\n\t\t\t\t\t\t\t\t\tif(d.a_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.a_attr[i] = d.a_attr[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\tif(d && d.children && d.children === true) {\n\t\t\t\t\t\t\t\ttmp.state.loaded = false;\n\t\t\t\t\t\t\t\ttmp.children = [];\n\t\t\t\t\t\t\t\ttmp.children_d = [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm[tmp.id] = tmp;\n\t\t\t\t\t\t\tfor(i = 0, j = tmp.children.length; i < j; i++) {\n\t\t\t\t\t\t\t\tc = parse_flat(m[tmp.children[i]], tmp.id, ps);\n\t\t\t\t\t\t\t\te = m[c];\n\t\t\t\t\t\t\t\ttmp.children_d.push(c);\n\t\t\t\t\t\t\t\tif(e.children_d.length) {\n\t\t\t\t\t\t\t\t\ttmp.children_d = tmp.children_d.concat(e.children_d);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete d.data;\n\t\t\t\t\t\t\tdelete d.children;\n\t\t\t\t\t\t\tm[tmp.id].original = d;\n\t\t\t\t\t\t\tif(tmp.state.selected) {\n\t\t\t\t\t\t\t\tadd.push(tmp.id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn tmp.id;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tparse_nest = function (d, p, ps) {\n\t\t\t\t\t\t\tif(!ps) { ps = []; }\n\t\t\t\t\t\t\telse { ps = ps.concat(); }\n\t\t\t\t\t\t\tif(p) { ps.unshift(p); }\n\t\t\t\t\t\t\tvar tid = false, i, j, c, e, tmp;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\ttid = 'j' + t_id + '_' + (++t_cnt);\n\t\t\t\t\t\t\t} while(m[tid]);\n\n\t\t\t\t\t\t\ttmp = {\n\t\t\t\t\t\t\t\tid\t\t\t: false,\n\t\t\t\t\t\t\t\ttext\t\t: typeof d === 'string' ? d : '',\n\t\t\t\t\t\t\t\ticon\t\t: typeof d === 'object' && d.icon !== undefined ? d.icon : true,\n\t\t\t\t\t\t\t\tparent\t\t: p,\n\t\t\t\t\t\t\t\tparents\t\t: ps,\n\t\t\t\t\t\t\t\tchildren\t: [],\n\t\t\t\t\t\t\t\tchildren_d\t: [],\n\t\t\t\t\t\t\t\tdata\t\t: null,\n\t\t\t\t\t\t\t\tstate\t\t: { },\n\t\t\t\t\t\t\t\tli_attr\t\t: { id : false },\n\t\t\t\t\t\t\t\ta_attr\t\t: { href : '#' },\n\t\t\t\t\t\t\t\toriginal\t: false\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfor(i in df) {\n\t\t\t\t\t\t\t\tif(df.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\ttmp.state[i] = df[i];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && d.id) { tmp.id = d.id.toString(); }\n\t\t\t\t\t\t\tif(d && d.text) { tmp.text = d.text; }\n\t\t\t\t\t\t\tif(d && d.data && d.data.jstree && d.data.jstree.icon) {\n\t\t\t\t\t\t\t\ttmp.icon = d.data.jstree.icon;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(tmp.icon === undefined || tmp.icon === null || tmp.icon === \"\") {\n\t\t\t\t\t\t\t\ttmp.icon = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && d.data) {\n\t\t\t\t\t\t\t\ttmp.data = d.data;\n\t\t\t\t\t\t\t\tif(d.data.jstree) {\n\t\t\t\t\t\t\t\t\tfor(i in d.data.jstree) {\n\t\t\t\t\t\t\t\t\t\tif(d.data.jstree.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\t\ttmp.state[i] = d.data.jstree[i];\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\tif(d && typeof d.state === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.state) {\n\t\t\t\t\t\t\t\t\tif(d.state.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.state[i] = d.state[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\tif(d && typeof d.li_attr === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.li_attr) {\n\t\t\t\t\t\t\t\t\tif(d.li_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.li_attr[i] = d.li_attr[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\tif(tmp.li_attr.id && !tmp.id) {\n\t\t\t\t\t\t\t\ttmp.id = tmp.li_attr.id.toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(!tmp.id) {\n\t\t\t\t\t\t\t\ttmp.id = tid;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(!tmp.li_attr.id) {\n\t\t\t\t\t\t\t\ttmp.li_attr.id = tmp.id;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && typeof d.a_attr === 'object') {\n\t\t\t\t\t\t\t\tfor (i in d.a_attr) {\n\t\t\t\t\t\t\t\t\tif(d.a_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\t\t\t\t\ttmp.a_attr[i] = d.a_attr[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\tif(d && d.children && d.children.length) {\n\t\t\t\t\t\t\t\tfor(i = 0, j = d.children.length; i < j; i++) {\n\t\t\t\t\t\t\t\t\tc = parse_nest(d.children[i], tmp.id, ps);\n\t\t\t\t\t\t\t\t\te = m[c];\n\t\t\t\t\t\t\t\t\ttmp.children.push(c);\n\t\t\t\t\t\t\t\t\tif(e.children_d.length) {\n\t\t\t\t\t\t\t\t\t\ttmp.children_d = tmp.children_d.concat(e.children_d);\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\ttmp.children_d = tmp.children_d.concat(tmp.children);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d && d.children && d.children === true) {\n\t\t\t\t\t\t\t\ttmp.state.loaded = false;\n\t\t\t\t\t\t\t\ttmp.children = [];\n\t\t\t\t\t\t\t\ttmp.children_d = [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete d.data;\n\t\t\t\t\t\t\tdelete d.children;\n\t\t\t\t\t\t\ttmp.original = d;\n\t\t\t\t\t\t\tm[tmp.id] = tmp;\n\t\t\t\t\t\t\tif(tmp.state.selected) {\n\t\t\t\t\t\t\t\tadd.push(tmp.id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn tmp.id;\n\t\t\t\t\t\t};\n\n\t\t\t\t\tif(dat.length && dat[0].id !== undefined && dat[0].parent !== undefined) {\n\t\t\t\t\t\t// Flat JSON support (for easy import from DB):\n\t\t\t\t\t\t// 1) convert to object (foreach)\n\t\t\t\t\t\tfor(i = 0, j = dat.length; i < j; i++) {\n\t\t\t\t\t\t\tif(!dat[i].children) {\n\t\t\t\t\t\t\t\tdat[i].children = [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm[dat[i].id.toString()] = dat[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 2) populate children (foreach)\n\t\t\t\t\t\tfor(i = 0, j = dat.length; i < j; i++) {\n\t\t\t\t\t\t\tm[dat[i].parent.toString()].children.push(dat[i].id.toString());\n\t\t\t\t\t\t\t// populate parent.children_d\n\t\t\t\t\t\t\tp.children_d.push(dat[i].id.toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// 3) normalize && populate parents and children_d with recursion\n\t\t\t\t\t\tfor(i = 0, j = p.children.length; i < j; i++) {\n\t\t\t\t\t\t\ttmp = parse_flat(m[p.children[i]], par, p.parents.concat());\n\t\t\t\t\t\t\tdpc.push(tmp);\n\t\t\t\t\t\t\tif(m[tmp].children_d.length) {\n\t\t\t\t\t\t\t\tdpc = dpc.concat(m[tmp].children_d);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor(i = 0, j = p.parents.length; i < j; i++) {\n\t\t\t\t\t\t\tm[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// ?) three_state selection - p.state.selected && t - (if three_state foreach(dat => ch) -> foreach(parents) if(parent.selected) child.selected = true;\n\t\t\t\t\t\trslt = {\n\t\t\t\t\t\t\t'cnt' : t_cnt,\n\t\t\t\t\t\t\t'mod' : m,\n\t\t\t\t\t\t\t'sel' : sel,\n\t\t\t\t\t\t\t'par' : par,\n\t\t\t\t\t\t\t'dpc' : dpc,\n\t\t\t\t\t\t\t'add' : add\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\tfor(i = 0, j = dat.length; i < j; i++) {\n\t\t\t\t\t\t\ttmp = parse_nest(dat[i], par, p.parents.concat());\n\t\t\t\t\t\t\tif(tmp) {\n\t\t\t\t\t\t\t\tchd.push(tmp);\n\t\t\t\t\t\t\t\tdpc.push(tmp);\n\t\t\t\t\t\t\t\tif(m[tmp].children_d.length) {\n\t\t\t\t\t\t\t\t\tdpc = dpc.concat(m[tmp].children_d);\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\tp.children = chd;\n\t\t\t\t\t\tp.children_d = dpc;\n\t\t\t\t\t\tfor(i = 0, j = p.parents.length; i < j; i++) {\n\t\t\t\t\t\t\tm[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc);\n\t\t\t\t\t\t}\n\t\t\t\t\t\trslt = {\n\t\t\t\t\t\t\t'cnt' : t_cnt,\n\t\t\t\t\t\t\t'mod' : m,\n\t\t\t\t\t\t\t'sel' : sel,\n\t\t\t\t\t\t\t'par' : par,\n\t\t\t\t\t\t\t'dpc' : dpc,\n\t\t\t\t\t\t\t'add' : add\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tif(typeof window === 'undefined' || typeof window.document === 'undefined') {\n\t\t\t\t\t\tpostMessage(rslt);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\treturn rslt;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\trslt = function (rslt, worker) {\n\t\t\t\t\tif(this.element === null) { return; }\n\t\t\t\t\tthis._cnt = rslt.cnt;\n\t\t\t\t\tvar i, m = this._model.data;\n\t\t\t\t\tfor (i in m) {\n\t\t\t\t\t\tif (m.hasOwnProperty(i) && m[i].state && m[i].state.loading && rslt.mod[i]) {\n\t\t\t\t\t\t\trslt.mod[i].state.loading = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._model.data = rslt.mod; // breaks the reference in load_node - careful\n\n\t\t\t\t\tif(worker) {\n\t\t\t\t\t\tvar j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice();\n\t\t\t\t\t\tm = this._model.data;\n\t\t\t\t\t\t// if selection was changed while calculating in worker\n\t\t\t\t\t\tif(r.length !== s.length || $.vakata.array_unique(r.concat(s)).length !== r.length) {\n\t\t\t\t\t\t\t// deselect nodes that are no longer selected\n\t\t\t\t\t\t\tfor(i = 0, j = r.length; i < j; i++) {\n\t\t\t\t\t\t\t\tif($.inArray(r[i], a) === -1 && $.inArray(r[i], s) === -1) {\n\t\t\t\t\t\t\t\t\tm[r[i]].state.selected = false;\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// select nodes that were selected in the mean time\n\t\t\t\t\t\t\tfor(i = 0, j = s.length; i < j; i++) {\n\t\t\t\t\t\t\t\tif($.inArray(s[i], r) === -1) {\n\t\t\t\t\t\t\t\t\tm[s[i]].state.selected = 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}\n\t\t\t\t\tif(rslt.add.length) {\n\t\t\t\t\t\tthis._data.core.selected = this._data.core.selected.concat(rslt.add);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.trigger('model', { \"nodes\" : rslt.dpc, 'parent' : rslt.par });\n\n\t\t\t\t\tif(rslt.par !== $.jstree.root) {\n\t\t\t\t\t\tthis._node_changed(rslt.par);\n\t\t\t\t\t\tthis.redraw();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// this.get_container_ul().children('.jstree-initial-node').remove();\n\t\t\t\t\t\tthis.redraw(true);\n\t\t\t\t\t}\n\t\t\t\t\tif(rslt.add.length) {\n\t\t\t\t\t\tthis.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected });\n\t\t\t\t\t}\n\t\t\t\t\tcb.call(this, true);\n\t\t\t\t};\n\t\t\tif(this.settings.core.worker && window.Blob && window.URL && window.Worker) {\n\t\t\t\ttry {\n\t\t\t\t\tif(this._wrk === null) {\n\t\t\t\t\t\tthis._wrk = window.URL.createObjectURL(\n\t\t\t\t\t\t\tnew window.Blob(\n\t\t\t\t\t\t\t\t['self.onmessage = ' + func.toString()],\n\t\t\t\t\t\t\t\t{type:\"text/javascript\"}\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(!this._data.core.working || force_processing) {\n\t\t\t\t\t\tthis._data.core.working = true;\n\t\t\t\t\t\tw = new window.Worker(this._wrk);\n\t\t\t\t\t\tw.onmessage = $.proxy(function (e) {\n\t\t\t\t\t\t\trslt.call(this, e.data, true);\n\t\t\t\t\t\t\ttry { w.terminate(); w = null; } catch(ignore) { }\n\t\t\t\t\t\t\tif(this._data.core.worker_queue.length) {\n\t\t\t\t\t\t\t\tthis._append_json_data.apply(this, this._data.core.worker_queue.shift());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis._data.core.working = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this);\n\t\t\t\t\t\tif(!args.par) {\n\t\t\t\t\t\t\tif(this._data.core.worker_queue.length) {\n\t\t\t\t\t\t\t\tthis._append_json_data.apply(this, this._data.core.worker_queue.shift());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthis._data.core.working = false;\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\tw.postMessage(args);\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\tthis._data.core.worker_queue.push([dom, data, cb, true]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch(e) {\n\t\t\t\t\trslt.call(this, func(args), false);\n\t\t\t\t\tif(this._data.core.worker_queue.length) {\n\t\t\t\t\t\tthis._append_json_data.apply(this, this._data.core.worker_queue.shift());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._data.core.working = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\trslt.call(this, func(args), false);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * parses a node from a jQuery object and appends them to the in memory tree model. Used internally.\n\t\t * @private\n\t\t * @name _parse_model_from_html(d [, p, ps])\n\t\t * @param  {jQuery} d the jQuery object to parse\n\t\t * @param  {String} p the parent ID\n\t\t * @param  {Array} ps list of all parents\n\t\t * @return {String} the ID of the object added to the model\n\t\t */\n\t\t_parse_model_from_html : function (d, p, ps) {\n\t\t\tif(!ps) { ps = []; }\n\t\t\telse { ps = [].concat(ps); }\n\t\t\tif(p) { ps.unshift(p); }\n\t\t\tvar c, e, m = this._model.data,\n\t\t\t\tdata = {\n\t\t\t\t\tid\t\t\t: false,\n\t\t\t\t\ttext\t\t: false,\n\t\t\t\t\ticon\t\t: true,\n\t\t\t\t\tparent\t\t: p,\n\t\t\t\t\tparents\t\t: ps,\n\t\t\t\t\tchildren\t: [],\n\t\t\t\t\tchildren_d\t: [],\n\t\t\t\t\tdata\t\t: null,\n\t\t\t\t\tstate\t\t: { },\n\t\t\t\t\tli_attr\t\t: { id : false },\n\t\t\t\t\ta_attr\t\t: { href : '#' },\n\t\t\t\t\toriginal\t: false\n\t\t\t\t}, i, tmp, tid;\n\t\t\tfor(i in this._model.default_state) {\n\t\t\t\tif(this._model.default_state.hasOwnProperty(i)) {\n\t\t\t\t\tdata.state[i] = this._model.default_state[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmp = $.vakata.attributes(d, true);\n\t\t\t$.each(tmp, function (i, v) {\n\t\t\t\tv = $.trim(v);\n\t\t\t\tif(!v.length) { return true; }\n\t\t\t\tdata.li_attr[i] = v;\n\t\t\t\tif(i === 'id') {\n\t\t\t\t\tdata.id = v.toString();\n\t\t\t\t}\n\t\t\t});\n\t\t\ttmp = d.children('a').first();\n\t\t\tif(tmp.length) {\n\t\t\t\ttmp = $.vakata.attributes(tmp, true);\n\t\t\t\t$.each(tmp, function (i, v) {\n\t\t\t\t\tv = $.trim(v);\n\t\t\t\t\tif(v.length) {\n\t\t\t\t\t\tdata.a_attr[i] = v;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\ttmp = d.children(\"a\").first().length ? d.children(\"a\").first().clone() : d.clone();\n\t\t\ttmp.children(\"ins, i, ul\").remove();\n\t\t\ttmp = tmp.html();\n\t\t\ttmp = $('<div />').html(tmp);\n\t\t\tdata.text = this.settings.core.force_text ? tmp.text() : tmp.html();\n\t\t\ttmp = d.data();\n\t\t\tdata.data = tmp ? $.extend(true, {}, tmp) : null;\n\t\t\tdata.state.opened = d.hasClass('jstree-open');\n\t\t\tdata.state.selected = d.children('a').hasClass('jstree-clicked');\n\t\t\tdata.state.disabled = d.children('a').hasClass('jstree-disabled');\n\t\t\tif(data.data && data.data.jstree) {\n\t\t\t\tfor(i in data.data.jstree) {\n\t\t\t\t\tif(data.data.jstree.hasOwnProperty(i)) {\n\t\t\t\t\t\tdata.state[i] = data.data.jstree[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmp = d.children(\"a\").children(\".jstree-themeicon\");\n\t\t\tif(tmp.length) {\n\t\t\t\tdata.icon = tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel');\n\t\t\t}\n\t\t\tif(data.state.icon !== undefined) {\n\t\t\t\tdata.icon = data.state.icon;\n\t\t\t}\n\t\t\tif(data.icon === undefined || data.icon === null || data.icon === \"\") {\n\t\t\t\tdata.icon = true;\n\t\t\t}\n\t\t\ttmp = d.children(\"ul\").children(\"li\");\n\t\t\tdo {\n\t\t\t\ttid = 'j' + this._id + '_' + (++this._cnt);\n\t\t\t} while(m[tid]);\n\t\t\tdata.id = data.li_attr.id ? data.li_attr.id.toString() : tid;\n\t\t\tif(tmp.length) {\n\t\t\t\ttmp.each($.proxy(function (i, v) {\n\t\t\t\t\tc = this._parse_model_from_html($(v), data.id, ps);\n\t\t\t\t\te = this._model.data[c];\n\t\t\t\t\tdata.children.push(c);\n\t\t\t\t\tif(e.children_d.length) {\n\t\t\t\t\t\tdata.children_d = data.children_d.concat(e.children_d);\n\t\t\t\t\t}\n\t\t\t\t}, this));\n\t\t\t\tdata.children_d = data.children_d.concat(data.children);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(d.hasClass('jstree-closed')) {\n\t\t\t\t\tdata.state.loaded = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(data.li_attr['class']) {\n\t\t\t\tdata.li_attr['class'] = data.li_attr['class'].replace('jstree-closed','').replace('jstree-open','');\n\t\t\t}\n\t\t\tif(data.a_attr['class']) {\n\t\t\t\tdata.a_attr['class'] = data.a_attr['class'].replace('jstree-clicked','').replace('jstree-disabled','');\n\t\t\t}\n\t\t\tm[data.id] = data;\n\t\t\tif(data.state.selected) {\n\t\t\t\tthis._data.core.selected.push(data.id);\n\t\t\t}\n\t\t\treturn data.id;\n\t\t},\n\t\t/**\n\t\t * parses a node from a JSON object (used when dealing with flat data, which has no nesting of children, but has id and parent properties) and appends it to the in memory tree model. Used internally.\n\t\t * @private\n\t\t * @name _parse_model_from_flat_json(d [, p, ps])\n\t\t * @param  {Object} d the JSON object to parse\n\t\t * @param  {String} p the parent ID\n\t\t * @param  {Array} ps list of all parents\n\t\t * @return {String} the ID of the object added to the model\n\t\t */\n\t\t_parse_model_from_flat_json : function (d, p, ps) {\n\t\t\tif(!ps) { ps = []; }\n\t\t\telse { ps = ps.concat(); }\n\t\t\tif(p) { ps.unshift(p); }\n\t\t\tvar tid = d.id.toString(),\n\t\t\t\tm = this._model.data,\n\t\t\t\tdf = this._model.default_state,\n\t\t\t\ti, j, c, e,\n\t\t\t\ttmp = {\n\t\t\t\t\tid\t\t\t: tid,\n\t\t\t\t\ttext\t\t: d.text || '',\n\t\t\t\t\ticon\t\t: d.icon !== undefined ? d.icon : true,\n\t\t\t\t\tparent\t\t: p,\n\t\t\t\t\tparents\t\t: ps,\n\t\t\t\t\tchildren\t: d.children || [],\n\t\t\t\t\tchildren_d\t: d.children_d || [],\n\t\t\t\t\tdata\t\t: d.data,\n\t\t\t\t\tstate\t\t: { },\n\t\t\t\t\tli_attr\t\t: { id : false },\n\t\t\t\t\ta_attr\t\t: { href : '#' },\n\t\t\t\t\toriginal\t: false\n\t\t\t\t};\n\t\t\tfor(i in df) {\n\t\t\t\tif(df.hasOwnProperty(i)) {\n\t\t\t\t\ttmp.state[i] = df[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && d.data && d.data.jstree && d.data.jstree.icon) {\n\t\t\t\ttmp.icon = d.data.jstree.icon;\n\t\t\t}\n\t\t\tif(tmp.icon === undefined || tmp.icon === null || tmp.icon === \"\") {\n\t\t\t\ttmp.icon = true;\n\t\t\t}\n\t\t\tif(d && d.data) {\n\t\t\t\ttmp.data = d.data;\n\t\t\t\tif(d.data.jstree) {\n\t\t\t\t\tfor(i in d.data.jstree) {\n\t\t\t\t\t\tif(d.data.jstree.hasOwnProperty(i)) {\n\t\t\t\t\t\t\ttmp.state[i] = d.data.jstree[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\tif(d && typeof d.state === 'object') {\n\t\t\t\tfor (i in d.state) {\n\t\t\t\t\tif(d.state.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.state[i] = d.state[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && typeof d.li_attr === 'object') {\n\t\t\t\tfor (i in d.li_attr) {\n\t\t\t\t\tif(d.li_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.li_attr[i] = d.li_attr[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!tmp.li_attr.id) {\n\t\t\t\ttmp.li_attr.id = tid;\n\t\t\t}\n\t\t\tif(d && typeof d.a_attr === 'object') {\n\t\t\t\tfor (i in d.a_attr) {\n\t\t\t\t\tif(d.a_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.a_attr[i] = d.a_attr[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && d.children && d.children === true) {\n\t\t\t\ttmp.state.loaded = false;\n\t\t\t\ttmp.children = [];\n\t\t\t\ttmp.children_d = [];\n\t\t\t}\n\t\t\tm[tmp.id] = tmp;\n\t\t\tfor(i = 0, j = tmp.children.length; i < j; i++) {\n\t\t\t\tc = this._parse_model_from_flat_json(m[tmp.children[i]], tmp.id, ps);\n\t\t\t\te = m[c];\n\t\t\t\ttmp.children_d.push(c);\n\t\t\t\tif(e.children_d.length) {\n\t\t\t\t\ttmp.children_d = tmp.children_d.concat(e.children_d);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdelete d.data;\n\t\t\tdelete d.children;\n\t\t\tm[tmp.id].original = d;\n\t\t\tif(tmp.state.selected) {\n\t\t\t\tthis._data.core.selected.push(tmp.id);\n\t\t\t}\n\t\t\treturn tmp.id;\n\t\t},\n\t\t/**\n\t\t * parses a node from a JSON object and appends it to the in memory tree model. Used internally.\n\t\t * @private\n\t\t * @name _parse_model_from_json(d [, p, ps])\n\t\t * @param  {Object} d the JSON object to parse\n\t\t * @param  {String} p the parent ID\n\t\t * @param  {Array} ps list of all parents\n\t\t * @return {String} the ID of the object added to the model\n\t\t */\n\t\t_parse_model_from_json : function (d, p, ps) {\n\t\t\tif(!ps) { ps = []; }\n\t\t\telse { ps = ps.concat(); }\n\t\t\tif(p) { ps.unshift(p); }\n\t\t\tvar tid = false, i, j, c, e, m = this._model.data, df = this._model.default_state, tmp;\n\t\t\tdo {\n\t\t\t\ttid = 'j' + this._id + '_' + (++this._cnt);\n\t\t\t} while(m[tid]);\n\n\t\t\ttmp = {\n\t\t\t\tid\t\t\t: false,\n\t\t\t\ttext\t\t: typeof d === 'string' ? d : '',\n\t\t\t\ticon\t\t: typeof d === 'object' && d.icon !== undefined ? d.icon : true,\n\t\t\t\tparent\t\t: p,\n\t\t\t\tparents\t\t: ps,\n\t\t\t\tchildren\t: [],\n\t\t\t\tchildren_d\t: [],\n\t\t\t\tdata\t\t: null,\n\t\t\t\tstate\t\t: { },\n\t\t\t\tli_attr\t\t: { id : false },\n\t\t\t\ta_attr\t\t: { href : '#' },\n\t\t\t\toriginal\t: false\n\t\t\t};\n\t\t\tfor(i in df) {\n\t\t\t\tif(df.hasOwnProperty(i)) {\n\t\t\t\t\ttmp.state[i] = df[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && d.id) { tmp.id = d.id.toString(); }\n\t\t\tif(d && d.text) { tmp.text = d.text; }\n\t\t\tif(d && d.data && d.data.jstree && d.data.jstree.icon) {\n\t\t\t\ttmp.icon = d.data.jstree.icon;\n\t\t\t}\n\t\t\tif(tmp.icon === undefined || tmp.icon === null || tmp.icon === \"\") {\n\t\t\t\ttmp.icon = true;\n\t\t\t}\n\t\t\tif(d && d.data) {\n\t\t\t\ttmp.data = d.data;\n\t\t\t\tif(d.data.jstree) {\n\t\t\t\t\tfor(i in d.data.jstree) {\n\t\t\t\t\t\tif(d.data.jstree.hasOwnProperty(i)) {\n\t\t\t\t\t\t\ttmp.state[i] = d.data.jstree[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\tif(d && typeof d.state === 'object') {\n\t\t\t\tfor (i in d.state) {\n\t\t\t\t\tif(d.state.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.state[i] = d.state[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && typeof d.li_attr === 'object') {\n\t\t\t\tfor (i in d.li_attr) {\n\t\t\t\t\tif(d.li_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.li_attr[i] = d.li_attr[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(tmp.li_attr.id && !tmp.id) {\n\t\t\t\ttmp.id = tmp.li_attr.id.toString();\n\t\t\t}\n\t\t\tif(!tmp.id) {\n\t\t\t\ttmp.id = tid;\n\t\t\t}\n\t\t\tif(!tmp.li_attr.id) {\n\t\t\t\ttmp.li_attr.id = tmp.id;\n\t\t\t}\n\t\t\tif(d && typeof d.a_attr === 'object') {\n\t\t\t\tfor (i in d.a_attr) {\n\t\t\t\t\tif(d.a_attr.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.a_attr[i] = d.a_attr[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(d && d.children && d.children.length) {\n\t\t\t\tfor(i = 0, j = d.children.length; i < j; i++) {\n\t\t\t\t\tc = this._parse_model_from_json(d.children[i], tmp.id, ps);\n\t\t\t\t\te = m[c];\n\t\t\t\t\ttmp.children.push(c);\n\t\t\t\t\tif(e.children_d.length) {\n\t\t\t\t\t\ttmp.children_d = tmp.children_d.concat(e.children_d);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttmp.children_d = tmp.children_d.concat(tmp.children);\n\t\t\t}\n\t\t\tif(d && d.children && d.children === true) {\n\t\t\t\ttmp.state.loaded = false;\n\t\t\t\ttmp.children = [];\n\t\t\t\ttmp.children_d = [];\n\t\t\t}\n\t\t\tdelete d.data;\n\t\t\tdelete d.children;\n\t\t\ttmp.original = d;\n\t\t\tm[tmp.id] = tmp;\n\t\t\tif(tmp.state.selected) {\n\t\t\t\tthis._data.core.selected.push(tmp.id);\n\t\t\t}\n\t\t\treturn tmp.id;\n\t\t},\n\t\t/**\n\t\t * redraws all nodes that need to be redrawn. Used internally.\n\t\t * @private\n\t\t * @name _redraw()\n\t\t * @trigger redraw.jstree\n\t\t */\n\t\t_redraw : function () {\n\t\t\tvar nodes = this._model.force_full_redraw ? this._model.data[$.jstree.root].children.concat([]) : this._model.changed.concat([]),\n\t\t\t\tf = document.createElement('UL'), tmp, i, j, fe = this._data.core.focused;\n\t\t\tfor(i = 0, j = nodes.length; i < j; i++) {\n\t\t\t\ttmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw);\n\t\t\t\tif(tmp && this._model.force_full_redraw) {\n\t\t\t\t\tf.appendChild(tmp);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(this._model.force_full_redraw) {\n\t\t\t\tf.className = this.get_container_ul()[0].className;\n\t\t\t\tf.setAttribute('role','group');\n\t\t\t\tthis.element.empty().append(f);\n\t\t\t\t//this.get_container_ul()[0].appendChild(f);\n\t\t\t}\n\t\t\tif(fe !== null) {\n\t\t\t\ttmp = this.get_node(fe, true);\n\t\t\t\tif(tmp && tmp.length && tmp.children('.jstree-anchor')[0] !== document.activeElement) {\n\t\t\t\t\ttmp.children('.jstree-anchor').focus();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis._data.core.focused = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._model.force_full_redraw = false;\n\t\t\tthis._model.changed = [];\n\t\t\t/**\n\t\t\t * triggered after nodes are redrawn\n\t\t\t * @event\n\t\t\t * @name redraw.jstree\n\t\t\t * @param {array} nodes the redrawn nodes\n\t\t\t */\n\t\t\tthis.trigger('redraw', { \"nodes\" : nodes });\n\t\t},\n\t\t/**\n\t\t * redraws all nodes that need to be redrawn or optionally - the whole tree\n\t\t * @name redraw([full])\n\t\t * @param {Boolean} full if set to `true` all nodes are redrawn.\n\t\t */\n\t\tredraw : function (full) {\n\t\t\tif(full) {\n\t\t\t\tthis._model.force_full_redraw = true;\n\t\t\t}\n\t\t\t//if(this._model.redraw_timeout) {\n\t\t\t//\tclearTimeout(this._model.redraw_timeout);\n\t\t\t//}\n\t\t\t//this._model.redraw_timeout = setTimeout($.proxy(this._redraw, this),0);\n\t\t\tthis._redraw();\n\t\t},\n\t\t/**\n\t\t * redraws a single node's children. Used internally.\n\t\t * @private\n\t\t * @name draw_children(node)\n\t\t * @param {mixed} node the node whose children will be redrawn\n\t\t */\n\t\tdraw_children : function (node) {\n\t\t\tvar obj = this.get_node(node),\n\t\t\t\ti = false,\n\t\t\t\tj = false,\n\t\t\t\tk = false,\n\t\t\t\td = document;\n\t\t\tif(!obj) { return false; }\n\t\t\tif(obj.id === $.jstree.root) { return this.redraw(true); }\n\t\t\tnode = this.get_node(node, true);\n\t\t\tif(!node || !node.length) { return false; } // TODO: quick toggle\n\n\t\t\tnode.children('.jstree-children').remove();\n\t\t\tnode = node[0];\n\t\t\tif(obj.children.length && obj.state.loaded) {\n\t\t\t\tk = d.createElement('UL');\n\t\t\t\tk.setAttribute('role', 'group');\n\t\t\t\tk.className = 'jstree-children';\n\t\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\t\tk.appendChild(this.redraw_node(obj.children[i], true, true));\n\t\t\t\t}\n\t\t\t\tnode.appendChild(k);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * redraws a single node. Used internally.\n\t\t * @private\n\t\t * @name redraw_node(node, deep, is_callback, force_render)\n\t\t * @param {mixed} node the node to redraw\n\t\t * @param {Boolean} deep should child nodes be redrawn too\n\t\t * @param {Boolean} is_callback is this a recursion call\n\t\t * @param {Boolean} force_render should children of closed parents be drawn anyway\n\t\t */\n\t\tredraw_node : function (node, deep, is_callback, force_render) {\n\t\t\tvar obj = this.get_node(node),\n\t\t\t\tpar = false,\n\t\t\t\tind = false,\n\t\t\t\told = false,\n\t\t\t\ti = false,\n\t\t\t\tj = false,\n\t\t\t\tk = false,\n\t\t\t\tc = '',\n\t\t\t\td = document,\n\t\t\t\tm = this._model.data,\n\t\t\t\tf = false,\n\t\t\t\ts = false,\n\t\t\t\ttmp = null,\n\t\t\t\tt = 0,\n\t\t\t\tl = 0,\n\t\t\t\thas_children = false,\n\t\t\t\tlast_sibling = false;\n\t\t\tif(!obj) { return false; }\n\t\t\tif(obj.id === $.jstree.root) {  return this.redraw(true); }\n\t\t\tdeep = deep || obj.children.length === 0;\n\t\t\tnode = !document.querySelector ? document.getElementById(obj.id) : this.element[0].querySelector('#' + (\"0123456789\".indexOf(obj.id[0]) !== -1 ? '\\\\3' + obj.id[0] + ' ' + obj.id.substr(1).replace($.jstree.idregex,'\\\\$&') : obj.id.replace($.jstree.idregex,'\\\\$&')) ); //, this.element);\n\t\t\tif(!node) {\n\t\t\t\tdeep = true;\n\t\t\t\t//node = d.createElement('LI');\n\t\t\t\tif(!is_callback) {\n\t\t\t\t\tpar = obj.parent !== $.jstree.root ? $('#' + obj.parent.replace($.jstree.idregex,'\\\\$&'), this.element)[0] : null;\n\t\t\t\t\tif(par !== null && (!par || !m[obj.parent].state.opened)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tind = $.inArray(obj.id, par === null ? m[$.jstree.root].children : m[obj.parent].children);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnode = $(node);\n\t\t\t\tif(!is_callback) {\n\t\t\t\t\tpar = node.parent().parent()[0];\n\t\t\t\t\tif(par === this.element[0]) {\n\t\t\t\t\t\tpar = null;\n\t\t\t\t\t}\n\t\t\t\t\tind = node.index();\n\t\t\t\t}\n\t\t\t\t// m[obj.id].data = node.data(); // use only node's data, no need to touch jquery storage\n\t\t\t\tif(!deep && obj.children.length && !node.children('.jstree-children').length) {\n\t\t\t\t\tdeep = true;\n\t\t\t\t}\n\t\t\t\tif(!deep) {\n\t\t\t\t\told = node.children('.jstree-children')[0];\n\t\t\t\t}\n\t\t\t\tf = node.children('.jstree-anchor')[0] === document.activeElement;\n\t\t\t\tnode.remove();\n\t\t\t\t//node = d.createElement('LI');\n\t\t\t\t//node = node[0];\n\t\t\t}\n\t\t\tnode = this._data.core.node.cloneNode(true);\n\t\t\t// node is DOM, deep is boolean\n\n\t\t\tc = 'jstree-node ';\n\t\t\tfor(i in obj.li_attr) {\n\t\t\t\tif(obj.li_attr.hasOwnProperty(i)) {\n\t\t\t\t\tif(i === 'id') { continue; }\n\t\t\t\t\tif(i !== 'class') {\n\t\t\t\t\t\tnode.setAttribute(i, obj.li_attr[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tc += obj.li_attr[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!obj.a_attr.id) {\n\t\t\t\tobj.a_attr.id = obj.id + '_anchor';\n\t\t\t}\n\t\t\tnode.setAttribute('aria-selected', !!obj.state.selected);\n\t\t\tnode.setAttribute('aria-level', obj.parents.length);\n\t\t\tnode.setAttribute('aria-labelledby', obj.a_attr.id);\n\t\t\tif(obj.state.disabled) {\n\t\t\t\tnode.setAttribute('aria-disabled', true);\n\t\t\t}\n\n\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\tif(!m[obj.children[i]].state.hidden) {\n\t\t\t\t\thas_children = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(obj.parent !== null && m[obj.parent] && !obj.state.hidden) {\n\t\t\t\ti = $.inArray(obj.id, m[obj.parent].children);\n\t\t\t\tlast_sibling = obj.id;\n\t\t\t\tif(i !== -1) {\n\t\t\t\t\ti++;\n\t\t\t\t\tfor(j = m[obj.parent].children.length; i < j; i++) {\n\t\t\t\t\t\tif(!m[m[obj.parent].children[i]].state.hidden) {\n\t\t\t\t\t\t\tlast_sibling = m[obj.parent].children[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(last_sibling !== obj.id) {\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\tif(obj.state.hidden) {\n\t\t\t\tc += ' jstree-hidden';\n\t\t\t}\n\t\t\tif(obj.state.loaded && !has_children) {\n\t\t\t\tc += ' jstree-leaf';\n\t\t\t}\n\t\t\telse {\n\t\t\t\tc += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed';\n\t\t\t\tnode.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) );\n\t\t\t}\n\t\t\tif(last_sibling === obj.id) {\n\t\t\t\tc += ' jstree-last';\n\t\t\t}\n\t\t\tnode.id = obj.id;\n\t\t\tnode.className = c;\n\t\t\tc = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : '');\n\t\t\tfor(j in obj.a_attr) {\n\t\t\t\tif(obj.a_attr.hasOwnProperty(j)) {\n\t\t\t\t\tif(j === 'href' && obj.a_attr[j] === '#') { continue; }\n\t\t\t\t\tif(j !== 'class') {\n\t\t\t\t\t\tnode.childNodes[1].setAttribute(j, obj.a_attr[j]);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tc += ' ' + obj.a_attr[j];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(c.length) {\n\t\t\t\tnode.childNodes[1].className = 'jstree-anchor ' + c;\n\t\t\t}\n\t\t\tif((obj.icon && obj.icon !== true) || obj.icon === false) {\n\t\t\t\tif(obj.icon === false) {\n\t\t\t\t\tnode.childNodes[1].childNodes[0].className += ' jstree-themeicon-hidden';\n\t\t\t\t}\n\t\t\t\telse if(obj.icon.indexOf('/') === -1 && obj.icon.indexOf('.') === -1) {\n\t\t\t\t\tnode.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom';\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnode.childNodes[1].childNodes[0].style.backgroundImage = 'url(\"'+obj.icon+'\")';\n\t\t\t\t\tnode.childNodes[1].childNodes[0].style.backgroundPosition = 'center center';\n\t\t\t\t\tnode.childNodes[1].childNodes[0].style.backgroundSize = 'auto';\n\t\t\t\t\tnode.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(this.settings.core.force_text) {\n\t\t\t\tnode.childNodes[1].appendChild(d.createTextNode(obj.text));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnode.childNodes[1].innerHTML += obj.text;\n\t\t\t}\n\n\n\t\t\tif(deep && obj.children.length && (obj.state.opened || force_render) && obj.state.loaded) {\n\t\t\t\tk = d.createElement('UL');\n\t\t\t\tk.setAttribute('role', 'group');\n\t\t\t\tk.className = 'jstree-children';\n\t\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\t\tk.appendChild(this.redraw_node(obj.children[i], deep, true));\n\t\t\t\t}\n\t\t\t\tnode.appendChild(k);\n\t\t\t}\n\t\t\tif(old) {\n\t\t\t\tnode.appendChild(old);\n\t\t\t}\n\t\t\tif(!is_callback) {\n\t\t\t\t// append back using par / ind\n\t\t\t\tif(!par) {\n\t\t\t\t\tpar = this.element[0];\n\t\t\t\t}\n\t\t\t\tfor(i = 0, j = par.childNodes.length; i < j; i++) {\n\t\t\t\t\tif(par.childNodes[i] && par.childNodes[i].className && par.childNodes[i].className.indexOf('jstree-children') !== -1) {\n\t\t\t\t\t\ttmp = par.childNodes[i];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(!tmp) {\n\t\t\t\t\ttmp = d.createElement('UL');\n\t\t\t\t\ttmp.setAttribute('role', 'group');\n\t\t\t\t\ttmp.className = 'jstree-children';\n\t\t\t\t\tpar.appendChild(tmp);\n\t\t\t\t}\n\t\t\t\tpar = tmp;\n\n\t\t\t\tif(ind < par.childNodes.length) {\n\t\t\t\t\tpar.insertBefore(node, par.childNodes[ind]);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpar.appendChild(node);\n\t\t\t\t}\n\t\t\t\tif(f) {\n\t\t\t\t\tt = this.element[0].scrollTop;\n\t\t\t\t\tl = this.element[0].scrollLeft;\n\t\t\t\t\tnode.childNodes[1].focus();\n\t\t\t\t\tthis.element[0].scrollTop = t;\n\t\t\t\t\tthis.element[0].scrollLeft = l;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(obj.state.opened && !obj.state.loaded) {\n\t\t\t\tobj.state.opened = false;\n\t\t\t\tsetTimeout($.proxy(function () {\n\t\t\t\t\tthis.open_node(obj.id, false, 0);\n\t\t\t\t}, this), 0);\n\t\t\t}\n\t\t\treturn node;\n\t\t},\n\t\t/**\n\t\t * opens a node, revaling its children. If the node is not loaded it will be loaded and opened once ready.\n\t\t * @name open_node(obj [, callback, animation])\n\t\t * @param {mixed} obj the node to open\n\t\t * @param {Function} callback a function to execute once the node is opened\n\t\t * @param {Number} animation the animation duration in milliseconds when opening the node (overrides the `core.animation` setting). Use `false` for no animation.\n\t\t * @trigger open_node.jstree, after_open.jstree, before_open.jstree\n\t\t */\n\t\topen_node : function (obj, callback, animation) {\n\t\t\tvar t1, t2, d, t;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.open_node(obj[t1], callback, animation);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tanimation = animation === undefined ? this.settings.core.animation : animation;\n\t\t\tif(!this.is_closed(obj)) {\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback.call(this, obj, false);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(!this.is_loaded(obj)) {\n\t\t\t\tif(this.is_loading(obj)) {\n\t\t\t\t\treturn setTimeout($.proxy(function () {\n\t\t\t\t\t\tthis.open_node(obj, callback, animation);\n\t\t\t\t\t}, this), 500);\n\t\t\t\t}\n\t\t\t\tthis.load_node(obj, function (o, ok) {\n\t\t\t\t\treturn ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false);\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\td = this.get_node(obj, true);\n\t\t\t\tt = this;\n\t\t\t\tif(d.length) {\n\t\t\t\t\tif(animation && d.children(\".jstree-children\").length) {\n\t\t\t\t\t\td.children(\".jstree-children\").stop(true, true);\n\t\t\t\t\t}\n\t\t\t\t\tif(obj.children.length && !this._firstChild(d.children('.jstree-children')[0])) {\n\t\t\t\t\t\tthis.draw_children(obj);\n\t\t\t\t\t\t//d = this.get_node(obj, true);\n\t\t\t\t\t}\n\t\t\t\t\tif(!animation) {\n\t\t\t\t\t\tthis.trigger('before_open', { \"node\" : obj });\n\t\t\t\t\t\td[0].className = d[0].className.replace('jstree-closed', 'jstree-open');\n\t\t\t\t\t\td[0].setAttribute(\"aria-expanded\", true);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.trigger('before_open', { \"node\" : obj });\n\t\t\t\t\t\td\n\t\t\t\t\t\t\t.children(\".jstree-children\").css(\"display\",\"none\").end()\n\t\t\t\t\t\t\t.removeClass(\"jstree-closed\").addClass(\"jstree-open\").attr(\"aria-expanded\", true)\n\t\t\t\t\t\t\t.children(\".jstree-children\").stop(true, true)\n\t\t\t\t\t\t\t\t.slideDown(animation, function () {\n\t\t\t\t\t\t\t\t\tthis.style.display = \"\";\n\t\t\t\t\t\t\t\t\tif (t.element) {\n\t\t\t\t\t\t\t\t\t\tt.trigger(\"after_open\", { \"node\" : obj });\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}\n\t\t\t\t}\n\t\t\t\tobj.state.opened = true;\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback.call(this, obj, true);\n\t\t\t\t}\n\t\t\t\tif(!d.length) {\n\t\t\t\t\t/**\n\t\t\t\t\t * triggered when a node is about to be opened (if the node is supposed to be in the DOM, it will be, but it won't be visible yet)\n\t\t\t\t\t * @event\n\t\t\t\t\t * @name before_open.jstree\n\t\t\t\t\t * @param {Object} node the opened node\n\t\t\t\t\t */\n\t\t\t\t\tthis.trigger('before_open', { \"node\" : obj });\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * triggered when a node is opened (if there is an animation it will not be completed yet)\n\t\t\t\t * @event\n\t\t\t\t * @name open_node.jstree\n\t\t\t\t * @param {Object} node the opened node\n\t\t\t\t */\n\t\t\t\tthis.trigger('open_node', { \"node\" : obj });\n\t\t\t\tif(!animation || !d.length) {\n\t\t\t\t\t/**\n\t\t\t\t\t * triggered when a node is opened and the animation is complete\n\t\t\t\t\t * @event\n\t\t\t\t\t * @name after_open.jstree\n\t\t\t\t\t * @param {Object} node the opened node\n\t\t\t\t\t */\n\t\t\t\t\tthis.trigger(\"after_open\", { \"node\" : obj });\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * opens every parent of a node (node should be loaded)\n\t\t * @name _open_to(obj)\n\t\t * @param {mixed} obj the node to reveal\n\t\t * @private\n\t\t */\n\t\t_open_to : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar i, j, p = obj.parents;\n\t\t\tfor(i = 0, j = p.length; i < j; i+=1) {\n\t\t\t\tif(i !== $.jstree.root) {\n\t\t\t\t\tthis.open_node(p[i], false, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn $('#' + obj.id.replace($.jstree.idregex,'\\\\$&'), this.element);\n\t\t},\n\t\t/**\n\t\t * closes a node, hiding its children\n\t\t * @name close_node(obj [, animation])\n\t\t * @param {mixed} obj the node to close\n\t\t * @param {Number} animation the animation duration in milliseconds when closing the node (overrides the `core.animation` setting). Use `false` for no animation.\n\t\t * @trigger close_node.jstree, after_close.jstree\n\t\t */\n\t\tclose_node : function (obj, animation) {\n\t\t\tvar t1, t2, t, d;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.close_node(obj[t1], animation);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(this.is_closed(obj)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tanimation = animation === undefined ? this.settings.core.animation : animation;\n\t\t\tt = this;\n\t\t\td = this.get_node(obj, true);\n\n\t\t\tobj.state.opened = false;\n\t\t\t/**\n\t\t\t * triggered when a node is closed (if there is an animation it will not be complete yet)\n\t\t\t * @event\n\t\t\t * @name close_node.jstree\n\t\t\t * @param {Object} node the closed node\n\t\t\t */\n\t\t\tthis.trigger('close_node',{ \"node\" : obj });\n\t\t\tif(!d.length) {\n\t\t\t\t/**\n\t\t\t\t * triggered when a node is closed and the animation is complete\n\t\t\t\t * @event\n\t\t\t\t * @name after_close.jstree\n\t\t\t\t * @param {Object} node the closed node\n\t\t\t\t */\n\t\t\t\tthis.trigger(\"after_close\", { \"node\" : obj });\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(!animation) {\n\t\t\t\t\td[0].className = d[0].className.replace('jstree-open', 'jstree-closed');\n\t\t\t\t\td.attr(\"aria-expanded\", false).children('.jstree-children').remove();\n\t\t\t\t\tthis.trigger(\"after_close\", { \"node\" : obj });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\td\n\t\t\t\t\t\t.children(\".jstree-children\").attr(\"style\",\"display:block !important\").end()\n\t\t\t\t\t\t.removeClass(\"jstree-open\").addClass(\"jstree-closed\").attr(\"aria-expanded\", false)\n\t\t\t\t\t\t.children(\".jstree-children\").stop(true, true).slideUp(animation, function () {\n\t\t\t\t\t\t\tthis.style.display = \"\";\n\t\t\t\t\t\t\td.children('.jstree-children').remove();\n\t\t\t\t\t\t\tif (t.element) {\n\t\t\t\t\t\t\t\tt.trigger(\"after_close\", { \"node\" : obj });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * toggles a node - closing it if it is open, opening it if it is closed\n\t\t * @name toggle_node(obj)\n\t\t * @param {mixed} obj the node to toggle\n\t\t */\n\t\ttoggle_node : function (obj) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.toggle_node(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(this.is_closed(obj)) {\n\t\t\t\treturn this.open_node(obj);\n\t\t\t}\n\t\t\tif(this.is_open(obj)) {\n\t\t\t\treturn this.close_node(obj);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * opens all nodes within a node (or the tree), revaling their children. If the node is not loaded it will be loaded and opened once ready.\n\t\t * @name open_all([obj, animation, original_obj])\n\t\t * @param {mixed} obj the node to open recursively, omit to open all nodes in the tree\n\t\t * @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation\n\t\t * @param {jQuery} reference to the node that started the process (internal use)\n\t\t * @trigger open_all.jstree\n\t\t */\n\t\topen_all : function (obj, animation, original_obj) {\n\t\t\tif(!obj) { obj = $.jstree.root; }\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj) { return false; }\n\t\t\tvar dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), i, j, _this;\n\t\t\tif(!dom.length) {\n\t\t\t\tfor(i = 0, j = obj.children_d.length; i < j; i++) {\n\t\t\t\t\tif(this.is_closed(this._model.data[obj.children_d[i]])) {\n\t\t\t\t\t\tthis._model.data[obj.children_d[i]].state.opened = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this.trigger('open_all', { \"node\" : obj });\n\t\t\t}\n\t\t\toriginal_obj = original_obj || dom;\n\t\t\t_this = this;\n\t\t\tdom = this.is_closed(obj) ? dom.find('.jstree-closed').addBack() : dom.find('.jstree-closed');\n\t\t\tdom.each(function () {\n\t\t\t\t_this.open_node(\n\t\t\t\t\tthis,\n\t\t\t\t\tfunction(node, status) { if(status && this.is_parent(node)) { this.open_all(node, animation, original_obj); } },\n\t\t\t\t\tanimation || 0\n\t\t\t\t);\n\t\t\t});\n\t\t\tif(original_obj.find('.jstree-closed').length === 0) {\n\t\t\t\t/**\n\t\t\t\t * triggered when an `open_all` call completes\n\t\t\t\t * @event\n\t\t\t\t * @name open_all.jstree\n\t\t\t\t * @param {Object} node the opened node\n\t\t\t\t */\n\t\t\t\tthis.trigger('open_all', { \"node\" : this.get_node(original_obj) });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * closes all nodes within a node (or the tree), revaling their children\n\t\t * @name close_all([obj, animation])\n\t\t * @param {mixed} obj the node to close recursively, omit to close all nodes in the tree\n\t\t * @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation\n\t\t * @trigger close_all.jstree\n\t\t */\n\t\tclose_all : function (obj, animation) {\n\t\t\tif(!obj) { obj = $.jstree.root; }\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj) { return false; }\n\t\t\tvar dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true),\n\t\t\t\t_this = this, i, j;\n\t\t\tif(dom.length) {\n\t\t\t\tdom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open');\n\t\t\t\t$(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); });\n\t\t\t}\n\t\t\tfor(i = 0, j = obj.children_d.length; i < j; i++) {\n\t\t\t\tthis._model.data[obj.children_d[i]].state.opened = false;\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when an `close_all` call completes\n\t\t\t * @event\n\t\t\t * @name close_all.jstree\n\t\t\t * @param {Object} node the closed node\n\t\t\t */\n\t\t\tthis.trigger('close_all', { \"node\" : obj });\n\t\t},\n\t\t/**\n\t\t * checks if a node is disabled (not selectable)\n\t\t * @name is_disabled(obj)\n\t\t * @param  {mixed} obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_disabled : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj && obj.state && obj.state.disabled;\n\t\t},\n\t\t/**\n\t\t * enables a node - so that it can be selected\n\t\t * @name enable_node(obj)\n\t\t * @param {mixed} obj the node to enable\n\t\t * @trigger enable_node.jstree\n\t\t */\n\t\tenable_node : function (obj) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.enable_node(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tobj.state.disabled = false;\n\t\t\tthis.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled').attr('aria-disabled', false);\n\t\t\t/**\n\t\t\t * triggered when an node is enabled\n\t\t\t * @event\n\t\t\t * @name enable_node.jstree\n\t\t\t * @param {Object} node the enabled node\n\t\t\t */\n\t\t\tthis.trigger('enable_node', { 'node' : obj });\n\t\t},\n\t\t/**\n\t\t * disables a node - so that it can not be selected\n\t\t * @name disable_node(obj)\n\t\t * @param {mixed} obj the node to disable\n\t\t * @trigger disable_node.jstree\n\t\t */\n\t\tdisable_node : function (obj) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.disable_node(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tobj.state.disabled = true;\n\t\t\tthis.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled').attr('aria-disabled', true);\n\t\t\t/**\n\t\t\t * triggered when an node is disabled\n\t\t\t * @event\n\t\t\t * @name disable_node.jstree\n\t\t\t * @param {Object} node the disabled node\n\t\t\t */\n\t\t\tthis.trigger('disable_node', { 'node' : obj });\n\t\t},\n\t\t/**\n\t\t * determines if a node is hidden\n\t\t * @name is_hidden(obj)\n\t\t * @param {mixed} obj the node\n\t\t */\n\t\tis_hidden : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn obj.state.hidden === true;\n\t\t},\n\t\t/**\n\t\t * hides a node - it is still in the structure but will not be visible\n\t\t * @name hide_node(obj)\n\t\t * @param {mixed} obj the node to hide\n\t\t * @param {Boolean} skip_redraw internal parameter controlling if redraw is called\n\t\t * @trigger hide_node.jstree\n\t\t */\n\t\thide_node : function (obj, skip_redraw) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.hide_node(obj[t1], true);\n\t\t\t\t}\n\t\t\t\tif (!skip_redraw) {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(!obj.state.hidden) {\n\t\t\t\tobj.state.hidden = true;\n\t\t\t\tthis._node_changed(obj.parent);\n\t\t\t\tif(!skip_redraw) {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * triggered when an node is hidden\n\t\t\t\t * @event\n\t\t\t\t * @name hide_node.jstree\n\t\t\t\t * @param {Object} node the hidden node\n\t\t\t\t */\n\t\t\t\tthis.trigger('hide_node', { 'node' : obj });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * shows a node\n\t\t * @name show_node(obj)\n\t\t * @param {mixed} obj the node to show\n\t\t * @param {Boolean} skip_redraw internal parameter controlling if redraw is called\n\t\t * @trigger show_node.jstree\n\t\t */\n\t\tshow_node : function (obj, skip_redraw) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.show_node(obj[t1], true);\n\t\t\t\t}\n\t\t\t\tif (!skip_redraw) {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(obj.state.hidden) {\n\t\t\t\tobj.state.hidden = false;\n\t\t\t\tthis._node_changed(obj.parent);\n\t\t\t\tif(!skip_redraw) {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * triggered when an node is shown\n\t\t\t\t * @event\n\t\t\t\t * @name show_node.jstree\n\t\t\t\t * @param {Object} node the shown node\n\t\t\t\t */\n\t\t\t\tthis.trigger('show_node', { 'node' : obj });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * hides all nodes\n\t\t * @name hide_all()\n\t\t * @trigger hide_all.jstree\n\t\t */\n\t\thide_all : function (skip_redraw) {\n\t\t\tvar i, m = this._model.data, ids = [];\n\t\t\tfor(i in m) {\n\t\t\t\tif(m.hasOwnProperty(i) && i !== $.jstree.root && !m[i].state.hidden) {\n\t\t\t\t\tm[i].state.hidden = true;\n\t\t\t\t\tids.push(i);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._model.force_full_redraw = true;\n\t\t\tif(!skip_redraw) {\n\t\t\t\tthis.redraw();\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when all nodes are hidden\n\t\t\t * @event\n\t\t\t * @name hide_all.jstree\n\t\t\t * @param {Array} nodes the IDs of all hidden nodes\n\t\t\t */\n\t\t\tthis.trigger('hide_all', { 'nodes' : ids });\n\t\t\treturn ids;\n\t\t},\n\t\t/**\n\t\t * shows all nodes\n\t\t * @name show_all()\n\t\t * @trigger show_all.jstree\n\t\t */\n\t\tshow_all : function (skip_redraw) {\n\t\t\tvar i, m = this._model.data, ids = [];\n\t\t\tfor(i in m) {\n\t\t\t\tif(m.hasOwnProperty(i) && i !== $.jstree.root && m[i].state.hidden) {\n\t\t\t\t\tm[i].state.hidden = false;\n\t\t\t\t\tids.push(i);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._model.force_full_redraw = true;\n\t\t\tif(!skip_redraw) {\n\t\t\t\tthis.redraw();\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when all nodes are shown\n\t\t\t * @event\n\t\t\t * @name show_all.jstree\n\t\t\t * @param {Array} nodes the IDs of all shown nodes\n\t\t\t */\n\t\t\tthis.trigger('show_all', { 'nodes' : ids });\n\t\t\treturn ids;\n\t\t},\n\t\t/**\n\t\t * called when a node is selected by the user. Used internally.\n\t\t * @private\n\t\t * @name activate_node(obj, e)\n\t\t * @param {mixed} obj the node\n\t\t * @param {Object} e the related event\n\t\t * @trigger activate_node.jstree, changed.jstree\n\t\t */\n\t\tactivate_node : function (obj, e) {\n\t\t\tif(this.is_disabled(obj)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(!e || typeof e !== 'object') {\n\t\t\t\te = {};\n\t\t\t}\n\n\t\t\t// ensure last_clicked is still in the DOM, make it fresh (maybe it was moved?) and make sure it is still selected, if not - make last_clicked the last selected node\n\t\t\tthis._data.core.last_clicked = this._data.core.last_clicked && this._data.core.last_clicked.id !== undefined ? this.get_node(this._data.core.last_clicked.id) : null;\n\t\t\tif(this._data.core.last_clicked && !this._data.core.last_clicked.state.selected) { this._data.core.last_clicked = null; }\n\t\t\tif(!this._data.core.last_clicked && this._data.core.selected.length) { this._data.core.last_clicked = this.get_node(this._data.core.selected[this._data.core.selected.length - 1]); }\n\n\t\t\tif(!this.settings.core.multiple || (!e.metaKey && !e.ctrlKey && !e.shiftKey) || (e.shiftKey && (!this._data.core.last_clicked || !this.get_parent(obj) || this.get_parent(obj) !== this._data.core.last_clicked.parent ) )) {\n\t\t\t\tif(!this.settings.core.multiple && (e.metaKey || e.ctrlKey || e.shiftKey) && this.is_selected(obj)) {\n\t\t\t\t\tthis.deselect_node(obj, false, e);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.deselect_all(true);\n\t\t\t\t\tthis.select_node(obj, false, false, e);\n\t\t\t\t\tthis._data.core.last_clicked = this.get_node(obj);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(e.shiftKey) {\n\t\t\t\t\tvar o = this.get_node(obj).id,\n\t\t\t\t\t\tl = this._data.core.last_clicked.id,\n\t\t\t\t\t\tp = this.get_node(this._data.core.last_clicked.parent).children,\n\t\t\t\t\t\tc = false,\n\t\t\t\t\t\ti, j;\n\t\t\t\t\tfor(i = 0, j = p.length; i < j; i += 1) {\n\t\t\t\t\t\t// separate IFs work whem o and l are the same\n\t\t\t\t\t\tif(p[i] === o) {\n\t\t\t\t\t\t\tc = !c;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(p[i] === l) {\n\t\t\t\t\t\t\tc = !c;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!this.is_disabled(p[i]) && (c || p[i] === o || p[i] === l)) {\n\t\t\t\t\t\t\tif (!this.is_hidden(p[i])) {\n\t\t\t\t\t\t\t\tthis.select_node(p[i], true, false, e);\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\tthis.deselect_node(p[i], true, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.trigger('changed', { 'action' : 'select_node', 'node' : this.get_node(obj), 'selected' : this._data.core.selected, 'event' : e });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(!this.is_selected(obj)) {\n\t\t\t\t\t\tthis.select_node(obj, false, false, e);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.deselect_node(obj, false, e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when an node is clicked or intercated with by the user\n\t\t\t * @event\n\t\t\t * @name activate_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {Object} event the ooriginal event (if any) which triggered the call (may be an empty object)\n\t\t\t */\n\t\t\tthis.trigger('activate_node', { 'node' : this.get_node(obj), 'event' : e });\n\t\t},\n\t\t/**\n\t\t * applies the hover state on a node, called when a node is hovered by the user. Used internally.\n\t\t * @private\n\t\t * @name hover_node(obj)\n\t\t * @param {mixed} obj\n\t\t * @trigger hover_node.jstree\n\t\t */\n\t\thover_node : function (obj) {\n\t\t\tobj = this.get_node(obj, true);\n\t\t\tif(!obj || !obj.length || obj.children('.jstree-hovered').length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar o = this.element.find('.jstree-hovered'), t = this.element;\n\t\t\tif(o && o.length) { this.dehover_node(o); }\n\n\t\t\tobj.children('.jstree-anchor').addClass('jstree-hovered');\n\t\t\t/**\n\t\t\t * triggered when an node is hovered\n\t\t\t * @event\n\t\t\t * @name hover_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t */\n\t\t\tthis.trigger('hover_node', { 'node' : this.get_node(obj) });\n\t\t\tsetTimeout(function () { t.attr('aria-activedescendant', obj[0].id); }, 0);\n\t\t},\n\t\t/**\n\t\t * removes the hover state from a nodecalled when a node is no longer hovered by the user. Used internally.\n\t\t * @private\n\t\t * @name dehover_node(obj)\n\t\t * @param {mixed} obj\n\t\t * @trigger dehover_node.jstree\n\t\t */\n\t\tdehover_node : function (obj) {\n\t\t\tobj = this.get_node(obj, true);\n\t\t\tif(!obj || !obj.length || !obj.children('.jstree-hovered').length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tobj.children('.jstree-anchor').removeClass('jstree-hovered');\n\t\t\t/**\n\t\t\t * triggered when an node is no longer hovered\n\t\t\t * @event\n\t\t\t * @name dehover_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t */\n\t\t\tthis.trigger('dehover_node', { 'node' : this.get_node(obj) });\n\t\t},\n\t\t/**\n\t\t * select a node\n\t\t * @name select_node(obj [, supress_event, prevent_open])\n\t\t * @param {mixed} obj an array can be used to select multiple nodes\n\t\t * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered\n\t\t * @param {Boolean} prevent_open if set to `true` parents of the selected node won't be opened\n\t\t * @trigger select_node.jstree, changed.jstree\n\t\t */\n\t\tselect_node : function (obj, supress_event, prevent_open, e) {\n\t\t\tvar dom, t1, t2, th;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.select_node(obj[t1], supress_event, prevent_open, e);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tdom = this.get_node(obj, true);\n\t\t\tif(!obj.state.selected) {\n\t\t\t\tobj.state.selected = true;\n\t\t\t\tthis._data.core.selected.push(obj.id);\n\t\t\t\tif(!prevent_open) {\n\t\t\t\t\tdom = this._open_to(obj);\n\t\t\t\t}\n\t\t\t\tif(dom && dom.length) {\n\t\t\t\t\tdom.attr('aria-selected', true).children('.jstree-anchor').addClass('jstree-clicked');\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * triggered when an node is selected\n\t\t\t\t * @event\n\t\t\t\t * @name select_node.jstree\n\t\t\t\t * @param {Object} node\n\t\t\t\t * @param {Array} selected the current selection\n\t\t\t\t * @param {Object} event the event (if any) that triggered this select_node\n\t\t\t\t */\n\t\t\t\tthis.trigger('select_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });\n\t\t\t\tif(!supress_event) {\n\t\t\t\t\t/**\n\t\t\t\t\t * triggered when selection changes\n\t\t\t\t\t * @event\n\t\t\t\t\t * @name changed.jstree\n\t\t\t\t\t * @param {Object} node\n\t\t\t\t\t * @param {Object} action the action that caused the selection to change\n\t\t\t\t\t * @param {Array} selected the current selection\n\t\t\t\t\t * @param {Object} event the event (if any) that triggered this changed event\n\t\t\t\t\t */\n\t\t\t\t\tthis.trigger('changed', { 'action' : 'select_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * deselect a node\n\t\t * @name deselect_node(obj [, supress_event])\n\t\t * @param {mixed} obj an array can be used to deselect multiple nodes\n\t\t * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered\n\t\t * @trigger deselect_node.jstree, changed.jstree\n\t\t */\n\t\tdeselect_node : function (obj, supress_event, e) {\n\t\t\tvar t1, t2, dom;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.deselect_node(obj[t1], supress_event, e);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tdom = this.get_node(obj, true);\n\t\t\tif(obj.state.selected) {\n\t\t\t\tobj.state.selected = false;\n\t\t\t\tthis._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id);\n\t\t\t\tif(dom.length) {\n\t\t\t\t\tdom.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-clicked');\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * triggered when an node is deselected\n\t\t\t\t * @event\n\t\t\t\t * @name deselect_node.jstree\n\t\t\t\t * @param {Object} node\n\t\t\t\t * @param {Array} selected the current selection\n\t\t\t\t * @param {Object} event the event (if any) that triggered this deselect_node\n\t\t\t\t */\n\t\t\t\tthis.trigger('deselect_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });\n\t\t\t\tif(!supress_event) {\n\t\t\t\t\tthis.trigger('changed', { 'action' : 'deselect_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e });\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * select all nodes in the tree\n\t\t * @name select_all([supress_event])\n\t\t * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered\n\t\t * @trigger select_all.jstree, changed.jstree\n\t\t */\n\t\tselect_all : function (supress_event) {\n\t\t\tvar tmp = this._data.core.selected.concat([]), i, j;\n\t\t\tthis._data.core.selected = this._model.data[$.jstree.root].children_d.concat();\n\t\t\tfor(i = 0, j = this._data.core.selected.length; i < j; i++) {\n\t\t\t\tif(this._model.data[this._data.core.selected[i]]) {\n\t\t\t\t\tthis._model.data[this._data.core.selected[i]].state.selected = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.redraw(true);\n\t\t\t/**\n\t\t\t * triggered when all nodes are selected\n\t\t\t * @event\n\t\t\t * @name select_all.jstree\n\t\t\t * @param {Array} selected the current selection\n\t\t\t */\n\t\t\tthis.trigger('select_all', { 'selected' : this._data.core.selected });\n\t\t\tif(!supress_event) {\n\t\t\t\tthis.trigger('changed', { 'action' : 'select_all', 'selected' : this._data.core.selected, 'old_selection' : tmp });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * deselect all selected nodes\n\t\t * @name deselect_all([supress_event])\n\t\t * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered\n\t\t * @trigger deselect_all.jstree, changed.jstree\n\t\t */\n\t\tdeselect_all : function (supress_event) {\n\t\t\tvar tmp = this._data.core.selected.concat([]), i, j;\n\t\t\tfor(i = 0, j = this._data.core.selected.length; i < j; i++) {\n\t\t\t\tif(this._model.data[this._data.core.selected[i]]) {\n\t\t\t\t\tthis._model.data[this._data.core.selected[i]].state.selected = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._data.core.selected = [];\n\t\t\tthis.element.find('.jstree-clicked').removeClass('jstree-clicked').parent().attr('aria-selected', false);\n\t\t\t/**\n\t\t\t * triggered when all nodes are deselected\n\t\t\t * @event\n\t\t\t * @name deselect_all.jstree\n\t\t\t * @param {Object} node the previous selection\n\t\t\t * @param {Array} selected the current selection\n\t\t\t */\n\t\t\tthis.trigger('deselect_all', { 'selected' : this._data.core.selected, 'node' : tmp });\n\t\t\tif(!supress_event) {\n\t\t\t\tthis.trigger('changed', { 'action' : 'deselect_all', 'selected' : this._data.core.selected, 'old_selection' : tmp });\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * checks if a node is selected\n\t\t * @name is_selected(obj)\n\t\t * @param  {mixed}  obj\n\t\t * @return {Boolean}\n\t\t */\n\t\tis_selected : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn obj.state.selected;\n\t\t},\n\t\t/**\n\t\t * get an array of all selected nodes\n\t\t * @name get_selected([full])\n\t\t * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned\n\t\t * @return {Array}\n\t\t */\n\t\tget_selected : function (full) {\n\t\t\treturn full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected.slice();\n\t\t},\n\t\t/**\n\t\t * get an array of all top level selected nodes (ignoring children of selected nodes)\n\t\t * @name get_top_selected([full])\n\t\t * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned\n\t\t * @return {Array}\n\t\t */\n\t\tget_top_selected : function (full) {\n\t\t\tvar tmp = this.get_selected(true),\n\t\t\t\tobj = {}, i, j, k, l;\n\t\t\tfor(i = 0, j = tmp.length; i < j; i++) {\n\t\t\t\tobj[tmp[i].id] = tmp[i];\n\t\t\t}\n\t\t\tfor(i = 0, j = tmp.length; i < j; i++) {\n\t\t\t\tfor(k = 0, l = tmp[i].children_d.length; k < l; k++) {\n\t\t\t\t\tif(obj[tmp[i].children_d[k]]) {\n\t\t\t\t\t\tdelete obj[tmp[i].children_d[k]];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmp = [];\n\t\t\tfor(i in obj) {\n\t\t\t\tif(obj.hasOwnProperty(i)) {\n\t\t\t\t\ttmp.push(i);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;\n\t\t},\n\t\t/**\n\t\t * get an array of all bottom level selected nodes (ignoring selected parents)\n\t\t * @name get_bottom_selected([full])\n\t\t * @param  {mixed}  full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned\n\t\t * @return {Array}\n\t\t */\n\t\tget_bottom_selected : function (full) {\n\t\t\tvar tmp = this.get_selected(true),\n\t\t\t\tobj = [], i, j;\n\t\t\tfor(i = 0, j = tmp.length; i < j; i++) {\n\t\t\t\tif(!tmp[i].children.length) {\n\t\t\t\t\tobj.push(tmp[i].id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;\n\t\t},\n\t\t/**\n\t\t * gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally.\n\t\t * @name get_state()\n\t\t * @private\n\t\t * @return {Object}\n\t\t */\n\t\tget_state : function () {\n\t\t\tvar state\t= {\n\t\t\t\t'core' : {\n\t\t\t\t\t'open' : [],\n\t\t\t\t\t'scroll' : {\n\t\t\t\t\t\t'left' : this.element.scrollLeft(),\n\t\t\t\t\t\t'top' : this.element.scrollTop()\n\t\t\t\t\t},\n\t\t\t\t\t/*!\n\t\t\t\t\t'themes' : {\n\t\t\t\t\t\t'name' : this.get_theme(),\n\t\t\t\t\t\t'icons' : this._data.core.themes.icons,\n\t\t\t\t\t\t'dots' : this._data.core.themes.dots\n\t\t\t\t\t},\n\t\t\t\t\t*/\n\t\t\t\t\t'selected' : []\n\t\t\t\t}\n\t\t\t}, i;\n\t\t\tfor(i in this._model.data) {\n\t\t\t\tif(this._model.data.hasOwnProperty(i)) {\n\t\t\t\t\tif(i !== $.jstree.root) {\n\t\t\t\t\t\tif(this._model.data[i].state.opened) {\n\t\t\t\t\t\t\tstate.core.open.push(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(this._model.data[i].state.selected) {\n\t\t\t\t\t\t\tstate.core.selected.push(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\treturn state;\n\t\t},\n\t\t/**\n\t\t * sets the state of the tree. Used internally.\n\t\t * @name set_state(state [, callback])\n\t\t * @private\n\t\t * @param {Object} state the state to restore. Keep in mind this object is passed by reference and jstree will modify it.\n\t\t * @param {Function} callback an optional function to execute once the state is restored.\n\t\t * @trigger set_state.jstree\n\t\t */\n\t\tset_state : function (state, callback) {\n\t\t\tif(state) {\n\t\t\t\tif(state.core && state.core.selected && state.core.initial_selection === undefined) {\n\t\t\t\t\tstate.core.initial_selection = this._data.core.selected.concat([]).sort().join(',');\n\t\t\t\t}\n\t\t\t\tif(state.core) {\n\t\t\t\t\tvar res, n, t, _this, i;\n\t\t\t\t\tif(state.core.open) {\n\t\t\t\t\t\tif(!$.isArray(state.core.open) || !state.core.open.length) {\n\t\t\t\t\t\t\tdelete state.core.open;\n\t\t\t\t\t\t\tthis.set_state(state, callback);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis._load_nodes(state.core.open, function (nodes) {\n\t\t\t\t\t\t\t\tthis.open_node(nodes, false, 0);\n\t\t\t\t\t\t\t\tdelete state.core.open;\n\t\t\t\t\t\t\t\tthis.set_state(state, callback);\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\t\tif(state.core.scroll) {\n\t\t\t\t\t\tif(state.core.scroll && state.core.scroll.left !== undefined) {\n\t\t\t\t\t\t\tthis.element.scrollLeft(state.core.scroll.left);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(state.core.scroll && state.core.scroll.top !== undefined) {\n\t\t\t\t\t\t\tthis.element.scrollTop(state.core.scroll.top);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete state.core.scroll;\n\t\t\t\t\t\tthis.set_state(state, callback);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif(state.core.selected) {\n\t\t\t\t\t\t_this = this;\n\t\t\t\t\t\tif (state.core.initial_selection === undefined ||\n\t\t\t\t\t\t\tstate.core.initial_selection === this._data.core.selected.concat([]).sort().join(',')\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthis.deselect_all();\n\t\t\t\t\t\t\t$.each(state.core.selected, function (i, v) {\n\t\t\t\t\t\t\t\t_this.select_node(v, false, true);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete state.core.initial_selection;\n\t\t\t\t\t\tdelete state.core.selected;\n\t\t\t\t\t\tthis.set_state(state, callback);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tfor(i in state) {\n\t\t\t\t\t\tif(state.hasOwnProperty(i) && i !== \"core\" && $.inArray(i, this.settings.plugins) === -1) {\n\t\t\t\t\t\t\tdelete state[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif($.isEmptyObject(state.core)) {\n\t\t\t\t\t\tdelete state.core;\n\t\t\t\t\t\tthis.set_state(state, callback);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif($.isEmptyObject(state)) {\n\t\t\t\t\tstate = null;\n\t\t\t\t\tif(callback) { callback.call(this); }\n\t\t\t\t\t/**\n\t\t\t\t\t * triggered when a `set_state` call completes\n\t\t\t\t\t * @event\n\t\t\t\t\t * @name set_state.jstree\n\t\t\t\t\t */\n\t\t\t\t\tthis.trigger('set_state');\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\t/**\n\t\t * refreshes the tree - all nodes are reloaded with calls to `load_node`.\n\t\t * @name refresh()\n\t\t * @param {Boolean} skip_loading an option to skip showing the loading indicator\n\t\t * @param {Mixed} forget_state if set to `true` state will not be reapplied, if set to a function (receiving the current state as argument) the result of that function will be used as state\n\t\t * @trigger refresh.jstree\n\t\t */\n\t\trefresh : function (skip_loading, forget_state) {\n\t\t\tthis._data.core.state = forget_state === true ? {} : this.get_state();\n\t\t\tif(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); }\n\t\t\tthis._cnt = 0;\n\t\t\tthis._model.data = {};\n\t\t\tthis._model.data[$.jstree.root] = {\n\t\t\t\tid : $.jstree.root,\n\t\t\t\tparent : null,\n\t\t\t\tparents : [],\n\t\t\t\tchildren : [],\n\t\t\t\tchildren_d : [],\n\t\t\t\tstate : { loaded : false }\n\t\t\t};\n\t\t\tthis._data.core.selected = [];\n\t\t\tthis._data.core.last_clicked = null;\n\t\t\tthis._data.core.focused = null;\n\n\t\t\tvar c = this.get_container_ul()[0].className;\n\t\t\tif(!skip_loading) {\n\t\t\t\tthis.element.html(\"<\"+\"ul class='\"+c+\"' role='group'><\"+\"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j\"+this._id+\"_loading'><i class='jstree-icon jstree-ocl'></i><\"+\"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>\" + this.get_string(\"Loading ...\") + \"</a></li></ul>\");\n\t\t\t\tthis.element.attr('aria-activedescendant','j'+this._id+'_loading');\n\t\t\t}\n\t\t\tthis.load_node($.jstree.root, function (o, s) {\n\t\t\t\tif(s) {\n\t\t\t\t\tthis.get_container_ul()[0].className = c;\n\t\t\t\t\tif(this._firstChild(this.get_container_ul()[0])) {\n\t\t\t\t\t\tthis.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);\n\t\t\t\t\t}\n\t\t\t\t\tthis.set_state($.extend(true, {}, this._data.core.state), function () {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * triggered when a `refresh` call completes\n\t\t\t\t\t\t * @event\n\t\t\t\t\t\t * @name refresh.jstree\n\t\t\t\t\t\t */\n\t\t\t\t\t\tthis.trigger('refresh');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis._data.core.state = null;\n\t\t\t});\n\t\t},\n\t\t/**\n\t\t * refreshes a node in the tree (reload its children) all opened nodes inside that node are reloaded with calls to `load_node`.\n\t\t * @name refresh_node(obj)\n\t\t * @param  {mixed} obj the node\n\t\t * @trigger refresh_node.jstree\n\t\t */\n\t\trefresh_node : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\tvar opened = [], to_load = [], s = this._data.core.selected.concat([]);\n\t\t\tto_load.push(obj.id);\n\t\t\tif(obj.state.opened === true) { opened.push(obj.id); }\n\t\t\tthis.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); });\n\t\t\tthis._load_nodes(to_load, $.proxy(function (nodes) {\n\t\t\t\tthis.open_node(opened, false, 0);\n\t\t\t\tthis.select_node(s);\n\t\t\t\t/**\n\t\t\t\t * triggered when a node is refreshed\n\t\t\t\t * @event\n\t\t\t\t * @name refresh_node.jstree\n\t\t\t\t * @param {Object} node - the refreshed node\n\t\t\t\t * @param {Array} nodes - an array of the IDs of the nodes that were reloaded\n\t\t\t\t */\n\t\t\t\tthis.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes });\n\t\t\t}, this), false, true);\n\t\t},\n\t\t/**\n\t\t * set (change) the ID of a node\n\t\t * @name set_id(obj, id)\n\t\t * @param  {mixed} obj the node\n\t\t * @param  {String} id the new ID\n\t\t * @return {Boolean}\n\t\t * @trigger set_id.jstree\n\t\t */\n\t\tset_id : function (obj, id) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\tvar i, j, m = this._model.data, old = obj.id;\n\t\t\tid = id.toString();\n\t\t\t// update parents (replace current ID with new one in children and children_d)\n\t\t\tm[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id;\n\t\t\tfor(i = 0, j = obj.parents.length; i < j; i++) {\n\t\t\t\tm[obj.parents[i]].children_d[$.inArray(obj.id, m[obj.parents[i]].children_d)] = id;\n\t\t\t}\n\t\t\t// update children (replace current ID with new one in parent and parents)\n\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\tm[obj.children[i]].parent = id;\n\t\t\t}\n\t\t\tfor(i = 0, j = obj.children_d.length; i < j; i++) {\n\t\t\t\tm[obj.children_d[i]].parents[$.inArray(obj.id, m[obj.children_d[i]].parents)] = id;\n\t\t\t}\n\t\t\ti = $.inArray(obj.id, this._data.core.selected);\n\t\t\tif(i !== -1) { this._data.core.selected[i] = id; }\n\t\t\t// update model and obj itself (obj.id, this._model.data[KEY])\n\t\t\ti = this.get_node(obj.id, true);\n\t\t\tif(i) {\n\t\t\t\ti.attr('id', id); //.children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor');\n\t\t\t\tif(this.element.attr('aria-activedescendant') === obj.id) {\n\t\t\t\t\tthis.element.attr('aria-activedescendant', id);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdelete m[obj.id];\n\t\t\tobj.id = id;\n\t\t\tobj.li_attr.id = id;\n\t\t\tm[id] = obj;\n\t\t\t/**\n\t\t\t * triggered when a node id value is changed\n\t\t\t * @event\n\t\t\t * @name set_id.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {String} old the old id\n\t\t\t */\n\t\t\tthis.trigger('set_id',{ \"node\" : obj, \"new\" : obj.id, \"old\" : old });\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * get the text value of a node\n\t\t * @name get_text(obj)\n\t\t * @param  {mixed} obj the node\n\t\t * @return {String}\n\t\t */\n\t\tget_text : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn (!obj || obj.id === $.jstree.root) ? false : obj.text;\n\t\t},\n\t\t/**\n\t\t * set the text value of a node. Used internally, please use `rename_node(obj, val)`.\n\t\t * @private\n\t\t * @name set_text(obj, val)\n\t\t * @param  {mixed} obj the node, you can pass an array to set the text on multiple nodes\n\t\t * @param  {String} val the new text value\n\t\t * @return {Boolean}\n\t\t * @trigger set_text.jstree\n\t\t */\n\t\tset_text : function (obj, val) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.set_text(obj[t1], val);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\tobj.text = val;\n\t\t\tif(this.get_node(obj, true).length) {\n\t\t\t\tthis.redraw_node(obj.id);\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when a node text value is changed\n\t\t\t * @event\n\t\t\t * @name set_text.jstree\n\t\t\t * @param {Object} obj\n\t\t\t * @param {String} text the new value\n\t\t\t */\n\t\t\tthis.trigger('set_text',{ \"obj\" : obj, \"text\" : val });\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * gets a JSON representation of a node (or the whole tree)\n\t\t * @name get_json([obj, options])\n\t\t * @param  {mixed} obj\n\t\t * @param  {Object} options\n\t\t * @param  {Boolean} options.no_state do not return state information\n\t\t * @param  {Boolean} options.no_id do not return ID\n\t\t * @param  {Boolean} options.no_children do not include children\n\t\t * @param  {Boolean} options.no_data do not include node data\n\t\t * @param  {Boolean} options.no_li_attr do not include LI attributes\n\t\t * @param  {Boolean} options.no_a_attr do not include A attributes\n\t\t * @param  {Boolean} options.flat return flat JSON instead of nested\n\t\t * @return {Object}\n\t\t */\n\t\tget_json : function (obj, options, flat) {\n\t\t\tobj = this.get_node(obj || $.jstree.root);\n\t\t\tif(!obj) { return false; }\n\t\t\tif(options && options.flat && !flat) { flat = []; }\n\t\t\tvar tmp = {\n\t\t\t\t'id' : obj.id,\n\t\t\t\t'text' : obj.text,\n\t\t\t\t'icon' : this.get_icon(obj),\n\t\t\t\t'li_attr' : $.extend(true, {}, obj.li_attr),\n\t\t\t\t'a_attr' : $.extend(true, {}, obj.a_attr),\n\t\t\t\t'state' : {},\n\t\t\t\t'data' : options && options.no_data ? false : $.extend(true, $.isArray(obj.data)?[]:{}, obj.data)\n\t\t\t\t//( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ),\n\t\t\t}, i, j;\n\t\t\tif(options && options.flat) {\n\t\t\t\ttmp.parent = obj.parent;\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttmp.children = [];\n\t\t\t}\n\t\t\tif(!options || !options.no_state) {\n\t\t\t\tfor(i in obj.state) {\n\t\t\t\t\tif(obj.state.hasOwnProperty(i)) {\n\t\t\t\t\t\ttmp.state[i] = obj.state[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdelete tmp.state;\n\t\t\t}\n\t\t\tif(options && options.no_li_attr) {\n\t\t\t\tdelete tmp.li_attr;\n\t\t\t}\n\t\t\tif(options && options.no_a_attr) {\n\t\t\t\tdelete tmp.a_attr;\n\t\t\t}\n\t\t\tif(options && options.no_id) {\n\t\t\t\tdelete tmp.id;\n\t\t\t\tif(tmp.li_attr && tmp.li_attr.id) {\n\t\t\t\t\tdelete tmp.li_attr.id;\n\t\t\t\t}\n\t\t\t\tif(tmp.a_attr && tmp.a_attr.id) {\n\t\t\t\t\tdelete tmp.a_attr.id;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(options && options.flat && obj.id !== $.jstree.root) {\n\t\t\t\tflat.push(tmp);\n\t\t\t}\n\t\t\tif(!options || !options.no_children) {\n\t\t\t\tfor(i = 0, j = obj.children.length; i < j; i++) {\n\t\t\t\t\tif(options && options.flat) {\n\t\t\t\t\t\tthis.get_json(obj.children[i], options, flat);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\ttmp.children.push(this.get_json(obj.children[i], options));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn options && options.flat ? flat : (obj.id === $.jstree.root ? tmp.children : tmp);\n\t\t},\n\t\t/**\n\t\t * create a new node (do not confuse with load_node)\n\t\t * @name create_node([par, node, pos, callback, is_loaded])\n\t\t * @param  {mixed}   par       the parent node (to create a root node use either \"#\" (string) or `null`)\n\t\t * @param  {mixed}   node      the data for the new node (a valid JSON object, or a simple string with the name)\n\t\t * @param  {mixed}   pos       the index at which to insert the node, \"first\" and \"last\" are also supported, default is \"last\"\n\t\t * @param  {Function} callback a function to be called once the node is created\n\t\t * @param  {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded\n\t\t * @return {String}            the ID of the newly create node\n\t\t * @trigger model.jstree, create_node.jstree\n\t\t */\n\t\tcreate_node : function (par, node, pos, callback, is_loaded) {\n\t\t\tif(par === null) { par = $.jstree.root; }\n\t\t\tpar = this.get_node(par);\n\t\t\tif(!par) { return false; }\n\t\t\tpos = pos === undefined ? \"last\" : pos;\n\t\t\tif(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {\n\t\t\t\treturn this.load_node(par, function () { this.create_node(par, node, pos, callback, true); });\n\t\t\t}\n\t\t\tif(!node) { node = { \"text\" : this.get_string('New node') }; }\n\t\t\tif(typeof node === \"string\") {\n\t\t\t\tnode = { \"text\" : node };\n\t\t\t} else {\n\t\t\t\tnode = $.extend(true, {}, node);\n\t\t\t}\n\t\t\tif(node.text === undefined) { node.text = this.get_string('New node'); }\n\t\t\tvar tmp, dpc, i, j;\n\n\t\t\tif(par.id === $.jstree.root) {\n\t\t\t\tif(pos === \"before\") { pos = \"first\"; }\n\t\t\t\tif(pos === \"after\") { pos = \"last\"; }\n\t\t\t}\n\t\t\tswitch(pos) {\n\t\t\t\tcase \"before\":\n\t\t\t\t\ttmp = this.get_node(par.parent);\n\t\t\t\t\tpos = $.inArray(par.id, tmp.children);\n\t\t\t\t\tpar = tmp;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"after\" :\n\t\t\t\t\ttmp = this.get_node(par.parent);\n\t\t\t\t\tpos = $.inArray(par.id, tmp.children) + 1;\n\t\t\t\t\tpar = tmp;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"inside\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\tpos = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"last\":\n\t\t\t\t\tpos = par.children.length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tif(!pos) { pos = 0; }\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(pos > par.children.length) { pos = par.children.length; }\n\t\t\tif(!node.id) { node.id = true; }\n\t\t\tif(!this.check(\"create_node\", node, par, pos)) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(node.id === true) { delete node.id; }\n\t\t\tnode = this._parse_model_from_json(node, par.id, par.parents.concat());\n\t\t\tif(!node) { return false; }\n\t\t\ttmp = this.get_node(node);\n\t\t\tdpc = [];\n\t\t\tdpc.push(node);\n\t\t\tdpc = dpc.concat(tmp.children_d);\n\t\t\tthis.trigger('model', { \"nodes\" : dpc, \"parent\" : par.id });\n\n\t\t\tpar.children_d = par.children_d.concat(dpc);\n\t\t\tfor(i = 0, j = par.parents.length; i < j; i++) {\n\t\t\t\tthis._model.data[par.parents[i]].children_d = this._model.data[par.parents[i]].children_d.concat(dpc);\n\t\t\t}\n\t\t\tnode = tmp;\n\t\t\ttmp = [];\n\t\t\tfor(i = 0, j = par.children.length; i < j; i++) {\n\t\t\t\ttmp[i >= pos ? i+1 : i] = par.children[i];\n\t\t\t}\n\t\t\ttmp[pos] = node.id;\n\t\t\tpar.children = tmp;\n\n\t\t\tthis.redraw_node(par, true);\n\t\t\t/**\n\t\t\t * triggered when a node is created\n\t\t\t * @event\n\t\t\t * @name create_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {String} parent the parent's ID\n\t\t\t * @param {Number} position the position of the new node among the parent's children\n\t\t\t */\n\t\t\tthis.trigger('create_node', { \"node\" : this.get_node(node), \"parent\" : par.id, \"position\" : pos });\n\t\t\tif(callback) { callback.call(this, this.get_node(node)); }\n\t\t\treturn node.id;\n\t\t},\n\t\t/**\n\t\t * set the text value of a node\n\t\t * @name rename_node(obj, val)\n\t\t * @param  {mixed} obj the node, you can pass an array to rename multiple nodes to the same name\n\t\t * @param  {String} val the new text value\n\t\t * @return {Boolean}\n\t\t * @trigger rename_node.jstree\n\t\t */\n\t\trename_node : function (obj, val) {\n\t\t\tvar t1, t2, old;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.rename_node(obj[t1], val);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\told = obj.text;\n\t\t\tif(!this.check(\"rename_node\", obj, this.get_parent(obj), val)) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.set_text(obj, val); // .apply(this, Array.prototype.slice.call(arguments))\n\t\t\t/**\n\t\t\t * triggered when a node is renamed\n\t\t\t * @event\n\t\t\t * @name rename_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {String} text the new value\n\t\t\t * @param {String} old the old value\n\t\t\t */\n\t\t\tthis.trigger('rename_node', { \"node\" : obj, \"text\" : val, \"old\" : old });\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * remove a node\n\t\t * @name delete_node(obj)\n\t\t * @param  {mixed} obj the node, you can pass an array to delete multiple nodes\n\t\t * @return {Boolean}\n\t\t * @trigger delete_node.jstree, changed.jstree\n\t\t */\n\t\tdelete_node : function (obj) {\n\t\t\tvar t1, t2, par, pos, tmp, i, j, k, l, c, top, lft;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.delete_node(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\tpar = this.get_node(obj.parent);\n\t\t\tpos = $.inArray(obj.id, par.children);\n\t\t\tc = false;\n\t\t\tif(!this.check(\"delete_node\", obj, par, pos)) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(pos !== -1) {\n\t\t\t\tpar.children = $.vakata.array_remove(par.children, pos);\n\t\t\t}\n\t\t\ttmp = obj.children_d.concat([]);\n\t\t\ttmp.push(obj.id);\n\t\t\tfor(i = 0, j = obj.parents.length; i < j; i++) {\n\t\t\t\tthis._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {\n\t\t\t\t\treturn $.inArray(v, tmp) === -1;\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor(k = 0, l = tmp.length; k < l; k++) {\n\t\t\t\tif(this._model.data[tmp[k]].state.selected) {\n\t\t\t\t\tc = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (c) {\n\t\t\t\tthis._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {\n\t\t\t\t\treturn $.inArray(v, tmp) === -1;\n\t\t\t\t});\n\t\t\t}\n\t\t\t/**\n\t\t\t * triggered when a node is deleted\n\t\t\t * @event\n\t\t\t * @name delete_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {String} parent the parent's ID\n\t\t\t */\n\t\t\tthis.trigger('delete_node', { \"node\" : obj, \"parent\" : par.id });\n\t\t\tif(c) {\n\t\t\t\tthis.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id });\n\t\t\t}\n\t\t\tfor(k = 0, l = tmp.length; k < l; k++) {\n\t\t\t\tdelete this._model.data[tmp[k]];\n\t\t\t}\n\t\t\tif($.inArray(this._data.core.focused, tmp) !== -1) {\n\t\t\t\tthis._data.core.focused = null;\n\t\t\t\ttop = this.element[0].scrollTop;\n\t\t\t\tlft = this.element[0].scrollLeft;\n\t\t\t\tif(par.id === $.jstree.root) {\n\t\t\t\t\tif (this._model.data[$.jstree.root].children[0]) {\n\t\t\t\t\t\tthis.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.get_node(par, true).children('.jstree-anchor').focus();\n\t\t\t\t}\n\t\t\t\tthis.element[0].scrollTop  = top;\n\t\t\t\tthis.element[0].scrollLeft = lft;\n\t\t\t}\n\t\t\tthis.redraw_node(par, true);\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * check if an operation is premitted on the tree. Used internally.\n\t\t * @private\n\t\t * @name check(chk, obj, par, pos)\n\t\t * @param  {String} chk the operation to check, can be \"create_node\", \"rename_node\", \"delete_node\", \"copy_node\" or \"move_node\"\n\t\t * @param  {mixed} obj the node\n\t\t * @param  {mixed} par the parent\n\t\t * @param  {mixed} pos the position to insert at, or if \"rename_node\" - the new name\n\t\t * @param  {mixed} more some various additional information, for example if a \"move_node\" operations is triggered by DND this will be the hovered node\n\t\t * @return {Boolean}\n\t\t */\n\t\tcheck : function (chk, obj, par, pos, more) {\n\t\t\tobj = obj && obj.id ? obj : this.get_node(obj);\n\t\t\tpar = par && par.id ? par : this.get_node(par);\n\t\t\tvar tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj,\n\t\t\t\tchc = this.settings.core.check_callback;\n\t\t\tif(chk === \"move_node\" || chk === \"copy_node\") {\n\t\t\t\tif((!more || !more.is_multi) && (obj.id === par.id || (chk === \"move_node\" && $.inArray(obj.id, par.children) === pos) || $.inArray(par.id, obj.children_d) !== -1)) {\n\t\t\t\t\tthis._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(tmp && tmp.data) { tmp = tmp.data; }\n\t\t\tif(tmp && tmp.functions && (tmp.functions[chk] === false || tmp.functions[chk] === true)) {\n\t\t\t\tif(tmp.functions[chk] === false) {\n\t\t\t\t\tthis._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_02', 'reason' : 'Node data prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };\n\t\t\t\t}\n\t\t\t\treturn tmp.functions[chk];\n\t\t\t}\n\t\t\tif(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) {\n\t\t\t\tthis._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * get the last error\n\t\t * @name last_error()\n\t\t * @return {Object}\n\t\t */\n\t\tlast_error : function () {\n\t\t\treturn this._data.core.last_error;\n\t\t},\n\t\t/**\n\t\t * move a node to a new parent\n\t\t * @name move_node(obj, par [, pos, callback, is_loaded])\n\t\t * @param  {mixed} obj the node to move, pass an array to move multiple nodes\n\t\t * @param  {mixed} par the new parent\n\t\t * @param  {mixed} pos the position to insert at (besides integer values, \"first\" and \"last\" are supported, as well as \"before\" and \"after\"), defaults to integer `0`\n\t\t * @param  {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position\n\t\t * @param  {Boolean} is_loaded internal parameter indicating if the parent node has been loaded\n\t\t * @param  {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn\n\t\t * @param  {Boolean} instance internal parameter indicating if the node comes from another instance\n\t\t * @trigger move_node.jstree\n\t\t */\n\t\tmove_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) {\n\t\t\tvar t1, t2, old_par, old_pos, new_par, old_ins, is_multi, dpc, tmp, i, j, k, l, p;\n\n\t\t\tpar = this.get_node(par);\n\t\t\tpos = pos === undefined ? 0 : pos;\n\t\t\tif(!par) { return false; }\n\t\t\tif(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {\n\t\t\t\treturn this.load_node(par, function () { this.move_node(obj, par, pos, callback, true, false, origin); });\n\t\t\t}\n\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tif(obj.length === 1) {\n\t\t\t\t\tobj = obj[0];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t//obj = obj.slice();\n\t\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\t\tif((tmp = this.move_node(obj[t1], par, pos, callback, is_loaded, false, origin))) {\n\t\t\t\t\t\t\tpar = tmp;\n\t\t\t\t\t\t\tpos = \"after\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.redraw();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tobj = obj && obj.id ? obj : this.get_node(obj);\n\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\n\t\t\told_par = (obj.parent || $.jstree.root).toString();\n\t\t\tnew_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);\n\t\t\told_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));\n\t\t\tis_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);\n\t\t\told_pos = old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1;\n\t\t\tif(old_ins && old_ins._id) {\n\t\t\t\tobj = old_ins._model.data[obj.id];\n\t\t\t}\n\n\t\t\tif(is_multi) {\n\t\t\t\tif((tmp = this.copy_node(obj, par, pos, callback, is_loaded, false, origin))) {\n\t\t\t\t\tif(old_ins) { old_ins.delete_node(obj); }\n\t\t\t\t\treturn tmp;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//var m = this._model.data;\n\t\t\tif(par.id === $.jstree.root) {\n\t\t\t\tif(pos === \"before\") { pos = \"first\"; }\n\t\t\t\tif(pos === \"after\") { pos = \"last\"; }\n\t\t\t}\n\t\t\tswitch(pos) {\n\t\t\t\tcase \"before\":\n\t\t\t\t\tpos = $.inArray(par.id, new_par.children);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"after\" :\n\t\t\t\t\tpos = $.inArray(par.id, new_par.children) + 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"inside\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\tpos = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"last\":\n\t\t\t\t\tpos = new_par.children.length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tif(!pos) { pos = 0; }\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(pos > new_par.children.length) { pos = new_par.children.length; }\n\t\t\tif(!this.check(\"move_node\", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(obj.parent === new_par.id) {\n\t\t\t\tdpc = new_par.children.concat();\n\t\t\t\ttmp = $.inArray(obj.id, dpc);\n\t\t\t\tif(tmp !== -1) {\n\t\t\t\t\tdpc = $.vakata.array_remove(dpc, tmp);\n\t\t\t\t\tif(pos > tmp) { pos--; }\n\t\t\t\t}\n\t\t\t\ttmp = [];\n\t\t\t\tfor(i = 0, j = dpc.length; i < j; i++) {\n\t\t\t\t\ttmp[i >= pos ? i+1 : i] = dpc[i];\n\t\t\t\t}\n\t\t\t\ttmp[pos] = obj.id;\n\t\t\t\tnew_par.children = tmp;\n\t\t\t\tthis._node_changed(new_par.id);\n\t\t\t\tthis.redraw(new_par.id === $.jstree.root);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// clean old parent and up\n\t\t\t\ttmp = obj.children_d.concat();\n\t\t\t\ttmp.push(obj.id);\n\t\t\t\tfor(i = 0, j = obj.parents.length; i < j; i++) {\n\t\t\t\t\tdpc = [];\n\t\t\t\t\tp = old_ins._model.data[obj.parents[i]].children_d;\n\t\t\t\t\tfor(k = 0, l = p.length; k < l; k++) {\n\t\t\t\t\t\tif($.inArray(p[k], tmp) === -1) {\n\t\t\t\t\t\t\tdpc.push(p[k]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\told_ins._model.data[obj.parents[i]].children_d = dpc;\n\t\t\t\t}\n\t\t\t\told_ins._model.data[old_par].children = $.vakata.array_remove_item(old_ins._model.data[old_par].children, obj.id);\n\n\t\t\t\t// insert into new parent and up\n\t\t\t\tfor(i = 0, j = new_par.parents.length; i < j; i++) {\n\t\t\t\t\tthis._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(tmp);\n\t\t\t\t}\n\t\t\t\tdpc = [];\n\t\t\t\tfor(i = 0, j = new_par.children.length; i < j; i++) {\n\t\t\t\t\tdpc[i >= pos ? i+1 : i] = new_par.children[i];\n\t\t\t\t}\n\t\t\t\tdpc[pos] = obj.id;\n\t\t\t\tnew_par.children = dpc;\n\t\t\t\tnew_par.children_d.push(obj.id);\n\t\t\t\tnew_par.children_d = new_par.children_d.concat(obj.children_d);\n\n\t\t\t\t// update object\n\t\t\t\tobj.parent = new_par.id;\n\t\t\t\ttmp = new_par.parents.concat();\n\t\t\t\ttmp.unshift(new_par.id);\n\t\t\t\tp = obj.parents.length;\n\t\t\t\tobj.parents = tmp;\n\n\t\t\t\t// update object children\n\t\t\t\ttmp = tmp.concat();\n\t\t\t\tfor(i = 0, j = obj.children_d.length; i < j; i++) {\n\t\t\t\t\tthis._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1);\n\t\t\t\t\tArray.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp);\n\t\t\t\t}\n\n\t\t\t\tif(old_par === $.jstree.root || new_par.id === $.jstree.root) {\n\t\t\t\t\tthis._model.force_full_redraw = true;\n\t\t\t\t}\n\t\t\t\tif(!this._model.force_full_redraw) {\n\t\t\t\t\tthis._node_changed(old_par);\n\t\t\t\t\tthis._node_changed(new_par.id);\n\t\t\t\t}\n\t\t\t\tif(!skip_redraw) {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(callback) { callback.call(this, obj, new_par, pos); }\n\t\t\t/**\n\t\t\t * triggered when a node is moved\n\t\t\t * @event\n\t\t\t * @name move_node.jstree\n\t\t\t * @param {Object} node\n\t\t\t * @param {String} parent the parent's ID\n\t\t\t * @param {Number} position the position of the node among the parent's children\n\t\t\t * @param {String} old_parent the old parent of the node\n\t\t\t * @param {Number} old_position the old position of the node\n\t\t\t * @param {Boolean} is_multi do the node and new parent belong to different instances\n\t\t\t * @param {jsTree} old_instance the instance the node came from\n\t\t\t * @param {jsTree} new_instance the instance of the new parent\n\t\t\t */\n\t\t\tthis.trigger('move_node', { \"node\" : obj, \"parent\" : new_par.id, \"position\" : pos, \"old_parent\" : old_par, \"old_position\" : old_pos, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this });\n\t\t\treturn obj.id;\n\t\t},\n\t\t/**\n\t\t * copy a node to a new parent\n\t\t * @name copy_node(obj, par [, pos, callback, is_loaded])\n\t\t * @param  {mixed} obj the node to copy, pass an array to copy multiple nodes\n\t\t * @param  {mixed} par the new parent\n\t\t * @param  {mixed} pos the position to insert at (besides integer values, \"first\" and \"last\" are supported, as well as \"before\" and \"after\"), defaults to integer `0`\n\t\t * @param  {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position\n\t\t * @param  {Boolean} is_loaded internal parameter indicating if the parent node has been loaded\n\t\t * @param  {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn\n\t\t * @param  {Boolean} instance internal parameter indicating if the node comes from another instance\n\t\t * @trigger model.jstree copy_node.jstree\n\t\t */\n\t\tcopy_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) {\n\t\t\tvar t1, t2, dpc, tmp, i, j, node, old_par, new_par, old_ins, is_multi;\n\n\t\t\tpar = this.get_node(par);\n\t\t\tpos = pos === undefined ? 0 : pos;\n\t\t\tif(!par) { return false; }\n\t\t\tif(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {\n\t\t\t\treturn this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true, false, origin); });\n\t\t\t}\n\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tif(obj.length === 1) {\n\t\t\t\t\tobj = obj[0];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t//obj = obj.slice();\n\t\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\t\tif((tmp = this.copy_node(obj[t1], par, pos, callback, is_loaded, true, origin))) {\n\t\t\t\t\t\t\tpar = tmp;\n\t\t\t\t\t\t\tpos = \"after\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.redraw();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tobj = obj && obj.id ? obj : this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\n\t\t\told_par = (obj.parent || $.jstree.root).toString();\n\t\t\tnew_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);\n\t\t\told_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));\n\t\t\tis_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);\n\n\t\t\tif(old_ins && old_ins._id) {\n\t\t\t\tobj = old_ins._model.data[obj.id];\n\t\t\t}\n\n\t\t\tif(par.id === $.jstree.root) {\n\t\t\t\tif(pos === \"before\") { pos = \"first\"; }\n\t\t\t\tif(pos === \"after\") { pos = \"last\"; }\n\t\t\t}\n\t\t\tswitch(pos) {\n\t\t\t\tcase \"before\":\n\t\t\t\t\tpos = $.inArray(par.id, new_par.children);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"after\" :\n\t\t\t\t\tpos = $.inArray(par.id, new_par.children) + 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"inside\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\tpos = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"last\":\n\t\t\t\t\tpos = new_par.children.length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tif(!pos) { pos = 0; }\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(pos > new_par.children.length) { pos = new_par.children.length; }\n\t\t\tif(!this.check(\"copy_node\", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tnode = old_ins ? old_ins.get_json(obj, { no_id : true, no_data : true, no_state : true }) : obj;\n\t\t\tif(!node) { return false; }\n\t\t\tif(node.id === true) { delete node.id; }\n\t\t\tnode = this._parse_model_from_json(node, new_par.id, new_par.parents.concat());\n\t\t\tif(!node) { return false; }\n\t\t\ttmp = this.get_node(node);\n\t\t\tif(obj && obj.state && obj.state.loaded === false) { tmp.state.loaded = false; }\n\t\t\tdpc = [];\n\t\t\tdpc.push(node);\n\t\t\tdpc = dpc.concat(tmp.children_d);\n\t\t\tthis.trigger('model', { \"nodes\" : dpc, \"parent\" : new_par.id });\n\n\t\t\t// insert into new parent and up\n\t\t\tfor(i = 0, j = new_par.parents.length; i < j; i++) {\n\t\t\t\tthis._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(dpc);\n\t\t\t}\n\t\t\tdpc = [];\n\t\t\tfor(i = 0, j = new_par.children.length; i < j; i++) {\n\t\t\t\tdpc[i >= pos ? i+1 : i] = new_par.children[i];\n\t\t\t}\n\t\t\tdpc[pos] = tmp.id;\n\t\t\tnew_par.children = dpc;\n\t\t\tnew_par.children_d.push(tmp.id);\n\t\t\tnew_par.children_d = new_par.children_d.concat(tmp.children_d);\n\n\t\t\tif(new_par.id === $.jstree.root) {\n\t\t\t\tthis._model.force_full_redraw = true;\n\t\t\t}\n\t\t\tif(!this._model.force_full_redraw) {\n\t\t\t\tthis._node_changed(new_par.id);\n\t\t\t}\n\t\t\tif(!skip_redraw) {\n\t\t\t\tthis.redraw(new_par.id === $.jstree.root);\n\t\t\t}\n\t\t\tif(callback) { callback.call(this, tmp, new_par, pos); }\n\t\t\t/**\n\t\t\t * triggered when a node is copied\n\t\t\t * @event\n\t\t\t * @name copy_node.jstree\n\t\t\t * @param {Object} node the copied node\n\t\t\t * @param {Object} original the original node\n\t\t\t * @param {String} parent the parent's ID\n\t\t\t * @param {Number} position the position of the node among the parent's children\n\t\t\t * @param {String} old_parent the old parent of the node\n\t\t\t * @param {Number} old_position the position of the original node\n\t\t\t * @param {Boolean} is_multi do the node and new parent belong to different instances\n\t\t\t * @param {jsTree} old_instance the instance the node came from\n\t\t\t * @param {jsTree} new_instance the instance of the new parent\n\t\t\t */\n\t\t\tthis.trigger('copy_node', { \"node\" : tmp, \"original\" : obj, \"parent\" : new_par.id, \"position\" : pos, \"old_parent\" : old_par, \"old_position\" : old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1,'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this });\n\t\t\treturn tmp.id;\n\t\t},\n\t\t/**\n\t\t * cut a node (a later call to `paste(obj)` would move the node)\n\t\t * @name cut(obj)\n\t\t * @param  {mixed} obj multiple objects can be passed using an array\n\t\t * @trigger cut.jstree\n\t\t */\n\t\tcut : function (obj) {\n\t\t\tif(!obj) { obj = this._data.core.selected.concat(); }\n\t\t\tif(!$.isArray(obj)) { obj = [obj]; }\n\t\t\tif(!obj.length) { return false; }\n\t\t\tvar tmp = [], o, t1, t2;\n\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\to = this.get_node(obj[t1]);\n\t\t\t\tif(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }\n\t\t\t}\n\t\t\tif(!tmp.length) { return false; }\n\t\t\tccp_node = tmp;\n\t\t\tccp_inst = this;\n\t\t\tccp_mode = 'move_node';\n\t\t\t/**\n\t\t\t * triggered when nodes are added to the buffer for moving\n\t\t\t * @event\n\t\t\t * @name cut.jstree\n\t\t\t * @param {Array} node\n\t\t\t */\n\t\t\tthis.trigger('cut', { \"node\" : obj });\n\t\t},\n\t\t/**\n\t\t * copy a node (a later call to `paste(obj)` would copy the node)\n\t\t * @name copy(obj)\n\t\t * @param  {mixed} obj multiple objects can be passed using an array\n\t\t * @trigger copy.jstree\n\t\t */\n\t\tcopy : function (obj) {\n\t\t\tif(!obj) { obj = this._data.core.selected.concat(); }\n\t\t\tif(!$.isArray(obj)) { obj = [obj]; }\n\t\t\tif(!obj.length) { return false; }\n\t\t\tvar tmp = [], o, t1, t2;\n\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\to = this.get_node(obj[t1]);\n\t\t\t\tif(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }\n\t\t\t}\n\t\t\tif(!tmp.length) { return false; }\n\t\t\tccp_node = tmp;\n\t\t\tccp_inst = this;\n\t\t\tccp_mode = 'copy_node';\n\t\t\t/**\n\t\t\t * triggered when nodes are added to the buffer for copying\n\t\t\t * @event\n\t\t\t * @name copy.jstree\n\t\t\t * @param {Array} node\n\t\t\t */\n\t\t\tthis.trigger('copy', { \"node\" : obj });\n\t\t},\n\t\t/**\n\t\t * get the current buffer (any nodes that are waiting for a paste operation)\n\t\t * @name get_buffer()\n\t\t * @return {Object} an object consisting of `mode` (\"copy_node\" or \"move_node\"), `node` (an array of objects) and `inst` (the instance)\n\t\t */\n\t\tget_buffer : function () {\n\t\t\treturn { 'mode' : ccp_mode, 'node' : ccp_node, 'inst' : ccp_inst };\n\t\t},\n\t\t/**\n\t\t * check if there is something in the buffer to paste\n\t\t * @name can_paste()\n\t\t * @return {Boolean}\n\t\t */\n\t\tcan_paste : function () {\n\t\t\treturn ccp_mode !== false && ccp_node !== false; // && ccp_inst._model.data[ccp_node];\n\t\t},\n\t\t/**\n\t\t * copy or move the previously cut or copied nodes to a new parent\n\t\t * @name paste(obj [, pos])\n\t\t * @param  {mixed} obj the new parent\n\t\t * @param  {mixed} pos the position to insert at (besides integer, \"first\" and \"last\" are supported), defaults to integer `0`\n\t\t * @trigger paste.jstree\n\t\t */\n\t\tpaste : function (obj, pos) {\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || !ccp_mode || !ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; }\n\t\t\tif(this[ccp_mode](ccp_node, obj, pos, false, false, false, ccp_inst)) {\n\t\t\t\t/**\n\t\t\t\t * triggered when paste is invoked\n\t\t\t\t * @event\n\t\t\t\t * @name paste.jstree\n\t\t\t\t * @param {String} parent the ID of the receiving node\n\t\t\t\t * @param {Array} node the nodes in the buffer\n\t\t\t\t * @param {String} mode the performed operation - \"copy_node\" or \"move_node\"\n\t\t\t\t */\n\t\t\t\tthis.trigger('paste', { \"parent\" : obj.id, \"node\" : ccp_node, \"mode\" : ccp_mode });\n\t\t\t}\n\t\t\tccp_node = false;\n\t\t\tccp_mode = false;\n\t\t\tccp_inst = false;\n\t\t},\n\t\t/**\n\t\t * clear the buffer of previously copied or cut nodes\n\t\t * @name clear_buffer()\n\t\t * @trigger clear_buffer.jstree\n\t\t */\n\t\tclear_buffer : function () {\n\t\t\tccp_node = false;\n\t\t\tccp_mode = false;\n\t\t\tccp_inst = false;\n\t\t\t/**\n\t\t\t * triggered when the copy / cut buffer is cleared\n\t\t\t * @event\n\t\t\t * @name clear_buffer.jstree\n\t\t\t */\n\t\t\tthis.trigger('clear_buffer');\n\t\t},\n\t\t/**\n\t\t * put a node in edit mode (input field to rename the node)\n\t\t * @name edit(obj [, default_text, callback])\n\t\t * @param  {mixed} obj\n\t\t * @param  {String} default_text the text to populate the input with (if omitted or set to a non-string value the node's text value is used)\n\t\t * @param  {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise) and a boolean indicating if the user cancelled the edit. You can access the node's title using .text\n\t\t */\n\t\tedit : function (obj, default_text, callback) {\n\t\t\tvar rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false;\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj) { return false; }\n\t\t\tif(!this.check(\"edit\", obj, this.get_parent(obj))) {\n\t\t\t\tthis.settings.core.error.call(this, this._data.core.last_error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttmp = obj;\n\t\t\tdefault_text = typeof default_text === 'string' ? default_text : obj.text;\n\t\t\tthis.set_text(obj, \"\");\n\t\t\tobj = this._open_to(obj);\n\t\t\ttmp.text = default_text;\n\n\t\t\trtl = this._data.core.rtl;\n\t\t\tw  = this.element.width();\n\t\t\tthis._data.core.focused = tmp.id;\n\t\t\ta  = obj.children('.jstree-anchor').focus();\n\t\t\ts  = $('<span>');\n\t\t\t/*!\n\t\t\toi = obj.children(\"i:visible\"),\n\t\t\tai = a.children(\"i:visible\"),\n\t\t\tw1 = oi.width() * oi.length,\n\t\t\tw2 = ai.width() * ai.length,\n\t\t\t*/\n\t\t\tt  = default_text;\n\t\t\th1 = $(\"<\"+\"div />\", { css : { \"position\" : \"absolute\", \"top\" : \"-200px\", \"left\" : (rtl ? \"0px\" : \"-1000px\"), \"visibility\" : \"hidden\" } }).appendTo(\"body\");\n\t\t\th2 = $(\"<\"+\"input />\", {\n\t\t\t\t\t\t\"value\" : t,\n\t\t\t\t\t\t\"class\" : \"jstree-rename-input\",\n\t\t\t\t\t\t// \"size\" : t.length,\n\t\t\t\t\t\t\"css\" : {\n\t\t\t\t\t\t\t\"padding\" : \"0\",\n\t\t\t\t\t\t\t\"border\" : \"1px solid silver\",\n\t\t\t\t\t\t\t\"box-sizing\" : \"border-box\",\n\t\t\t\t\t\t\t\"display\" : \"inline-block\",\n\t\t\t\t\t\t\t\"height\" : (this._data.core.li_height) + \"px\",\n\t\t\t\t\t\t\t\"lineHeight\" : (this._data.core.li_height) + \"px\",\n\t\t\t\t\t\t\t\"width\" : \"150px\" // will be set a bit further down\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"blur\" : $.proxy(function (e) {\n\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tvar i = s.children(\".jstree-rename-input\"),\n\t\t\t\t\t\t\t\tv = i.val(),\n\t\t\t\t\t\t\t\tf = this.settings.core.force_text,\n\t\t\t\t\t\t\t\tnv;\n\t\t\t\t\t\t\tif(v === \"\") { v = t; }\n\t\t\t\t\t\t\th1.remove();\n\t\t\t\t\t\t\ts.replaceWith(a);\n\t\t\t\t\t\t\ts.remove();\n\t\t\t\t\t\t\tt = f ? t : $('<div></div>').append($.parseHTML(t)).html();\n\t\t\t\t\t\t\tthis.set_text(obj, t);\n\t\t\t\t\t\t\tnv = !!this.rename_node(obj, f ? $('<div></div>').text(v).text() : $('<div></div>').append($.parseHTML(v)).html());\n\t\t\t\t\t\t\tif(!nv) {\n\t\t\t\t\t\t\t\tthis.set_text(obj, t); // move this up? and fix #483\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._data.core.focused = tmp.id;\n\t\t\t\t\t\t\tsetTimeout($.proxy(function () {\n\t\t\t\t\t\t\t\tvar node = this.get_node(tmp.id, true);\n\t\t\t\t\t\t\t\tif(node.length) {\n\t\t\t\t\t\t\t\t\tthis._data.core.focused = tmp.id;\n\t\t\t\t\t\t\t\t\tnode.children('.jstree-anchor').focus();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this), 0);\n\t\t\t\t\t\t\tif(callback) {\n\t\t\t\t\t\t\t\tcallback.call(this, tmp, nv, cancel);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\th2 = null;\n\t\t\t\t\t\t}, this),\n\t\t\t\t\t\t\"keydown\" : function (e) {\n\t\t\t\t\t\t\tvar key = e.which;\n\t\t\t\t\t\t\tif(key === 27) {\n\t\t\t\t\t\t\t\tcancel = true;\n\t\t\t\t\t\t\t\tthis.value = t;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) {\n\t\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(key === 27 || key === 13) {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tthis.blur();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"click\" : function (e) { e.stopImmediatePropagation(); },\n\t\t\t\t\t\t\"mousedown\" : function (e) { e.stopImmediatePropagation(); },\n\t\t\t\t\t\t\"keyup\" : function (e) {\n\t\t\t\t\t\t\th2.width(Math.min(h1.text(\"pW\" + this.value).width(),w));\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"keypress\" : function(e) {\n\t\t\t\t\t\t\tif(e.which === 13) { return false; }\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\tfn = {\n\t\t\t\t\t\tfontFamily\t\t: a.css('fontFamily')\t\t|| '',\n\t\t\t\t\t\tfontSize\t\t: a.css('fontSize')\t\t\t|| '',\n\t\t\t\t\t\tfontWeight\t\t: a.css('fontWeight')\t\t|| '',\n\t\t\t\t\t\tfontStyle\t\t: a.css('fontStyle')\t\t|| '',\n\t\t\t\t\t\tfontStretch\t\t: a.css('fontStretch')\t\t|| '',\n\t\t\t\t\t\tfontVariant\t\t: a.css('fontVariant')\t\t|| '',\n\t\t\t\t\t\tletterSpacing\t: a.css('letterSpacing')\t|| '',\n\t\t\t\t\t\twordSpacing\t\t: a.css('wordSpacing')\t\t|| ''\n\t\t\t\t};\n\t\t\ts.attr('class', a.attr('class')).append(a.contents().clone()).append(h2);\n\t\t\ta.replaceWith(s);\n\t\t\th1.css(fn);\n\t\t\th2.css(fn).width(Math.min(h1.text(\"pW\" + h2[0].value).width(),w))[0].select();\n\t\t\t$(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) {\n\t\t\t\tif (h2 && e.target !== h2) {\n\t\t\t\t\t$(h2).blur();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\t/**\n\t\t * changes the theme\n\t\t * @name set_theme(theme_name [, theme_url])\n\t\t * @param {String} theme_name the name of the new theme to apply\n\t\t * @param {mixed} theme_url  the location of the CSS file for this theme. Omit or set to `false` if you manually included the file. Set to `true` to autoload from the `core.themes.dir` directory.\n\t\t * @trigger set_theme.jstree\n\t\t */\n\t\tset_theme : function (theme_name, theme_url) {\n\t\t\tif(!theme_name) { return false; }\n\t\t\tif(theme_url === true) {\n\t\t\t\tvar dir = this.settings.core.themes.dir;\n\t\t\t\tif(!dir) { dir = $.jstree.path + '/themes'; }\n\t\t\t\ttheme_url = dir + '/' + theme_name + '/style.css';\n\t\t\t}\n\t\t\tif(theme_url && $.inArray(theme_url, themes_loaded) === -1) {\n\t\t\t\t$('head').append('<'+'link rel=\"stylesheet\" href=\"' + theme_url + '\" type=\"text/css\" />');\n\t\t\t\tthemes_loaded.push(theme_url);\n\t\t\t}\n\t\t\tif(this._data.core.themes.name) {\n\t\t\t\tthis.element.removeClass('jstree-' + this._data.core.themes.name);\n\t\t\t}\n\t\t\tthis._data.core.themes.name = theme_name;\n\t\t\tthis.element.addClass('jstree-' + theme_name);\n\t\t\tthis.element[this.settings.core.themes.responsive ? 'addClass' : 'removeClass' ]('jstree-' + theme_name + '-responsive');\n\t\t\t/**\n\t\t\t * triggered when a theme is set\n\t\t\t * @event\n\t\t\t * @name set_theme.jstree\n\t\t\t * @param {String} theme the new theme\n\t\t\t */\n\t\t\tthis.trigger('set_theme', { 'theme' : theme_name });\n\t\t},\n\t\t/**\n\t\t * gets the name of the currently applied theme name\n\t\t * @name get_theme()\n\t\t * @return {String}\n\t\t */\n\t\tget_theme : function () { return this._data.core.themes.name; },\n\t\t/**\n\t\t * changes the theme variant (if the theme has variants)\n\t\t * @name set_theme_variant(variant_name)\n\t\t * @param {String|Boolean} variant_name the variant to apply (if `false` is used the current variant is removed)\n\t\t */\n\t\tset_theme_variant : function (variant_name) {\n\t\t\tif(this._data.core.themes.variant) {\n\t\t\t\tthis.element.removeClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant);\n\t\t\t}\n\t\t\tthis._data.core.themes.variant = variant_name;\n\t\t\tif(variant_name) {\n\t\t\t\tthis.element.addClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * gets the name of the currently applied theme variant\n\t\t * @name get_theme()\n\t\t * @return {String}\n\t\t */\n\t\tget_theme_variant : function () { return this._data.core.themes.variant; },\n\t\t/**\n\t\t * shows a striped background on the container (if the theme supports it)\n\t\t * @name show_stripes()\n\t\t */\n\t\tshow_stripes : function () {\n\t\t\tthis._data.core.themes.stripes = true;\n\t\t\tthis.get_container_ul().addClass(\"jstree-striped\");\n\t\t\t/**\n\t\t\t * triggered when stripes are shown\n\t\t\t * @event\n\t\t\t * @name show_stripes.jstree\n\t\t\t */\n\t\t\tthis.trigger('show_stripes');\n\t\t},\n\t\t/**\n\t\t * hides the striped background on the container\n\t\t * @name hide_stripes()\n\t\t */\n\t\thide_stripes : function () {\n\t\t\tthis._data.core.themes.stripes = false;\n\t\t\tthis.get_container_ul().removeClass(\"jstree-striped\");\n\t\t\t/**\n\t\t\t * triggered when stripes are hidden\n\t\t\t * @event\n\t\t\t * @name hide_stripes.jstree\n\t\t\t */\n\t\t\tthis.trigger('hide_stripes');\n\t\t},\n\t\t/**\n\t\t * toggles the striped background on the container\n\t\t * @name toggle_stripes()\n\t\t */\n\t\ttoggle_stripes : function () { if(this._data.core.themes.stripes) { this.hide_stripes(); } else { this.show_stripes(); } },\n\t\t/**\n\t\t * shows the connecting dots (if the theme supports it)\n\t\t * @name show_dots()\n\t\t */\n\t\tshow_dots : function () {\n\t\t\tthis._data.core.themes.dots = true;\n\t\t\tthis.get_container_ul().removeClass(\"jstree-no-dots\");\n\t\t\t/**\n\t\t\t * triggered when dots are shown\n\t\t\t * @event\n\t\t\t * @name show_dots.jstree\n\t\t\t */\n\t\t\tthis.trigger('show_dots');\n\t\t},\n\t\t/**\n\t\t * hides the connecting dots\n\t\t * @name hide_dots()\n\t\t */\n\t\thide_dots : function () {\n\t\t\tthis._data.core.themes.dots = false;\n\t\t\tthis.get_container_ul().addClass(\"jstree-no-dots\");\n\t\t\t/**\n\t\t\t * triggered when dots are hidden\n\t\t\t * @event\n\t\t\t * @name hide_dots.jstree\n\t\t\t */\n\t\t\tthis.trigger('hide_dots');\n\t\t},\n\t\t/**\n\t\t * toggles the connecting dots\n\t\t * @name toggle_dots()\n\t\t */\n\t\ttoggle_dots : function () { if(this._data.core.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },\n\t\t/**\n\t\t * show the node icons\n\t\t * @name show_icons()\n\t\t */\n\t\tshow_icons : function () {\n\t\t\tthis._data.core.themes.icons = true;\n\t\t\tthis.get_container_ul().removeClass(\"jstree-no-icons\");\n\t\t\t/**\n\t\t\t * triggered when icons are shown\n\t\t\t * @event\n\t\t\t * @name show_icons.jstree\n\t\t\t */\n\t\t\tthis.trigger('show_icons');\n\t\t},\n\t\t/**\n\t\t * hide the node icons\n\t\t * @name hide_icons()\n\t\t */\n\t\thide_icons : function () {\n\t\t\tthis._data.core.themes.icons = false;\n\t\t\tthis.get_container_ul().addClass(\"jstree-no-icons\");\n\t\t\t/**\n\t\t\t * triggered when icons are hidden\n\t\t\t * @event\n\t\t\t * @name hide_icons.jstree\n\t\t\t */\n\t\t\tthis.trigger('hide_icons');\n\t\t},\n\t\t/**\n\t\t * toggle the node icons\n\t\t * @name toggle_icons()\n\t\t */\n\t\ttoggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } },\n\t\t/**\n\t\t * show the node ellipsis\n\t\t * @name show_icons()\n\t\t */\n\t\tshow_ellipsis : function () {\n\t\t\tthis._data.core.themes.ellipsis = true;\n\t\t\tthis.get_container_ul().addClass(\"jstree-ellipsis\");\n\t\t\t/**\n\t\t\t * triggered when ellisis is shown\n\t\t\t * @event\n\t\t\t * @name show_ellipsis.jstree\n\t\t\t */\n\t\t\tthis.trigger('show_ellipsis');\n\t\t},\n\t\t/**\n\t\t * hide the node ellipsis\n\t\t * @name hide_ellipsis()\n\t\t */\n\t\thide_ellipsis : function () {\n\t\t\tthis._data.core.themes.ellipsis = false;\n\t\t\tthis.get_container_ul().removeClass(\"jstree-ellipsis\");\n\t\t\t/**\n\t\t\t * triggered when ellisis is hidden\n\t\t\t * @event\n\t\t\t * @name hide_ellipsis.jstree\n\t\t\t */\n\t\t\tthis.trigger('hide_ellipsis');\n\t\t},\n\t\t/**\n\t\t * toggle the node ellipsis\n\t\t * @name toggle_icons()\n\t\t */\n\t\ttoggle_ellipsis : function () { if(this._data.core.themes.ellipsis) { this.hide_ellipsis(); } else { this.show_ellipsis(); } },\n\t\t/**\n\t\t * set the node icon for a node\n\t\t * @name set_icon(obj, icon)\n\t\t * @param {mixed} obj\n\t\t * @param {String} icon the new icon - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class\n\t\t */\n\t\tset_icon : function (obj, icon) {\n\t\t\tvar t1, t2, dom, old;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.set_icon(obj[t1], icon);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj.id === $.jstree.root) { return false; }\n\t\t\told = obj.icon;\n\t\t\tobj.icon = icon === true || icon === null || icon === undefined || icon === '' ? true : icon;\n\t\t\tdom = this.get_node(obj, true).children(\".jstree-anchor\").children(\".jstree-themeicon\");\n\t\t\tif(icon === false) {\n\t\t\t\tthis.hide_icon(obj);\n\t\t\t}\n\t\t\telse if(icon === true || icon === null || icon === undefined || icon === '') {\n\t\t\t\tdom.removeClass('jstree-themeicon-custom ' + old).css(\"background\",\"\").removeAttr(\"rel\");\n\t\t\t\tif(old === false) { this.show_icon(obj); }\n\t\t\t}\n\t\t\telse if(icon.indexOf(\"/\") === -1 && icon.indexOf(\".\") === -1) {\n\t\t\t\tdom.removeClass(old).css(\"background\",\"\");\n\t\t\t\tdom.addClass(icon + ' jstree-themeicon-custom').attr(\"rel\",icon);\n\t\t\t\tif(old === false) { this.show_icon(obj); }\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdom.removeClass(old).css(\"background\",\"\");\n\t\t\t\tdom.addClass('jstree-themeicon-custom').css(\"background\", \"url('\" + icon + \"') center center no-repeat\").attr(\"rel\",icon);\n\t\t\t\tif(old === false) { this.show_icon(obj); }\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * get the node icon for a node\n\t\t * @name get_icon(obj)\n\t\t * @param {mixed} obj\n\t\t * @return {String}\n\t\t */\n\t\tget_icon : function (obj) {\n\t\t\tobj = this.get_node(obj);\n\t\t\treturn (!obj || obj.id === $.jstree.root) ? false : obj.icon;\n\t\t},\n\t\t/**\n\t\t * hide the icon on an individual node\n\t\t * @name hide_icon(obj)\n\t\t * @param {mixed} obj\n\t\t */\n\t\thide_icon : function (obj) {\n\t\t\tvar t1, t2;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.hide_icon(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj === $.jstree.root) { return false; }\n\t\t\tobj.icon = false;\n\t\t\tthis.get_node(obj, true).children(\".jstree-anchor\").children(\".jstree-themeicon\").addClass('jstree-themeicon-hidden');\n\t\t\treturn true;\n\t\t},\n\t\t/**\n\t\t * show the icon on an individual node\n\t\t * @name show_icon(obj)\n\t\t * @param {mixed} obj\n\t\t */\n\t\tshow_icon : function (obj) {\n\t\t\tvar t1, t2, dom;\n\t\t\tif($.isArray(obj)) {\n\t\t\t\tobj = obj.slice();\n\t\t\t\tfor(t1 = 0, t2 = obj.length; t1 < t2; t1++) {\n\t\t\t\t\tthis.show_icon(obj[t1]);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tobj = this.get_node(obj);\n\t\t\tif(!obj || obj === $.jstree.root) { return false; }\n\t\t\tdom = this.get_node(obj, true);\n\t\t\tobj.icon = dom.length ? dom.children(\".jstree-anchor\").children(\".jstree-themeicon\").attr('rel') : true;\n\t\t\tif(!obj.icon) { obj.icon = true; }\n\t\t\tdom.children(\".jstree-anchor\").children(\".jstree-themeicon\").removeClass('jstree-themeicon-hidden');\n\t\t\treturn true;\n\t\t}\n\t};\n\n\t// helpers\n\t$.vakata = {};\n\t// collect attributes\n\t$.vakata.attributes = function(node, with_values) {\n\t\tnode = $(node)[0];\n\t\tvar attr = with_values ? {} : [];\n\t\tif(node && node.attributes) {\n\t\t\t$.each(node.attributes, function (i, v) {\n\t\t\t\tif($.inArray(v.name.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; }\n\t\t\t\tif(v.value !== null && $.trim(v.value) !== '') {\n\t\t\t\t\tif(with_values) { attr[v.name] = v.value; }\n\t\t\t\t\telse { attr.push(v.name); }\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn attr;\n\t};\n\t$.vakata.array_unique = function(array) {\n\t\tvar a = [], i, j, l, o = {};\n\t\tfor(i = 0, l = array.length; i < l; i++) {\n\t\t\tif(o[array[i]] === undefined) {\n\t\t\t\ta.push(array[i]);\n\t\t\t\to[array[i]] = true;\n\t\t\t}\n\t\t}\n\t\treturn a;\n\t};\n\t// remove item from array\n\t$.vakata.array_remove = function(array, from) {\n\t\tarray.splice(from, 1);\n\t\treturn array;\n\t\t//var rest = array.slice((to || from) + 1 || array.length);\n\t\t//array.length = from < 0 ? array.length + from : from;\n\t\t//array.push.apply(array, rest);\n\t\t//return array;\n\t};\n\t// remove item from array\n\t$.vakata.array_remove_item = function(array, item) {\n\t\tvar tmp = $.inArray(item, array);\n\t\treturn tmp !== -1 ? $.vakata.array_remove(array, tmp) : array;\n\t};\n\t$.vakata.array_filter = function(c,a,b,d,e) {\n\t\tif (c.filter) {\n\t\t\treturn c.filter(a, b);\n\t\t}\n\t\td=[];\n\t\tfor (e in c) {\n\t\t\tif (~~e+''===e+'' && e>=0 && a.call(b,c[e],+e,c)) {\n\t\t\t\td.push(c[e]);\n\t\t\t}\n\t\t}\n\t\treturn d;\n\t};\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/jvectormap/jquery-jvectormap-world-mill-en.js",
    "content": "$.fn.vectorMap('addMap', 'world_mill_en',{\"insets\": [{\"width\": 900.0, \"top\": 0, \"height\": 440.7063107441331, \"bbox\": [{\"y\": -12671671.123330014, \"x\": -20004297.151525836}, {\"y\": 6930392.02513512, \"x\": 20026572.394749384}], \"left\": 0}], \"paths\": {\"BD\": {\"path\": \"M652.71,228.85l-0.04,1.38l-0.46,-0.21l-0.42,0.3l0.05,0.65l-0.17,-1.37l-0.48,-1.26l-1.08,-1.6l-0.23,-0.13l-2.31,-0.11l-0.31,0.36l0.21,0.98l-0.6,1.11l-0.8,-0.4l-0.37,0.09l-0.23,0.3l-0.54,-0.21l-0.78,-0.19l-0.38,-2.04l-0.83,-1.89l0.4,-1.5l-0.16,-0.35l-1.24,-0.57l0.36,-0.62l1.5,-0.95l0.02,-0.49l-1.62,-1.26l0.64,-1.31l1.7,1.0l0.12,0.04l0.96,0.11l0.19,1.62l0.25,0.26l2.38,0.37l2.32,-0.04l1.06,0.33l-0.92,1.79l-0.97,0.13l-0.23,0.16l-0.77,1.51l0.05,0.35l1.37,1.37l0.5,-0.14l0.35,-1.46l0.24,-0.0l1.24,3.92Z\", \"name\": \"Bangladesh\"}, \"BE\": {\"path\": \"M429.28,143.95l1.76,0.25l0.13,-0.01l2.16,-0.64l1.46,1.34l1.26,0.71l-0.23,1.8l-0.44,0.08l-0.24,0.25l-0.2,1.36l-1.8,-1.22l-0.23,-0.05l-1.14,0.23l-1.62,-1.43l-1.15,-1.31l-0.21,-0.1l-0.95,-0.04l-0.21,-0.68l1.66,-0.54Z\", \"name\": \"Belgium\"}, \"BF\": {\"path\": \"M413.48,260.21l-1.22,-0.46l-0.13,-0.02l-1.17,0.1l-0.15,0.06l-0.73,0.53l-0.87,-0.41l-0.39,-0.75l-0.13,-0.13l-0.98,-0.48l-0.14,-1.2l0.63,-0.99l0.05,-0.18l-0.05,-0.73l1.9,-2.01l0.08,-0.14l0.35,-1.65l0.49,-0.44l1.05,0.3l0.21,-0.02l1.05,-0.52l0.13,-0.13l0.3,-0.58l1.87,-1.1l0.11,-0.1l0.43,-0.72l2.23,-1.01l1.21,-0.32l0.51,0.4l0.19,0.06l1.25,-0.01l-0.14,0.89l0.01,0.13l0.34,1.16l0.06,0.11l1.35,1.59l0.07,1.13l0.24,0.28l2.64,0.53l-0.05,1.39l-0.42,0.59l-1.11,0.21l-0.22,0.17l-0.46,0.99l-0.69,0.23l-2.12,-0.05l-1.14,-0.2l-0.19,0.03l-0.72,0.36l-1.07,-0.17l-4.35,0.12l-0.29,0.29l-0.06,1.44l0.25,1.45Z\", \"name\": \"Burkina Faso\"}, \"BG\": {\"path\": \"M477.63,166.84l0.51,0.9l0.33,0.14l0.9,-0.21l1.91,0.47l3.68,0.16l0.17,-0.05l1.2,-0.75l2.78,-0.67l1.72,1.05l1.02,0.24l-0.97,0.97l-0.91,2.17l0.0,0.24l0.56,1.19l-1.58,-0.3l-0.16,0.01l-2.55,0.95l-0.2,0.28l-0.02,1.23l-1.92,0.24l-1.68,-0.99l-0.27,-0.02l-1.94,0.8l-1.52,-0.07l-0.15,-1.72l-0.12,-0.21l-0.99,-0.76l0.18,-0.18l0.02,-0.39l-0.17,-0.22l0.33,-0.75l0.91,-0.91l0.01,-0.42l-1.16,-1.25l-0.18,-0.89l0.24,-0.27Z\", \"name\": \"Bulgaria\"}, \"BA\": {\"path\": \"M468.39,164.66l0.16,0.04l0.43,-0.0l-0.43,0.93l0.06,0.34l1.08,1.06l-0.28,1.09l-0.5,0.13l-0.47,0.28l-0.86,0.74l-0.1,0.16l-0.28,1.29l-1.81,-0.94l-0.9,-1.22l-1.0,-0.73l-1.1,-1.1l-0.55,-0.96l-1.11,-1.3l0.3,-0.75l0.59,0.46l0.42,-0.04l0.46,-0.54l1.0,-0.06l2.11,0.5l1.72,-0.03l1.06,0.64Z\", \"name\": \"Bosnia and Herzegovina\"}, \"BN\": {\"path\": \"M707.34,273.57l0.76,-0.72l1.59,-1.03l-0.18,1.93l-0.9,-0.06l-0.28,0.14l-0.31,0.51l-0.68,-0.78Z\", \"name\": \"Brunei\"}, \"BO\": {\"path\": \"M263.83,340.79l-0.23,-0.12l-2.86,-0.11l-0.28,0.17l-0.77,1.67l-1.17,-1.51l-0.18,-0.11l-3.28,-0.64l-0.28,0.1l-2.02,2.3l-1.43,0.29l-0.91,-3.35l-1.31,-2.88l0.75,-2.41l-0.09,-0.32l-1.23,-1.03l-0.31,-1.76l-0.05,-0.12l-1.12,-1.6l1.49,-2.62l0.01,-0.28l-1.0,-2.0l0.48,-0.72l0.02,-0.29l-0.37,-0.78l0.87,-1.13l0.06,-0.18l0.05,-2.17l0.12,-1.71l0.5,-0.8l0.01,-0.3l-1.9,-3.58l1.3,0.15l1.34,-0.05l0.23,-0.12l0.51,-0.7l2.12,-0.99l1.31,-0.93l2.81,-0.37l-0.21,1.51l0.01,0.13l0.29,0.91l-0.19,1.64l0.11,0.27l2.72,2.27l0.15,0.07l2.71,0.41l0.92,0.88l0.12,0.07l1.64,0.49l1.0,0.71l0.18,0.06l1.5,-0.02l1.24,0.64l0.1,1.31l0.05,0.14l0.44,0.68l0.02,0.73l-0.44,0.03l-0.27,0.39l0.96,2.99l0.28,0.21l4.43,0.1l-0.28,1.12l0.0,0.15l0.27,1.02l0.15,0.19l1.27,0.67l0.52,1.42l-0.42,1.91l-0.66,1.1l-0.04,0.2l0.21,1.3l-0.19,0.13l-0.01,-0.27l-0.15,-0.24l-2.33,-1.33l-0.14,-0.04l-2.38,-0.03l-4.36,0.76l-0.21,0.16l-1.2,2.29l-0.03,0.13l-0.06,1.37l-0.79,2.53l-0.05,-0.08Z\", \"name\": \"Bolivia\"}, \"JP\": {\"path\": \"M781.17,166.78l1.8,0.67l0.28,-0.04l1.38,-1.01l0.43,2.67l-3.44,0.77l-0.18,0.12l-2.04,2.79l-3.71,-1.94l-0.42,0.15l-1.29,3.11l-2.32,0.04l-0.3,-2.63l1.12,-2.1l2.51,-0.16l0.28,-0.25l0.73,-4.22l0.58,-1.9l2.59,2.84l2.0,1.1ZM773.66,187.36l-0.92,2.24l-0.01,0.2l0.4,1.3l-1.18,1.81l-3.06,1.28l-4.35,0.17l-0.19,0.08l-3.4,3.06l-1.36,-0.87l-0.1,-1.95l-0.34,-0.28l-4.35,0.62l-2.99,1.33l-2.87,0.05l-0.28,0.2l0.09,0.33l2.37,1.93l-1.57,4.44l-1.35,0.97l-0.9,-0.79l0.57,-2.32l-0.15,-0.34l-1.5,-0.77l-0.81,-1.53l2.04,-0.75l0.14,-0.1l1.28,-1.72l2.47,-1.43l1.84,-1.92l4.83,-0.82l2.62,0.57l0.33,-0.16l2.45,-4.77l1.38,1.14l0.38,0.0l5.1,-4.02l0.09,-0.11l1.57,-3.57l0.02,-0.16l-0.42,-3.22l0.94,-1.67l2.27,-0.47l1.26,3.82l-0.07,2.23l-2.26,2.86l-0.06,0.19l0.04,2.93ZM757.85,196.18l0.22,0.66l-1.11,1.33l-0.8,-0.7l-0.33,-0.04l-1.28,0.65l-0.14,0.15l-0.54,1.34l-1.17,-0.57l0.02,-1.03l1.2,-1.45l1.24,0.28l0.29,-0.1l0.9,-1.03l1.51,0.5Z\", \"name\": \"Japan\"}, \"BI\": {\"path\": \"M494.7,295.83l-0.14,-2.71l-0.04,-0.13l-0.34,-0.62l0.93,0.12l0.3,-0.16l0.67,-1.25l0.9,0.11l0.11,0.76l0.08,0.16l0.46,0.48l0.02,0.56l-0.55,0.48l-0.96,1.29l-0.82,0.82l-0.61,0.07Z\", \"name\": \"Burundi\"}, \"BJ\": {\"path\": \"M427.4,268.94l-1.58,0.22l-0.52,-1.45l0.11,-5.73l-0.08,-0.21l-0.43,-0.44l-0.09,-1.13l-0.09,-0.19l-1.52,-1.52l0.24,-1.01l0.7,-0.23l0.18,-0.16l0.45,-0.97l1.07,-0.21l0.19,-0.12l0.53,-0.73l0.73,-0.65l0.68,-0.0l1.69,1.3l-0.08,0.67l0.02,0.14l0.52,1.38l-0.44,0.9l-0.01,0.24l0.2,0.52l-1.1,1.42l-0.76,0.76l-0.08,0.13l-0.47,1.59l0.05,1.69l-0.13,3.79Z\", \"name\": \"Benin\"}, \"BT\": {\"path\": \"M650.38,213.78l0.88,0.75l-0.13,1.24l-1.77,0.07l-2.1,-0.18l-1.57,0.4l-2.02,-0.91l-0.02,-0.24l1.54,-1.87l1.18,-0.6l1.67,0.59l1.32,0.08l1.01,0.67Z\", \"name\": \"Bhutan\"}, \"JM\": {\"path\": \"M226.67,238.37l1.64,0.23l1.2,0.56l0.11,0.19l-1.25,0.03l-0.14,0.04l-0.65,0.37l-1.24,-0.37l-1.17,-0.77l0.11,-0.22l0.86,-0.15l0.52,0.08Z\", \"name\": \"Jamaica\"}, \"BW\": {\"path\": \"M484.91,331.96l0.53,0.52l0.82,1.53l2.83,2.86l0.14,0.08l0.85,0.22l0.03,0.81l0.74,1.66l0.21,0.17l1.87,0.39l1.17,0.87l-3.13,1.71l-2.3,2.01l-0.07,0.1l-0.82,1.74l-0.66,0.88l-1.24,0.19l-0.24,0.2l-0.65,1.98l-1.4,0.55l-1.9,-0.12l-1.2,-0.74l-1.06,-0.32l-0.22,0.02l-1.22,0.62l-0.14,0.14l-0.58,1.21l-1.16,0.79l-1.18,1.13l-1.5,0.23l-0.4,-0.68l0.22,-1.53l-0.04,-0.19l-1.48,-2.54l-0.11,-0.11l-0.53,-0.31l-0.0,-7.25l2.18,-0.08l0.29,-0.3l0.07,-9.0l1.63,-0.08l3.69,-0.86l0.84,0.93l0.38,0.05l1.53,-0.97l0.79,-0.03l1.3,-0.53l0.23,0.1l0.92,1.96Z\", \"name\": \"Botswana\"}, \"BR\": {\"path\": \"M259.49,274.87l1.42,0.25l1.97,0.62l0.28,-0.05l0.67,-0.55l1.76,-0.38l2.8,-0.94l0.12,-0.08l0.92,-0.96l0.05,-0.33l-0.15,-0.32l0.73,-0.06l0.36,0.35l-0.27,0.93l0.17,0.36l0.76,0.34l0.44,0.9l-0.58,0.73l-0.06,0.13l-0.4,2.13l0.03,0.19l0.62,1.22l0.17,1.11l0.11,0.19l1.54,1.18l0.15,0.06l1.23,0.12l0.29,-0.15l0.2,-0.36l0.71,-0.11l1.13,-0.44l0.79,-0.63l1.25,0.19l0.65,-0.08l1.32,0.2l0.32,-0.18l0.23,-0.51l-0.05,-0.31l-0.31,-0.37l0.11,-0.31l0.75,0.17l0.13,0.0l1.1,-0.24l1.34,0.5l1.08,0.51l0.33,-0.05l0.67,-0.58l0.27,0.05l0.28,0.57l0.31,0.17l1.2,-0.18l0.17,-0.08l1.03,-1.05l0.76,-1.82l1.39,-2.16l0.49,-0.07l0.52,1.17l1.4,4.37l0.2,0.2l1.14,0.35l0.05,1.39l-1.8,1.97l0.01,0.42l0.78,0.75l0.18,0.08l4.16,0.37l0.08,2.25l0.5,0.22l1.78,-1.54l2.98,0.85l4.07,1.5l1.07,1.28l-0.37,1.23l0.36,0.38l2.83,-0.75l4.8,1.3l3.75,-0.09l3.6,2.02l3.27,2.84l1.93,0.72l2.13,0.11l0.76,0.66l1.22,4.56l-0.96,4.03l-1.22,1.58l-3.52,3.51l-1.63,2.91l-1.75,2.09l-0.5,0.04l-0.26,0.19l-0.72,1.99l0.18,4.76l-0.95,5.56l-0.74,0.96l-0.06,0.15l-0.43,3.39l-2.49,3.34l-0.06,0.13l-0.4,2.56l-1.9,1.07l-0.13,0.16l-0.51,1.38l-2.59,0.0l-3.94,1.01l-1.82,1.19l-2.85,0.81l-3.01,2.17l-2.12,2.65l-0.06,0.13l-0.36,2.0l0.01,0.13l0.4,1.42l-0.45,2.63l-0.53,1.23l-1.76,1.53l-2.76,4.79l-2.16,2.15l-1.69,1.29l-0.09,0.12l-1.12,2.6l-1.3,1.26l-0.45,-1.02l0.99,-1.18l0.01,-0.37l-1.5,-1.95l-1.98,-1.54l-2.58,-1.77l-0.2,-0.05l-0.81,0.07l-2.42,-2.05l-0.25,-0.07l-0.77,0.14l2.75,-3.07l2.8,-2.61l1.67,-1.09l2.11,-1.49l0.13,-0.24l0.05,-2.15l-0.07,-0.2l-1.26,-1.54l-0.35,-0.09l-0.64,0.27l0.3,-0.95l0.34,-1.57l0.01,-1.52l-0.16,-0.26l-0.9,-0.48l-0.27,-0.01l-0.86,0.39l-0.65,-0.08l-0.23,-0.8l-0.23,-2.39l-0.04,-0.12l-0.47,-0.79l-0.14,-0.12l-1.69,-0.71l-0.25,0.01l-0.93,0.47l-2.29,-0.44l0.15,-3.3l-0.03,-0.15l-0.62,-1.22l0.57,-0.39l0.13,-0.3l-0.22,-1.37l0.67,-1.13l0.44,-2.04l-0.01,-0.17l-0.59,-1.61l-0.14,-0.16l-1.25,-0.66l-0.22,-0.82l0.35,-1.41l-0.28,-0.37l-4.59,-0.1l-0.78,-2.41l0.34,-0.02l0.28,-0.31l-0.03,-1.1l-0.05,-0.16l-0.45,-0.68l-0.1,-1.4l-0.16,-0.24l-1.45,-0.76l-0.14,-0.03l-1.48,0.02l-1.04,-0.73l-1.62,-0.48l-0.93,-0.9l-0.16,-0.08l-2.72,-0.41l-2.53,-2.12l0.18,-1.54l-0.01,-0.13l-0.29,-0.91l0.26,-1.83l-0.34,-0.34l-3.28,0.43l-0.14,0.05l-1.3,0.93l-2.16,1.01l-0.12,0.09l-0.47,0.65l-1.12,0.05l-1.84,-0.21l-0.12,0.01l-1.33,0.41l-0.82,-0.21l0.16,-3.6l-0.48,-0.26l-1.97,1.43l-1.96,-0.06l-0.86,-1.23l-0.22,-0.13l-1.23,-0.11l0.34,-0.69l-0.05,-0.33l-1.36,-1.5l-0.92,-2.0l0.45,-0.32l0.13,-0.25l-0.0,-0.87l1.34,-0.64l0.17,-0.32l-0.23,-1.23l0.56,-0.77l0.05,-0.13l0.16,-1.03l2.7,-1.61l2.01,-0.47l0.16,-0.09l0.24,-0.27l2.11,0.11l0.31,-0.25l1.13,-6.87l0.06,-1.12l-0.4,-1.53l-0.1,-0.15l-1.0,-0.82l0.01,-1.45l1.08,-0.32l0.39,0.2l0.44,-0.24l0.08,-0.96l-0.25,-0.32l-1.22,-0.22l-0.02,-1.01l4.57,0.05l0.22,-0.09l0.6,-0.63l0.44,0.5l0.47,1.42l0.45,0.16l0.27,-0.18l1.21,1.16l0.23,0.08l1.95,-0.16l0.23,-0.14l0.43,-0.67l1.76,-0.55l1.05,-0.42l0.18,-0.2l0.25,-0.92l1.65,-0.66l0.18,-0.35l-0.14,-0.53l-0.26,-0.22l-1.91,-0.19l-0.29,-1.33l0.1,-1.64l-0.15,-0.28l-0.44,-0.25Z\", \"name\": \"Brazil\"}, \"BS\": {\"path\": \"M227.51,216.69l0.3,0.18l-0.24,1.07l0.03,-1.04l-0.09,-0.21ZM226.5,224.03l-0.13,0.03l-0.54,-1.3l-0.09,-0.12l-0.78,-0.64l0.4,-1.26l0.33,0.05l0.79,2.0l0.01,1.24ZM225.76,216.5l-2.16,0.34l-0.07,-0.41l0.85,-0.16l1.36,0.07l0.02,0.16Z\", \"name\": \"The Bahamas\"}, \"BY\": {\"path\": \"M480.08,135.28l2.09,0.02l0.13,-0.03l2.72,-1.3l0.16,-0.19l0.55,-1.83l1.94,-1.06l0.15,-0.31l-0.2,-1.33l1.33,-0.52l2.58,-1.3l2.39,0.8l0.3,0.75l0.37,0.17l1.22,-0.39l2.18,0.75l0.2,1.36l-0.48,0.85l0.01,0.32l1.57,2.26l0.92,0.6l-0.1,0.41l0.19,0.35l1.61,0.57l0.48,0.6l-0.64,0.49l-1.91,-0.11l-0.18,0.05l-0.48,0.32l-0.1,0.39l0.57,1.1l0.51,1.78l-1.79,0.17l-0.18,0.08l-0.77,0.73l-0.09,0.19l-0.13,1.31l-0.75,-0.22l-2.11,0.15l-0.56,-0.66l-0.39,-0.06l-0.8,0.49l-0.79,-0.4l-0.13,-0.03l-1.94,-0.07l-2.76,-0.79l-2.58,-0.27l-1.98,0.07l-0.15,0.05l-1.31,0.86l-0.8,0.09l-0.04,-1.16l-0.03,-0.12l-0.63,-1.28l1.22,-0.56l0.17,-0.27l0.01,-1.35l-0.04,-0.15l-0.66,-1.24l-0.08,-1.12Z\", \"name\": \"Belarus\"}, \"BZ\": {\"path\": \"M198.03,239.7l0.28,0.19l0.43,-0.1l0.82,-1.42l0.0,0.07l0.29,0.29l0.16,0.0l-0.02,0.35l-0.39,1.08l0.02,0.25l0.16,0.29l-0.23,0.8l0.04,0.24l0.09,0.14l-0.25,1.12l-0.38,0.53l-0.33,0.06l-0.21,0.15l-0.41,0.74l-0.25,0.0l0.17,-2.58l0.01,-2.2Z\", \"name\": \"Belize\"}, \"RU\": {\"path\": \"M688.57,38.85l0.63,2.39l0.44,0.19l2.22,-1.23l7.18,0.07l5.54,2.49l1.85,1.77l-0.55,2.34l-2.64,1.42l-6.57,2.76l-1.95,1.5l0.12,0.53l3.09,0.68l3.69,1.23l0.21,-0.01l1.98,-0.81l1.16,2.84l0.5,0.08l1.03,-1.18l3.86,-0.74l7.79,0.78l0.56,2.05l0.27,0.22l10.47,0.71l0.32,-0.29l0.13,-3.34l4.98,0.8l3.96,-0.02l3.88,2.43l1.06,2.79l-1.38,1.83l0.01,0.38l3.15,3.64l0.1,0.08l3.94,1.86l0.4,-0.14l2.28,-4.56l3.75,1.94l0.22,0.02l4.18,-1.22l4.76,1.4l0.26,-0.04l1.74,-1.23l3.98,0.63l0.32,-0.41l-1.71,-4.1l3.0,-1.86l22.39,3.04l2.06,2.67l0.1,0.08l6.55,3.51l0.17,0.03l10.08,-0.86l4.86,0.73l1.91,1.72l-0.29,3.13l0.18,0.31l3.08,1.26l0.19,0.01l3.32,-0.9l4.37,-0.11l4.78,0.87l4.61,-0.48l4.26,3.82l0.32,0.05l3.1,-1.4l0.12,-0.45l-1.91,-2.67l0.92,-1.64l7.78,1.22l5.22,-0.26l7.12,2.1l9.6,5.22l6.4,4.15l-0.2,2.44l0.14,0.28l1.69,1.04l0.45,-0.31l-0.51,-2.66l6.31,0.58l4.52,3.61l-2.1,1.52l-4.02,0.42l-0.27,0.29l-0.06,3.83l-0.81,0.67l-2.14,-0.11l-1.91,-1.39l-3.19,-1.13l-0.51,-1.63l-0.21,-0.2l-2.54,-0.67l-0.13,-0.0l-2.69,0.5l-1.12,-1.19l0.48,-1.36l-0.38,-0.39l-3.0,0.98l-0.17,0.44l1.02,1.76l-1.27,1.55l-3.09,1.71l-3.15,-0.29l-0.3,0.18l0.07,0.34l2.22,2.1l1.47,3.22l1.15,1.09l0.25,1.41l-0.48,0.76l-4.47,-0.81l-0.17,0.02l-6.97,2.9l-2.2,0.44l-0.11,0.05l-3.83,2.68l-3.63,2.32l-0.1,0.11l-0.76,1.4l-3.3,-2.4l-0.3,-0.03l-6.31,2.85l-0.99,-1.21l-0.4,-0.06l-2.32,1.54l-3.23,-0.49l-0.33,0.2l-0.79,2.39l-2.97,3.51l-0.07,0.21l0.09,1.47l0.22,0.27l2.62,0.74l-0.3,4.7l-2.06,0.12l-0.26,0.2l-1.07,2.94l0.04,0.27l0.83,1.19l-4.03,1.63l-0.18,0.21l-0.83,3.72l-3.55,0.79l-0.23,0.23l-0.73,3.32l-3.22,2.76l-0.76,-1.88l-1.07,-4.88l-1.39,-7.59l1.17,-4.76l2.05,-2.08l0.09,-0.19l0.11,-1.46l3.67,-0.77l0.15,-0.08l4.47,-4.61l4.29,-3.82l4.48,-3.01l0.11,-0.14l2.01,-5.43l-0.31,-0.4l-3.04,0.33l-0.24,0.17l-1.47,3.11l-5.98,3.94l-1.91,-4.36l-0.33,-0.17l-6.46,1.3l-0.15,0.08l-6.27,6.33l-0.01,0.41l1.7,1.87l-5.04,0.87l-3.51,0.34l0.16,-2.32l-0.26,-0.32l-3.89,-0.56l-0.19,0.04l-3.02,1.77l-7.63,-0.63l-8.24,1.1l-0.16,0.07l-8.11,7.09l-9.6,8.31l0.16,0.52l3.79,0.42l1.16,2.03l0.17,0.14l2.43,0.76l0.31,-0.08l1.5,-1.61l2.49,0.2l3.46,3.6l0.08,2.67l-1.91,3.26l-0.04,0.14l-0.21,3.91l-1.11,5.09l-3.73,4.55l-0.87,2.21l-6.73,7.14l-1.59,1.77l-3.23,1.72l-1.38,0.03l-1.48,-1.39l-0.37,-0.03l-3.36,2.22l-0.11,0.14l-0.16,0.42l-0.01,-1.09l1.0,-0.06l0.28,-0.27l0.36,-3.6l-0.61,-2.51l1.85,-0.94l2.94,0.53l0.32,-0.15l1.71,-3.1l0.84,-3.38l0.97,-1.18l1.32,-2.88l-0.34,-0.42l-4.14,0.95l-2.18,1.25l-3.51,-0.0l-0.95,-2.81l-0.1,-0.14l-2.97,-2.3l-0.11,-0.05l-4.19,-1.0l-0.89,-3.08l-0.87,-2.03l-0.95,-1.46l-1.54,-3.37l-0.12,-0.14l-2.27,-1.28l-3.83,-1.02l-3.37,0.1l-3.11,0.61l-0.13,0.06l-2.07,1.69l0.04,0.49l1.23,0.72l0.03,1.53l-1.34,1.05l-2.26,3.51l-0.05,0.17l0.02,1.27l-3.25,1.9l-2.87,-1.17l-0.14,-0.02l-2.86,0.26l-1.22,-1.02l-0.12,-0.06l-1.5,-0.35l-0.23,0.04l-3.62,2.27l-3.24,0.53l-2.28,0.79l-3.08,-0.51l-2.24,0.03l-1.49,-1.61l-2.45,-1.57l-0.11,-0.04l-2.6,-0.43l-3.17,0.43l-2.31,0.59l-3.31,-1.28l-0.45,-2.31l-0.21,-0.23l-2.94,-0.85l-2.26,-0.39l-2.77,-1.36l-0.37,0.09l-2.59,3.45l-0.03,0.32l0.91,1.74l-2.15,2.01l-3.47,-0.79l-2.44,-0.12l-1.59,-1.46l-0.2,-0.08l-2.55,-0.05l-2.12,-0.98l-0.24,-0.01l-3.85,1.57l-4.74,2.79l-2.59,0.55l-0.79,0.21l-1.21,-1.81l-0.29,-0.13l-3.05,0.41l-0.96,-1.25l-0.14,-0.1l-1.65,-0.6l-1.15,-1.82l-0.13,-0.12l-1.38,-0.6l-0.19,-0.02l-3.49,0.82l-3.35,-1.85l-0.38,0.08l-1.08,1.4l-5.36,-8.17l-3.02,-2.52l0.72,-0.85l0.01,-0.38l-0.37,-0.08l-6.22,3.21l-1.98,0.16l0.17,-1.51l-0.2,-0.31l-3.22,-1.17l-0.19,-0.0l-2.3,0.74l-0.72,-3.27l-0.24,-0.23l-4.5,-0.75l-0.21,0.04l-2.2,1.42l-6.21,1.27l-0.11,0.05l-1.16,0.81l-9.3,1.19l-0.18,0.09l-1.15,1.17l-0.02,0.39l1.56,2.01l-2.02,0.74l-0.16,0.42l0.35,0.68l-2.18,1.49l0.02,0.51l3.83,2.16l-0.45,1.13l-3.31,-0.13l-0.25,0.12l-0.57,0.77l-2.97,-1.59l-0.15,-0.04l-3.97,0.07l-0.13,0.03l-2.53,1.32l-2.84,-1.28l-5.52,-2.3l-0.12,-0.02l-3.91,0.09l-0.16,0.05l-5.17,3.6l-0.13,0.21l-0.25,1.89l-2.17,-1.6l-0.44,0.1l-2.0,3.59l0.06,0.37l0.55,0.5l-1.32,2.23l0.04,0.36l2.13,2.17l0.23,0.09l1.7,-0.08l1.42,1.89l-0.23,1.5l0.19,0.32l0.94,0.38l-0.89,1.44l-2.3,0.49l-0.17,0.11l-2.49,3.2l0.0,0.37l2.2,2.81l-0.23,1.93l0.06,0.22l2.56,3.32l-1.27,1.02l-0.4,0.66l-0.8,-0.15l-1.65,-1.75l-0.18,-0.09l-0.66,-0.09l-1.45,-0.64l-0.72,-1.16l-0.18,-0.13l-2.34,-0.63l-0.17,0.0l-1.32,0.41l-0.31,-0.4l-0.12,-0.09l-3.49,-1.48l-3.67,-0.49l-2.1,-0.52l-0.3,0.1l-0.12,0.14l-2.96,-2.4l-2.89,-1.19l-1.69,-1.42l1.27,-0.35l0.16,-0.1l2.08,-2.61l-0.04,-0.41l-1.02,-0.9l3.21,-1.12l0.2,-0.31l-0.07,-0.69l-0.37,-0.26l-1.86,0.42l0.05,-0.86l1.11,-0.76l2.35,-0.23l0.25,-0.19l0.39,-1.07l0.0,-0.19l-0.51,-1.64l0.95,-1.58l0.04,-0.16l-0.03,-0.95l-0.22,-0.28l-3.69,-1.06l-1.43,0.02l-1.45,-1.44l-0.29,-0.08l-1.83,0.49l-2.88,-1.04l0.04,-0.42l-0.04,-0.18l-0.89,-1.43l-0.23,-0.14l-1.77,-0.14l-0.13,-0.66l0.52,-0.56l0.01,-0.4l-1.6,-1.9l-0.27,-0.1l-2.55,0.32l-0.71,-0.16l-0.3,0.1l-0.53,0.63l-0.58,-0.08l-0.56,-1.97l-0.48,-0.94l0.17,-0.11l1.92,0.11l0.2,-0.06l0.97,-0.74l0.05,-0.42l-0.72,-0.91l-0.13,-0.1l-1.43,-0.51l0.09,-0.36l-0.13,-0.33l-0.97,-0.59l-1.43,-2.06l0.44,-0.77l0.04,-0.19l-0.25,-1.64l-0.2,-0.24l-2.45,-0.84l-0.19,-0.0l-1.05,0.34l-0.25,-0.62l-0.18,-0.17l-2.5,-0.84l-0.74,-1.93l-0.21,-1.7l-0.13,-0.21l-0.92,-0.63l0.83,-0.89l0.07,-0.27l-0.71,-3.26l1.69,-2.01l0.03,-0.34l-0.24,-0.41l2.63,-1.9l-0.01,-0.49l-2.31,-1.57l5.08,-4.61l2.33,-2.24l1.01,-2.08l-0.09,-0.37l-3.52,-2.56l0.94,-2.38l-0.04,-0.29l-2.14,-2.86l1.61,-3.35l-0.01,-0.29l-2.81,-4.58l2.19,-3.04l-0.06,-0.42l-3.7,-2.76l0.32,-2.67l1.87,-0.38l4.26,-1.77l2.46,-1.47l3.96,2.58l0.12,0.05l6.81,1.04l9.37,4.87l1.81,1.92l0.15,2.55l-2.61,2.06l-3.95,1.07l-11.1,-3.15l-0.17,0.0l-1.84,0.53l-0.1,0.53l3.97,2.97l0.15,1.77l0.16,4.14l0.19,0.27l3.21,1.22l1.94,1.03l0.44,-0.22l0.32,-1.94l-0.07,-0.25l-1.32,-1.52l1.25,-1.2l5.87,2.45l0.24,-0.01l2.11,-0.98l0.13,-0.42l-1.55,-2.75l5.52,-3.84l2.13,0.22l2.28,1.42l0.43,-0.12l1.46,-2.87l-0.04,-0.33l-1.97,-2.37l1.14,-2.38l-0.02,-0.3l-1.42,-2.07l6.15,1.22l1.14,1.92l-2.74,0.46l-0.25,0.3l0.02,2.36l0.12,0.24l1.97,1.44l0.25,0.05l3.87,-0.91l0.22,-0.23l0.58,-2.55l5.09,-1.98l8.67,-3.69l1.22,0.14l-2.06,2.2l0.18,0.5l3.11,0.45l0.23,-0.07l1.71,-1.41l4.59,-0.12l0.12,-0.03l3.53,-1.72l2.7,2.48l0.42,-0.01l2.85,-2.88l-0.0,-0.43l-2.42,-2.35l1.0,-1.13l7.2,1.31l3.42,1.36l9.06,4.97l0.39,-0.08l1.67,-2.27l-0.04,-0.4l-2.46,-2.23l-0.06,-0.82l-0.26,-0.27l-2.64,-0.38l0.69,-1.76l0.0,-0.22l-1.32,-3.47l-0.07,-1.27l4.52,-4.09l0.08,-0.11l1.6,-4.18l1.67,-0.84l6.33,1.2l0.46,2.31l-2.31,3.67l0.05,0.38l1.49,1.41l0.77,3.04l-0.56,6.05l0.09,0.24l2.62,2.54l-0.99,2.65l-4.87,5.96l0.17,0.48l2.86,0.61l0.31,-0.13l0.94,-1.42l2.67,-1.04l0.18,-0.19l0.64,-2.01l2.11,-1.98l0.05,-0.37l-1.38,-2.32l1.11,-2.74l-0.24,-0.41l-2.53,-0.33l-0.53,-2.16l1.96,-4.42l-0.05,-0.32l-3.03,-3.48l4.21,-2.94l0.12,-0.3l-0.52,-3.04l0.72,-0.06l1.18,2.35l-0.97,4.39l0.2,0.35l2.68,0.84l0.37,-0.38l-1.05,-3.07l3.89,-1.71l5.05,-0.24l4.55,2.62l0.36,-0.05l0.05,-0.36l-2.19,-3.84l-0.23,-4.78l4.07,-0.92l5.98,0.21l5.47,-0.64l0.2,-0.48l-1.88,-2.37l2.65,-2.99l2.75,-0.13l0.12,-0.03l4.82,-2.48l6.56,-0.67l0.23,-0.14l0.76,-1.27l6.33,-0.46l1.97,1.11l0.28,0.01l5.55,-2.71l4.53,0.08l0.29,-0.21l0.67,-2.18l2.29,-2.15l5.75,-2.13l3.48,1.4l-2.7,1.03l-0.19,0.31l0.26,0.26l5.47,0.78ZM871.83,65.73l0.25,-0.15l1.99,0.01l3.3,1.2l-0.08,0.22l-2.41,1.03l-5.73,0.49l-0.31,-1.0l2.99,-1.8ZM797.64,48.44l-2.22,1.51l-3.85,-0.43l-4.35,-1.85l0.42,-1.13l4.42,0.72l5.59,1.17ZM783.82,46.06l-1.71,3.25l-9.05,-0.14l-4.11,1.15l-4.64,-3.04l1.21,-3.13l3.11,-0.91l6.53,0.22l8.66,2.59ZM780.37,145.71l2.28,5.23l-3.09,-0.89l-0.37,0.19l-1.54,4.65l0.04,0.27l2.38,3.17l-0.05,1.4l-1.41,-1.41l-0.46,0.04l-1.23,1.81l-0.33,-1.86l0.28,-3.1l-0.28,-3.41l0.58,-2.46l0.11,-4.39l-0.03,-0.13l-1.44,-3.2l0.21,-4.39l2.19,-1.49l0.09,-0.41l-0.81,-1.3l0.48,-0.21l0.56,1.94l0.86,3.23l-0.05,3.36l1.03,3.35ZM780.16,57.18l-3.4,0.03l-5.06,-0.53l1.97,-1.59l2.95,-0.42l3.35,1.75l0.18,0.77ZM683.84,31.18l-13.29,1.97l4.16,-6.56l1.88,-0.58l1.77,0.34l6.08,3.02l-0.6,1.8ZM670.94,28.02l-5.18,0.65l-6.89,-1.58l-4.03,-2.07l-1.88,-3.98l-0.18,-0.16l-2.8,-0.93l5.91,-3.62l5.25,-1.29l4.73,2.88l5.63,5.44l-0.57,4.66ZM564.37,68.98l-0.85,0.23l-7.93,-0.57l-0.6,-1.84l-0.21,-0.2l-4.34,-1.18l-0.3,-2.08l2.34,-0.92l0.19,-0.29l-0.08,-2.43l4.85,-4.0l-0.12,-0.52l-1.68,-0.43l5.47,-3.94l0.11,-0.33l-0.6,-2.02l5.36,-2.55l8.22,-3.27l8.29,-0.96l4.34,-1.94l4.67,-0.65l1.45,1.72l-1.43,1.37l-8.8,2.52l-7.65,2.42l-7.92,4.84l-3.73,4.75l-3.92,4.58l-0.07,0.23l0.51,3.88l0.11,0.2l4.32,3.39ZM548.86,18.57l-3.28,0.75l-2.25,0.44l-0.22,0.19l-0.3,0.81l-2.67,0.86l-2.27,-1.14l1.2,-1.51l-0.23,-0.49l-3.14,-0.1l2.48,-0.54l3.55,-0.07l0.44,1.36l0.49,0.12l1.4,-1.35l2.2,-0.9l3.13,1.08l-0.54,0.49ZM477.5,133.25l-4.21,0.05l-2.69,-0.34l0.39,-1.03l3.24,-1.06l2.51,0.58l0.85,0.43l-0.2,0.71l-0.0,0.15l0.12,0.52Z\", \"name\": \"Russia\"}, \"RW\": {\"path\": \"M497.03,288.12l0.78,1.11l-0.12,1.19l-0.49,0.21l-1.25,-0.15l-0.3,0.16l-0.67,1.24l-1.01,-0.13l0.16,-0.92l0.22,-0.12l0.15,-0.24l0.09,-1.37l0.49,-0.48l0.42,0.18l0.25,-0.01l1.26,-0.65Z\", \"name\": \"Rwanda\"}, \"RS\": {\"path\": \"M469.75,168.65l0.21,-0.21l0.36,-1.44l-0.08,-0.29l-1.06,-1.03l0.54,-1.16l-0.28,-0.43l-0.26,0.0l0.55,-0.67l-0.01,-0.39l-0.77,-0.86l-0.45,-0.89l1.56,-0.67l1.39,0.12l1.22,1.1l0.26,0.91l0.16,0.19l1.38,0.66l0.17,1.12l0.14,0.21l1.46,0.9l0.35,-0.03l0.62,-0.54l0.09,0.06l-0.28,0.25l-0.03,0.42l0.29,0.34l-0.44,0.5l-0.07,0.26l0.22,1.12l0.07,0.14l1.02,1.1l-0.81,0.84l-0.42,0.96l0.04,0.3l0.12,0.15l-0.15,0.16l-1.04,0.04l-0.39,0.08l0.33,-0.81l-0.29,-0.41l-0.21,0.01l-0.39,-0.45l-0.13,-0.09l-0.32,-0.11l-0.27,-0.4l-0.14,-0.11l-0.4,-0.16l-0.31,-0.37l-0.34,-0.09l-0.45,0.17l-0.18,0.18l-0.29,0.84l-0.96,-0.65l-0.81,-0.33l-0.32,-0.37l-0.22,-0.18Z\", \"name\": \"Republic of Serbia\"}, \"LT\": {\"path\": \"M478.13,133.31l-0.14,-0.63l0.25,-0.88l-0.15,-0.35l-1.17,-0.58l-2.43,-0.57l-0.45,-2.51l2.58,-0.97l4.14,0.22l2.3,-0.32l0.26,0.54l0.22,0.17l1.26,0.22l2.25,1.6l0.19,1.23l-1.87,1.01l-0.14,0.18l-0.54,1.83l-2.54,1.21l-2.18,-0.02l-0.52,-0.91l-0.18,-0.14l-1.11,-0.32Z\", \"name\": \"Lithuania\"}, \"LU\": {\"path\": \"M435.95,147.99l0.33,0.49l-0.11,1.07l-0.39,0.04l-0.29,-0.15l0.21,-1.4l0.25,-0.05Z\", \"name\": \"Luxembourg\"}, \"LR\": {\"path\": \"M401.37,273.67l-0.32,0.01l-2.48,-1.15l-2.24,-1.89l-2.14,-1.38l-1.47,-1.42l0.44,-0.59l0.05,-0.13l0.12,-0.65l1.07,-1.3l1.08,-1.09l0.52,-0.07l0.43,-0.18l0.84,1.24l-0.15,0.89l0.07,0.25l0.49,0.54l0.22,0.1l0.71,0.01l0.27,-0.16l0.42,-0.83l0.19,0.02l-0.06,0.52l0.23,1.12l-0.5,1.03l0.06,0.35l0.73,0.69l0.14,0.08l0.71,0.15l0.92,0.91l0.06,0.76l-0.17,0.22l-0.06,0.15l-0.17,1.8Z\", \"name\": \"Liberia\"}, \"RO\": {\"path\": \"M477.94,155.19l1.02,-0.64l1.49,0.33l1.52,0.01l1.09,0.73l0.32,0.01l0.81,-0.46l1.8,-0.3l0.18,-0.1l0.54,-0.64l0.86,0.0l0.64,0.26l0.71,0.87l0.8,1.35l1.39,1.81l0.07,1.25l-0.26,1.3l0.01,0.15l0.45,1.42l0.15,0.18l1.12,0.57l0.25,0.01l1.05,-0.45l0.86,0.4l0.03,0.43l-0.92,0.51l-0.63,-0.24l-0.4,0.22l-0.64,3.41l-1.12,-0.24l-1.78,-1.09l-0.23,-0.04l-2.95,0.71l-1.25,0.77l-3.55,-0.16l-1.89,-0.47l-0.14,-0.0l-0.75,0.17l-0.61,-1.07l-0.3,-0.36l0.36,-0.32l-0.04,-0.48l-0.62,-0.38l-0.36,0.03l-0.62,0.54l-1.15,-0.71l-0.18,-1.14l-0.17,-0.22l-1.4,-0.67l-0.24,-0.86l-0.09,-0.14l-0.96,-0.87l1.49,-0.44l0.16,-0.11l1.51,-2.14l1.15,-2.09l1.44,-0.63Z\", \"name\": \"Romania\"}, \"GW\": {\"path\": \"M383.03,256.73l-1.12,-0.88l-0.14,-0.06l-0.94,-0.15l-0.43,-0.54l0.01,-0.27l-0.13,-0.26l-0.68,-0.48l-0.05,-0.16l0.99,-0.31l0.77,0.08l0.15,-0.02l0.61,-0.26l4.25,0.1l-0.02,0.44l-0.19,0.18l-0.08,0.29l0.17,0.66l-0.17,0.14l-0.44,0.0l-0.16,0.05l-0.57,0.37l-0.66,-0.04l-0.24,0.1l-0.92,1.03Z\", \"name\": \"Guinea Bissau\"}, \"GT\": {\"path\": \"M195.13,249.89l-1.05,-0.35l-1.5,-0.04l-1.06,-0.47l-1.19,-0.93l0.04,-0.53l0.27,-0.55l-0.03,-0.31l-0.24,-0.32l1.02,-1.77l3.04,-0.01l0.3,-0.28l0.06,-0.88l-0.19,-0.3l-0.3,-0.11l-0.23,-0.45l-0.11,-0.12l-0.9,-0.58l-0.35,-0.33l0.37,-0.0l0.3,-0.3l0.0,-1.15l4.05,0.02l-0.02,1.74l-0.2,2.89l0.3,0.32l0.67,-0.0l0.75,0.42l0.4,-0.11l-0.62,0.53l-1.17,0.7l-0.13,0.16l-0.18,0.49l0.0,0.21l0.14,0.34l-0.35,0.44l-0.49,0.13l-0.2,0.41l0.03,0.06l-0.27,0.16l-0.86,0.64l-0.12,0.22ZM199.35,245.38l0.07,-0.13l0.05,0.02l-0.13,0.11Z\", \"name\": \"Guatemala\"}, \"GR\": {\"path\": \"M487.2,174.55l-0.64,1.54l-0.43,0.24l-1.41,-0.08l-1.28,-0.28l-0.14,0.0l-3.03,0.77l-0.13,0.51l1.39,1.34l-0.78,0.29l-1.2,0.0l-1.23,-1.42l-0.47,0.02l-0.47,0.65l-0.04,0.27l0.56,1.76l0.06,0.11l1.02,1.12l-0.66,0.45l-0.04,0.46l1.39,1.35l1.15,0.79l0.02,1.06l-1.91,-0.63l-0.36,0.42l0.56,1.12l-1.2,0.23l-0.22,0.4l0.8,2.14l-1.15,0.02l-1.89,-1.15l-0.89,-2.19l-0.43,-1.91l-0.05,-0.11l-0.98,-1.35l-1.24,-1.62l-0.13,-0.63l1.07,-1.32l0.06,-0.14l0.13,-0.81l0.68,-0.36l0.16,-0.25l0.03,-0.54l1.4,-0.23l0.12,-0.05l0.87,-0.6l1.26,0.05l0.25,-0.11l0.34,-0.43l0.33,-0.07l1.81,0.08l0.13,-0.02l1.87,-0.77l1.64,0.97l0.19,0.04l2.28,-0.28l0.26,-0.29l0.02,-0.95l0.56,0.36ZM480.44,192.0l1.05,0.74l0.01,0.0l-1.26,-0.23l0.2,-0.51ZM481.76,192.79l1.86,-0.15l1.53,0.17l-0.02,0.19l0.34,0.3l-2.28,0.15l0.01,-0.13l-0.25,-0.31l-1.19,-0.22ZM485.65,193.28l0.65,-0.16l-0.05,0.12l-0.6,0.04Z\", \"name\": \"Greece\"}, \"GQ\": {\"path\": \"M444.81,282.04l-0.21,-0.17l0.74,-2.4l3.56,0.05l0.02,2.42l-3.34,-0.02l-0.76,0.13Z\", \"name\": \"Equatorial Guinea\"}, \"GY\": {\"path\": \"M271.34,264.25l1.43,0.81l1.44,1.53l0.06,1.19l0.28,0.28l0.84,0.05l2.13,1.92l-0.34,1.93l-1.37,0.59l-0.17,0.34l0.12,0.51l-0.43,1.21l0.03,0.26l1.11,1.82l0.26,0.14l0.56,0.0l0.32,1.29l1.25,1.78l-0.08,0.01l-1.34,-0.21l-0.24,0.06l-0.78,0.64l-1.06,0.41l-0.76,0.1l-0.22,0.15l-0.18,0.32l-0.95,-0.1l-1.38,-1.05l-0.19,-1.13l-0.6,-1.18l0.37,-1.96l0.65,-0.83l0.03,-0.32l-0.57,-1.17l-0.15,-0.14l-0.62,-0.27l0.25,-0.85l-0.08,-0.3l-0.58,-0.58l-0.24,-0.09l-1.15,0.1l-1.41,-1.58l0.48,-0.49l0.09,-0.22l-0.04,-0.92l1.31,-0.34l0.73,-0.52l0.04,-0.44l-0.75,-0.82l0.16,-0.66l1.74,-1.3Z\", \"name\": \"Guyana\"}, \"GE\": {\"path\": \"M525.41,174.19l0.26,-0.88l-0.0,-0.17l-0.63,-2.06l-0.1,-0.15l-1.45,-1.12l-0.11,-0.05l-1.31,-0.33l-0.66,-0.69l1.97,0.48l3.65,0.49l3.3,1.41l0.39,0.5l0.33,0.1l1.43,-0.45l2.14,0.58l0.7,1.14l0.13,0.12l1.06,0.47l-0.18,0.11l-0.08,0.43l1.08,1.41l-0.06,0.06l-1.16,-0.15l-1.82,-0.84l-0.31,0.04l-0.55,0.44l-3.29,0.44l-2.32,-1.41l-0.17,-0.04l-2.25,0.12Z\", \"name\": \"Georgia\"}, \"GB\": {\"path\": \"M412.82,118.6l-2.31,3.4l-0.0,0.33l0.31,0.13l2.52,-0.49l2.34,0.02l-0.56,2.51l-2.22,3.13l0.22,0.47l2.43,0.21l2.35,4.35l0.17,0.14l1.58,0.51l1.49,3.78l0.73,1.37l0.2,0.15l2.76,0.59l-0.25,1.75l-1.18,0.91l-0.08,0.39l0.87,1.49l-1.96,1.51l-3.31,-0.02l-4.15,0.88l-1.07,-0.59l-0.35,0.04l-1.55,1.44l-2.17,-0.35l-0.22,0.05l-1.61,1.15l-0.78,-0.38l3.31,-3.12l2.18,-0.7l0.21,-0.31l-0.26,-0.27l-3.78,-0.54l-0.48,-0.9l2.3,-0.92l0.13,-0.46l-1.29,-1.71l0.39,-1.83l3.46,0.29l0.32,-0.24l0.37,-1.99l-0.06,-0.24l-1.71,-2.17l-0.18,-0.11l-2.91,-0.58l-0.43,-0.68l0.82,-1.4l-0.03,-0.35l-0.82,-0.97l-0.46,0.01l-0.85,1.05l-0.11,-2.6l-0.05,-0.16l-1.19,-1.7l0.86,-3.53l1.81,-2.75l1.88,0.26l2.38,-0.24ZM406.39,132.84l-1.09,1.92l-1.65,-0.62l-1.26,0.02l0.41,-1.46l0.0,-0.16l-0.42,-1.51l1.62,-0.11l2.39,1.92Z\", \"name\": \"United Kingdom\"}, \"GA\": {\"path\": \"M448.76,294.47l-2.38,-2.34l-1.63,-2.04l-1.46,-2.48l0.06,-0.66l0.54,-0.81l0.61,-1.82l0.46,-1.69l0.63,-0.11l3.62,0.03l0.3,-0.3l-0.02,-2.75l0.88,-0.12l1.47,0.32l0.13,0.0l1.39,-0.3l-0.13,0.87l0.03,0.19l0.7,1.29l0.3,0.16l1.74,-0.19l0.36,0.29l-1.01,2.7l0.05,0.29l1.13,1.42l0.25,1.82l-0.3,1.56l-0.64,0.99l-1.93,-0.09l-1.26,-1.13l-0.5,0.17l-0.16,0.91l-1.48,0.27l-0.12,0.05l-0.86,0.63l-0.08,0.39l0.81,1.42l-1.48,1.08Z\", \"name\": \"Gabon\"}, \"GN\": {\"path\": \"M399.83,265.31l-0.69,-0.06l-0.3,0.16l-0.43,0.85l-0.39,-0.01l-0.3,-0.33l0.14,-0.87l-0.05,-0.22l-1.05,-1.54l-0.37,-0.11l-0.61,0.27l-0.84,0.12l0.02,-0.54l-0.04,-0.17l-0.35,-0.57l0.07,-0.63l-0.03,-0.17l-0.57,-1.11l-0.7,-0.9l-0.24,-0.12l-2.0,-0.0l-0.19,0.07l-0.51,0.42l-0.6,0.05l-0.21,0.11l-0.43,0.55l-0.3,0.7l-1.04,0.86l-0.91,-1.24l-1.0,-1.02l-0.69,-0.37l-0.52,-0.42l-0.3,-1.11l-0.37,-0.56l-0.1,-0.1l-0.4,-0.23l0.77,-0.85l0.62,0.04l0.18,-0.05l0.58,-0.38l0.46,-0.0l0.19,-0.07l0.39,-0.34l0.1,-0.3l-0.17,-0.67l0.15,-0.14l0.09,-0.2l0.03,-0.57l0.87,0.02l1.76,0.6l0.13,0.01l0.55,-0.06l0.22,-0.13l0.08,-0.12l1.18,0.17l0.17,-0.02l0.09,0.56l0.3,0.25l0.4,-0.0l0.14,-0.03l0.56,-0.29l0.23,0.05l0.63,0.59l0.15,0.07l1.07,0.2l0.24,-0.06l0.65,-0.52l0.77,-0.32l0.55,-0.32l0.3,0.04l0.44,0.45l0.34,0.74l0.84,0.87l-0.35,0.45l-0.06,0.15l-0.1,0.82l0.42,0.31l0.35,-0.16l0.05,0.04l-0.1,0.59l0.09,0.27l0.42,0.4l-0.06,0.02l-0.18,0.21l-0.2,0.86l0.03,0.21l0.56,1.02l0.52,1.71l-0.65,0.21l-0.15,0.12l-0.24,0.35l-0.03,0.28l0.16,0.41l-0.1,0.76l-0.12,0.0Z\", \"name\": \"Guinea\"}, \"GM\": {\"path\": \"M379.18,251.48l0.15,-0.55l2.51,-0.07l0.21,-0.09l0.48,-0.52l0.58,-0.03l0.91,0.58l0.16,0.05l0.78,0.01l0.14,-0.03l0.59,-0.31l0.16,0.24l-0.71,0.38l-0.94,-0.04l-1.02,-0.51l-0.3,0.01l-0.86,0.55l-0.37,0.02l-0.14,0.04l-0.53,0.31l-1.81,-0.04Z\", \"name\": \"Gambia\"}, \"GL\": {\"path\": \"M304.13,6.6l8.19,-3.63l8.72,0.28l0.19,-0.06l3.12,-2.28l8.75,-0.61l19.94,0.8l14.93,4.75l-3.92,2.01l-9.52,0.27l-13.48,0.6l-0.27,0.2l0.09,0.33l1.26,1.09l0.22,0.07l8.81,-0.67l7.49,2.07l0.19,-0.01l4.68,-1.78l1.76,1.84l-2.59,3.26l-0.01,0.36l0.34,0.11l6.35,-2.2l12.09,-2.32l7.31,1.14l1.17,2.13l-9.9,4.05l-1.43,1.32l-7.91,0.98l-0.26,0.31l0.29,0.29l5.25,0.25l-2.63,3.72l-2.02,3.61l-0.04,0.15l0.08,6.05l0.07,0.19l2.61,3.0l-3.4,0.2l-4.12,1.66l-0.04,0.54l4.5,2.67l0.53,3.9l-2.39,0.42l-0.19,0.48l2.91,3.83l-5.0,0.32l-0.27,0.22l0.12,0.33l2.69,1.84l-0.65,1.35l-3.36,0.71l-3.46,0.01l-0.21,0.51l3.05,3.15l0.02,1.53l-4.54,-1.79l-0.32,0.06l-1.29,1.26l0.11,0.5l3.33,1.15l3.17,2.74l0.85,3.29l-4.0,0.78l-1.83,-1.66l-3.1,-2.64l-0.36,-0.02l-0.13,0.33l0.8,2.92l-2.76,2.26l-0.09,0.33l0.28,0.2l6.59,0.19l2.47,0.18l-5.86,3.38l-6.76,3.43l-7.26,1.48l-2.73,0.02l-0.16,0.05l-2.67,1.72l-3.44,4.42l-5.28,2.86l-1.73,0.18l-3.33,1.01l-3.59,0.96l-0.15,0.1l-2.15,2.52l-0.07,0.19l-0.03,2.76l-1.21,2.49l-4.03,3.1l-0.1,0.33l0.98,2.94l-2.31,6.57l-3.21,0.21l-3.6,-3.0l-0.19,-0.07l-4.9,-0.02l-2.29,-1.97l-1.69,-3.78l-4.31,-4.86l-1.23,-2.52l-0.34,-3.58l-0.08,-0.17l-3.35,-3.67l0.85,-2.92l-0.09,-0.31l-1.5,-1.34l2.33,-4.7l3.67,-1.57l0.15,-0.13l1.02,-1.93l0.52,-3.47l-0.44,-0.31l-2.85,1.57l-1.33,0.64l-2.12,0.59l-2.81,-1.32l-0.15,-2.79l0.88,-2.17l2.09,-0.06l5.07,1.2l0.34,-0.17l-0.11,-0.37l-4.3,-2.9l-2.24,-1.58l-0.25,-0.05l-2.38,0.62l-1.7,-0.93l2.62,-4.1l-0.03,-0.36l-1.51,-1.75l-1.97,-3.3l-3.01,-5.21l-0.1,-0.11l-3.04,-1.85l0.03,-1.94l-0.18,-0.28l-6.82,-3.01l-5.35,-0.38l-6.69,0.21l-6.03,0.37l-2.81,-1.59l-3.84,-2.9l5.94,-1.5l5.01,-0.28l0.28,-0.29l-0.26,-0.31l-10.68,-1.38l-5.38,-2.1l0.27,-1.68l9.3,-2.6l9.18,-2.68l0.19,-0.16l0.97,-2.05l-0.18,-0.42l-6.29,-1.91l1.81,-1.9l8.58,-4.05l3.6,-0.63l0.23,-0.4l-0.92,-2.37l5.59,-1.5l7.66,-0.95l7.58,-0.05l2.65,1.84l0.31,0.02l6.52,-3.29l5.85,2.24l3.55,0.49l5.17,1.95l0.38,-0.16l-0.13,-0.39l-5.77,-3.16l0.29,-2.26Z\", \"name\": \"Greenland\"}, \"KW\": {\"path\": \"M540.87,207.81l0.41,0.94l-0.18,0.51l0.0,0.21l0.65,1.66l-1.15,0.05l-0.54,-1.12l-0.24,-0.17l-1.73,-0.2l1.44,-2.06l1.33,0.18Z\", \"name\": \"Kuwait\"}, \"GH\": {\"path\": \"M423.16,269.88l-3.58,1.34l-1.41,0.87l-2.13,0.69l-1.91,-0.61l0.09,-0.75l-0.03,-0.17l-1.04,-2.07l0.62,-2.7l1.04,-2.08l0.03,-0.19l-1.0,-5.46l0.05,-1.12l4.04,-0.11l1.08,0.18l0.18,-0.03l0.72,-0.36l0.75,0.13l-0.11,0.48l0.06,0.26l0.98,1.22l-0.0,1.77l0.24,1.99l0.05,0.13l0.55,0.81l-0.52,2.14l0.19,1.37l0.69,1.66l0.38,0.62Z\", \"name\": \"Ghana\"}, \"OM\": {\"path\": \"M568.16,231.0l-0.08,0.1l-0.84,1.61l-0.93,-0.11l-0.27,0.11l-0.58,0.73l-0.4,1.32l-0.01,0.14l0.29,1.61l-0.07,0.09l-1.0,-0.01l-0.16,0.04l-1.56,0.97l-0.14,0.2l-0.23,1.17l-0.41,0.4l-1.44,-0.02l-0.17,0.05l-0.98,0.65l-0.13,0.25l0.01,0.87l-0.97,0.57l-1.27,-0.22l-0.19,0.03l-1.63,0.84l-0.88,0.11l-2.55,-5.57l7.2,-2.49l0.19,-0.19l1.67,-5.23l-0.03,-0.25l-1.1,-1.78l0.05,-0.89l0.68,-1.03l0.05,-0.16l0.01,-0.89l0.96,-0.44l0.07,-0.5l-0.32,-0.26l0.16,-1.31l0.85,-0.01l1.03,1.67l0.09,0.09l1.4,0.96l0.11,0.05l1.82,0.34l1.37,0.45l1.75,2.32l0.13,0.1l0.7,0.26l-0.0,0.3l-1.25,2.19l-1.01,0.8ZM561.88,218.47l-0.01,0.02l-0.15,-0.29l0.3,-0.38l-0.14,0.65Z\", \"name\": \"Oman\"}, \"_3\": {\"path\": \"M543.2,261.06l-1.07,1.46l-1.65,1.99l-1.91,0.01l-8.08,-2.95l-0.89,-0.84l-0.9,-1.19l-0.81,-1.23l0.44,-0.73l0.76,-1.12l0.49,0.28l0.52,1.05l1.13,1.06l0.2,0.08l1.24,0.01l2.42,-0.65l2.77,-0.31l2.17,-0.78l1.31,-0.19l0.84,-0.43l1.03,-0.06l-0.01,4.54Z\", \"name\": \"Somaliland\"}, \"_2\": {\"path\": \"M384.23,230.37l0.07,-0.06l0.28,-0.89l0.99,-1.13l0.07,-0.13l0.8,-3.54l3.4,-2.8l0.09,-0.13l0.76,-2.17l0.07,5.5l-2.07,0.21l-0.24,0.17l-0.61,1.36l-0.02,0.16l0.43,3.46l-4.01,-0.01ZM391.82,218.2l0.07,-0.06l0.75,-1.93l1.86,-0.25l0.94,0.34l1.14,0.0l0.18,-0.06l0.73,-0.56l1.41,-0.08l-0.0,2.72l-7.08,-0.12Z\", \"name\": \"Western Sahara\"}, \"_1\": {\"path\": \"M472.71,172.84l-0.07,-0.43l-0.16,-0.22l-0.53,-0.27l-0.38,-0.58l0.3,-0.43l0.51,-0.19l0.18,-0.18l0.3,-0.87l0.12,-0.04l0.22,0.26l0.12,0.09l0.38,0.15l0.28,0.41l0.15,0.12l0.34,0.12l0.43,0.5l0.15,0.07l-0.12,0.3l-0.27,0.32l-0.03,0.18l-0.31,0.06l-1.48,0.47l-0.15,0.17Z\", \"name\": \"Kosovo\"}, \"_0\": {\"path\": \"M503.54,192.92l0.09,-0.17l0.41,0.01l-0.08,0.01l-0.42,0.15ZM504.23,192.76l1.02,0.02l0.4,-0.13l-0.09,0.29l0.03,0.08l-0.35,0.16l-0.24,-0.04l-0.06,-0.1l-0.18,-0.17l-0.19,-0.08l-0.33,-0.02Z\", \"name\": \"Northern Cyprus\"}, \"JO\": {\"path\": \"M510.26,200.93l0.28,-0.57l2.53,1.0l0.27,-0.02l4.57,-2.77l0.84,2.84l-0.28,0.25l-4.95,1.37l-0.14,0.49l2.24,2.48l-0.5,0.28l-0.13,0.14l-0.35,0.78l-1.76,0.35l-0.2,0.14l-0.57,0.94l-0.94,0.73l-2.45,-0.38l-0.03,-0.12l1.23,-4.32l-0.04,-1.1l0.34,-0.75l0.03,-0.12l0.0,-1.63Z\", \"name\": \"Jordan\"}, \"HR\": {\"path\": \"M455.49,162.73l1.53,0.09l0.24,-0.1l0.29,-0.34l0.64,0.38l0.14,0.04l0.98,0.06l0.32,-0.3l-0.01,-0.66l0.67,-0.25l0.19,-0.22l0.21,-1.11l1.72,-0.72l0.65,0.32l1.94,1.37l2.07,0.6l0.22,-0.02l0.67,-0.33l0.47,0.94l0.67,0.76l-0.63,0.77l-0.91,-0.55l-0.16,-0.04l-1.69,0.04l-2.2,-0.51l-1.17,0.07l-0.21,0.11l-0.36,0.42l-0.67,-0.53l-0.46,0.12l-0.52,1.29l0.05,0.31l1.21,1.42l0.58,0.99l1.15,1.14l0.95,0.68l0.92,1.23l0.1,0.09l1.75,0.91l-1.87,-0.89l-1.5,-1.11l-2.23,-0.88l-1.77,-1.9l0.12,-0.06l0.1,-0.47l-1.07,-1.22l-0.04,-0.94l-0.21,-0.27l-1.61,-0.49l-0.35,0.14l-0.53,0.93l-0.41,-0.57l0.04,-0.73Z\", \"name\": \"Croatia\"}, \"HT\": {\"path\": \"M237.82,234.68l1.35,0.1l1.95,0.37l0.18,1.15l-0.16,0.83l-0.51,0.37l-0.06,0.44l0.57,0.68l-0.02,0.22l-1.31,-0.35l-1.26,0.17l-1.49,-0.18l-0.15,0.02l-1.03,0.43l-1.02,-0.61l0.09,-0.36l2.04,0.32l1.9,0.21l0.19,-0.05l0.9,-0.58l0.05,-0.47l-1.05,-1.03l0.02,-0.86l-0.23,-0.3l-1.13,-0.29l0.18,-0.23Z\", \"name\": \"Haiti\"}, \"HU\": {\"path\": \"M461.96,157.92l0.68,-1.66l-0.03,-0.29l-0.15,-0.22l0.84,-0.0l0.3,-0.26l0.12,-0.84l0.88,0.57l0.98,0.38l0.16,0.01l2.1,-0.39l0.23,-0.21l0.14,-0.45l0.88,-0.1l1.06,-0.43l0.13,0.1l0.28,0.04l1.18,-0.4l0.14,-0.1l0.52,-0.67l0.63,-0.15l2.6,0.95l0.26,-0.03l0.38,-0.23l1.12,0.7l0.1,0.49l-1.31,0.57l-0.14,0.13l-1.18,2.14l-1.44,2.04l-1.85,0.55l-1.51,-0.13l-0.14,0.02l-1.92,0.82l-0.85,0.42l-1.91,-0.55l-1.83,-1.31l-0.74,-0.37l-0.44,-0.97l-0.26,-0.18Z\", \"name\": \"Hungary\"}, \"HN\": {\"path\": \"M202.48,251.87l-0.33,-0.62l-0.18,-0.14l-0.5,-0.15l0.13,-0.76l-0.11,-0.28l-0.34,-0.28l-0.6,-0.23l-0.18,-0.01l-0.81,0.22l-0.16,-0.24l-0.72,-0.39l-0.51,-0.48l-0.12,-0.07l-0.31,-0.09l0.24,-0.3l0.04,-0.3l-0.16,-0.4l0.1,-0.28l1.14,-0.69l1.0,-0.86l0.09,0.04l0.3,-0.05l0.47,-0.39l0.49,-0.03l0.14,0.13l0.29,0.06l0.31,-0.1l1.16,0.22l1.24,-0.08l0.81,-0.28l0.29,-0.25l0.63,0.1l0.69,0.18l0.65,-0.06l0.49,-0.2l1.04,0.32l0.38,0.06l0.7,0.44l0.71,0.56l0.92,0.41l0.1,0.11l-0.11,-0.01l-0.23,0.09l-0.3,0.3l-0.76,0.29l-0.58,0.0l-0.15,0.04l-0.45,0.26l-0.31,-0.07l-0.37,-0.34l-0.28,-0.07l-0.26,0.07l-0.18,0.15l-0.23,0.43l-0.04,-0.0l-0.33,0.28l-0.03,0.4l-0.76,0.61l-0.45,0.3l-0.15,0.16l-0.51,-0.36l-0.41,0.06l-0.45,0.56l-0.41,-0.01l-0.59,0.06l-0.27,0.31l0.04,0.96l-0.07,0.0l-0.25,0.16l-0.24,0.45l-0.42,0.06Z\", \"name\": \"Honduras\"}, \"PR\": {\"path\": \"M254.95,238.31l1.15,0.21l0.2,0.23l-0.36,0.36l-1.76,-0.01l-1.2,0.07l-0.09,-0.69l0.17,-0.18l1.89,0.01Z\", \"name\": \"Puerto Rico\"}, \"PS\": {\"path\": \"M509.66,201.06l-0.0,1.44l-0.29,0.63l-0.59,0.19l0.02,-0.11l0.52,-0.31l-0.02,-0.53l-0.41,-0.2l0.36,-1.28l0.41,0.17Z\", \"name\": \"West Bank\"}, \"PT\": {\"path\": \"M398.65,173.6l0.75,-0.63l0.7,-0.3l0.51,1.2l0.28,0.18l1.48,-0.0l0.2,-0.08l0.33,-0.3l1.16,0.08l0.52,1.11l-0.95,0.66l-0.13,0.24l-0.03,2.2l-0.33,0.35l-0.08,0.18l-0.08,1.17l-0.86,0.19l-0.2,0.44l0.93,1.64l-0.64,1.79l0.07,0.31l0.72,0.72l-0.24,0.56l-0.9,1.05l-0.07,0.26l0.17,0.77l-0.73,0.54l-1.18,-0.36l-0.16,-0.0l-0.85,0.21l0.31,-1.81l-0.23,-1.87l-0.23,-0.25l-0.99,-0.24l-0.49,-0.91l0.18,-1.72l0.93,-0.99l0.08,-0.16l0.17,-1.17l0.52,-1.76l-0.04,-1.36l-0.51,-1.14l-0.09,-0.8Z\", \"name\": \"Portugal\"}, \"PY\": {\"path\": \"M264.33,341.43l0.93,-2.96l0.07,-1.42l1.1,-2.1l4.19,-0.73l2.22,0.04l2.12,1.21l0.07,0.76l0.7,1.38l-0.16,3.48l0.24,0.31l2.64,0.5l0.19,-0.03l0.9,-0.45l1.47,0.62l0.38,0.64l0.23,2.35l0.3,1.07l0.25,0.21l0.93,0.12l0.16,-0.02l0.8,-0.37l0.61,0.33l-0.0,1.25l-0.33,1.53l-0.5,1.57l-0.39,2.26l-2.14,1.94l-1.85,0.4l-2.74,-0.4l-2.13,-0.62l2.26,-3.75l0.03,-0.24l-0.36,-1.18l-0.17,-0.19l-2.55,-1.03l-3.04,-1.95l-2.07,-0.43l-4.4,-4.12Z\", \"name\": \"Paraguay\"}, \"PA\": {\"path\": \"M213.65,263.79l0.18,-0.43l0.02,-0.18l-0.06,-0.28l0.23,-0.18l-0.01,-0.48l-0.4,-0.29l-0.01,-0.62l0.57,-0.13l0.68,0.69l-0.04,0.39l0.26,0.33l1.0,0.11l0.27,-0.1l0.49,0.44l0.24,0.07l1.34,-0.22l1.04,-0.62l1.49,-0.5l0.86,-0.73l0.99,0.11l0.18,0.28l1.35,0.08l1.02,0.4l0.78,0.72l0.71,0.53l-0.1,0.12l-0.05,0.3l0.53,1.34l-0.28,0.44l-0.6,-0.13l-0.36,0.22l-0.2,0.76l-0.41,-0.36l-0.44,-1.12l0.49,-0.53l-0.14,-0.49l-0.51,-0.14l-0.41,-0.72l-0.11,-0.11l-1.25,-0.7l-0.19,-0.04l-1.1,0.16l-0.22,0.15l-0.47,0.81l-0.9,0.56l-0.49,0.08l-0.22,0.17l-0.25,0.52l0.05,0.32l0.93,1.07l-0.41,0.21l-0.29,0.3l-0.81,0.09l-0.36,-1.26l-0.53,-0.1l-0.21,0.28l-0.5,-0.09l-0.44,-0.88l-0.22,-0.16l-0.99,-0.16l-0.61,-0.28l-0.13,-0.03l-1.0,0.0Z\", \"name\": \"Panama\"}, \"PG\": {\"path\": \"M808.4,298.6l0.62,0.46l1.19,1.56l1.04,0.77l-0.18,0.37l-0.42,0.15l-0.92,-0.82l-1.05,-1.53l-0.27,-0.96ZM804.09,296.06l-0.3,0.26l-0.36,-1.11l-0.66,-1.06l-2.55,-1.89l-1.42,-0.59l0.17,-0.15l1.16,0.6l0.85,0.55l1.01,0.58l0.97,1.02l0.9,0.76l0.24,1.03ZM796.71,297.99l0.15,0.82l0.34,0.24l1.43,-0.19l0.19,-0.11l0.68,-0.82l1.36,-0.87l0.13,-0.31l-0.21,-1.13l1.04,-0.03l0.3,0.25l-0.04,1.17l-0.74,1.34l-1.17,0.18l-0.22,0.15l-0.35,0.62l-2.51,1.13l-1.21,-0.0l-1.99,-0.71l-1.19,-0.58l0.07,-0.28l1.98,0.32l1.46,-0.2l0.24,-0.21l0.25,-0.79ZM789.24,303.52l0.11,0.15l2.19,1.62l1.6,2.62l0.27,0.14l1.09,-0.06l-0.07,0.77l0.23,0.32l1.23,0.27l-0.14,0.09l0.05,0.53l2.39,0.95l-0.11,0.28l-1.33,0.14l-0.51,-0.55l-0.18,-0.09l-4.59,-0.65l-1.87,-1.55l-1.38,-1.35l-1.28,-2.17l-0.16,-0.13l-3.27,-1.1l-0.19,0.0l-2.12,0.72l-1.58,0.85l-0.15,0.31l0.28,1.63l-1.65,0.73l-1.37,-0.4l-2.3,-0.09l-0.08,-15.65l3.95,1.57l4.58,1.42l1.67,1.25l1.32,1.19l0.36,1.39l0.19,0.21l4.06,1.51l0.39,0.85l-1.9,0.22l-0.25,0.39l0.55,1.68Z\", \"name\": \"Papua New Guinea\"}, \"PE\": {\"path\": \"M246.44,329.21l-0.63,1.25l-1.05,0.54l-2.25,-1.33l-0.19,-0.93l-0.16,-0.21l-4.95,-2.58l-4.46,-2.79l-1.87,-1.52l-0.94,-1.91l0.33,-0.6l-0.01,-0.31l-2.11,-3.33l-2.46,-4.66l-2.36,-5.02l-1.04,-1.18l-0.77,-1.81l-0.08,-0.11l-1.95,-1.64l-1.54,-0.88l0.61,-0.85l0.02,-0.31l-1.15,-2.27l0.69,-1.56l1.59,-1.26l0.12,0.42l-0.56,0.47l-0.11,0.25l0.07,0.92l0.36,0.27l0.97,-0.19l0.85,0.23l0.99,1.19l0.41,0.05l1.42,-1.03l0.11,-0.16l0.46,-1.64l1.45,-2.06l2.92,-0.96l0.11,-0.07l2.73,-2.62l0.84,-1.72l0.02,-0.18l-0.3,-1.65l0.28,-0.1l1.49,1.06l0.77,1.14l0.1,0.09l1.08,0.6l1.43,2.55l0.21,0.15l1.86,0.31l0.18,-0.03l1.25,-0.6l0.77,0.37l0.17,0.03l1.4,-0.2l1.57,0.96l-1.45,2.29l0.23,0.46l0.63,0.05l0.66,0.7l-1.51,-0.08l-0.24,0.1l-0.27,0.31l-1.96,0.46l-2.95,1.74l-0.14,0.21l-0.17,1.1l-0.6,0.82l-0.05,0.23l0.21,1.13l-1.31,0.63l-0.17,0.27l0.0,0.91l-0.53,0.37l-0.1,0.37l1.04,2.27l1.31,1.46l-0.44,0.9l0.24,0.43l1.52,0.13l0.87,1.23l0.24,0.13l2.21,0.07l0.18,-0.06l1.55,-1.13l-0.14,3.22l0.23,0.3l1.14,0.29l0.16,-0.0l1.18,-0.36l1.97,3.71l-0.45,0.71l-0.04,0.14l-0.12,1.8l-0.05,2.07l-0.92,1.2l-0.03,0.31l0.38,0.8l-0.48,0.72l-0.02,0.3l1.01,2.02l-1.5,2.64Z\", \"name\": \"Peru\"}, \"PK\": {\"path\": \"M609.08,187.76l1.66,1.21l0.71,2.11l0.2,0.19l3.62,1.01l-1.98,1.95l-2.65,0.4l-3.75,-0.68l-0.26,0.08l-1.23,1.22l-0.07,0.31l0.89,2.46l0.88,1.92l0.1,0.12l1.67,1.14l-1.8,1.35l-0.12,0.25l0.04,1.85l-2.35,2.67l-1.59,2.79l-2.5,2.72l-2.76,-0.2l-0.24,0.09l-2.76,2.83l0.04,0.45l1.54,1.13l0.27,1.94l0.09,0.17l1.34,1.29l0.4,1.83l-5.14,-0.01l-0.22,0.09l-1.53,1.63l-1.52,-0.56l-0.76,-1.88l-1.93,-2.03l-0.25,-0.09l-4.6,0.5l-4.05,0.05l-3.1,0.33l0.77,-2.53l3.48,-1.33l0.19,-0.33l-0.21,-1.24l-0.19,-0.23l-1.01,-0.37l-0.06,-2.18l-0.17,-0.26l-2.32,-1.16l-0.96,-1.57l-0.56,-0.65l3.16,1.05l0.14,0.01l2.45,-0.4l1.44,0.33l0.3,-0.1l0.4,-0.47l1.58,0.22l0.14,-0.01l3.25,-1.14l0.2,-0.27l0.08,-2.23l1.23,-1.38l1.73,0.0l0.28,-0.2l0.22,-0.61l1.68,-0.32l0.86,0.24l0.27,-0.05l0.98,-0.78l0.11,-0.26l-0.13,-1.57l0.96,-1.52l1.51,-0.67l0.14,-0.41l-0.74,-1.4l1.86,0.07l0.26,-0.13l0.69,-1.01l0.05,-0.2l-0.09,-0.94l1.14,-1.09l0.09,-0.28l-0.29,-1.41l-0.51,-1.07l1.23,-1.05l2.6,-0.58l2.86,-0.33l1.33,-0.54l1.3,-0.29Z\", \"name\": \"Pakistan\"}, \"PH\": {\"path\": \"M737.11,263.82l0.25,1.66l0.14,1.34l-0.54,1.46l-0.64,-1.79l-0.5,-0.1l-1.17,1.28l-0.05,0.32l0.74,1.71l-0.49,0.81l-2.6,-1.28l-0.61,-1.57l0.68,-1.07l-0.07,-0.4l-1.59,-1.19l-0.42,0.06l-0.69,0.91l-1.01,-0.08l-0.21,0.06l-1.58,1.2l-0.17,-0.3l0.87,-1.88l1.48,-0.66l1.18,-0.81l0.71,0.92l0.34,0.1l1.9,-0.69l0.18,-0.18l0.34,-0.94l1.57,-0.06l0.29,-0.32l-0.1,-1.38l1.41,0.83l0.36,2.06ZM734.94,254.42l0.56,2.24l-1.41,-0.49l-0.4,0.3l0.07,0.94l0.51,1.3l-0.54,0.26l-0.08,-1.34l-0.25,-0.28l-0.56,-0.1l-0.23,-0.91l1.03,0.14l0.34,-0.31l-0.03,-0.96l-0.06,-0.18l-1.14,-1.44l1.62,0.04l0.57,0.78ZM724.68,238.33l1.48,0.71l0.33,-0.04l0.44,-0.38l0.05,0.13l-0.37,0.97l0.01,0.23l0.81,1.75l-0.59,1.92l-1.37,0.79l-0.14,0.2l-0.39,2.07l0.01,0.14l0.56,2.04l0.23,0.21l1.33,0.28l0.14,-0.0l1.0,-0.27l2.82,1.28l-0.2,1.16l0.12,0.29l0.66,0.5l-0.13,0.56l-1.54,-0.99l-0.89,-1.29l-0.49,0.0l-0.44,0.65l-1.34,-1.28l-0.26,-0.08l-2.18,0.36l-0.96,-0.44l0.09,-0.72l0.69,-0.57l-0.01,-0.47l-0.75,-0.59l-0.47,0.14l-0.15,0.43l-0.86,-1.02l-0.34,-1.02l-0.07,-1.74l0.49,0.41l0.49,-0.21l0.26,-3.99l0.73,-2.1l1.23,0.0ZM731.12,258.92l-0.82,0.75l-0.83,1.64l-0.52,0.5l-1.17,-1.33l0.36,-0.47l0.62,-0.7l0.07,-0.15l0.24,-1.35l0.73,-0.08l-0.31,1.29l0.16,0.34l0.37,-0.09l1.21,-1.6l-0.12,1.24ZM726.66,255.58l0.85,0.45l0.14,0.03l1.28,-0.0l-0.03,0.62l-1.04,0.96l-1.15,0.55l-0.05,-0.71l0.17,-1.26l-0.01,-0.13l-0.16,-0.51ZM724.92,252.06l-0.45,1.5l-0.7,-0.83l-0.95,-1.43l1.44,0.06l0.67,0.7ZM717.48,261.28l-1.87,1.35l0.21,-0.3l1.81,-1.57l1.5,-1.75l0.97,-1.84l0.23,1.08l-1.56,1.33l-1.29,1.7Z\", \"name\": \"Philippines\"}, \"PL\": {\"path\": \"M458.8,144.25l-0.96,-1.98l0.18,-1.06l-0.01,-0.15l-0.62,-1.8l-0.82,-1.11l0.56,-0.73l0.05,-0.28l-0.51,-1.51l1.48,-0.87l3.88,-1.58l3.06,-1.14l2.23,0.52l0.15,0.66l0.29,0.23l2.4,0.04l3.11,0.39l4.56,-0.05l1.12,0.32l0.51,0.89l0.1,1.45l0.03,0.12l0.66,1.23l-0.01,1.08l-1.33,0.61l-0.14,0.41l0.74,1.5l0.07,1.53l1.22,2.79l-0.19,0.66l-1.09,0.33l-0.14,0.09l-2.27,2.72l-0.04,0.31l0.35,0.8l-2.22,-1.16l-0.21,-0.02l-1.72,0.44l-1.1,-0.31l-0.21,0.02l-1.3,0.61l-1.11,-1.02l-0.32,-0.05l-0.81,0.35l-1.15,-1.61l-0.21,-0.12l-1.65,-0.17l-0.19,-0.82l-0.23,-0.23l-1.72,-0.37l-0.34,0.17l-0.25,0.56l-0.88,-0.44l0.12,-0.69l-0.25,-0.35l-1.78,-0.27l-1.08,-0.97Z\", \"name\": \"Poland\"}, \"ZM\": {\"path\": \"M502.81,308.32l1.09,1.04l0.58,1.94l-0.39,0.66l-0.5,2.05l-0.0,0.14l0.45,1.95l-0.69,0.77l-0.06,0.11l-0.76,2.37l0.15,0.36l0.62,0.31l-6.85,1.9l-0.22,0.33l0.2,1.54l-1.62,0.3l-0.12,0.05l-1.43,1.02l-0.11,0.15l-0.25,0.73l-0.73,0.17l-0.14,0.08l-2.18,2.12l-1.33,1.6l-0.65,0.05l-0.83,-0.29l-2.75,-0.28l-0.24,-0.1l-0.15,-0.27l-0.99,-0.58l-0.12,-0.04l-1.73,-0.14l-1.88,0.54l-1.5,-1.48l-1.61,-2.01l0.11,-7.73l4.92,0.03l0.29,-0.37l-0.19,-0.79l0.34,-0.86l0.0,-0.21l-0.41,-1.11l0.26,-1.14l-0.01,-0.16l-0.12,-0.36l0.18,0.01l0.1,0.56l0.31,0.25l1.14,-0.06l1.44,0.21l0.76,1.05l0.19,0.12l2.01,0.35l0.19,-0.03l1.24,-0.65l0.44,1.03l0.22,0.18l1.81,0.34l0.85,0.99l1.02,1.39l0.24,0.12l1.92,0.02l0.3,-0.32l-0.21,-2.74l-0.47,-0.23l-0.53,0.36l-1.58,-0.89l-0.51,-0.34l0.29,-2.36l0.44,-2.99l-0.03,-0.18l-0.5,-0.99l0.61,-1.38l0.53,-0.24l3.26,-0.41l0.89,0.23l1.01,0.62l1.04,0.44l1.6,0.43l1.35,0.72Z\", \"name\": \"Zambia\"}, \"EE\": {\"path\": \"M482.19,120.88l0.23,-1.68l-0.43,-0.31l-0.75,0.37l-1.34,-1.1l-0.18,-1.75l2.92,-0.95l3.07,-0.53l2.66,0.6l2.48,-0.1l0.18,0.31l-1.65,1.96l-0.06,0.26l0.71,3.25l-0.88,0.94l-1.85,-0.01l-2.08,-1.3l-1.14,-0.47l-0.2,-0.01l-1.69,0.51Z\", \"name\": \"Estonia\"}, \"EG\": {\"path\": \"M508.07,208.8l-0.66,1.06l-0.53,2.03l-0.64,1.32l-0.32,0.26l-1.74,-1.85l-1.77,-3.86l-0.48,-0.09l-0.26,0.25l-0.07,0.32l1.04,2.88l1.55,2.76l1.89,4.18l0.94,1.48l0.83,1.54l2.08,2.73l-0.3,0.28l-0.1,0.23l0.08,1.72l0.11,0.22l2.91,2.37l-28.78,0.0l0.0,-19.06l-0.73,-2.2l0.61,-1.59l0.0,-0.2l-0.34,-1.04l0.73,-1.08l3.13,-0.04l2.36,0.72l2.48,0.81l1.15,0.43l0.23,-0.01l1.93,-0.87l1.02,-0.78l2.08,-0.21l1.59,0.31l0.62,1.24l0.52,0.03l0.46,-0.71l1.86,0.59l1.95,0.16l0.17,-0.04l0.92,-0.52l1.48,4.24Z\", \"name\": \"Egypt\"}, \"ZA\": {\"path\": \"M467.06,373.27l-0.13,-0.29l0.01,-1.58l-0.02,-0.12l-0.71,-1.64l0.59,-0.37l0.14,-0.26l-0.07,-2.13l-0.05,-0.15l-1.63,-2.58l-1.25,-2.31l-1.71,-3.37l0.88,-0.98l0.7,0.52l0.39,1.08l0.23,0.19l1.1,0.19l1.55,0.51l0.14,0.01l1.35,-0.2l0.11,-0.04l2.24,-1.39l0.14,-0.25l0.0,-9.4l0.16,0.09l1.39,2.38l-0.22,1.53l0.04,0.19l0.56,0.94l0.3,0.14l1.79,-0.27l0.16,-0.08l1.23,-1.18l1.17,-0.79l0.1,-0.12l0.57,-1.19l1.02,-0.52l0.9,0.28l1.16,0.73l0.14,0.05l2.04,0.13l0.13,-0.02l1.6,-0.62l0.18,-0.19l0.63,-1.93l1.18,-0.19l0.19,-0.12l0.78,-1.05l0.81,-1.71l2.18,-1.91l3.44,-1.88l0.89,0.02l1.17,0.43l0.21,-0.0l0.76,-0.29l1.07,0.21l1.15,3.55l0.63,1.82l-0.44,2.9l0.1,0.52l-0.74,-0.29l-0.18,-0.01l-0.72,0.19l-0.21,0.2l-0.22,0.74l-0.66,0.97l-0.05,0.18l0.02,0.93l0.09,0.21l1.49,1.46l0.27,0.08l1.47,-0.29l0.22,-0.18l0.43,-1.01l1.29,0.02l-0.51,1.63l-0.29,2.2l-0.59,1.12l-2.2,1.78l-1.06,1.39l-0.72,1.44l-1.39,1.93l-2.81,2.84l-1.75,1.65l-1.85,1.24l-2.55,1.06l-1.23,0.14l-0.24,0.18l-0.22,0.54l-1.27,-0.35l-0.2,0.01l-1.15,0.5l-2.62,-0.52l-0.12,0.0l-1.46,0.33l-0.98,-0.14l-0.16,0.02l-2.55,1.1l-2.11,0.44l-1.59,1.07l-0.93,0.06l-0.97,-0.92l-0.19,-0.08l-0.72,-0.04l-1.0,-1.16l-0.25,0.05ZM493.72,359.24l-1.12,-0.86l-0.31,-0.03l-1.23,0.59l-1.36,1.07l-1.39,1.78l0.01,0.38l1.88,2.11l0.31,0.09l0.9,-0.27l0.18,-0.15l0.4,-0.77l1.28,-0.39l0.18,-0.16l0.42,-0.88l0.76,-1.32l-0.05,-0.37l-0.87,-0.82Z\", \"name\": \"South Africa\"}, \"EC\": {\"path\": \"M220.2,293.48l1.25,-1.76l0.02,-0.31l-0.54,-1.09l-0.5,-0.06l-0.78,0.94l-1.03,-0.75l0.33,-0.46l0.05,-0.23l-0.38,-2.04l0.66,-0.28l0.17,-0.19l0.45,-1.52l0.93,-1.58l0.04,-0.2l-0.13,-0.78l1.19,-0.47l1.57,-0.91l2.35,1.34l0.17,0.04l0.28,-0.02l0.52,0.91l0.21,0.15l2.12,0.35l0.2,-0.03l0.55,-0.31l1.08,0.73l0.97,0.54l0.31,1.67l-0.71,1.49l-2.64,2.54l-2.95,0.97l-0.15,0.11l-1.53,2.18l-0.49,1.68l-1.1,0.8l-0.87,-1.05l-0.15,-0.1l-1.01,-0.27l-0.13,-0.0l-0.7,0.14l-0.03,-0.43l0.6,-0.5l0.1,-0.31l-0.26,-0.91Z\", \"name\": \"Ecuador\"}, \"AL\": {\"path\": \"M470.27,171.7l0.38,0.19l0.45,-0.18l0.4,0.61l0.11,0.1l0.46,0.24l0.13,0.87l-0.3,0.95l-0.0,0.17l0.36,1.28l0.12,0.17l0.9,0.63l-0.03,0.44l-0.67,0.35l-0.16,0.22l-0.14,0.88l-0.96,1.18l-0.06,-0.03l-0.04,-0.48l-0.12,-0.22l-1.28,-0.92l-0.19,-1.25l0.2,-1.96l0.33,-0.89l-0.06,-0.3l-0.36,-0.41l-0.13,-0.75l0.66,-0.9Z\", \"name\": \"Albania\"}, \"AO\": {\"path\": \"M461.62,299.93l0.55,1.67l0.73,1.54l1.56,2.18l0.28,0.12l1.66,-0.2l0.81,-0.34l1.28,0.33l0.33,-0.14l0.39,-0.67l0.56,-1.3l1.37,-0.09l0.27,-0.21l0.07,-0.23l0.67,-0.01l-0.13,0.53l0.29,0.37l2.74,-0.02l0.04,1.29l0.03,0.13l0.46,0.87l-0.35,1.52l0.18,1.55l0.07,0.16l0.75,0.85l-0.13,2.89l0.41,0.29l0.56,-0.21l1.11,0.05l1.5,-0.37l0.9,0.12l0.18,0.53l-0.27,1.15l0.01,0.17l0.4,1.08l-0.33,0.85l-0.01,0.18l0.12,0.51l-4.83,-0.03l-0.3,0.3l-0.12,8.13l0.07,0.19l1.69,2.1l1.27,1.25l-4.03,0.92l-5.93,-0.36l-1.66,-1.19l-0.18,-0.06l-10.15,0.11l-0.34,0.13l-1.35,-1.05l-0.17,-0.06l-1.62,-0.08l-1.6,0.45l-0.88,0.36l-0.17,-1.2l0.34,-2.19l0.85,-2.32l0.14,-1.13l0.79,-2.24l0.57,-1.0l1.42,-1.64l0.82,-1.15l0.05,-0.13l0.26,-1.88l-0.13,-1.51l-0.07,-0.16l-0.72,-0.87l-1.23,-2.91l0.09,-0.37l0.73,-0.95l0.05,-0.27l-1.27,-4.12l-1.19,-1.54l0.1,-0.2l0.86,-0.28l0.78,0.03l0.83,-0.29l7.12,0.03ZM451.81,298.94l-0.17,0.07l-0.5,-1.42l0.85,-0.92l0.53,-0.29l0.48,0.44l-0.56,0.32l-0.1,0.1l-0.41,0.65l-0.05,0.14l-0.07,0.91Z\", \"name\": \"Angola\"}, \"KZ\": {\"path\": \"M598.42,172.08l-1.37,0.54l-3.3,2.09l-0.11,0.12l-1.01,1.97l-0.56,0.01l-0.6,-1.24l-0.26,-0.17l-2.95,-0.09l-0.46,-2.22l-0.29,-0.24l-0.91,-0.02l0.17,-2.72l-0.12,-0.26l-3.0,-2.22l-0.2,-0.06l-4.29,0.24l-2.8,0.42l-2.36,-2.7l-6.4,-3.65l-0.23,-0.03l-6.45,1.83l-0.22,0.29l0.1,10.94l-0.84,0.1l-1.65,-2.21l-0.11,-0.09l-1.69,-0.84l-0.2,-0.02l-2.84,0.63l-0.14,0.07l-0.71,0.64l-0.02,-0.11l0.57,-1.17l0.0,-0.26l-0.48,-1.05l-0.17,-0.16l-2.78,-0.99l-1.08,-2.62l-0.13,-0.15l-1.24,-0.7l-0.04,-0.48l2.07,0.25l0.34,-0.29l0.09,-2.03l1.84,-0.44l2.12,0.45l0.36,-0.25l0.45,-3.04l-0.45,-2.06l-0.31,-0.23l-2.44,0.15l-2.07,-0.75l-0.23,0.01l-2.88,1.38l-2.21,0.62l-0.96,-0.38l0.22,-1.39l-0.06,-0.23l-1.6,-2.12l-0.25,-0.12l-1.72,0.08l-1.87,-1.91l1.33,-2.24l-0.06,-0.38l-0.55,-0.5l1.72,-3.08l2.3,1.7l0.48,-0.2l0.29,-2.26l4.99,-3.48l3.76,-0.08l5.46,2.27l2.96,1.33l0.26,-0.01l2.59,-1.36l3.82,-0.06l3.13,1.67l0.38,-0.09l0.63,-0.85l3.36,0.14l0.29,-0.19l0.63,-1.57l-0.13,-0.37l-3.64,-2.05l2.0,-1.36l0.1,-0.38l-0.32,-0.62l2.09,-0.76l0.13,-0.47l-1.65,-2.13l0.89,-0.91l9.27,-1.18l0.13,-0.05l1.17,-0.82l6.2,-1.27l2.26,-1.43l4.19,0.7l0.74,3.39l0.38,0.22l2.52,-0.81l2.9,1.06l-0.18,1.63l0.32,0.33l2.52,-0.23l5.0,-2.58l0.03,0.39l3.16,2.62l5.57,8.48l0.49,0.02l1.18,-1.53l3.22,1.78l0.21,0.03l3.5,-0.83l1.21,0.52l1.16,1.82l0.15,0.12l1.67,0.61l1.01,1.32l0.28,0.11l3.04,-0.41l1.1,1.64l-1.68,1.89l-1.97,0.28l-0.26,0.29l-0.12,3.09l-1.2,1.23l-4.81,-1.01l-0.35,0.2l-1.77,5.51l-1.14,0.62l-4.92,1.23l-0.2,0.41l2.14,5.06l-1.45,0.67l-0.17,0.31l0.15,1.28l-1.05,-0.3l-1.21,-1.04l-0.17,-0.07l-3.73,-0.32l-4.15,-0.08l-0.92,0.31l-3.46,-1.24l-0.22,0.01l-1.42,0.63l-0.17,0.21l-0.32,1.49l-3.82,-0.97l-0.15,0.0l-1.65,0.43l-0.2,0.17l-0.51,1.21Z\", \"name\": \"Kazakhstan\"}, \"ET\": {\"path\": \"M516.0,247.63l1.21,0.92l0.3,0.04l1.3,-0.53l0.46,0.41l0.19,0.08l1.65,0.03l2.05,0.96l0.67,0.88l1.07,0.79l1.0,1.45l0.7,0.68l-0.72,0.92l-0.85,1.19l-0.04,0.25l0.19,0.67l0.04,0.74l0.29,0.28l1.4,0.04l0.55,-0.15l0.23,0.19l-0.41,0.67l0.01,0.32l0.92,1.39l0.93,1.23l0.99,0.94l0.1,0.06l8.19,2.99l1.51,0.01l-6.51,6.95l-3.14,0.11l-0.18,0.06l-2.15,1.71l-1.51,0.04l-0.22,0.1l-0.6,0.69l-1.46,-0.0l-0.93,-0.78l-0.32,-0.04l-2.29,1.05l-0.12,0.1l-0.64,0.9l-1.44,-0.17l-0.51,-0.26l-0.17,-0.03l-0.56,0.07l-0.68,-0.02l-3.1,-2.08l-0.17,-0.05l-1.62,0.0l-0.68,-0.65l0.0,-1.28l-0.21,-0.29l-1.19,-0.38l-1.42,-2.63l-0.13,-0.12l-1.05,-0.53l-0.46,-1.0l-1.27,-1.23l-0.17,-0.08l-1.08,-0.13l0.53,-0.9l1.17,-0.05l0.26,-0.17l0.37,-0.77l0.03,-0.14l-0.03,-2.23l0.7,-2.49l1.08,-0.65l0.14,-0.19l0.24,-1.0l1.03,-1.85l1.47,-1.22l0.09,-0.12l1.02,-2.51l0.36,-1.96l2.62,0.48l0.33,-0.18l0.63,-1.55Z\", \"name\": \"Ethiopia\"}, \"ZW\": {\"path\": \"M498.95,341.2l-1.16,-0.23l-0.16,0.01l-0.74,0.28l-1.11,-0.41l-1.02,-0.04l-1.52,-1.13l-0.12,-0.05l-1.79,-0.37l-0.65,-1.46l-0.01,-0.86l-0.22,-0.29l-0.99,-0.26l-2.74,-2.77l-0.77,-1.46l-0.52,-0.5l-0.72,-1.54l2.24,0.23l0.78,0.28l0.12,0.02l0.85,-0.06l0.21,-0.11l1.38,-1.66l2.11,-2.05l0.81,-0.18l0.22,-0.2l0.27,-0.8l1.29,-0.93l1.53,-0.28l0.11,0.66l0.3,0.25l2.02,-0.05l1.04,0.48l0.5,0.59l0.18,0.1l1.13,0.18l1.11,0.7l0.01,3.06l-0.49,1.82l-0.11,1.94l0.03,0.16l0.35,0.68l-0.24,1.3l-0.27,0.17l-0.12,0.15l-0.64,1.83l-2.49,2.8Z\", \"name\": \"Zimbabwe\"}, \"ES\": {\"path\": \"M398.67,172.8l0.09,-1.45l-0.06,-0.2l-0.82,-1.05l3.16,-1.96l3.01,0.54l3.33,-0.02l2.64,0.52l2.14,-0.15l3.9,0.1l0.91,1.08l0.14,0.09l4.61,1.38l0.26,-0.04l0.77,-0.55l2.66,1.29l0.17,0.03l2.59,-0.35l0.1,1.28l-2.2,1.85l-3.13,0.62l-0.23,0.23l-0.21,0.92l-1.54,1.68l-0.97,2.4l0.02,0.26l0.85,1.46l-1.27,1.14l-0.09,0.14l-0.5,1.73l-1.73,0.53l-0.15,0.1l-1.68,2.1l-3.03,0.04l-2.38,-0.05l-0.17,0.05l-1.57,1.01l-0.9,1.01l-0.96,-0.19l-0.82,-0.86l-0.69,-1.6l-0.22,-0.18l-2.14,-0.41l-0.13,-0.62l0.83,-0.97l0.39,-0.86l-0.06,-0.33l-0.73,-0.73l0.63,-1.74l-0.02,-0.25l-0.8,-1.41l0.69,-0.15l0.23,-0.27l0.09,-1.29l0.33,-0.36l0.08,-0.2l0.03,-2.16l1.03,-0.72l0.1,-0.37l-0.7,-1.5l-0.25,-0.17l-1.46,-0.11l-0.22,0.07l-0.34,0.3l-1.17,0.0l-0.55,-1.29l-0.39,-0.16l-1.02,0.44l-0.45,0.36Z\", \"name\": \"Spain\"}, \"ER\": {\"path\": \"M527.15,253.05l-0.77,-0.74l-1.01,-1.47l-1.14,-0.86l-0.62,-0.84l-0.11,-0.09l-2.18,-1.02l-0.12,-0.03l-1.61,-0.03l-0.52,-0.46l-0.31,-0.05l-1.31,0.54l-1.38,-1.06l-0.46,0.12l-0.69,1.68l-2.49,-0.46l-0.2,-0.76l1.06,-3.69l0.24,-1.65l0.66,-0.66l1.76,-0.4l0.16,-0.1l0.97,-1.13l1.24,2.55l0.68,2.34l0.09,0.14l1.4,1.27l3.39,2.4l1.37,1.43l2.14,2.34l0.94,0.6l-0.32,0.26l-0.85,-0.17Z\", \"name\": \"Eritrea\"}, \"ME\": {\"path\": \"M469.05,172.9l-0.57,-0.8l-0.1,-0.09l-0.82,-0.46l0.16,-0.33l0.35,-1.57l0.72,-0.62l0.27,-0.16l0.48,0.38l0.35,0.4l0.12,0.08l0.79,0.32l0.66,0.43l-0.43,0.62l-0.28,0.11l-0.07,-0.25l-0.53,-0.1l-1.09,1.49l-0.05,0.23l0.06,0.32Z\", \"name\": \"Montenegro\"}, \"MD\": {\"path\": \"M488.2,153.75l0.14,-0.11l1.49,-0.28l1.75,0.95l1.06,0.14l0.92,0.7l-0.15,0.9l0.15,0.31l0.8,0.46l0.33,1.2l0.09,0.14l0.72,0.66l-0.11,0.28l0.1,0.33l-0.06,0.02l-1.25,-0.08l-0.17,-0.29l-0.39,-0.12l-0.52,0.25l-0.16,0.36l0.13,0.42l-0.6,0.88l-0.43,1.03l-0.22,0.12l-0.32,-1.0l0.25,-1.34l-0.08,-1.38l-0.06,-0.17l-1.43,-1.87l-0.81,-1.36l-0.78,-0.95l-0.12,-0.09l-0.29,-0.12Z\", \"name\": \"Moldova\"}, \"MG\": {\"path\": \"M544.77,316.45l0.64,1.04l0.6,1.62l0.4,3.04l0.63,1.21l-0.22,1.07l-0.15,0.26l-0.59,-1.05l-0.52,-0.01l-0.47,0.76l-0.04,0.23l0.46,1.84l-0.19,0.92l-0.61,0.53l-0.1,0.21l-0.16,2.15l-0.97,2.98l-1.24,3.59l-1.55,4.97l-0.96,3.67l-1.08,2.93l-1.94,0.61l-2.05,1.06l-3.2,-1.53l-0.62,-1.26l-0.18,-2.39l-0.87,-2.07l-0.22,-1.8l0.4,-1.69l1.01,-0.4l0.19,-0.28l0.01,-0.79l1.15,-1.91l0.04,-0.11l0.23,-1.66l-0.03,-0.17l-0.57,-1.21l-0.46,-1.58l-0.19,-2.25l0.82,-1.36l0.33,-1.51l1.11,-0.1l1.4,-0.53l0.9,-0.45l1.03,-0.03l0.21,-0.09l1.41,-1.45l2.12,-1.65l0.75,-1.29l0.03,-0.24l-0.17,-0.56l0.53,0.15l0.32,-0.1l1.38,-1.77l0.06,-0.18l0.04,-1.44l0.54,-0.74l0.62,0.77Z\", \"name\": \"Madagascar\"}, \"MA\": {\"path\": \"M378.66,230.13l0.07,-0.75l0.93,-0.72l0.82,-1.37l0.04,-0.21l-0.14,-0.8l0.8,-1.74l1.33,-1.61l0.79,-0.4l0.14,-0.15l0.66,-1.55l0.08,-1.46l0.83,-1.52l1.6,-0.94l0.11,-0.11l1.56,-2.71l1.2,-0.99l2.24,-0.29l0.17,-0.08l1.95,-1.83l1.3,-0.77l2.09,-2.28l0.07,-0.26l-0.61,-3.34l0.92,-2.3l0.33,-1.44l1.52,-1.79l2.48,-1.27l1.86,-1.16l0.1,-0.11l1.67,-2.93l0.72,-1.59l1.54,0.01l1.43,1.14l0.21,0.06l2.33,-0.19l2.55,0.62l0.97,0.03l0.83,1.6l0.15,1.71l0.86,2.96l0.09,0.14l0.5,0.45l-0.31,0.73l-3.11,0.44l-0.16,0.07l-1.07,0.97l-1.36,0.23l-0.25,0.28l-0.1,1.85l-2.74,1.02l-0.14,0.11l-0.9,1.3l-1.93,0.69l-2.56,0.44l-4.04,2.01l-0.17,0.27l0.02,2.91l-0.08,0.0l-0.3,0.31l0.05,1.15l-1.25,0.07l-0.16,0.06l-0.73,0.55l-0.98,0.0l-0.85,-0.33l-0.15,-0.02l-2.11,0.29l-0.24,0.19l-0.76,1.95l-0.63,0.16l-0.21,0.19l-1.15,3.29l-3.42,2.81l-0.1,0.17l-0.81,3.57l-0.98,1.12l-0.3,0.85l-5.13,0.19Z\", \"name\": \"Morocco\"}, \"UZ\": {\"path\": \"M587.83,186.48l0.06,-1.46l-0.19,-0.29l-3.31,-1.24l-2.57,-1.4l-1.63,-1.38l-2.79,-1.98l-1.2,-2.98l-0.12,-0.14l-0.84,-0.54l-0.18,-0.05l-2.61,0.13l-0.76,-0.48l-0.25,-2.25l-0.17,-0.24l-3.37,-1.6l-0.32,0.04l-2.08,1.73l-2.11,1.02l-0.16,0.35l0.31,1.14l-2.14,0.03l-0.09,-10.68l6.1,-1.74l6.25,3.57l2.36,2.72l0.27,0.1l2.92,-0.44l4.17,-0.23l2.78,2.06l-0.18,2.87l0.29,0.32l0.98,0.02l0.46,2.22l0.28,0.24l3.0,0.09l0.61,1.25l0.28,0.17l0.93,-0.02l0.26,-0.16l1.06,-2.06l3.21,-2.03l1.3,-0.5l0.19,0.08l-1.75,1.62l0.05,0.48l1.85,1.12l0.27,0.02l1.65,-0.69l2.4,1.27l-2.69,1.79l-1.79,-0.27l-0.89,0.06l-0.22,-0.52l0.48,-1.26l-0.34,-0.4l-3.35,0.69l-0.22,0.18l-0.78,1.87l-1.07,1.47l-1.93,-0.13l-0.29,0.16l-0.65,1.29l0.16,0.42l1.69,0.64l0.48,1.91l-1.25,2.6l-1.64,-0.53l-1.18,-0.03Z\", \"name\": \"Uzbekistan\"}, \"MM\": {\"path\": \"M670.1,233.39l-1.46,1.11l-1.68,0.11l-0.26,0.19l-1.1,2.7l-0.95,0.42l-0.14,0.42l1.21,2.27l1.61,1.92l0.94,1.55l-0.82,1.99l-0.77,0.42l-0.13,0.39l0.64,1.35l1.62,1.97l0.26,1.32l-0.04,1.15l0.02,0.13l0.92,2.18l-1.3,2.23l-0.79,1.69l-0.1,-0.77l0.74,-1.87l-0.02,-0.26l-0.8,-1.42l0.2,-2.68l-0.06,-0.2l-0.98,-1.27l-0.8,-2.98l-0.45,-3.22l-1.11,-2.22l-0.45,-0.1l-1.64,1.28l-2.74,1.76l-1.26,-0.2l-1.27,-0.49l0.79,-2.93l0.0,-0.14l-0.52,-2.42l-1.93,-2.97l0.26,-0.8l-0.22,-0.39l-1.37,-0.31l-1.65,-1.98l-0.12,-1.5l0.41,0.19l0.42,-0.26l0.05,-1.7l1.08,-0.54l0.16,-0.34l-0.24,-1.0l0.5,-0.79l0.05,-0.15l0.08,-2.35l1.58,0.49l0.36,-0.15l1.12,-2.19l0.15,-1.34l1.35,-2.18l0.04,-0.17l-0.07,-1.35l2.97,-1.71l1.67,0.45l0.38,-0.33l-0.18,-1.46l0.7,-0.4l0.15,-0.32l-0.13,-0.72l0.94,-0.13l0.74,1.41l0.11,0.12l0.95,0.56l0.07,1.89l-0.09,2.08l-2.28,2.15l-0.09,0.19l-0.3,3.15l0.35,0.32l2.37,-0.39l0.53,2.17l0.2,0.21l1.3,0.42l-0.63,1.9l0.14,0.36l1.86,0.99l1.1,0.49l0.24,0.0l1.45,-0.6l0.04,0.51l-2.01,1.6l-0.56,0.96l-1.34,0.56Z\", \"name\": \"Myanmar\"}, \"ML\": {\"path\": \"M390.79,248.2l0.67,-0.37l0.14,-0.18l0.36,-1.31l0.51,-0.04l1.68,0.69l0.21,0.0l1.34,-0.48l0.89,0.16l0.3,-0.13l0.29,-0.44l9.89,-0.04l0.29,-0.21l0.56,-1.8l-0.11,-0.33l-0.33,-0.24l-2.37,-22.1l3.41,-0.04l8.37,5.73l8.38,5.68l0.56,1.15l0.14,0.14l1.56,0.75l0.99,0.36l0.03,1.45l0.33,0.29l2.45,-0.22l0.01,5.52l-1.3,1.64l-0.06,0.15l-0.18,1.37l-1.99,0.36l-3.4,0.22l-0.19,0.09l-0.85,0.83l-1.48,0.09l-1.49,0.01l-0.54,-0.43l-0.26,-0.05l-1.38,0.36l-2.39,1.08l-0.13,0.12l-0.44,0.73l-1.88,1.11l-0.11,0.12l-0.3,0.57l-0.86,0.42l-1.1,-0.31l-0.28,0.07l-0.69,0.62l-0.09,0.16l-0.35,1.66l-1.93,2.04l-0.08,0.23l0.05,0.76l-0.63,0.99l-0.04,0.19l0.14,1.23l-0.81,0.29l-0.32,0.17l-0.27,-0.75l-0.39,-0.18l-0.65,0.26l-0.36,-0.04l-0.29,0.14l-0.37,0.6l-1.69,-0.02l-0.63,-0.34l-0.32,0.02l-0.12,0.09l-0.47,-0.45l0.1,-0.6l-0.09,-0.27l-0.31,-0.3l-0.33,-0.05l-0.05,0.02l0.02,-0.21l0.46,-0.59l-0.02,-0.39l-0.99,-1.02l-0.34,-0.74l-0.56,-0.56l-0.17,-0.09l-0.5,-0.07l-0.19,0.04l-0.58,0.35l-0.79,0.33l-0.65,0.51l-0.85,-0.16l-0.63,-0.59l-0.14,-0.07l-0.41,-0.08l-0.2,0.03l-0.59,0.31l-0.07,0.0l-0.1,-0.63l0.11,-0.85l-0.21,-0.98l-0.11,-0.17l-0.86,-0.66l-0.45,-1.34l-0.1,-1.36Z\", \"name\": \"Mali\"}, \"MN\": {\"path\": \"M641.06,150.59l2.41,-0.53l4.76,-2.8l3.67,-1.49l2.06,0.96l0.12,0.03l2.5,0.05l1.59,1.45l0.19,0.08l2.47,0.12l3.59,0.81l0.27,-0.07l2.43,-2.28l0.06,-0.36l-0.93,-1.77l2.33,-3.1l2.66,1.3l2.26,0.39l2.75,0.8l0.44,2.3l0.19,0.22l3.56,1.38l0.18,0.01l2.35,-0.6l3.1,-0.42l2.4,0.41l2.37,1.52l1.49,1.63l0.23,0.1l2.29,-0.03l3.13,0.52l0.15,-0.01l2.28,-0.79l3.27,-0.53l0.11,-0.04l3.56,-2.23l1.31,0.31l1.26,1.05l0.22,0.07l2.45,-0.22l-0.98,1.96l-1.77,3.21l-0.01,0.28l0.64,1.31l0.35,0.16l1.35,-0.38l2.4,0.48l0.22,-0.04l1.78,-1.09l1.82,0.92l2.11,2.07l-0.17,0.68l-1.79,-0.31l-3.74,0.45l-1.85,0.96l-1.78,2.01l-3.74,1.18l-2.46,1.61l-2.45,-0.6l-1.42,-0.28l-0.31,0.13l-1.31,1.99l0.0,0.33l0.78,1.15l0.3,0.74l-1.58,0.93l-1.75,1.59l-2.83,1.03l-3.77,0.12l-4.05,1.05l-2.81,1.54l-0.95,-0.8l-0.19,-0.07l-2.96,0.0l-3.64,-1.8l-2.55,-0.48l-3.38,0.41l-5.13,-0.67l-2.66,0.06l-1.35,-1.65l-1.12,-2.78l-0.21,-0.18l-1.5,-0.33l-2.98,-1.89l-0.12,-0.04l-3.37,-0.43l-2.84,-0.51l-0.75,-1.13l0.93,-3.54l-0.04,-0.24l-1.73,-2.55l-0.15,-0.12l-3.52,-1.18l-1.99,-1.61l-0.54,-1.85Z\", \"name\": \"Mongolia\"}, \"MK\": {\"path\": \"M472.73,173.87l0.08,0.01l0.32,-0.25l0.08,-0.44l1.29,-0.41l1.37,-0.28l1.03,-0.04l1.06,0.82l0.14,1.59l-0.22,0.04l-0.17,0.11l-0.32,0.4l-1.2,-0.05l-0.18,0.05l-0.9,0.61l-1.45,0.23l-0.85,-0.59l-0.3,-1.09l0.22,-0.71Z\", \"name\": \"Macedonia\"}, \"MW\": {\"path\": \"M507.18,313.84l-0.67,1.85l-0.01,0.16l0.7,3.31l0.31,0.24l0.75,-0.03l0.78,0.71l0.99,1.75l0.2,3.03l-0.91,0.45l-0.14,0.15l-0.59,1.38l-1.24,-1.21l-0.17,-1.62l0.49,-1.12l0.02,-0.16l-0.15,-1.03l-0.13,-0.21l-0.99,-0.65l-0.26,-0.03l-0.53,0.18l-1.31,-1.12l-1.15,-0.59l0.66,-2.06l0.75,-0.84l0.07,-0.27l-0.47,-2.04l0.48,-1.94l0.4,-0.65l0.03,-0.24l-0.64,-2.15l-0.08,-0.13l-0.44,-0.42l1.34,0.26l1.25,1.73l0.67,3.3Z\", \"name\": \"Malawi\"}, \"MR\": {\"path\": \"M390.54,247.66l-1.48,-1.58l-1.51,-1.88l-0.12,-0.09l-1.64,-0.67l-1.17,-0.74l-0.17,-0.05l-1.4,0.03l-0.12,0.03l-1.14,0.52l-1.15,-0.21l-0.26,0.08l-0.44,0.43l-0.11,-0.72l0.68,-1.29l0.31,-2.43l-0.28,-2.63l-0.29,-1.27l0.24,-1.24l-0.03,-0.2l-0.65,-1.24l-1.19,-1.05l0.32,-0.51l9.64,0.02l0.3,-0.34l-0.46,-3.71l0.51,-1.12l2.17,-0.22l0.27,-0.3l-0.08,-6.5l7.91,0.13l0.31,-0.3l0.01,-3.5l8.17,5.63l-2.89,0.04l-0.29,0.33l2.42,22.56l0.12,0.21l0.26,0.19l-0.43,1.38l-9.83,0.04l-0.25,0.13l-0.27,0.41l-0.77,-0.14l-0.15,0.01l-1.3,0.47l-1.64,-0.67l-0.14,-0.02l-0.79,0.06l-0.27,0.22l-0.39,1.39l-0.53,0.29Z\", \"name\": \"Mauritania\"}, \"UG\": {\"path\": \"M500.74,287.17l-2.84,-0.02l-0.92,0.32l-1.37,0.71l-0.29,-0.12l0.02,-1.6l0.54,-0.89l0.04,-0.13l0.14,-1.96l0.49,-1.09l0.91,-1.24l0.97,-0.68l0.8,-0.89l-0.13,-0.49l-0.79,-0.27l0.13,-2.55l0.78,-0.52l1.45,0.51l0.18,0.01l1.97,-0.57l1.72,0.01l0.18,-0.06l1.29,-0.97l0.98,1.44l0.29,1.24l1.05,2.75l-0.84,1.68l-1.94,2.66l-0.06,0.18l0.02,2.36l-4.8,0.18Z\", \"name\": \"Uganda\"}, \"MY\": {\"path\": \"M717.6,273.52l-1.51,0.7l-2.13,-0.41l-2.88,-0.0l-0.29,0.21l-0.84,2.77l-0.9,0.82l-0.08,0.12l-1.23,3.34l-1.81,0.47l-2.29,-0.68l-0.14,-0.01l-1.2,0.22l-0.14,0.07l-1.36,1.18l-1.47,-0.17l-0.12,0.01l-1.46,0.46l-1.51,-1.25l-0.24,-0.97l1.26,0.59l0.2,0.02l1.93,-0.47l0.22,-0.22l0.47,-1.98l0.9,-0.4l2.97,-0.54l0.17,-0.09l1.8,-1.98l1.02,-1.32l0.9,1.03l0.48,-0.04l0.43,-0.7l1.02,0.07l0.32,-0.27l0.25,-2.72l1.84,-1.67l1.23,-1.89l0.73,-0.01l1.12,1.11l0.1,0.99l0.18,0.24l1.66,0.71l1.85,0.67l-0.09,0.51l-1.45,0.11l-0.26,0.4l0.35,0.97ZM673.78,269.53l0.17,1.14l0.35,0.25l1.65,-0.3l0.18,-0.11l0.68,-0.86l0.31,0.13l1.41,1.45l0.99,1.59l0.13,1.57l-0.26,1.09l0.0,0.15l0.24,0.84l0.18,1.46l0.11,0.2l0.82,0.64l0.92,2.08l-0.03,0.52l-1.4,0.13l-2.29,-1.79l-2.86,-1.92l-0.27,-1.16l-0.07,-0.13l-1.39,-1.61l-0.33,-1.99l-0.05,-0.12l-0.84,-1.27l0.26,-1.72l-0.03,-0.18l-0.45,-0.87l0.13,-0.13l1.71,0.92Z\", \"name\": \"Malaysia\"}, \"MX\": {\"path\": \"M133.41,213.83l0.61,0.09l0.27,-0.09l0.93,-1.01l0.08,-0.18l0.09,-1.22l-0.09,-0.23l-1.93,-1.94l-1.46,-0.77l-2.96,-5.62l-0.86,-2.1l2.44,-0.18l2.68,-0.25l-0.03,0.08l0.17,0.4l3.79,1.35l5.81,1.97l6.96,-0.02l0.3,-0.3l0.0,-0.84l3.91,0.0l0.87,0.93l1.27,0.87l1.44,1.17l0.79,1.37l0.62,1.49l0.12,0.14l1.35,0.85l2.08,0.82l0.35,-0.1l1.49,-2.04l1.81,-0.05l1.63,1.01l1.21,1.8l0.86,1.58l1.47,1.55l0.53,1.82l0.73,1.32l0.14,0.13l1.98,0.84l1.78,0.59l0.61,-0.03l-0.78,1.89l-0.45,1.96l-0.19,3.58l-0.24,1.27l0.01,0.14l0.43,1.43l0.78,1.31l0.49,1.98l0.06,0.12l1.63,1.9l0.61,1.51l0.98,1.28l0.16,0.11l2.58,0.67l0.98,1.02l0.31,0.08l2.17,-0.71l1.91,-0.26l1.87,-0.47l1.67,-0.49l1.59,-1.06l0.11,-0.14l0.6,-1.52l0.22,-2.21l0.35,-0.62l1.58,-0.64l2.59,-0.59l2.18,0.09l1.43,-0.2l0.39,0.36l-0.07,1.02l-1.28,1.48l-0.65,1.68l0.07,0.32l0.33,0.32l-0.79,2.49l-0.28,-0.3l-0.24,-0.09l-1.0,0.08l-0.24,0.15l-0.74,1.28l-0.19,-0.13l-0.28,-0.03l-0.3,0.12l-0.19,0.29l0.0,0.06l-4.34,-0.02l-0.3,0.3l-0.0,1.16l-0.83,0.0l-0.28,0.19l0.08,0.33l0.93,0.86l0.9,0.58l0.24,0.48l0.16,0.15l0.2,0.08l-0.03,0.38l-2.94,0.01l-0.26,0.15l-1.21,2.09l0.02,0.33l0.25,0.33l-0.21,0.44l-0.04,0.22l-2.42,-2.35l-1.36,-0.87l-2.04,-0.67l-0.13,-0.01l-1.4,0.19l-2.07,0.98l-1.14,0.23l-1.72,-0.66l-1.85,-0.48l-2.31,-1.16l-1.92,-0.38l-2.79,-1.18l-2.04,-1.2l-0.6,-0.66l-0.19,-0.1l-1.37,-0.15l-2.45,-0.78l-1.07,-1.18l-2.63,-1.44l-1.2,-1.56l-0.44,-0.93l0.5,-0.15l0.2,-0.39l-0.2,-0.58l0.46,-0.55l0.07,-0.19l0.01,-0.91l-0.06,-0.18l-0.81,-1.13l-0.25,-1.08l-0.86,-1.36l-2.21,-2.63l-2.53,-2.09l-1.2,-1.63l-0.11,-0.09l-2.08,-1.06l-0.34,-0.48l0.35,-1.53l-0.16,-0.34l-1.24,-0.61l-1.39,-1.23l-0.6,-1.81l-0.24,-0.2l-1.25,-0.2l-1.38,-1.35l-1.11,-1.25l-0.1,-0.76l-0.05,-0.13l-1.33,-2.04l-0.85,-2.02l0.04,-0.99l-0.14,-0.27l-1.81,-1.1l-0.2,-0.04l-0.74,0.11l-1.34,-0.72l-0.42,0.16l-0.4,1.12l-0.0,0.19l0.41,1.3l0.24,2.04l0.06,0.15l0.88,1.16l1.84,1.86l0.4,0.61l0.12,0.1l0.27,0.14l0.29,0.82l0.31,0.2l0.2,-0.02l0.43,1.51l0.09,0.14l0.72,0.65l0.51,0.91l1.58,1.4l0.8,2.42l0.77,1.23l0.66,1.19l0.13,1.34l0.28,0.27l1.08,0.08l0.92,1.1l0.83,1.08l-0.03,0.24l-0.88,0.81l-0.13,-0.0l-0.59,-1.42l-0.07,-0.11l-1.67,-1.53l-1.81,-1.28l-1.15,-0.61l0.07,-1.85l-0.38,-1.45l-0.12,-0.17l-2.91,-2.03l-0.39,0.04l-0.11,0.11l-0.42,-0.46l-0.11,-0.08l-1.49,-0.63l-1.09,-1.16Z\", \"name\": \"Mexico\"}, \"VU\": {\"path\": \"M839.92,325.66l0.78,0.73l-0.18,0.07l-0.6,-0.8ZM839.13,322.74l0.27,1.36l-0.13,-0.06l-0.21,-0.02l-0.29,0.08l-0.22,-0.43l-0.03,-1.32l0.61,0.4Z\", \"name\": \"Vanuatu\"}, \"FR\": {\"path\": \"M444.58,172.63l-0.68,1.92l-0.72,-0.38l-0.51,-1.79l0.43,-0.95l1.15,-0.83l0.33,2.04ZM429.71,147.03l1.77,1.57l0.26,0.07l1.16,-0.23l2.12,1.44l0.56,0.28l0.16,0.03l0.61,-0.06l1.09,0.78l0.13,0.05l3.18,0.53l-1.09,1.94l-0.3,2.16l-0.48,0.38l-1.0,-0.26l-0.37,0.32l0.07,0.66l-1.73,1.68l-0.09,0.21l-0.04,1.42l0.41,0.29l0.96,-0.4l0.67,1.07l-0.09,0.78l0.04,0.19l0.61,0.97l-0.71,0.78l-0.07,0.28l0.65,2.39l0.21,0.21l1.09,0.31l-0.2,0.95l-2.08,1.58l-4.81,-0.8l-0.13,0.01l-3.65,0.99l-0.22,0.24l-0.25,1.6l-2.59,0.35l-2.74,-1.33l-0.31,0.03l-0.79,0.57l-4.38,-1.31l-0.79,-0.94l1.16,-1.64l0.05,-0.15l0.48,-6.17l-0.06,-0.21l-2.58,-3.3l-1.89,-1.65l-0.11,-0.06l-3.64,-1.17l-0.2,-1.88l2.92,-0.63l4.14,0.82l0.35,-0.36l-0.65,-3.0l1.77,1.05l0.27,0.02l5.83,-2.54l0.17,-0.19l0.71,-2.54l1.75,-0.53l0.27,0.88l0.27,0.21l1.04,0.05l1.08,1.23ZM289.1,278.45l-0.85,0.84l-0.88,0.13l-0.25,-0.51l-0.21,-0.16l-0.56,-0.1l-0.25,0.07l-0.63,0.55l-0.62,-0.29l0.5,-0.88l0.21,-1.11l0.42,-1.05l-0.03,-0.28l-0.93,-1.42l-0.18,-1.54l1.13,-1.87l2.42,0.78l2.55,2.04l0.33,0.81l-1.4,2.16l-0.77,1.84Z\", \"name\": \"France\"}, \"FI\": {\"path\": \"M492.26,76.42l-0.38,3.12l0.12,0.28l3.6,2.69l-2.14,2.96l-0.01,0.33l2.83,4.61l-1.61,3.36l0.03,0.31l2.15,2.87l-0.96,2.44l0.1,0.35l3.51,2.55l-0.81,1.72l-2.28,2.19l-5.28,4.79l-4.51,0.31l-4.39,1.37l-3.87,0.75l-1.34,-1.89l-0.11,-0.09l-2.23,-1.14l0.53,-3.54l-0.01,-0.14l-1.17,-3.37l1.12,-2.13l2.23,-2.44l5.69,-4.33l1.65,-0.84l0.16,-0.31l-0.26,-1.73l-0.15,-0.22l-3.4,-1.91l-0.77,-1.47l-0.07,-6.45l-0.12,-0.24l-3.91,-2.94l-3.0,-1.92l0.97,-0.76l2.6,2.17l0.21,0.07l3.2,-0.21l2.63,1.03l0.3,-0.05l2.39,-1.94l0.09,-0.13l1.18,-3.12l3.63,-1.42l2.87,1.59l-0.98,2.87Z\", \"name\": \"Finland\"}, \"FJ\": {\"path\": \"M869.98,327.07l-1.31,0.44l-0.14,-0.41l0.96,-0.41l0.85,-0.17l1.43,-0.78l-0.16,0.65l-1.64,0.67ZM867.58,329.12l0.54,0.47l-0.31,1.0l-1.32,0.3l-1.13,-0.26l-0.17,-0.78l0.72,-0.66l0.98,0.27l0.25,-0.04l0.43,-0.29Z\", \"name\": \"Fiji\"}, \"FK\": {\"path\": \"M268.15,427.89l2.6,-1.73l1.98,0.77l0.31,-0.05l1.32,-1.17l1.58,1.18l-0.54,0.84l-3.1,0.92l-1.0,-1.04l-0.39,-0.04l-1.9,1.35l-0.86,-1.04Z\", \"name\": \"Falkland Islands\"}, \"NI\": {\"path\": \"M202.1,252.6l0.23,-0.0l0.12,-0.11l0.68,-0.09l0.22,-0.15l0.23,-0.43l0.2,-0.01l0.28,-0.31l-0.04,-0.97l0.29,-0.03l0.5,0.02l0.25,-0.11l0.37,-0.46l0.51,0.35l0.4,-0.06l0.23,-0.28l0.45,-0.29l0.87,-0.7l0.11,-0.21l0.02,-0.26l0.23,-0.12l0.25,-0.48l0.29,0.27l0.14,0.07l0.5,0.12l0.22,-0.03l0.48,-0.28l0.66,-0.02l0.87,-0.33l0.36,-0.32l0.21,0.01l-0.11,0.48l0.0,0.14l0.22,0.8l-0.54,0.85l-0.27,1.03l-0.09,1.18l0.14,0.72l0.05,0.95l-0.24,0.15l-0.13,0.19l-0.23,1.09l0.0,0.14l0.14,0.53l-0.42,0.53l-0.06,0.24l0.12,0.69l0.08,0.15l0.18,0.19l-0.26,0.23l-0.49,-0.11l-0.35,-0.44l-0.16,-0.1l-0.79,-0.21l-0.23,0.03l-0.45,0.26l-1.51,-0.62l-0.31,0.05l-0.17,0.15l-1.81,-1.62l-0.6,-0.9l-1.04,-0.79l-0.77,-0.71Z\", \"name\": \"Nicaragua\"}, \"NL\": {\"path\": \"M436.22,136.65l1.82,0.08l0.36,0.89l-0.6,2.96l-0.53,1.06l-1.32,0.0l-0.3,0.34l0.35,2.89l-0.83,-0.47l-1.56,-1.43l-0.29,-0.07l-2.26,0.67l-1.02,-0.15l0.68,-0.48l0.1,-0.12l2.14,-4.84l3.25,-1.35Z\", \"name\": \"Netherlands\"}, \"NO\": {\"path\": \"M491.45,67.31l7.06,3.0l-2.52,0.94l-0.11,0.49l2.43,2.49l-3.82,1.59l-1.48,0.3l0.89,-2.61l-0.14,-0.36l-3.21,-1.78l-0.25,-0.02l-3.89,1.52l-0.17,0.17l-1.2,3.17l-2.19,1.78l-2.53,-0.99l-0.13,-0.02l-3.15,0.21l-2.69,-2.25l-0.38,-0.01l-1.43,1.11l-1.47,0.17l-0.26,0.26l-0.33,2.57l-4.42,-0.65l-0.33,0.22l-0.6,2.19l-2.17,-0.01l-0.27,0.16l-4.15,7.68l-3.88,5.76l-0.0,0.33l0.81,1.23l-0.7,1.27l-2.3,-0.06l-0.28,0.18l-1.63,3.72l-0.02,0.13l0.15,5.17l0.07,0.18l1.51,1.84l-0.79,4.24l-2.04,2.5l-0.92,1.75l-1.39,-1.88l-0.44,-0.05l-4.89,4.21l-3.16,0.81l-3.24,-1.74l-0.86,-3.82l-0.78,-8.6l2.18,-2.36l6.56,-3.28l5.0,-4.16l4.63,-5.74l5.99,-8.09l4.17,-3.23l6.84,-5.49l5.39,-1.92l4.06,0.24l0.23,-0.09l3.72,-3.67l4.51,0.19l4.4,-0.89ZM484.58,19.95l4.42,1.82l-3.25,2.68l-7.14,0.65l-7.16,-0.91l-0.39,-1.37l-0.28,-0.22l-3.48,-0.1l-2.25,-2.15l7.09,-1.48l3.55,1.36l0.28,-0.03l2.42,-1.66l6.18,1.41ZM481.99,33.92l-4.73,1.85l-3.76,-1.06l1.27,-1.02l0.04,-0.43l-1.18,-1.35l4.46,-0.94l0.89,1.83l0.17,0.15l2.83,0.96ZM466.5,23.95l7.64,3.87l-5.63,1.94l-0.19,0.19l-1.35,3.88l-2.08,0.96l-0.16,0.19l-1.14,4.18l-2.71,0.18l-4.94,-2.95l1.95,-1.63l-0.08,-0.51l-3.7,-1.54l-4.79,-4.54l-1.78,-4.01l6.29,-1.88l1.25,1.81l0.25,0.13l3.57,-0.08l0.26,-0.17l0.87,-1.79l3.41,-0.18l3.08,1.94Z\", \"name\": \"Norway\"}, \"NA\": {\"path\": \"M461.88,357.98l-1.61,-1.77l-0.94,-1.9l-0.54,-2.58l-0.62,-1.95l-0.83,-4.05l-0.06,-3.13l-0.33,-1.5l-0.07,-0.14l-0.95,-1.06l-1.27,-2.12l-1.3,-3.1l-0.59,-1.71l-1.98,-2.46l-0.13,-1.67l0.99,-0.4l1.44,-0.42l1.48,0.07l1.42,1.11l0.31,0.03l0.32,-0.15l9.99,-0.11l1.66,1.18l0.16,0.06l6.06,0.37l4.69,-1.06l2.01,-0.57l1.5,0.14l0.63,0.37l-1.0,0.41l-0.7,0.01l-0.16,0.05l-1.38,0.88l-0.79,-0.88l-0.29,-0.09l-3.83,0.9l-1.84,0.08l-0.29,0.3l-0.07,8.99l-2.18,0.08l-0.29,0.3l-0.0,17.47l-2.04,1.27l-1.21,0.18l-1.51,-0.49l-0.99,-0.18l-0.36,-1.0l-0.1,-0.14l-0.99,-0.74l-0.4,0.04l-0.98,1.09Z\", \"name\": \"Namibia\"}, \"NC\": {\"path\": \"M835.87,338.68l2.06,1.63l1.01,0.94l-0.49,0.32l-1.21,-0.62l-1.76,-1.16l-1.58,-1.36l-1.61,-1.79l-0.16,-0.41l0.54,0.02l1.32,0.83l1.08,0.87l0.79,0.73Z\", \"name\": \"New Caledonia\"}, \"NE\": {\"path\": \"M426.67,254.17l0.03,-1.04l-0.24,-0.3l-2.66,-0.53l-0.06,-1.0l-0.07,-0.17l-1.37,-1.62l-0.3,-1.04l0.15,-0.94l1.37,-0.09l0.19,-0.09l0.85,-0.83l3.34,-0.22l2.22,-0.41l0.24,-0.26l0.2,-1.5l1.32,-1.65l0.07,-0.19l-0.01,-5.74l3.4,-1.13l7.24,-5.12l8.46,-4.95l3.76,1.08l1.35,1.39l0.36,0.05l1.39,-0.77l0.55,3.66l0.12,0.2l0.82,0.6l0.03,0.69l0.1,0.21l0.87,0.74l-0.47,0.99l-0.96,5.26l-0.13,3.25l-3.08,2.34l-0.1,0.15l-1.08,3.37l0.08,0.31l0.94,0.86l-0.01,1.51l0.29,0.3l1.25,0.05l-0.14,0.66l-0.51,0.11l-0.24,0.26l-0.06,0.57l-0.04,0.0l-1.59,-2.62l-0.21,-0.14l-0.59,-0.1l-0.23,0.05l-1.83,1.33l-1.79,-0.68l-1.42,-0.17l-0.17,0.03l-0.65,0.32l-1.39,-0.07l-0.19,0.06l-1.4,1.03l-1.12,0.05l-2.97,-1.29l-0.26,0.01l-1.12,0.59l-1.08,-0.04l-0.85,-0.88l-0.11,-0.07l-2.51,-0.95l-0.14,-0.02l-2.69,0.3l-0.16,0.07l-0.65,0.55l-0.1,0.16l-0.34,1.41l-0.69,0.98l-0.05,0.15l-0.13,1.72l-1.47,-1.13l-0.18,-0.06l-0.9,0.01l-0.2,0.08l-0.32,0.28Z\", \"name\": \"Niger\"}, \"NG\": {\"path\": \"M442.0,272.7l-2.4,0.83l-0.88,-0.12l-0.19,0.04l-0.89,0.52l-1.78,-0.05l-1.23,-1.44l-0.88,-1.87l-1.77,-1.66l-0.21,-0.08l-3.78,0.03l0.13,-3.75l-0.06,-1.58l0.44,-1.47l0.74,-0.75l1.21,-1.56l0.04,-0.29l-0.22,-0.56l0.44,-0.9l0.01,-0.24l-0.54,-1.44l0.26,-2.97l0.72,-1.06l0.33,-1.37l0.51,-0.43l2.53,-0.28l2.38,0.9l0.89,0.91l0.2,0.09l1.28,0.04l0.15,-0.03l1.06,-0.56l2.9,1.26l0.13,0.02l1.28,-0.06l0.16,-0.06l1.39,-1.02l1.36,0.07l0.15,-0.03l0.64,-0.32l1.22,0.13l1.9,0.73l0.28,-0.04l1.86,-1.35l0.33,0.06l1.62,2.67l0.29,0.14l0.32,-0.04l0.73,0.74l-0.19,0.37l-0.12,0.74l-2.03,1.89l-0.07,0.11l-0.66,1.62l-0.35,1.28l-0.48,0.51l-0.07,0.12l-0.48,1.67l-1.26,0.98l-0.1,0.15l-0.38,1.24l-0.58,1.07l-0.2,0.91l-1.43,0.7l-1.26,-0.93l-0.19,-0.06l-0.95,0.04l-0.2,0.09l-1.41,1.39l-0.61,0.02l-0.26,0.17l-1.19,2.42l-0.61,1.67Z\", \"name\": \"Nigeria\"}, \"NZ\": {\"path\": \"M857.9,379.62l1.85,3.1l0.33,0.14l0.22,-0.28l0.04,-1.41l0.57,0.4l0.35,2.06l0.17,0.22l2.02,0.94l1.78,0.26l0.22,-0.06l1.31,-1.01l0.84,0.22l-0.53,2.27l-0.67,1.5l-1.71,-0.05l-0.25,0.12l-0.67,0.89l-0.05,0.23l0.21,1.15l-0.31,0.46l-2.15,3.57l-1.6,0.99l-0.28,-0.51l-0.15,-0.13l-0.72,-0.3l1.27,-2.15l0.01,-0.29l-0.82,-1.63l-0.15,-0.14l-2.5,-1.09l0.05,-0.69l1.67,-0.94l0.15,-0.21l0.42,-2.24l-0.11,-1.95l-0.03,-0.12l-0.97,-1.85l0.05,-0.41l-0.09,-0.25l-1.18,-1.17l-1.94,-2.49l-0.86,-1.64l0.38,-0.09l1.24,1.43l0.12,0.08l1.81,0.68l0.67,2.39ZM853.93,393.55l0.57,1.24l0.44,0.12l1.51,-1.03l0.52,0.91l0.0,1.09l-0.88,1.31l-1.62,2.2l-1.26,1.2l-0.05,0.38l0.64,1.02l-1.4,0.03l-0.14,0.04l-2.14,1.16l-0.14,0.17l-0.67,2.0l-1.38,3.06l-3.07,2.19l-2.12,-0.06l-1.55,-0.99l-0.14,-0.05l-2.53,-0.2l-0.31,-0.84l1.25,-2.15l3.07,-2.97l1.62,-0.59l1.81,-1.17l2.18,-1.63l1.55,-1.65l1.08,-2.18l0.9,-0.72l0.11,-0.17l0.35,-1.56l1.37,-1.07l0.4,0.91Z\", \"name\": \"New Zealand\"}, \"NP\": {\"path\": \"M641.26,213.53l-0.14,0.95l0.32,1.64l-0.21,0.78l-1.83,0.04l-2.98,-0.62l-1.86,-0.25l-1.37,-1.3l-0.18,-0.08l-3.38,-0.34l-3.21,-1.49l-2.38,-1.34l-2.16,-0.92l0.84,-2.2l1.51,-1.18l0.89,-0.57l1.83,0.77l2.5,1.76l1.39,0.41l0.78,1.21l0.17,0.13l1.91,0.53l2.0,1.17l2.92,0.66l2.63,0.24Z\", \"name\": \"Nepal\"}, \"CI\": {\"path\": \"M413.53,272.08l-0.83,0.02l-1.79,-0.49l-1.64,0.03l-3.04,0.46l-1.73,0.72l-2.4,0.89l-0.12,-0.02l0.16,-1.7l0.19,-0.25l0.06,-0.2l-0.08,-0.99l-0.09,-0.19l-1.06,-1.05l-0.15,-0.08l-0.71,-0.15l-0.51,-0.48l0.45,-0.92l0.02,-0.19l-0.24,-1.16l0.07,-0.43l0.14,-0.0l0.3,-0.26l0.15,-1.1l-0.02,-0.15l-0.13,-0.34l0.09,-0.13l0.83,-0.27l0.19,-0.37l-0.62,-2.02l-0.55,-1.0l0.14,-0.59l0.35,-0.14l0.24,-0.16l0.53,0.29l0.14,0.04l1.93,0.02l0.26,-0.14l0.36,-0.58l0.39,0.01l0.43,-0.17l0.28,0.79l0.43,0.16l0.56,-0.31l0.89,-0.32l0.92,0.45l0.39,0.75l0.14,0.13l1.13,0.53l0.3,-0.03l0.81,-0.59l1.02,-0.08l1.49,0.57l0.62,3.33l-1.03,2.09l-0.65,2.84l0.02,0.2l1.05,2.08l-0.07,0.64Z\", \"name\": \"Ivory Coast\"}, \"CH\": {\"path\": \"M444.71,156.27l0.05,0.3l-0.34,0.69l0.13,0.4l1.13,0.58l1.07,0.1l-0.12,0.81l-0.87,0.42l-1.75,-0.37l-0.34,0.18l-0.47,1.1l-0.86,0.07l-0.33,-0.38l-0.41,-0.04l-1.34,1.01l-1.02,0.13l-0.93,-0.58l-0.82,-1.32l-0.37,-0.12l-0.77,0.32l0.02,-0.84l1.74,-1.69l0.09,-0.25l-0.04,-0.38l0.73,0.19l0.26,-0.06l0.6,-0.48l2.02,0.02l0.24,-0.12l0.38,-0.51l2.31,0.84Z\", \"name\": \"Switzerland\"}, \"CO\": {\"path\": \"M232.24,284.95l-0.94,-0.52l-1.22,-0.82l-0.31,-0.01l-0.62,0.35l-1.88,-0.31l-0.54,-0.95l-0.29,-0.15l-0.37,0.03l-2.34,-1.33l-0.15,-0.35l0.57,-0.11l0.24,-0.32l-0.1,-1.15l0.46,-0.71l1.11,-0.15l0.21,-0.13l1.05,-1.57l0.95,-1.31l-0.08,-0.43l-0.73,-0.47l0.4,-1.24l0.01,-0.16l-0.53,-2.15l0.44,-0.54l0.06,-0.24l-0.4,-2.13l-0.06,-0.13l-0.93,-1.22l0.21,-0.8l0.52,0.12l0.32,-0.13l0.47,-0.75l0.03,-0.27l-0.52,-1.32l0.09,-0.11l1.14,0.07l0.22,-0.08l1.82,-1.71l0.96,-0.25l0.22,-0.28l0.02,-0.81l0.43,-2.01l1.28,-1.04l1.48,-0.05l0.27,-0.19l0.12,-0.31l1.73,0.19l0.2,-0.05l1.96,-1.28l0.97,-0.56l1.16,-1.16l0.64,0.11l0.43,0.44l-0.31,0.55l-1.49,0.39l-0.19,0.16l-0.6,1.2l-0.97,0.74l-0.73,0.94l-0.06,0.13l-0.3,1.76l-0.68,1.44l0.23,0.43l1.1,0.14l0.27,0.97l0.08,0.13l0.49,0.49l0.17,0.85l-0.27,0.86l-0.01,0.14l0.09,0.53l0.2,0.23l0.52,0.18l0.54,0.79l0.27,0.13l3.18,-0.24l1.31,0.29l1.7,2.08l0.31,0.1l0.96,-0.26l1.75,0.13l1.41,-0.27l0.56,0.27l-0.36,1.07l-0.54,0.81l-0.05,0.13l-0.2,1.8l0.51,1.79l0.07,0.12l0.65,0.68l0.05,0.32l-1.16,1.14l0.05,0.47l0.86,0.52l0.6,0.79l0.31,1.01l-0.7,-0.81l-0.44,-0.01l-0.74,0.77l-4.75,-0.05l-0.3,0.31l0.03,1.57l0.25,0.29l1.2,0.21l-0.02,0.24l-0.1,-0.05l-0.22,-0.02l-1.41,0.41l-0.22,0.29l-0.01,1.82l0.11,0.23l1.04,0.85l0.35,1.3l-0.06,1.02l-1.02,6.26l-0.84,-0.89l-0.19,-0.09l-0.25,-0.02l1.35,-2.13l-0.1,-0.42l-1.92,-1.17l-0.2,-0.04l-1.41,0.2l-0.82,-0.39l-0.26,0.0l-1.29,0.62l-1.63,-0.27l-1.4,-2.5l-0.12,-0.12l-1.1,-0.61l-0.83,-1.2l-1.67,-1.19l-0.27,-0.04l-0.54,0.19Z\", \"name\": \"Colombia\"}, \"CN\": {\"path\": \"M740.32,148.94l0.22,0.21l4.3,1.03l2.84,2.2l0.99,2.92l0.28,0.2l3.8,0.0l0.15,-0.04l2.13,-1.24l3.5,-0.8l-1.05,2.29l-0.95,1.13l-0.06,0.12l-0.85,3.41l-1.56,2.81l-2.83,-0.51l-0.19,0.03l-2.15,1.09l-0.15,0.34l0.65,2.59l-0.33,3.3l-1.03,0.07l-0.28,0.3l0.01,0.75l-1.09,-1.2l-0.48,0.05l-0.94,1.6l-3.76,1.26l-0.2,0.36l0.29,1.19l-1.67,-0.08l-1.11,-0.88l-0.42,0.05l-1.69,2.08l-2.71,1.57l-2.04,1.88l-3.42,0.84l-0.11,0.05l-1.8,1.34l-1.54,0.46l0.52,-0.53l0.06,-0.33l-0.44,-0.96l1.84,-1.84l0.02,-0.41l-1.32,-1.56l-0.36,-0.08l-2.23,1.08l-2.83,2.06l-1.52,1.85l-2.32,0.13l-0.2,0.09l-1.28,1.37l-0.03,0.37l1.32,1.97l0.18,0.13l1.83,0.43l0.07,1.08l0.18,0.26l1.98,0.84l0.3,-0.03l2.66,-1.96l2.06,1.04l0.12,0.03l1.4,0.07l0.27,1.0l-3.24,0.73l-0.17,0.11l-1.13,1.5l-2.38,1.4l-0.1,0.1l-1.29,1.99l0.1,0.42l2.6,1.5l0.97,2.72l1.52,2.56l1.66,2.08l-0.03,1.76l-1.4,0.67l-0.15,0.38l0.6,1.47l0.13,0.15l1.29,0.75l-0.35,2.0l-0.58,1.96l-1.22,0.21l-0.2,0.14l-1.83,2.93l-2.02,3.51l-2.29,3.13l-3.4,2.42l-3.42,2.18l-2.75,0.3l-0.15,0.06l-1.32,1.01l-0.68,-0.67l-0.41,-0.01l-1.37,1.27l-3.42,1.28l-2.62,0.4l-0.24,0.21l-0.8,2.57l-0.95,0.11l-0.53,-1.54l0.52,-0.89l-0.19,-0.44l-3.36,-0.84l-0.17,0.01l-1.09,0.4l-2.36,-0.64l-1.0,-0.9l0.35,-1.34l-0.23,-0.37l-2.22,-0.47l-1.15,-0.94l-0.36,-0.02l-2.08,1.37l-2.35,0.29l-1.98,-0.01l-0.13,0.03l-1.32,0.63l-1.28,0.38l-0.21,0.33l0.33,2.65l-0.78,-0.04l-0.14,-0.39l-0.07,-1.04l-0.41,-0.26l-1.72,0.71l-0.96,-0.43l-1.63,-0.86l0.65,-1.95l-0.19,-0.38l-1.43,-0.46l-0.56,-2.27l-0.34,-0.22l-2.26,0.38l0.25,-2.65l2.29,-2.15l0.09,-0.2l0.1,-2.21l-0.07,-2.09l-0.15,-0.25l-1.02,-0.6l-0.8,-1.52l-0.31,-0.16l-1.42,0.2l-2.16,-0.32l0.55,-0.74l0.01,-0.35l-1.17,-1.7l-0.41,-0.08l-1.67,1.07l-1.97,-0.63l-0.25,0.03l-2.89,1.73l-2.26,1.99l-1.82,0.3l-1.0,-0.66l-0.15,-0.05l-1.28,-0.06l-1.75,-0.61l-0.24,0.02l-1.35,0.69l-0.1,0.08l-1.2,1.45l-0.14,-1.41l-0.4,-0.25l-1.46,0.55l-2.83,-0.26l-2.77,-0.61l-1.99,-1.17l-1.91,-0.54l-0.78,-1.21l-0.17,-0.13l-1.36,-0.38l-2.54,-1.79l-2.01,-0.84l-0.28,0.02l-0.89,0.56l-3.31,-1.83l-2.35,-1.67l-0.57,-2.49l1.34,0.28l0.36,-0.28l0.08,-1.42l-0.05,-0.19l-0.93,-1.34l0.24,-2.18l-0.07,-0.22l-2.69,-3.32l-0.15,-0.1l-3.97,-1.11l-0.69,-2.05l-0.11,-0.15l-1.79,-1.3l-0.39,-0.73l-0.36,-1.57l0.08,-1.09l-0.18,-0.3l-1.52,-0.66l-0.22,-0.01l-0.51,0.18l-0.52,-2.21l0.59,-0.55l0.06,-0.35l-0.22,-0.44l2.12,-1.24l1.63,-0.55l2.58,0.39l0.31,-0.16l0.87,-1.75l3.05,-0.34l0.21,-0.12l0.84,-1.12l3.87,-1.59l0.15,-0.14l0.35,-0.68l0.03,-0.17l-0.17,-1.51l1.52,-0.7l0.15,-0.39l-2.12,-5.0l4.62,-1.15l1.35,-0.72l0.14,-0.17l1.72,-5.37l4.7,0.99l0.28,-0.08l1.39,-1.43l0.08,-0.2l0.11,-2.95l1.83,-0.26l0.18,-0.1l1.85,-2.08l0.61,-0.17l0.57,1.97l0.1,0.15l2.2,1.75l3.48,1.17l1.59,2.36l-0.93,3.53l0.04,0.24l0.9,1.35l0.2,0.13l2.98,0.53l3.32,0.43l2.97,1.89l1.49,0.35l1.08,2.67l1.52,1.88l0.24,0.11l2.74,-0.07l5.15,0.67l3.36,-0.41l2.39,0.43l3.67,1.81l0.13,0.03l2.92,-0.0l1.02,0.86l0.34,0.03l2.88,-1.59l3.98,-1.03l3.81,-0.13l3.02,-1.12l1.77,-1.61l1.73,-1.01l0.13,-0.37l-0.41,-1.01l-0.72,-1.07l1.09,-1.66l1.21,0.24l2.57,0.63l0.24,-0.04l2.46,-1.62l3.78,-1.19l0.13,-0.09l1.8,-2.03l1.66,-0.84l3.54,-0.41l1.93,0.35l0.34,-0.22l0.27,-1.12l-0.08,-0.29l-2.27,-2.22l-2.08,-1.07l-0.29,0.01l-1.82,1.12l-2.36,-0.47l-0.14,0.01l-1.18,0.34l-0.46,-0.94l1.69,-3.08l1.1,-2.21l2.75,1.12l0.26,-0.02l3.53,-2.06l0.15,-0.26l-0.02,-1.35l2.18,-3.39l1.35,-1.04l0.12,-0.24l-0.03,-1.85l-0.15,-0.25l-1.0,-0.58l1.68,-1.37l3.01,-0.59l3.25,-0.09l3.67,0.99l2.08,1.18l1.51,3.3l0.95,1.45l0.85,1.99l0.92,3.19ZM697.0,237.37l-1.95,1.12l-1.74,-0.68l-0.06,-1.9l1.08,-1.03l2.62,-0.7l1.23,0.05l0.37,0.65l-1.01,1.08l-0.54,1.4Z\", \"name\": \"China\"}, \"CM\": {\"path\": \"M453.76,278.92l-0.26,-0.11l-0.18,-0.02l-1.42,0.31l-1.56,-0.33l-1.17,0.16l-3.7,-0.05l0.3,-1.63l-0.04,-0.21l-0.98,-1.66l-0.15,-0.13l-1.03,-0.38l-0.46,-1.01l-0.13,-0.14l-0.48,-0.27l0.02,-0.46l0.62,-1.72l1.1,-2.25l0.54,-0.02l0.2,-0.09l1.41,-1.39l0.73,-0.03l1.32,0.97l0.31,0.03l1.72,-0.85l0.16,-0.2l0.22,-1.0l0.57,-1.03l0.36,-1.18l1.26,-0.98l0.1,-0.15l0.49,-1.7l0.48,-0.51l0.07,-0.13l0.35,-1.3l0.63,-1.54l2.06,-1.92l0.09,-0.17l0.12,-0.79l0.24,-0.41l-0.04,-0.36l-0.89,-0.91l0.04,-0.45l0.28,-0.06l0.85,1.39l0.16,1.59l-0.09,1.66l0.04,0.17l1.09,1.84l-0.86,-0.02l-0.72,0.17l-1.07,-0.24l-0.34,0.17l-0.54,1.19l0.06,0.34l1.48,1.47l1.06,0.44l0.32,0.94l0.73,1.6l-0.32,0.57l-1.23,2.49l-0.54,0.41l-0.12,0.21l-0.19,1.95l0.24,1.08l-0.18,0.67l0.07,0.28l1.13,1.25l0.24,0.93l0.92,1.29l1.1,0.8l0.1,1.01l0.26,0.73l-0.12,0.93l-1.65,-0.49l-2.02,-0.66l-3.19,-0.11Z\", \"name\": \"Cameroon\"}, \"CL\": {\"path\": \"M246.8,429.1l-1.14,0.78l-2.25,1.21l-0.16,0.23l-0.37,2.94l-0.75,0.06l-2.72,-1.07l-2.83,-2.34l-3.06,-1.9l-0.71,-1.92l0.67,-1.84l-0.02,-0.25l-1.22,-2.13l-0.31,-5.41l1.02,-2.95l2.59,-2.4l-0.13,-0.51l-3.32,-0.8l2.06,-2.4l0.07,-0.15l0.79,-4.77l2.44,0.95l0.4,-0.22l1.31,-6.31l-0.16,-0.33l-1.68,-0.8l-0.42,0.21l-0.72,3.47l-1.01,-0.27l0.74,-4.06l0.85,-5.46l1.12,-1.96l0.03,-0.22l-0.71,-2.82l-0.19,-2.94l0.76,-0.07l0.26,-0.2l1.53,-4.62l1.73,-4.52l1.07,-4.2l-0.56,-4.2l0.73,-2.2l0.01,-0.12l-0.29,-3.3l1.46,-3.34l0.45,-5.19l0.8,-5.52l0.78,-5.89l-0.18,-4.33l-0.49,-3.47l1.1,-0.56l0.13,-0.13l0.44,-0.88l0.9,1.29l0.32,1.8l0.1,0.18l1.16,0.97l-0.73,2.33l0.01,0.21l1.33,2.91l0.97,3.6l0.35,0.22l1.57,-0.31l0.16,0.34l-0.79,2.51l-2.61,1.25l-0.17,0.28l0.08,4.36l-0.48,0.79l0.01,0.33l0.6,0.84l-1.62,1.55l-1.67,2.6l-0.89,2.47l-0.02,0.13l0.23,2.56l-1.5,2.76l-0.03,0.21l1.15,4.8l0.11,0.17l0.54,0.42l-0.01,2.37l-1.4,2.7l-0.03,0.15l0.06,2.25l-1.8,1.78l-0.09,0.21l0.02,2.73l0.71,2.63l-1.33,0.94l-0.12,0.17l-0.67,2.64l-0.59,3.03l0.4,3.55l-0.84,0.51l-0.14,0.31l0.58,3.5l0.08,0.16l0.96,0.99l-0.7,1.08l0.11,0.43l1.04,0.55l0.19,0.8l-0.89,0.48l-0.16,0.31l0.26,1.77l-0.89,4.06l-1.31,2.67l-0.03,0.19l0.28,1.53l-0.73,1.88l-1.85,1.37l-0.12,0.26l0.22,3.46l0.06,0.16l0.88,1.19l0.28,0.12l1.32,-0.17l-0.04,2.13l0.04,0.15l1.04,1.95l0.24,0.16l5.94,0.44ZM248.79,430.71l0.0,7.41l0.3,0.3l2.67,0.0l1.01,0.06l-0.54,0.91l-1.99,1.01l-1.13,-0.1l-1.42,-0.27l-1.87,-1.06l-2.57,-0.49l-3.09,-1.9l-2.52,-1.83l-2.65,-2.93l0.93,0.32l3.54,2.29l3.32,1.23l0.34,-0.09l1.29,-1.57l0.83,-2.32l2.11,-1.28l1.43,0.32Z\", \"name\": \"Chile\"}, \"CA\": {\"path\": \"M280.14,145.66l-1.66,2.88l0.06,0.37l0.37,0.03l1.5,-1.01l1.17,0.49l-0.64,0.83l0.13,0.46l2.22,0.89l0.28,-0.03l1.02,-0.7l2.09,0.83l-0.69,2.1l0.37,0.38l1.43,-0.45l0.27,1.43l0.74,1.88l-0.95,2.5l-0.88,0.09l-1.34,-0.48l0.49,-2.34l-0.14,-0.32l-0.7,-0.4l-0.36,0.04l-2.81,2.66l-0.63,-0.05l1.2,-1.01l-0.1,-0.52l-2.4,-0.77l-2.79,0.18l-4.65,-0.09l-0.22,-0.54l1.37,-0.99l0.01,-0.48l-0.82,-0.65l1.91,-1.79l2.57,-5.17l1.49,-1.81l2.04,-1.07l0.63,0.08l-0.27,0.51l-1.33,2.07ZM193.92,74.85l-0.01,4.24l0.19,0.28l0.33,-0.07l3.14,-3.22l2.65,2.5l-0.71,3.04l0.06,0.26l2.42,2.88l0.46,0.0l2.66,-3.14l1.83,-3.74l0.03,-0.12l0.13,-4.53l3.23,0.31l3.63,0.64l3.18,2.08l0.13,1.91l-1.79,2.22l-0.0,0.37l1.69,2.2l-0.28,1.8l-4.74,2.84l-3.33,0.62l-2.5,-1.21l-0.41,0.17l-0.73,2.05l-2.39,3.44l-0.74,1.78l-2.78,2.61l-3.48,0.26l-0.17,0.07l-1.98,1.68l-0.1,0.21l-0.15,2.33l-2.68,0.45l-0.17,0.09l-3.1,3.2l-2.75,4.38l-0.99,3.06l-0.14,4.31l0.25,0.31l3.5,0.58l1.07,3.24l1.18,2.76l0.34,0.18l3.43,-0.69l4.55,1.52l2.45,1.32l1.76,1.65l0.12,0.07l3.11,0.96l2.63,1.46l0.13,0.04l4.12,0.2l2.41,0.3l-0.36,2.81l0.8,3.51l1.81,3.78l0.08,0.1l3.73,3.17l0.34,0.03l1.93,-1.08l0.13,-0.15l1.35,-3.44l0.01,-0.18l-1.31,-5.38l-0.08,-0.14l-1.46,-1.5l3.68,-1.51l2.84,-2.46l1.45,-2.55l0.04,-0.17l-0.2,-2.39l-0.04,-0.12l-1.7,-3.07l-2.9,-2.64l2.79,-3.66l0.05,-0.27l-1.08,-3.38l-0.8,-5.75l1.45,-0.75l4.18,1.03l2.6,0.38l0.18,-0.03l1.93,-0.95l2.18,1.23l3.01,2.18l0.73,1.42l0.25,0.16l4.18,0.27l-0.06,2.95l0.83,4.7l0.22,0.24l2.19,0.55l1.75,2.08l0.38,0.07l3.63,-2.03l0.11,-0.11l2.38,-4.06l1.36,-1.43l1.76,3.01l3.26,4.68l2.68,4.19l-0.94,2.09l0.12,0.38l3.31,1.98l2.23,1.98l0.13,0.07l3.94,0.89l1.48,1.02l0.96,2.82l0.22,0.2l1.85,0.43l0.88,1.13l0.17,3.53l-1.68,1.16l-1.76,1.14l-4.08,1.17l-0.11,0.06l-3.08,2.65l-4.11,0.52l-5.35,-0.69l-3.76,-0.02l-2.62,0.23l-0.2,0.1l-2.05,2.29l-3.13,1.41l-0.11,0.08l-3.6,4.24l-2.87,2.92l-0.05,0.36l0.33,0.14l2.13,-0.52l0.15,-0.08l3.98,-4.15l5.16,-2.63l3.58,-0.31l1.82,1.3l-2.09,1.91l-0.09,0.29l0.8,3.46l0.82,2.37l0.15,0.17l3.25,1.56l0.16,0.03l4.14,-0.45l0.21,-0.12l2.03,-2.86l0.11,1.46l0.13,0.22l1.26,0.88l-2.7,1.78l-5.51,1.83l-2.52,1.26l-2.75,2.16l-1.52,-0.18l-0.08,-2.16l4.19,-2.47l0.14,-0.34l-0.3,-0.22l-4.01,0.1l-2.66,0.36l-1.45,-1.56l0.0,-4.16l-0.11,-0.23l-1.11,-0.91l-0.28,-0.05l-1.5,0.48l-0.7,-0.7l-0.45,0.02l-1.91,2.39l-0.8,2.5l-0.82,1.31l-0.95,0.43l-0.77,0.15l-0.23,0.2l-0.18,0.56l-8.2,0.02l-0.13,0.03l-1.19,0.61l-2.95,2.45l-0.78,1.13l-4.6,0.01l-0.12,0.02l-1.13,0.48l-0.13,0.44l0.37,0.55l0.2,0.82l-0.01,0.09l-3.1,1.42l-2.63,0.5l-2.84,1.57l-0.47,0.0l-0.72,-0.4l-0.18,-0.27l0.03,-0.15l0.52,-1.0l1.2,-1.71l0.73,-1.8l0.02,-0.17l-1.03,-5.47l-0.15,-0.21l-2.35,-1.32l0.16,-0.29l-0.05,-0.35l-0.37,-0.38l-0.22,-0.09l-0.56,0.0l-0.35,-0.34l-0.11,-0.65l-0.46,-0.2l-0.39,0.26l-0.2,-0.03l-0.11,-0.33l-0.48,-0.25l-0.21,-0.71l-0.15,-0.18l-3.97,-2.07l-4.8,-2.39l-0.25,-0.01l-2.19,0.89l-0.72,0.03l-3.04,-0.82l-0.14,-0.0l-1.94,0.4l-2.4,-0.98l-2.56,-0.51l-1.7,-0.19l-0.62,-0.44l-0.42,-1.67l-0.3,-0.23l-0.85,0.02l-0.29,0.3l-0.01,0.95l-69.26,-0.01l-4.77,-3.14l-1.78,-1.41l-4.51,-1.38l-1.3,-2.73l0.34,-1.96l-0.17,-0.33l-3.06,-1.37l-0.41,-2.58l-0.11,-0.18l-2.92,-2.4l-0.05,-1.53l1.32,-1.59l0.07,-0.2l-0.07,-2.21l-0.16,-0.26l-4.19,-2.22l-2.52,-4.02l-1.56,-2.6l-0.08,-0.09l-2.28,-1.64l-1.65,-1.48l-1.31,-1.89l-0.38,-0.1l-2.51,1.21l-2.28,1.92l-2.03,-2.22l-1.85,-1.71l-2.44,-1.04l-2.28,-0.12l0.03,-37.72l4.27,0.98l4.0,2.13l2.61,0.4l0.24,-0.07l2.17,-1.81l2.92,-1.33l3.63,0.53l0.18,-0.03l3.72,-1.94l3.89,-1.06l1.6,1.72l0.37,0.06l1.87,-1.04l0.14,-0.19l0.48,-1.83l1.37,0.38l4.18,3.96l0.41,0.0l2.89,-2.62l0.28,2.79l0.37,0.26l3.08,-0.73l0.17,-0.12l0.85,-1.16l2.81,0.24l3.83,1.86l5.86,1.61l3.46,0.75l2.44,-0.26l2.89,1.89l-3.12,1.89l-0.14,0.31l0.24,0.24l4.53,0.92l6.84,-0.5l2.04,-0.71l2.54,2.44l0.39,0.02l2.72,-2.16l-0.01,-0.48l-2.26,-1.61l1.27,-1.16l2.94,-0.19l1.94,-0.42l1.89,0.97l2.49,2.32l0.24,0.08l2.71,-0.33l4.35,1.9l0.17,0.02l3.86,-0.67l3.62,0.1l0.31,-0.33l-0.26,-2.44l1.9,-0.65l3.58,1.36l-0.01,3.84l0.23,0.29l0.34,-0.17l1.51,-3.23l1.81,0.1l0.31,-0.22l1.13,-4.37l-0.08,-0.29l-2.68,-2.73l-2.83,-1.76l0.19,-4.73l2.77,-3.15l3.06,0.69l2.44,1.97l3.24,4.88l-2.05,2.02l0.15,0.51l4.41,0.85ZM265.85,150.7l-0.84,0.04l-3.15,-0.99l-1.77,-1.17l0.19,-0.06l3.17,0.79l2.39,1.27l0.01,0.12ZM249.41,3.71l6.68,0.49l5.34,0.79l4.34,1.6l-0.08,1.24l-5.91,2.56l-6.03,1.21l-2.36,1.38l-0.14,0.34l0.29,0.22l4.37,-0.02l-4.96,3.01l-4.06,1.64l-0.11,0.08l-4.21,4.62l-5.07,0.92l-0.12,0.05l-1.53,1.1l-7.5,0.59l-0.28,0.28l0.24,0.31l2.67,0.54l-1.04,0.6l-0.09,0.44l1.89,2.49l-2.11,1.66l-3.83,1.52l-0.15,0.13l-1.14,2.01l-3.41,1.55l-0.16,0.36l0.35,1.19l0.3,0.22l3.98,-0.19l0.03,0.78l-6.42,2.99l-6.44,-1.41l-7.41,0.79l-3.72,-0.62l-4.48,-0.26l-0.25,-2.0l4.37,-1.13l0.21,-0.38l-1.14,-3.55l1.13,-0.28l6.61,2.29l0.35,-0.12l-0.04,-0.37l-3.41,-3.45l-0.14,-0.08l-3.57,-0.92l1.62,-1.7l4.36,-1.3l0.2,-0.18l0.71,-1.94l-0.12,-0.36l-3.45,-2.15l-0.88,-2.43l6.36,0.23l1.94,0.61l0.23,-0.02l3.91,-2.1l0.15,-0.32l-0.26,-0.24l-5.69,-0.67l-8.69,0.37l-4.3,-1.92l-2.12,-2.39l-2.82,-1.68l-0.44,-1.65l3.41,-1.06l2.93,-0.2l4.91,-0.99l3.69,-2.28l2.93,0.31l2.64,1.68l0.42,-0.1l1.84,-3.23l3.17,-0.96l4.45,-0.69l7.56,-0.26l1.26,0.64l0.18,0.03l7.2,-1.06l10.81,0.8ZM203.94,57.59l0.01,0.32l1.97,2.97l0.51,-0.01l2.26,-3.75l6.05,-1.89l4.08,4.72l-0.36,2.95l0.38,0.33l4.95,-1.36l0.11,-0.05l2.23,-1.77l5.37,2.31l3.32,2.14l0.3,1.89l0.36,0.25l4.48,-1.01l2.49,2.8l0.14,0.09l5.99,1.78l2.09,1.74l2.18,3.83l-4.29,1.91l-0.01,0.54l5.9,2.83l3.95,0.94l3.54,3.84l0.2,0.1l3.58,0.25l-0.67,2.51l-4.18,4.54l-2.84,-1.61l-3.91,-3.95l-0.26,-0.09l-3.24,0.52l-0.25,0.26l-0.32,2.37l0.1,0.26l2.63,2.38l3.42,1.89l0.96,1.0l1.57,3.8l-0.74,2.43l-2.85,-0.96l-6.26,-3.15l-0.38,0.09l0.04,0.39l3.54,3.4l2.55,2.31l0.23,0.78l-6.26,-1.43l-5.33,-2.25l-2.73,-1.73l0.67,-0.86l-0.09,-0.45l-7.38,-4.01l-0.44,0.27l0.03,0.89l-6.85,0.61l-1.8,-1.17l1.43,-2.6l4.56,-0.07l5.15,-0.52l0.23,-0.45l-0.76,-1.34l0.8,-1.89l3.21,-4.06l0.05,-0.29l-0.72,-1.95l-0.97,-1.47l-0.11,-0.1l-3.84,-2.1l-4.53,-1.33l1.09,-0.75l0.05,-0.45l-2.65,-2.75l-0.18,-0.09l-2.12,-0.24l-1.91,-1.47l-0.39,0.02l-1.27,1.25l-4.4,0.56l-9.06,-0.99l-5.28,-1.31l-4.01,-0.67l-1.72,-1.31l2.32,-1.85l0.1,-0.33l-0.28,-0.2l-3.3,-0.02l-0.74,-4.36l1.86,-4.09l2.46,-1.88l5.74,-1.15l-1.5,2.55ZM261.28,159.28l0.19,0.14l1.82,0.42l1.66,-0.05l-0.66,0.68l-0.75,0.16l-3.0,-1.25l-0.46,-0.77l0.51,-0.52l0.68,1.19ZM230.87,84.48l-2.48,0.19l-0.52,-1.74l0.96,-2.17l2.03,-0.53l1.71,1.04l0.02,1.6l-0.22,0.46l-1.5,1.16ZM229.52,58.19l0.14,0.82l-4.99,-0.22l-2.73,0.63l-0.59,-0.23l-2.61,-2.4l0.08,-1.38l0.94,-0.25l5.61,0.51l4.14,2.54ZM222.12,105.0l-0.79,1.63l-0.75,-0.22l-0.52,-0.91l0.04,-0.09l0.84,-1.01l0.74,0.06l0.44,0.55ZM183.77,38.22l2.72,1.65l0.16,0.04l4.83,-0.01l1.92,1.52l-0.51,1.75l0.18,0.36l2.84,1.14l1.56,1.19l0.16,0.06l3.37,0.22l3.65,0.42l4.07,-1.1l5.05,-0.43l3.96,0.35l2.53,1.8l0.48,1.79l-1.37,1.16l-3.6,1.03l-3.22,-0.59l-7.17,0.76l-5.1,0.09l-4.0,-0.6l-6.48,-1.56l-0.81,-2.57l-0.3,-2.49l-0.1,-0.19l-2.51,-2.25l-0.16,-0.07l-5.12,-0.63l-2.61,-1.45l0.75,-1.71l4.88,0.32ZM207.46,91.26l0.42,1.62l0.42,0.19l1.12,-0.55l1.35,0.99l2.74,1.39l2.73,1.2l0.2,1.74l0.35,0.26l1.72,-0.29l1.31,0.97l-1.72,0.96l-3.68,-0.9l-1.34,-1.71l-0.43,-0.04l-2.46,2.1l-3.23,1.85l-0.74,-1.98l-0.31,-0.19l-2.47,0.28l1.49,-1.34l0.1,-0.19l0.32,-3.15l0.79,-3.45l1.34,0.25ZM215.59,102.66l-2.73,2.0l-1.49,-0.08l-0.37,-0.7l1.61,-1.56l3.0,0.03l-0.02,0.3ZM202.79,24.07l0.11,0.12l2.54,1.53l-3.01,1.47l-4.55,4.07l-4.3,0.38l-5.07,-0.68l-2.51,-2.09l0.03,-1.72l1.86,-1.4l0.1,-0.34l-0.29,-0.2l-4.49,0.04l-2.63,-1.79l-1.45,-2.36l1.61,-2.38l1.65,-1.69l2.47,-0.4l0.19,-0.48l-0.72,-0.89l5.1,-0.26l3.1,3.05l0.13,0.07l4.21,1.25l3.99,1.06l1.92,3.65ZM187.5,59.3l-0.15,0.1l-2.59,3.4l-2.5,-0.15l-1.47,-3.92l0.04,-2.24l1.22,-1.92l2.34,-1.26l5.11,0.17l4.28,1.06l-3.36,3.86l-2.9,0.9ZM186.19,48.8l-1.15,1.63l-3.42,-0.35l-2.68,-1.15l1.11,-1.88l3.34,-1.27l2.01,1.63l0.79,1.38ZM185.78,35.41l-0.95,0.13l-4.48,-0.33l-0.4,-0.91l4.5,0.07l1.45,0.82l-0.1,0.21ZM180.76,32.56l-3.43,1.03l-1.85,-1.14l-1.01,-1.92l-0.16,-1.87l2.87,0.2l1.39,0.35l2.75,1.75l-0.55,1.6ZM181.03,76.32l-1.21,1.2l-3.19,-1.26l-0.18,-0.01l-1.92,0.45l-2.88,-1.67l1.84,-1.16l1.6,-1.77l2.45,1.17l1.45,0.77l2.05,2.28ZM169.72,54.76l2.83,0.97l0.14,0.01l4.25,-0.58l0.47,1.01l-2.19,2.16l0.07,0.48l3.61,1.95l-0.41,3.84l-3.87,1.68l-2.23,-0.36l-1.73,-1.75l-6.07,-3.53l0.03,-1.01l4.79,0.55l0.3,-0.16l-0.04,-0.34l-2.55,-2.89l2.59,-2.05ZM174.44,40.56l1.49,1.87l0.07,2.48l-1.07,3.52l-3.87,0.48l-2.41,-0.72l0.05,-2.72l-0.33,-0.3l-3.79,0.36l-0.13,-3.31l2.36,0.14l0.15,-0.03l3.7,-1.74l3.44,0.29l0.31,-0.22l0.03,-0.12ZM170.14,31.5l0.75,1.74l-3.52,-0.52l-4.19,-1.77l-4.65,-0.17l1.65,-1.11l-0.05,-0.52l-2.86,-1.26l-0.13,-1.58l4.52,0.7l6.66,1.99l1.84,2.5ZM134.64,58.08l-1.08,1.93l0.34,0.44l5.44,-1.41l3.37,2.32l0.37,-0.02l2.66,-2.28l2.03,1.38l2.01,4.53l0.53,0.04l1.26,-1.93l0.03,-0.27l-1.67,-4.55l1.82,-0.58l2.36,0.73l2.69,1.84l1.53,4.46l0.77,3.24l0.15,0.19l4.22,2.26l4.32,2.04l-0.21,1.51l-3.87,0.34l-0.19,0.5l1.45,1.54l-0.65,1.23l-4.3,-0.65l-4.4,-1.19l-2.97,0.28l-4.67,1.48l-6.31,0.65l-4.27,0.39l-1.26,-1.91l-0.15,-0.12l-3.42,-1.2l-0.16,-0.01l-2.05,0.45l-2.66,-3.02l1.2,-0.34l3.82,-0.76l3.58,0.19l3.27,-0.78l0.23,-0.29l-0.24,-0.29l-4.84,-1.06l-5.42,0.35l-3.4,-0.09l-0.97,-1.22l5.39,-1.7l0.21,-0.33l-0.3,-0.25l-3.82,0.06l-3.95,-1.1l1.88,-3.13l1.68,-1.81l6.54,-2.84l2.11,0.77ZM158.85,56.58l-1.82,2.62l-3.38,-2.9l0.49,-0.39l3.17,-0.18l1.54,0.86ZM149.71,42.7l1.0,1.87l0.37,0.14l2.17,-0.83l2.33,0.2l0.38,2.16l-1.38,2.17l-8.33,0.76l-6.34,2.15l-3.51,0.1l-0.22,-1.13l4.98,-2.12l0.17,-0.34l-0.31,-0.23l-11.27,0.6l-3.04,-0.78l3.14,-4.57l2.2,-1.35l6.87,1.7l4.4,3.0l0.14,0.05l4.37,0.39l0.27,-0.48l-3.41,-4.68l1.96,-1.62l2.28,0.53l0.79,2.32ZM145.44,29.83l-2.18,0.77l-3.79,-0.0l0.02,-0.31l2.34,-1.5l1.2,0.23l2.42,0.83ZM144.83,34.5l-4.44,1.46l-3.18,-1.48l1.6,-1.36l3.51,-0.53l3.1,0.75l-0.6,1.16ZM119.02,65.87l-6.17,2.07l-1.19,-1.82l-0.13,-0.11l-5.48,-2.32l0.92,-1.7l1.73,-3.44l2.16,-3.15l-0.02,-0.36l-2.09,-2.56l7.84,-0.71l3.59,1.02l6.32,0.27l2.35,1.37l2.25,1.71l-2.68,1.04l-6.21,3.41l-3.1,3.28l-0.08,0.21l0.0,1.81ZM129.66,35.4l-0.3,3.55l-1.77,1.67l-2.34,0.27l-4.62,2.2l-3.89,0.76l-2.83,-0.93l3.85,-3.52l5.04,-3.36l3.75,0.07l3.11,-0.7ZM111.24,152.74l-0.82,0.29l-3.92,-1.39l-0.7,-1.06l-0.12,-0.1l-2.15,-1.09l-0.41,-0.84l-0.2,-0.16l-2.44,-0.56l-0.84,-1.56l0.1,-0.36l2.34,0.64l1.53,0.5l2.28,0.34l0.78,1.04l1.24,1.55l0.09,0.08l2.42,1.3l0.81,1.39ZM88.54,134.82l0.14,0.02l2.0,-0.23l-0.67,3.48l0.06,0.24l1.78,2.22l-0.24,-0.0l-1.4,-1.42l-0.91,-1.53l-1.26,-1.08l-0.42,-1.35l0.09,-0.66l0.82,0.31Z\", \"name\": \"Canada\"}, \"CG\": {\"path\": \"M453.66,296.61l-0.9,-0.82l-0.35,-0.04l-0.83,0.48l-0.77,0.83l-1.65,-2.13l1.66,-1.2l0.08,-0.39l-0.81,-1.43l0.59,-0.43l1.62,-0.29l0.24,-0.24l0.1,-0.58l0.94,0.84l0.19,0.08l2.21,0.11l0.27,-0.14l0.81,-1.29l0.32,-1.76l-0.27,-1.96l-0.06,-0.15l-1.08,-1.35l1.02,-2.74l-0.09,-0.34l-0.62,-0.5l-0.22,-0.06l-1.66,0.18l-0.55,-1.03l0.12,-0.73l2.85,0.09l1.98,0.65l2.0,0.59l0.38,-0.25l0.17,-1.3l1.26,-2.24l1.34,-1.19l1.54,0.38l1.35,0.12l-0.11,1.15l-0.74,1.34l-0.5,1.61l-0.31,2.22l0.12,1.41l-0.4,0.9l-0.06,0.88l-0.24,0.67l-1.57,1.15l-1.24,1.41l-1.09,2.43l-0.03,0.13l0.08,1.95l-0.55,0.69l-1.46,1.23l-1.32,1.41l-0.61,-0.29l-0.13,-0.57l-0.29,-0.23l-1.36,-0.02l-0.23,0.1l-0.72,0.81l-0.41,-0.16Z\", \"name\": \"Republic of the Congo\"}, \"CF\": {\"path\": \"M459.41,266.56l1.9,-0.17l0.22,-0.12l0.36,-0.5l0.14,0.02l0.55,0.51l0.29,0.07l3.15,-0.96l0.12,-0.07l1.05,-0.97l1.29,-0.87l0.12,-0.33l-0.17,-0.61l0.38,-0.12l2.36,0.15l0.15,-0.03l2.36,-1.17l0.12,-0.1l1.78,-2.72l1.18,-0.96l1.23,-0.34l0.21,0.79l0.07,0.13l1.37,1.5l0.01,0.86l-0.39,1.0l-0.01,0.17l0.16,0.78l0.1,0.17l0.91,0.76l1.89,1.09l1.24,0.92l0.02,0.67l0.12,0.23l1.67,1.3l0.99,1.03l0.61,1.46l0.14,0.15l1.79,0.95l0.2,0.4l-0.44,0.14l-1.54,-0.06l-1.98,-0.26l-0.93,0.22l-0.19,0.14l-0.3,0.48l-0.57,0.05l-0.91,-0.49l-0.26,-0.01l-2.7,1.21l-1.04,-0.23l-0.21,0.03l-0.34,0.19l-0.12,0.13l-0.64,1.3l-1.67,-0.43l-1.77,-0.24l-1.58,-0.91l-2.06,-0.85l-0.27,0.02l-1.42,0.88l-0.97,1.27l-0.06,0.14l-0.19,1.46l-1.3,-0.11l-1.67,-0.42l-0.27,0.07l-1.55,1.41l-0.99,1.76l-0.14,-1.18l-0.13,-0.22l-1.1,-0.78l-0.86,-1.2l-0.2,-0.84l-0.07,-0.13l-1.07,-1.19l0.16,-0.59l0.0,-0.15l-0.24,-1.01l0.18,-1.77l0.5,-0.38l0.09,-0.11l1.18,-2.4Z\", \"name\": \"Central African Republic\"}, \"CD\": {\"path\": \"M497.85,276.25l-0.14,2.77l0.2,0.3l0.57,0.19l-0.47,0.52l-1.0,0.71l-0.96,1.31l-0.56,1.22l-0.16,2.04l-0.54,0.89l-0.04,0.15l-0.02,1.76l-0.63,0.61l-0.09,0.2l-0.08,1.33l-0.2,0.11l-0.15,0.21l-0.23,1.37l0.03,0.2l0.6,1.08l0.16,2.96l0.44,2.29l-0.24,1.25l0.01,0.15l0.5,1.46l0.07,0.12l1.41,1.37l1.09,2.56l-0.51,-0.11l-3.45,0.45l-0.67,0.3l-0.15,0.15l-0.71,1.61l0.01,0.26l0.52,1.03l-0.43,2.9l-0.31,2.55l0.13,0.29l0.7,0.46l1.75,0.99l0.31,-0.01l0.26,-0.17l0.15,1.9l-1.44,-0.02l-0.94,-1.28l-0.94,-1.1l-0.17,-0.1l-1.76,-0.33l-0.5,-1.18l-0.42,-0.15l-1.44,0.75l-1.79,-0.32l-0.77,-1.05l-0.2,-0.12l-1.59,-0.23l-0.97,0.04l-0.1,-0.53l-0.27,-0.25l-0.86,-0.06l-1.13,-0.15l-1.62,0.37l-1.04,-0.06l-0.32,0.09l0.11,-2.56l-0.08,-0.21l-0.77,-0.87l-0.17,-1.41l0.36,-1.47l-0.03,-0.21l-0.48,-0.91l-0.04,-1.52l-0.3,-0.29l-2.65,0.02l0.13,-0.53l-0.29,-0.37l-1.28,0.01l-0.28,0.21l-0.07,0.24l-1.35,0.09l-0.26,0.18l-0.62,1.45l-0.25,0.42l-1.17,-0.3l-0.19,0.01l-0.79,0.34l-1.44,0.18l-1.41,-1.96l-0.7,-1.47l-0.61,-1.86l-0.28,-0.21l-7.39,-0.03l-0.92,0.3l-0.78,-0.03l-0.78,0.25l-0.11,-0.25l0.35,-0.15l0.18,-0.26l0.07,-1.02l0.33,-0.52l0.72,-0.42l0.52,0.2l0.33,-0.08l0.76,-0.86l0.99,0.02l0.11,0.48l0.16,0.2l0.94,0.44l0.35,-0.07l1.46,-1.56l1.44,-1.21l0.68,-0.85l0.06,-0.2l-0.08,-1.99l1.04,-2.33l1.1,-1.23l1.62,-1.19l0.11,-0.14l0.29,-0.8l0.08,-0.94l0.38,-0.82l0.03,-0.16l-0.13,-1.38l0.3,-2.16l0.47,-1.51l0.73,-1.31l0.04,-0.12l0.15,-1.51l0.21,-1.66l0.89,-1.16l1.16,-0.7l1.9,0.79l1.69,0.95l1.81,0.24l1.85,0.48l0.35,-0.16l0.71,-1.43l0.16,-0.09l1.03,0.23l0.19,-0.02l2.65,-1.19l0.86,0.46l0.17,0.03l0.81,-0.08l0.23,-0.14l0.31,-0.5l0.75,-0.17l1.83,0.26l1.64,0.06l0.72,-0.21l1.39,1.9l0.16,0.11l1.12,0.3l0.24,-0.04l0.58,-0.36l1.05,0.15l0.15,-0.02l1.15,-0.44l0.47,0.84l0.08,0.09l2.08,1.57Z\", \"name\": \"Democratic Republic of the Congo\"}, \"CZ\": {\"path\": \"M463.29,152.22l-0.88,-0.47l-0.18,-0.03l-1.08,0.15l-1.86,-0.94l-0.21,-0.02l-0.88,0.24l-0.13,0.07l-1.25,1.17l-1.63,-0.91l-1.38,-1.36l-1.22,-0.75l-0.24,-1.24l-0.33,-0.75l1.53,-0.6l0.98,-0.84l1.74,-0.62l0.11,-0.07l0.47,-0.47l0.46,0.27l0.24,0.03l0.96,-0.3l1.06,0.95l0.15,0.07l1.57,0.24l-0.1,0.6l0.16,0.32l1.36,0.68l0.41,-0.15l0.28,-0.62l1.29,0.28l0.19,0.84l0.26,0.23l1.73,0.18l0.74,1.02l-0.17,0.0l-0.25,0.13l-0.32,0.49l-0.46,0.11l-0.22,0.23l-0.13,0.57l-0.32,0.1l-0.2,0.22l-0.03,0.14l-0.65,0.25l-1.05,-0.05l-0.28,0.17l-0.22,0.43Z\", \"name\": \"Czech Republic\"}, \"CY\": {\"path\": \"M505.03,193.75l-1.51,0.68l-1.0,-0.3l-0.32,-0.63l0.69,-0.06l0.41,0.13l0.19,-0.0l0.62,-0.22l0.31,0.02l0.06,0.22l0.49,0.17l0.06,-0.01Z\", \"name\": \"Cyprus\"}, \"CR\": {\"path\": \"M213.0,263.84l-0.98,-0.4l-0.3,-0.31l0.16,-0.24l0.05,-0.21l-0.09,-0.56l-0.1,-0.18l-0.76,-0.65l-0.99,-0.5l-0.74,-0.28l-0.13,-0.58l-0.12,-0.18l-0.66,-0.45l-0.34,-0.0l-0.13,0.31l0.13,0.59l-0.17,0.21l-0.34,-0.42l-0.14,-0.1l-0.7,-0.22l-0.23,-0.34l0.01,-0.62l0.31,-0.74l-0.14,-0.38l-0.3,-0.15l0.47,-0.4l1.48,0.6l0.26,-0.02l0.47,-0.27l0.58,0.15l0.35,0.44l0.17,0.11l0.74,0.17l0.27,-0.07l0.3,-0.27l0.52,1.09l0.97,1.02l0.77,0.71l-0.41,0.1l-0.23,0.3l0.01,1.02l0.12,0.24l0.2,0.14l-0.07,0.05l-0.11,0.3l0.08,0.37l-0.23,0.63Z\", \"name\": \"Costa Rica\"}, \"CU\": {\"path\": \"M215.01,226.09l2.08,0.18l1.94,0.03l2.24,0.86l0.95,0.92l0.25,0.08l2.22,-0.28l0.79,0.55l3.68,2.81l0.19,0.06l0.77,-0.03l1.18,0.42l-0.12,0.47l0.27,0.37l1.78,0.1l1.59,0.9l-0.11,0.22l-1.5,0.3l-1.64,0.13l-1.75,-0.2l-2.69,0.19l1.0,-0.86l-0.03,-0.48l-1.02,-0.68l-0.13,-0.05l-1.52,-0.16l-0.74,-0.64l-0.57,-1.42l-0.3,-0.19l-1.36,0.1l-2.23,-0.67l-0.71,-0.52l-0.14,-0.06l-3.2,-0.4l-0.42,-0.25l0.56,-0.39l0.12,-0.33l-0.27,-0.22l-2.46,-0.13l-0.2,0.06l-1.72,1.31l-0.94,0.03l-0.25,0.15l-0.29,0.53l-1.04,0.24l-0.29,-0.07l0.7,-0.43l0.1,-0.11l0.5,-0.87l1.04,-0.54l1.23,-0.49l1.86,-0.25l0.62,-0.28Z\", \"name\": \"Cuba\"}, \"SZ\": {\"path\": \"M500.95,353.41l-0.41,0.97l-1.16,0.23l-1.29,-1.26l-0.02,-0.71l0.63,-0.93l0.23,-0.7l0.47,-0.12l1.04,0.4l0.32,1.05l0.2,1.08Z\", \"name\": \"Swaziland\"}, \"SY\": {\"path\": \"M510.84,199.83l0.09,-0.11l0.07,-0.2l-0.04,-1.08l0.56,-1.4l1.3,-1.01l0.1,-0.34l-0.41,-1.11l-0.24,-0.19l-0.89,-0.11l-0.2,-1.84l0.55,-1.05l1.3,-1.22l0.09,-0.19l0.09,-1.09l0.39,0.27l0.25,0.04l2.66,-0.77l1.35,0.52l2.06,-0.01l2.93,-1.08l1.35,0.04l2.14,-0.34l-0.83,1.16l-1.31,0.68l-0.16,0.3l0.23,2.03l-0.9,3.25l-5.43,2.87l-4.79,2.91l-2.32,-0.92Z\", \"name\": \"Syria\"}, \"KG\": {\"path\": \"M599.04,172.15l0.38,-0.9l1.43,-0.37l4.04,1.02l0.37,-0.23l0.36,-1.64l1.17,-0.52l3.45,1.24l0.2,-0.0l0.86,-0.31l4.09,0.08l3.61,0.31l1.18,1.02l0.11,0.06l1.19,0.34l-0.13,0.26l-3.84,1.58l-0.13,0.1l-0.81,1.08l-3.08,0.34l-0.24,0.16l-0.85,1.7l-2.43,-0.37l-0.14,0.01l-1.79,0.61l-2.39,1.4l-0.12,0.39l0.25,0.49l-0.48,0.45l-4.57,0.43l-3.04,-0.94l-2.45,0.18l0.14,-1.02l2.42,0.44l0.27,-0.08l0.81,-0.81l1.76,0.27l0.21,-0.05l3.21,-2.14l-0.03,-0.51l-2.97,-1.57l-0.26,-0.01l-1.64,0.69l-1.38,-0.84l1.81,-1.67l-0.09,-0.5l-0.46,-0.18Z\", \"name\": \"Kyrgyzstan\"}, \"KE\": {\"path\": \"M523.3,287.04l0.06,0.17l1.29,1.8l-1.46,0.84l-0.11,0.11l-0.55,0.93l-0.81,0.16l-0.24,0.24l-0.34,1.69l-0.81,1.06l-0.46,1.58l-0.76,0.63l-3.3,-2.3l-0.16,-1.32l-0.15,-0.23l-9.35,-5.28l-0.02,-2.4l1.92,-2.63l0.91,-1.83l0.01,-0.24l-1.09,-2.86l-0.29,-1.24l-1.09,-1.63l2.93,-2.85l0.92,0.3l0.0,1.19l0.09,0.22l0.86,0.83l0.21,0.08l1.65,0.0l3.09,2.08l0.16,0.05l0.79,0.03l0.54,-0.06l0.58,0.28l1.67,0.2l0.28,-0.12l0.69,-0.98l2.04,-0.94l0.86,0.73l0.19,0.07l1.1,0.0l-1.82,2.36l-0.06,0.18l0.03,9.12Z\", \"name\": \"Kenya\"}, \"SS\": {\"path\": \"M505.7,261.39l0.02,1.64l-0.27,0.55l-1.15,0.05l-0.24,0.15l-0.85,1.44l0.22,0.45l1.44,0.17l1.15,1.12l0.42,0.95l0.14,0.15l1.06,0.54l1.33,2.45l-3.06,2.98l-1.44,1.08l-1.75,0.01l-1.92,0.56l-1.5,-0.53l-0.27,0.03l-0.85,0.57l-1.98,-1.5l-0.56,-1.02l-0.37,-0.13l-1.32,0.5l-1.08,-0.15l-0.2,0.04l-0.56,0.35l-0.9,-0.24l-1.44,-1.97l-0.39,-0.77l-0.13,-0.13l-1.78,-0.94l-0.65,-1.5l-1.08,-1.12l-1.57,-1.22l-0.02,-0.68l-0.12,-0.23l-1.37,-1.02l-1.17,-0.68l0.2,-0.08l0.86,-0.48l0.14,-0.18l0.63,-2.22l0.6,-1.02l1.47,-0.28l0.35,0.56l1.29,1.48l0.14,0.09l0.69,0.22l0.22,-0.02l0.83,-0.4l1.58,0.08l0.26,0.39l0.25,0.13l2.49,0.0l0.3,-0.25l0.06,-0.35l1.13,-0.42l0.18,-0.18l0.22,-0.63l0.68,-0.38l1.95,1.37l0.23,0.05l1.29,-0.26l0.19,-0.12l1.23,-1.8l1.36,-1.37l0.08,-0.25l-0.21,-1.52l-0.06,-0.15l-0.25,-0.3l0.94,-0.08l0.26,-0.21l0.1,-0.32l0.6,0.09l-0.25,1.67l0.3,1.83l0.11,0.19l1.22,0.94l0.25,0.73l-0.04,1.2l0.26,0.31l0.09,0.01Z\", \"name\": \"South Sudan\"}, \"SR\": {\"path\": \"M278.1,270.26l2.71,0.45l0.31,-0.14l0.19,-0.32l1.82,-0.16l2.25,0.56l-1.09,1.81l-0.04,0.19l0.2,1.72l0.05,0.13l0.9,1.35l-0.39,0.99l-0.21,1.09l-0.48,0.8l-1.2,-0.44l-0.17,-0.01l-1.12,0.24l-0.95,-0.21l-0.35,0.2l-0.25,0.73l0.05,0.29l0.3,0.35l-0.06,0.13l-1.01,-0.15l-1.42,-2.03l-0.32,-1.36l-0.29,-0.23l-0.63,-0.0l-0.95,-1.56l0.41,-1.16l0.01,-0.17l-0.08,-0.35l1.29,-0.56l0.18,-0.22l0.35,-1.97Z\", \"name\": \"Suriname\"}, \"KH\": {\"path\": \"M680.28,257.89l-0.93,-1.2l-1.24,-2.56l-0.56,-2.9l1.45,-1.92l3.07,-0.46l2.26,0.35l2.03,0.98l0.38,-0.11l1.0,-1.55l1.86,0.79l0.52,1.51l-0.28,2.82l-4.05,1.88l-0.12,0.45l0.79,1.1l-2.2,0.17l-2.08,0.98l-1.89,-0.33Z\", \"name\": \"Cambodia\"}, \"SV\": {\"path\": \"M197.02,248.89l0.18,-0.05l0.59,0.17l0.55,0.51l0.64,0.35l0.06,0.22l0.37,0.21l1.01,-0.28l0.38,0.13l0.16,0.13l-0.14,0.81l-0.18,0.38l-1.22,-0.03l-0.84,-0.23l-1.11,-0.52l-1.31,-0.15l-0.49,-0.38l0.02,-0.08l0.76,-0.57l0.46,-0.27l0.11,-0.35Z\", \"name\": \"El Salvador\"}, \"SK\": {\"path\": \"M468.01,150.02l0.05,0.07l0.36,0.1l0.85,-0.37l1.12,1.02l0.33,0.05l1.38,-0.65l1.07,0.3l0.16,0.0l1.69,-0.43l1.95,1.02l-0.51,0.64l-0.45,1.2l-0.32,0.2l-2.55,-0.93l-0.17,-0.01l-0.82,0.2l-0.17,0.11l-0.53,0.68l-0.94,0.32l-0.14,-0.11l-0.29,-0.04l-1.18,0.48l-0.95,0.09l-0.26,0.21l-0.15,0.47l-1.84,0.34l-0.82,-0.31l-1.14,-0.73l-0.2,-0.89l0.42,-0.84l0.91,0.05l0.12,-0.02l0.86,-0.33l0.18,-0.21l0.03,-0.13l0.32,-0.1l0.2,-0.22l0.12,-0.55l0.39,-0.1l0.18,-0.13l0.3,-0.45l0.43,-0.0Z\", \"name\": \"Slovakia\"}, \"KR\": {\"path\": \"M737.31,185.72l0.84,0.08l0.27,-0.12l0.89,-1.2l1.63,-0.13l1.1,-0.2l0.21,-0.16l0.12,-0.24l1.86,2.95l0.59,1.79l0.02,3.17l-0.84,1.38l-2.23,0.55l-1.95,1.14l-1.91,0.21l-0.22,-1.21l0.45,-2.07l-0.01,-0.17l-0.99,-2.67l1.54,-0.4l0.17,-0.46l-1.55,-2.24Z\", \"name\": \"South Korea\"}, \"SI\": {\"path\": \"M455.77,159.59l1.79,0.21l0.18,-0.04l1.2,-0.68l2.12,-0.08l0.21,-0.1l0.38,-0.42l0.1,0.01l0.28,0.62l-1.71,0.71l-0.18,0.22l-0.21,1.1l-0.71,0.26l-0.2,0.28l0.01,0.55l-0.59,-0.04l-0.79,-0.47l-0.38,0.06l-0.36,0.41l-0.84,-0.05l0.05,-0.15l-0.56,-1.24l0.21,-1.17Z\", \"name\": \"Slovenia\"}, \"KP\": {\"path\": \"M747.76,172.02l-0.23,-0.04l-0.26,0.08l-1.09,1.02l-0.78,1.06l-0.06,0.19l0.09,1.95l-1.12,0.57l-0.53,0.58l-0.88,0.82l-1.69,0.51l-1.09,0.79l-0.12,0.22l-0.07,1.17l-0.22,0.25l0.09,0.47l0.96,0.46l1.22,1.1l-0.19,0.37l-0.91,0.16l-1.75,0.14l-0.22,0.12l-0.87,1.18l-0.95,-0.09l-0.3,0.18l-0.97,-0.44l-0.39,0.13l-0.25,0.44l-0.29,0.09l-0.03,-0.2l-0.18,-0.23l-0.62,-0.25l-0.43,-0.29l0.52,-0.97l0.52,-0.3l0.13,-0.38l-0.18,-0.42l0.59,-1.47l0.01,-0.21l-0.16,-0.48l-0.22,-0.2l-1.41,-0.31l-0.82,-0.55l1.74,-1.62l2.73,-1.58l1.62,-1.96l0.96,0.76l0.17,0.06l2.17,0.11l0.31,-0.37l-0.32,-1.31l3.61,-1.21l0.16,-0.13l0.79,-1.34l1.25,1.38Z\", \"name\": \"North Korea\"}, \"SO\": {\"path\": \"M543.8,256.48l0.61,-0.05l1.14,-0.37l1.31,-0.25l0.12,-0.05l1.11,-0.81l0.57,-0.0l0.03,0.39l-0.23,1.49l0.01,1.25l-0.52,0.92l-0.7,2.71l-1.19,2.79l-1.54,3.2l-2.13,3.66l-2.12,2.79l-2.92,3.39l-2.47,2.0l-3.76,2.5l-2.33,1.9l-2.77,3.06l-0.61,1.35l-0.28,0.29l-1.22,-1.69l-0.03,-8.92l2.12,-2.76l0.59,-0.68l1.47,-0.04l0.18,-0.06l2.15,-1.71l3.16,-0.11l0.21,-0.09l7.08,-7.55l1.76,-2.12l1.14,-1.57l0.06,-0.18l0.01,-4.67Z\", \"name\": \"Somalia\"}, \"SN\": {\"path\": \"M379.28,250.34l-0.95,-1.82l-0.09,-0.1l-0.83,-0.6l0.62,-0.28l0.13,-0.11l1.21,-1.8l0.6,-1.31l0.71,-0.68l1.09,0.2l0.18,-0.02l1.17,-0.53l1.25,-0.03l1.17,0.73l1.59,0.65l1.47,1.83l1.59,1.7l0.12,1.56l0.49,1.46l0.1,0.14l0.85,0.65l0.18,0.82l-0.08,0.57l-0.13,0.05l-1.29,-0.19l-0.29,0.13l-0.11,0.16l-0.35,0.04l-1.83,-0.61l-5.84,-0.13l-0.12,0.02l-0.6,0.26l-0.87,-0.06l-1.01,0.32l-0.26,-1.26l1.9,0.04l0.16,-0.04l0.54,-0.32l0.37,-0.02l0.15,-0.05l0.78,-0.5l0.92,0.46l0.12,0.03l1.09,0.04l0.15,-0.03l1.08,-0.57l0.11,-0.44l-0.51,-0.74l-0.39,-0.1l-0.76,0.39l-0.62,-0.01l-0.92,-0.58l-0.18,-0.05l-0.79,0.04l-0.2,0.09l-0.48,0.51l-2.41,0.06Z\", \"name\": \"Senegal\"}, \"SL\": {\"path\": \"M392.19,267.53l-0.44,-0.12l-1.73,-0.97l-1.24,-1.28l-0.4,-0.84l-0.27,-1.65l1.21,-1.0l0.09,-0.12l0.27,-0.66l0.32,-0.41l0.56,-0.05l0.16,-0.07l0.5,-0.41l1.75,0.0l0.59,0.77l0.49,0.96l-0.07,0.64l0.04,0.19l0.36,0.58l-0.03,0.84l0.24,0.2l-0.64,0.65l-1.13,1.37l-0.06,0.14l-0.12,0.66l-0.43,0.58Z\", \"name\": \"Sierra Leone\"}, \"SB\": {\"path\": \"M826.74,311.51l0.23,0.29l-0.95,-0.01l-0.39,-0.63l0.65,0.27l0.45,0.09ZM825.01,308.52l-1.18,-1.39l-0.37,-1.06l0.24,0.0l0.82,1.84l0.49,0.6ZM823.21,309.42l-0.44,0.03l-1.43,-0.24l-0.32,-0.24l0.08,-0.5l1.29,0.31l0.72,0.47l0.11,0.18ZM817.9,303.81l2.59,1.44l0.3,0.41l-1.21,-0.66l-1.34,-0.89l-0.34,-0.3ZM813.77,302.4l0.48,0.34l0.1,0.08l-0.33,-0.17l-0.25,-0.25Z\", \"name\": \"Solomon Islands\"}, \"SA\": {\"path\": \"M528.24,243.1l-0.2,-0.69l-0.07,-0.12l-0.69,-0.71l-0.18,-0.94l-0.12,-0.19l-1.24,-0.89l-1.28,-2.09l-0.7,-2.08l-0.07,-0.11l-1.73,-1.79l-0.11,-0.07l-1.03,-0.39l-1.57,-2.36l-0.27,-1.72l0.1,-1.53l-0.03,-0.15l-1.44,-2.93l-1.25,-1.13l-1.34,-0.56l-0.72,-1.33l0.11,-0.49l-0.02,-0.2l-0.7,-1.38l-0.08,-0.1l-0.68,-0.56l-0.97,-1.98l-2.8,-4.03l-0.25,-0.13l-0.85,0.01l0.29,-1.11l0.12,-0.97l0.23,-0.81l2.52,0.39l0.23,-0.06l1.08,-0.84l0.6,-0.95l1.78,-0.35l0.22,-0.17l0.37,-0.83l0.74,-0.42l0.08,-0.46l-2.17,-2.4l4.55,-1.26l0.12,-0.06l0.36,-0.32l2.83,0.71l3.67,1.91l7.04,5.5l0.17,0.06l4.64,0.22l2.06,0.24l0.55,1.15l0.28,0.17l1.56,-0.06l0.9,2.15l0.14,0.15l1.14,0.57l0.39,0.85l0.11,0.13l1.59,1.06l0.12,0.91l-0.23,0.83l0.01,0.18l0.32,0.9l0.07,0.11l0.68,0.7l0.33,0.86l0.37,0.65l0.09,0.1l0.76,0.53l0.25,0.04l0.45,-0.12l0.35,0.75l0.1,0.63l0.96,2.68l0.23,0.19l7.53,1.33l0.27,-0.09l0.24,-0.26l0.87,1.41l-1.58,4.96l-7.34,2.54l-7.28,1.02l-2.34,1.17l-0.12,0.1l-1.74,2.63l-0.86,0.32l-0.49,-0.68l-0.28,-0.12l-0.92,0.12l-2.32,-0.25l-0.41,-0.23l-0.15,-0.04l-2.89,0.06l-0.63,0.2l-0.91,-0.59l-0.43,0.11l-0.66,1.27l-0.03,0.21l0.21,0.89l-0.6,0.45Z\", \"name\": \"Saudi Arabia\"}, \"SE\": {\"path\": \"M476.42,90.44l-0.15,0.1l-2.43,2.86l-0.07,0.24l0.36,2.31l-3.84,3.1l-4.83,3.38l-0.11,0.15l-1.82,5.45l0.03,0.26l1.78,2.68l2.27,1.99l-2.13,3.88l-2.49,0.82l-0.2,0.24l-0.95,6.05l-1.32,3.09l-2.82,-0.32l-0.3,0.16l-1.34,2.64l-2.48,0.14l-0.76,-3.15l-2.09,-4.04l-1.85,-5.01l1.03,-1.98l2.06,-2.53l0.06,-0.13l0.83,-4.45l-0.06,-0.25l-1.54,-1.86l-0.15,-5.0l1.52,-3.48l2.28,0.06l0.27,-0.16l0.87,-1.59l-0.01,-0.31l-0.8,-1.21l3.79,-5.63l4.07,-7.54l2.23,0.01l0.29,-0.22l0.59,-2.15l4.46,0.66l0.34,-0.26l0.34,-2.64l1.21,-0.14l3.24,2.08l3.78,2.85l0.06,6.37l0.03,0.14l0.67,1.29l-3.95,1.07Z\", \"name\": \"Sweden\"}, \"SD\": {\"path\": \"M505.98,259.75l-0.31,-0.9l-0.1,-0.14l-1.2,-0.93l-0.27,-1.66l0.29,-1.83l-0.25,-0.34l-1.16,-0.17l-0.33,0.21l-0.11,0.37l-1.3,0.11l-0.21,0.49l0.55,0.68l0.18,1.29l-1.31,1.33l-1.18,1.72l-1.04,0.21l-2.0,-1.4l-0.32,-0.02l-0.95,0.52l-0.14,0.16l-0.21,0.6l-1.16,0.43l-0.19,0.23l-0.04,0.27l-2.08,0.0l-0.25,-0.39l-0.24,-0.13l-1.81,-0.09l-0.14,0.03l-0.8,0.38l-0.49,-0.16l-1.22,-1.39l-0.42,-0.67l-0.31,-0.14l-1.81,0.35l-0.2,0.14l-0.72,1.24l-0.61,2.14l-0.73,0.4l-0.62,0.22l-0.83,-0.68l-0.12,-0.6l0.38,-0.97l0.01,-1.14l-0.08,-0.2l-1.39,-1.53l-0.25,-0.97l0.03,-0.57l-0.11,-0.25l-0.81,-0.66l-0.03,-1.34l-0.04,-0.14l-0.52,-0.98l-0.31,-0.15l-0.42,0.07l0.12,-0.44l0.63,-1.03l0.03,-0.23l-0.24,-0.88l0.69,-0.66l0.02,-0.41l-0.4,-0.46l0.58,-1.39l1.04,-1.71l1.97,0.16l0.32,-0.3l-0.12,-10.24l0.02,-0.8l2.59,-0.01l0.3,-0.3l0.0,-4.92l29.19,0.0l0.68,2.17l-0.4,0.35l-0.1,0.27l0.36,2.69l0.93,3.15l0.12,0.16l2.05,1.4l-0.99,1.15l-1.75,0.4l-0.15,0.08l-0.79,0.79l-0.08,0.17l-0.24,1.69l-1.07,3.75l-0.0,0.16l0.25,0.96l-0.38,2.1l-0.98,2.41l-1.52,1.3l-1.07,1.94l-0.25,0.99l-1.08,0.64l-0.13,0.18l-0.46,1.65Z\", \"name\": \"Sudan\"}, \"DO\": {\"path\": \"M241.7,234.97l0.15,-0.22l1.73,0.01l1.43,0.64l0.15,0.03l0.45,-0.04l0.36,0.74l0.28,0.17l1.02,-0.04l-0.04,0.43l0.27,0.33l1.03,0.09l0.91,0.7l-0.57,0.64l-0.99,-0.47l-0.16,-0.03l-1.11,0.11l-0.79,-0.12l-0.26,0.09l-0.38,0.4l-0.66,0.11l-0.28,-0.45l-0.38,-0.12l-0.83,0.37l-0.14,0.13l-0.85,1.49l-0.27,-0.17l-0.1,-0.58l0.05,-0.67l-0.07,-0.21l-0.44,-0.53l0.35,-0.25l0.12,-0.19l0.19,-1.0l-0.2,-1.4Z\", \"name\": \"Dominican Republic\"}, \"DJ\": {\"path\": \"M528.78,253.36l0.34,0.45l-0.06,0.76l-1.26,0.54l-0.05,0.53l0.82,0.53l-0.57,0.83l-0.3,-0.25l-0.27,-0.05l-0.56,0.17l-1.07,-0.03l-0.04,-0.56l-0.16,-0.56l0.76,-1.07l0.76,-0.97l0.89,0.18l0.25,-0.06l0.51,-0.42Z\", \"name\": \"Djibouti\"}, \"DK\": {\"path\": \"M452.4,129.07l-1.27,2.39l-2.25,-1.69l-0.26,-1.08l3.15,-1.0l0.63,1.39ZM447.87,126.25l-0.35,0.76l-0.47,-0.24l-0.38,0.09l-1.8,2.53l-0.03,0.29l0.56,1.4l-1.22,0.4l-1.68,-0.41l-0.92,-1.76l-0.07,-3.47l0.38,-0.88l0.62,-0.93l2.07,-0.21l0.19,-0.1l0.84,-0.95l1.5,-0.76l-0.06,1.26l-0.7,1.1l-0.03,0.25l0.3,1.0l0.18,0.19l1.06,0.42Z\", \"name\": \"Denmark\"}, \"DE\": {\"path\": \"M445.51,131.69l0.03,0.94l0.21,0.28l2.32,0.74l-0.02,1.0l0.37,0.3l2.55,-0.65l1.36,-0.89l2.63,1.27l1.09,1.01l0.51,1.51l-0.6,0.78l-0.0,0.36l0.88,1.17l0.58,1.68l-0.18,1.08l0.03,0.18l0.87,1.81l-0.66,0.2l-0.55,-0.32l-0.36,0.05l-0.58,0.58l-1.73,0.62l-0.99,0.84l-1.77,0.7l-0.16,0.4l0.42,0.94l0.26,1.34l0.14,0.2l1.25,0.76l1.22,1.2l-0.71,1.2l-0.81,0.37l-0.17,0.32l0.34,1.99l-0.04,0.09l-0.47,-0.39l-0.17,-0.07l-1.2,-0.1l-1.85,0.57l-2.15,-0.13l-0.29,0.18l-0.21,0.5l-0.96,-0.67l-0.24,-0.05l-0.67,0.16l-2.6,-0.94l-0.34,0.1l-0.42,0.57l-1.64,-0.02l0.26,-1.88l1.24,-2.15l-0.21,-0.45l-3.54,-0.58l-0.98,-0.71l0.12,-1.26l-0.05,-0.2l-0.44,-0.64l0.27,-2.18l-0.38,-3.14l1.17,-0.0l0.27,-0.17l0.63,-1.26l0.65,-3.17l-0.02,-0.17l-0.41,-1.0l0.32,-0.47l1.77,-0.16l0.37,0.6l0.47,0.06l1.7,-1.69l0.06,-0.33l-0.55,-1.24l-0.09,-1.51l1.5,0.36l0.16,-0.01l1.22,-0.4Z\", \"name\": \"Germany\"}, \"YE\": {\"path\": \"M553.53,242.65l-1.51,0.58l-0.17,0.16l-0.48,1.14l-0.07,0.79l-2.31,1.0l-3.98,1.19l-2.28,1.8l-0.97,0.12l-0.7,-0.14l-0.23,0.05l-1.42,1.03l-1.51,0.47l-2.07,0.13l-0.68,0.15l-0.17,0.1l-0.49,0.6l-0.57,0.16l-0.18,0.13l-0.3,0.49l-1.06,-0.05l-0.13,0.02l-0.73,0.32l-1.48,-0.11l-0.55,-1.26l0.07,-1.32l-0.04,-0.16l-0.39,-0.72l-0.48,-1.85l-0.52,-0.79l0.08,-0.02l0.22,-0.36l-0.23,-1.05l0.24,-0.39l0.04,-0.19l-0.09,-0.95l0.96,-0.72l0.11,-0.31l-0.23,-0.98l0.46,-0.88l0.75,0.49l0.26,0.03l0.63,-0.22l2.76,-0.06l0.5,0.25l2.42,0.26l0.85,-0.11l0.52,0.71l0.35,0.1l1.17,-0.43l0.15,-0.12l1.75,-2.64l2.22,-1.11l6.95,-0.96l2.55,5.58Z\", \"name\": \"Yemen\"}, \"AT\": {\"path\": \"M463.17,154.15l-0.14,0.99l-1.15,0.01l-0.24,0.47l0.39,0.56l-0.75,1.84l-0.36,0.4l-2.06,0.07l-0.14,0.04l-1.18,0.67l-1.96,-0.23l-3.43,-0.78l-0.5,-0.97l-0.33,-0.16l-2.47,0.55l-0.2,0.16l-0.18,0.37l-1.27,-0.38l-1.28,-0.09l-0.81,-0.41l0.25,-0.51l0.03,-0.18l-0.05,-0.28l0.35,-0.08l1.16,0.81l0.45,-0.13l0.27,-0.64l2.0,0.12l1.84,-0.57l1.05,0.09l0.71,0.59l0.47,-0.11l0.23,-0.54l0.02,-0.17l-0.32,-1.85l0.69,-0.31l0.13,-0.12l0.73,-1.23l1.61,0.89l0.35,-0.04l1.35,-1.27l0.7,-0.19l1.84,0.93l0.18,0.03l1.08,-0.15l0.81,0.43l-0.07,0.15l-0.02,0.2l0.24,1.06Z\", \"name\": \"Austria\"}, \"DZ\": {\"path\": \"M450.58,224.94l-8.31,4.86l-7.23,5.12l-3.46,1.13l-2.42,0.22l-0.02,-1.33l-0.2,-0.28l-1.15,-0.42l-1.45,-0.69l-0.55,-1.13l-0.1,-0.12l-8.45,-5.72l-17.72,-12.17l0.03,-0.38l-0.02,-3.21l3.84,-1.91l2.46,-0.41l2.1,-0.75l0.14,-0.11l0.9,-1.3l2.84,-1.06l0.19,-0.27l0.09,-1.81l1.21,-0.2l0.15,-0.07l1.06,-0.96l3.19,-0.46l0.23,-0.18l0.46,-1.08l-0.08,-0.34l-0.6,-0.54l-0.83,-2.85l-0.18,-1.8l-0.82,-1.57l2.13,-1.37l2.65,-0.49l0.13,-0.05l1.55,-1.15l2.34,-0.85l4.2,-0.51l4.07,-0.23l1.21,0.41l0.23,-0.01l2.3,-1.11l2.52,-0.02l0.94,0.62l0.2,0.05l1.25,-0.13l-0.36,1.03l-0.01,0.14l0.39,2.66l-0.56,2.2l-1.49,1.52l-0.08,0.24l0.22,2.12l0.11,0.2l1.94,1.58l0.02,0.54l0.12,0.23l1.45,1.06l1.04,4.85l0.81,2.42l0.13,1.19l-0.43,2.17l0.17,1.28l-0.31,1.53l0.2,1.56l-0.9,1.02l-0.01,0.38l1.43,1.88l0.09,1.06l0.04,0.13l0.89,1.48l0.37,0.12l1.03,-0.43l1.79,1.12l0.89,1.34Z\", \"name\": \"Algeria\"}, \"US\": {\"path\": \"M892.64,99.05l1.16,0.57l0.21,0.02l1.45,-0.38l1.92,0.99l2.17,0.47l-1.65,0.72l-1.75,-0.79l-0.93,-0.7l-0.21,-0.06l-2.11,0.22l-0.35,-0.2l0.09,-0.87ZM183.29,150.37l0.39,1.54l0.12,0.17l0.78,0.55l0.14,0.05l1.74,0.2l2.52,0.5l2.4,0.98l0.17,0.02l1.96,-0.4l3.01,0.81l0.91,-0.02l2.22,-0.88l4.67,2.33l3.86,2.01l0.21,0.71l0.15,0.18l0.33,0.17l-0.02,0.05l0.23,0.43l0.67,0.1l0.21,-0.05l0.1,-0.07l0.05,0.29l0.09,0.16l0.5,0.5l0.21,0.09l0.56,0.0l0.13,0.13l-0.2,0.36l0.12,0.41l2.49,1.39l0.99,5.24l-0.69,1.68l-1.16,1.64l-0.6,1.18l-0.06,0.31l0.04,0.22l0.28,0.43l0.11,0.1l0.85,0.47l0.15,0.04l0.63,0.0l0.14,-0.04l2.87,-1.58l2.6,-0.49l3.28,-1.5l0.17,-0.23l0.04,-0.43l-0.23,-0.93l-0.24,-0.39l0.74,-0.32l4.7,-0.01l0.25,-0.13l0.77,-1.15l2.9,-2.41l1.04,-0.52l8.35,-0.02l0.28,-0.21l0.2,-0.6l0.7,-0.14l1.06,-0.48l0.13,-0.11l0.92,-1.49l0.75,-2.39l1.67,-2.08l0.59,0.6l0.3,0.07l1.52,-0.49l0.88,0.72l-0.0,4.14l0.08,0.2l1.6,1.72l0.31,0.72l-2.42,1.35l-2.55,1.05l-2.64,0.9l-0.14,0.11l-1.33,1.81l-0.44,0.7l-0.05,0.15l-0.03,1.6l0.03,0.14l0.83,1.59l0.24,0.16l0.78,0.06l-1.15,0.33l-1.25,-0.04l-1.83,0.52l-2.51,0.29l-2.17,0.88l-0.17,0.36l0.33,0.22l3.55,-0.54l0.15,0.11l-2.87,0.73l-1.19,0.0l-0.16,-0.33l-0.36,0.06l-0.76,0.82l0.17,0.5l0.42,0.08l-0.45,1.75l-1.4,1.74l-0.04,-0.17l-0.21,-0.22l-0.48,-0.13l-0.77,-0.69l-0.36,-0.03l-0.12,0.34l0.52,1.58l0.09,0.14l0.52,0.43l0.03,0.87l-0.74,1.05l-0.39,0.63l0.05,-0.12l-0.08,-0.34l-1.19,-1.03l-0.28,-2.31l-0.26,-0.26l-0.32,0.19l-0.48,1.27l-0.01,0.19l0.39,1.33l-1.14,-0.31l-0.36,0.18l0.14,0.38l1.57,0.85l0.1,2.58l0.22,0.28l0.55,0.15l0.21,0.81l0.33,2.72l-1.46,1.94l-2.5,0.81l-0.12,0.07l-1.58,1.58l-1.15,0.17l-0.15,0.06l-1.27,1.03l-0.09,0.13l-0.32,0.85l-2.71,1.79l-1.45,1.37l-1.18,1.64l-0.05,0.12l-0.39,1.96l0.0,0.13l0.44,1.91l0.85,2.37l1.1,1.91l0.03,1.2l1.16,3.07l-0.08,1.74l-0.1,0.99l-0.57,1.48l-0.54,0.24l-0.97,-0.26l-0.34,-1.02l-0.12,-0.16l-0.89,-0.58l-2.44,-4.28l-0.34,-0.94l0.49,-1.71l-0.02,-0.21l-0.7,-1.5l-2.0,-2.35l-0.11,-0.08l-0.98,-0.42l-0.25,0.01l-2.42,1.19l-0.26,-0.08l-1.26,-1.29l-1.57,-0.68l-0.16,-0.02l-2.79,0.34l-2.18,-0.3l-1.98,0.19l-1.12,0.45l-0.14,0.44l0.4,0.65l-0.04,1.02l0.09,0.22l0.29,0.3l-0.06,0.05l-0.77,-0.33l-0.26,0.01l-0.87,0.48l-1.64,-0.08l-1.79,-1.39l-0.23,-0.06l-2.11,0.33l-1.75,-0.61l-0.14,-0.01l-1.61,0.2l-2.11,0.64l-0.11,0.06l-2.25,1.99l-2.53,1.21l-1.43,1.38l-0.58,1.22l-0.03,0.12l-0.03,1.86l0.13,1.32l0.3,0.62l-0.46,0.04l-1.71,-0.57l-1.85,-0.79l-0.63,-1.14l-0.54,-1.85l-0.07,-0.12l-1.45,-1.51l-0.86,-1.58l-1.26,-1.87l-0.09,-0.09l-1.76,-1.09l-0.17,-0.04l-2.05,0.05l-0.23,0.12l-1.44,1.97l-1.84,-0.72l-1.19,-0.76l-0.6,-1.45l-0.9,-1.52l-1.49,-1.21l-1.27,-0.87l-0.89,-0.96l-0.22,-0.1l-4.34,-0.0l-0.3,0.3l-0.0,0.84l-6.62,0.02l-5.66,-1.93l-3.48,-1.24l0.11,-0.25l-0.3,-0.42l-3.18,0.3l-2.6,0.2l-0.35,-1.19l-0.08,-0.13l-1.62,-1.61l-0.13,-0.08l-1.02,-0.29l-0.22,-0.66l-0.25,-0.2l-1.31,-0.13l-0.82,-0.7l-0.16,-0.07l-2.25,-0.27l-0.48,-0.34l-0.28,-1.44l-0.07,-0.14l-2.41,-2.84l-2.03,-3.89l0.08,-0.58l-0.1,-0.27l-1.08,-0.94l-1.87,-2.36l-0.33,-2.31l-0.07,-0.15l-1.24,-1.5l0.52,-2.4l-0.09,-2.57l-0.78,-2.3l0.96,-2.83l0.61,-5.66l-0.46,-4.26l-0.79,-2.71l-0.68,-1.4l0.13,-0.26l3.24,0.97l1.28,2.88l0.52,0.06l0.62,-0.84l0.06,-0.22l-0.4,-2.61l-0.74,-2.29l68.9,-0.0l0.3,-0.3l0.01,-0.95l0.32,-0.01ZM32.5,67.43l1.75,1.99l0.41,0.04l1.02,-0.81l3.79,0.25l-0.1,0.72l0.24,0.34l3.83,0.77l2.6,-0.44l5.21,1.41l4.84,0.43l1.9,0.57l0.15,0.01l3.25,-0.71l3.72,1.32l2.52,0.58l-0.03,38.14l0.29,0.3l2.41,0.11l2.34,1.0l1.7,1.59l2.22,2.42l0.42,0.03l2.41,-2.04l2.25,-1.08l1.23,1.76l1.71,1.53l2.24,1.62l1.54,2.56l2.56,4.09l0.11,0.11l4.1,2.17l0.06,1.93l-1.12,1.35l-1.22,-1.14l-2.08,-1.05l-0.68,-2.94l-0.09,-0.16l-3.18,-2.84l-1.32,-3.35l-0.25,-0.19l-2.43,-0.24l-3.93,-0.09l-2.85,-1.02l-5.24,-3.85l-6.77,-2.04l-3.52,0.3l-4.84,-1.7l-2.96,-1.6l-0.23,-0.02l-2.78,0.8l-0.21,0.35l0.46,2.31l-1.11,0.19l-2.9,0.78l-2.24,1.26l-2.42,0.68l-0.29,-1.79l1.07,-3.49l2.54,-1.11l0.12,-0.45l-0.69,-0.96l-0.41,-0.07l-3.19,2.12l-1.76,2.54l-3.57,2.62l-0.03,0.46l1.63,1.59l-2.14,2.38l-2.64,1.49l-2.49,1.09l-0.16,0.17l-0.58,1.48l-3.8,1.79l-0.14,0.14l-0.75,1.57l-2.75,1.41l-1.62,-0.25l-0.16,0.02l-2.35,0.98l-2.54,1.19l-2.06,1.15l-4.05,0.93l-0.1,-0.15l2.45,-1.45l2.49,-1.1l2.61,-1.88l3.03,-0.39l0.19,-0.1l1.2,-1.41l3.43,-2.11l0.61,-0.75l1.81,-1.24l0.13,-0.2l0.42,-2.7l1.24,-2.12l-0.03,-0.35l-0.34,-0.09l-2.73,1.05l-0.67,-0.53l-0.39,0.02l-1.13,1.11l-1.43,-1.62l-0.49,0.06l-0.41,0.8l-0.67,-1.31l-0.42,-0.12l-2.43,1.43l-1.18,-0.0l-0.18,-1.86l0.43,-1.3l-0.09,-0.33l-1.61,-1.33l-0.26,-0.06l-3.11,0.68l-2.0,-1.66l-1.61,-0.85l-0.01,-1.97l-0.11,-0.23l-1.76,-1.48l0.86,-1.96l2.01,-2.13l0.88,-1.94l1.79,-0.25l1.65,0.6l0.31,-0.06l1.91,-1.8l1.67,0.31l0.22,-0.04l1.91,-1.23l0.13,-0.33l-0.47,-1.82l-0.15,-0.19l-1.0,-0.52l1.51,-1.27l0.09,-0.34l-0.29,-0.19l-1.62,0.06l-2.66,0.88l-0.13,0.09l-0.62,0.72l-1.77,-0.8l-0.16,-0.02l-3.48,0.44l-3.5,-0.92l-1.06,-1.61l-2.78,-2.09l3.07,-1.51l5.52,-2.01l1.65,0.0l-0.28,1.73l0.31,0.35l5.29,-0.16l0.23,-0.49l-2.03,-2.59l-0.1,-0.08l-3.03,-1.58l-1.79,-2.12l-2.4,-1.83l-3.18,-1.27l1.13,-1.84l4.28,-0.14l0.15,-0.05l3.16,-2.0l0.13,-0.17l0.57,-2.07l2.43,-2.02l2.42,-0.52l4.67,-1.98l2.22,0.29l0.2,-0.04l3.74,-2.37l3.57,0.91ZM37.66,123.49l-2.31,1.26l-1.04,-0.75l-0.31,-1.35l2.06,-1.16l1.24,-0.51l1.48,0.22l0.76,0.81l-1.89,1.49ZM30.89,233.84l1.2,0.57l0.35,0.3l0.48,0.69l-1.6,0.86l-0.3,0.31l-0.24,-0.14l0.05,-0.54l-0.02,-0.15l-0.36,-0.83l0.05,-0.12l0.39,-0.38l0.07,-0.31l-0.09,-0.27ZM29.06,231.89l0.5,0.14l0.31,0.19l-0.46,0.1l-0.34,-0.43ZM25.02,230.13l0.2,-0.11l0.4,0.47l-0.43,-0.05l-0.17,-0.31ZM21.29,228.68l0.1,-0.07l0.22,0.02l0.02,0.21l-0.02,0.02l-0.32,-0.18ZM6.0,113.33l-1.19,0.45l-1.5,-0.64l-0.94,-0.63l1.76,-0.46l1.71,0.29l0.16,0.98Z\", \"name\": \"United States of America\"}, \"LV\": {\"path\": \"M473.99,127.16l0.07,-2.15l1.15,-2.11l2.05,-1.07l1.84,2.48l0.25,0.12l2.01,-0.07l0.29,-0.25l0.45,-2.58l1.85,-0.56l0.98,0.4l2.13,1.33l0.16,0.05l1.97,0.01l1.02,0.7l0.21,1.67l0.71,1.84l-2.44,1.23l-1.36,0.53l-2.28,-1.62l-0.12,-0.05l-1.18,-0.2l-0.28,-0.6l-0.31,-0.17l-2.43,0.35l-4.17,-0.23l-0.12,0.02l-2.45,0.93Z\", \"name\": \"Latvia\"}, \"UY\": {\"path\": \"M276.9,363.17l1.3,-0.23l2.4,2.04l0.22,0.07l0.82,-0.07l2.48,1.7l1.93,1.5l1.28,1.67l-0.95,1.14l-0.04,0.31l0.63,1.45l-0.96,1.57l-2.65,1.47l-1.73,-0.53l-0.15,-0.01l-1.25,0.28l-2.22,-1.16l-0.16,-0.03l-1.56,0.08l-1.33,-1.36l0.17,-1.58l0.48,-0.55l0.07,-0.2l-0.02,-2.74l0.66,-2.8l0.57,-2.02Z\", \"name\": \"Uruguay\"}, \"LB\": {\"path\": \"M510.44,198.11l-0.48,0.03l-0.26,0.17l-0.15,0.32l-0.21,-0.0l0.72,-1.85l1.19,-1.9l0.74,0.09l0.27,0.73l-1.19,0.93l-0.09,0.13l-0.54,1.36Z\", \"name\": \"Lebanon\"}, \"LA\": {\"path\": \"M684.87,248.8l0.61,-0.86l0.05,-0.16l0.11,-2.17l-0.08,-0.22l-1.96,-2.16l-0.15,-2.44l-0.08,-0.18l-1.9,-2.1l-0.19,-0.1l-1.89,-0.18l-0.29,0.15l-0.42,0.76l-1.21,0.06l-0.67,-0.41l-0.31,-0.0l-2.2,1.29l-0.05,-1.77l0.61,-2.7l-0.27,-0.37l-1.44,-0.1l-0.12,-1.31l-0.12,-0.21l-0.87,-0.65l0.38,-0.68l1.76,-1.41l0.08,0.22l0.27,0.2l1.33,0.07l0.31,-0.34l-0.35,-2.75l0.85,-0.25l1.32,1.88l1.11,2.36l0.27,0.17l2.89,0.02l0.78,1.82l-1.32,0.56l-0.12,0.09l-0.72,0.93l0.1,0.45l2.93,1.52l3.62,5.27l1.88,1.78l0.58,1.67l-0.38,2.11l-1.87,-0.79l-0.37,0.11l-0.99,1.54l-1.51,-0.73Z\", \"name\": \"Laos\"}, \"TW\": {\"path\": \"M725.6,222.5l-1.5,4.22l-0.82,1.65l-1.01,-1.7l-0.26,-1.8l1.4,-2.48l1.8,-1.81l0.76,0.53l-0.38,1.39Z\", \"name\": \"Taiwan\"}, \"TT\": {\"path\": \"M266.35,259.46l0.41,-0.39l0.09,-0.23l-0.04,-0.75l1.14,-0.26l0.2,0.03l-0.07,1.37l-1.73,0.23Z\", \"name\": \"Trinidad and Tobago\"}, \"TR\": {\"path\": \"M513.25,175.38l3.63,1.17l0.14,0.01l2.88,-0.45l2.11,0.26l0.18,-0.03l2.9,-1.53l2.51,-0.13l2.25,1.37l0.36,0.88l-0.23,1.36l0.19,0.33l1.81,0.72l0.61,0.53l-1.31,0.64l-0.16,0.34l0.76,3.24l-0.44,0.8l0.01,0.3l1.19,2.02l-0.71,0.29l-0.74,-0.62l-0.15,-0.07l-2.91,-0.37l-0.15,0.02l-1.04,0.43l-2.78,0.44l-1.44,-0.03l-2.83,1.06l-1.95,0.01l-1.28,-0.52l-0.2,-0.01l-2.62,0.76l-0.7,-0.48l-0.47,0.22l-0.13,1.49l-1.01,0.94l-0.58,-0.82l0.79,-0.9l0.04,-0.34l-0.31,-0.15l-1.46,0.23l-2.03,-0.64l-0.3,0.07l-1.65,1.58l-3.58,0.3l-1.94,-1.47l-0.17,-0.06l-2.7,-0.1l-0.28,0.17l-0.51,1.06l-1.47,0.29l-2.32,-1.46l-0.17,-0.05l-2.55,0.05l-1.4,-2.7l-1.72,-1.54l1.11,-2.06l-0.07,-0.37l-1.35,-1.19l2.47,-2.51l3.74,-0.11l0.26,-0.17l0.96,-2.07l4.56,0.38l0.19,-0.05l2.97,-1.92l2.84,-0.83l4.03,-0.06l4.31,2.08ZM488.85,176.8l-1.81,1.38l-0.57,-1.01l0.02,-0.36l0.45,-0.25l0.13,-0.15l0.78,-1.87l-0.11,-0.37l-0.72,-0.47l1.91,-0.71l1.89,0.35l0.25,0.97l0.17,0.2l1.87,0.83l-0.19,0.31l-2.82,0.16l-0.18,0.07l-1.06,0.91Z\", \"name\": \"Turkey\"}, \"LK\": {\"path\": \"M625.44,266.07l-0.35,2.4l-0.9,0.61l-1.91,0.5l-1.04,-1.75l-0.43,-3.5l1.0,-3.6l1.34,1.09l1.13,1.72l1.16,2.52Z\", \"name\": \"Sri Lanka\"}, \"TN\": {\"path\": \"M444.91,206.18l-0.99,-4.57l-0.12,-0.18l-1.43,-1.04l-0.02,-0.53l-0.11,-0.22l-1.95,-1.59l-0.19,-1.85l1.44,-1.47l0.08,-0.14l0.59,-2.34l-0.38,-2.77l0.44,-1.28l2.52,-1.08l1.41,0.28l-0.06,1.2l0.43,0.28l1.81,-0.9l0.02,0.06l-1.14,1.28l-0.08,0.2l-0.02,1.32l0.11,0.24l0.74,0.6l-0.29,2.18l-1.56,1.35l-0.09,0.32l0.48,1.54l0.28,0.21l1.11,0.04l0.55,1.17l0.15,0.14l0.76,0.35l-0.12,1.79l-1.1,0.72l-0.8,0.91l-1.68,1.04l-0.13,0.32l0.25,1.08l-0.18,0.96l-0.74,0.39Z\", \"name\": \"Tunisia\"}, \"TL\": {\"path\": \"M734.21,307.22l0.17,-0.34l1.99,-0.52l1.72,-0.08l0.78,-0.3l0.29,0.1l-0.43,0.32l-2.57,1.09l-1.71,0.59l-0.05,-0.49l-0.19,-0.36Z\", \"name\": \"East Timor\"}, \"TM\": {\"path\": \"M553.16,173.51l-0.12,1.0l-0.26,-0.65l0.38,-0.34ZM553.54,173.16l0.13,-0.12l0.43,-0.09l-0.56,0.21ZM555.68,172.6l0.65,-0.14l1.53,0.76l1.71,2.29l0.27,0.12l1.27,-0.14l2.81,-0.04l0.29,-0.38l-0.35,-1.27l1.98,-0.97l1.96,-1.63l3.05,1.44l0.25,2.23l0.14,0.22l0.96,0.61l0.18,0.05l2.61,-0.13l0.68,0.44l1.2,2.97l0.1,0.13l2.85,2.03l1.67,1.41l2.66,1.45l3.13,1.17l-0.05,1.23l-0.36,-0.04l-1.12,-0.73l-0.44,0.14l-0.34,0.89l-1.96,0.52l-0.22,0.23l-0.47,2.17l-1.26,0.78l-1.93,0.42l-0.21,0.18l-0.46,1.14l-1.64,0.33l-2.3,-0.97l-0.2,-2.23l-0.28,-0.27l-1.76,-0.1l-2.78,-2.48l-0.15,-0.07l-1.95,-0.31l-2.82,-1.48l-1.78,-0.27l-0.18,0.03l-1.03,0.51l-1.6,-0.08l-0.22,0.08l-1.72,1.6l-1.83,0.46l-0.39,-1.7l0.36,-3.0l-0.16,-0.3l-1.73,-0.88l0.57,-1.77l-0.25,-0.39l-1.33,-0.14l0.41,-1.85l2.05,0.63l0.21,-0.01l2.2,-0.95l0.09,-0.49l-1.78,-1.75l-0.69,-1.66l-0.07,-0.03Z\", \"name\": \"Turkmenistan\"}, \"TJ\": {\"path\": \"M597.99,178.71l-0.23,0.23l-2.57,-0.47l-0.35,0.25l-0.24,1.7l0.32,0.34l2.66,-0.22l3.15,0.95l4.47,-0.42l0.58,2.45l0.39,0.21l0.71,-0.25l1.22,0.53l-0.06,1.01l0.29,1.28l-2.19,-0.0l-1.71,-0.21l-0.23,0.07l-1.51,1.25l-1.05,0.27l-0.77,0.51l-0.71,-0.67l0.22,-2.28l-0.24,-0.32l-0.43,-0.08l0.17,-0.57l-0.16,-0.36l-1.36,-0.66l-0.34,0.05l-1.08,1.01l-0.09,0.15l-0.25,1.09l-0.24,0.26l-1.36,-0.05l-0.27,0.14l-0.65,1.06l-0.58,-0.39l-0.3,-0.02l-1.68,0.86l-0.36,-0.16l1.28,-2.65l0.02,-0.2l-0.54,-2.17l-0.18,-0.21l-1.53,-0.58l0.41,-0.82l1.89,0.13l0.26,-0.12l1.19,-1.63l0.77,-1.82l2.66,-0.55l-0.33,0.87l0.01,0.23l0.36,0.82l0.3,0.18l0.23,-0.02Z\", \"name\": \"Tajikistan\"}, \"LS\": {\"path\": \"M493.32,359.69l0.69,0.65l-0.65,1.12l-0.38,0.8l-1.27,0.39l-0.18,0.15l-0.4,0.77l-0.59,0.18l-1.59,-1.78l1.16,-1.5l1.3,-1.02l0.97,-0.46l0.94,0.72Z\", \"name\": \"Lesotho\"}, \"TH\": {\"path\": \"M677.42,253.68l-1.7,-0.88l-0.14,-0.03l-1.77,0.04l0.3,-1.64l-0.3,-0.35l-2.21,0.01l-0.3,0.28l-0.2,2.76l-2.15,5.9l-0.02,0.13l0.17,1.83l0.28,0.27l1.45,0.07l0.93,2.1l0.44,2.15l0.08,0.15l1.4,1.44l0.16,0.09l1.43,0.27l1.04,1.05l-0.58,0.73l-1.24,0.22l-0.15,-0.99l-0.15,-0.22l-2.04,-1.1l-0.36,0.06l-0.23,0.23l-0.72,-0.71l-0.41,-1.18l-0.06,-0.11l-1.33,-1.42l-1.22,-1.2l-0.5,0.13l-0.15,0.54l-0.14,-0.41l0.26,-1.48l0.73,-2.38l1.2,-2.57l1.37,-2.35l0.02,-0.27l-0.95,-2.26l0.03,-1.19l-0.29,-1.42l-0.06,-0.13l-1.65,-2.0l-0.46,-0.99l0.62,-0.34l0.13,-0.15l0.92,-2.23l-0.02,-0.27l-1.05,-1.74l-1.57,-1.86l-1.04,-1.96l0.76,-0.34l0.16,-0.16l1.07,-2.63l1.58,-0.1l0.16,-0.06l1.43,-1.11l1.24,-0.52l0.84,0.62l0.13,1.43l0.28,0.27l1.34,0.09l-0.54,2.39l0.05,2.39l0.45,0.25l2.48,-1.45l0.6,0.36l0.17,0.04l1.47,-0.07l0.25,-0.15l0.41,-0.73l1.58,0.15l1.76,1.93l0.15,2.44l0.08,0.18l1.94,2.15l-0.1,1.96l-0.66,0.93l-2.25,-0.34l-3.24,0.49l-0.19,0.12l-1.6,2.12l-0.06,0.24l0.48,2.46Z\", \"name\": \"Thailand\"}, \"TF\": {\"path\": \"M593.76,417.73l1.38,0.84l2.15,0.37l0.04,0.31l-0.59,1.24l-3.36,0.19l-0.05,-1.38l0.43,-1.56Z\", \"name\": \"French Southern and Antarctic Lands\"}, \"TG\": {\"path\": \"M425.23,269.29l-1.49,0.4l-0.43,-0.68l-0.64,-1.54l-0.18,-1.16l0.54,-2.21l-0.04,-0.24l-0.59,-0.86l-0.23,-1.9l0.0,-1.82l-0.07,-0.19l-0.95,-1.19l0.1,-0.41l1.58,0.04l-0.23,0.97l0.08,0.28l1.55,1.55l0.09,1.13l0.08,0.19l0.42,0.43l-0.11,5.66l0.52,1.53Z\", \"name\": \"Togo\"}, \"TD\": {\"path\": \"M457.57,252.46l0.23,-1.08l-0.28,-0.36l-1.32,-0.05l0.0,-1.35l-0.1,-0.22l-0.9,-0.82l0.99,-3.1l3.12,-2.37l0.12,-0.23l0.13,-3.33l0.95,-5.2l0.53,-1.09l-0.07,-0.36l-0.94,-0.81l-0.03,-0.7l-0.12,-0.23l-0.84,-0.61l-0.57,-3.76l2.21,-1.26l19.67,9.88l0.12,9.74l-1.83,-0.15l-0.28,0.14l-1.14,1.89l-0.68,1.62l0.05,0.31l0.33,0.38l-0.61,0.58l-0.08,0.3l0.25,0.93l-0.58,0.95l-0.29,1.01l0.34,0.37l0.67,-0.11l0.39,0.73l0.03,1.4l0.11,0.23l0.8,0.65l-0.01,0.24l-1.38,0.37l-0.11,0.06l-1.27,1.03l-1.83,2.76l-2.21,1.1l-2.34,-0.15l-0.82,0.25l-0.2,0.37l0.19,0.68l-1.16,0.79l-1.01,0.94l-2.92,0.89l-0.5,-0.46l-0.17,-0.08l-0.41,-0.05l-0.28,0.12l-0.38,0.54l-1.36,0.12l0.1,-0.18l0.01,-0.27l-0.78,-1.72l-0.35,-1.03l-0.17,-0.18l-1.03,-0.41l-1.29,-1.28l0.36,-0.78l0.9,0.2l0.14,-0.0l0.67,-0.17l1.36,0.02l0.26,-0.45l-1.32,-2.22l0.09,-1.64l-0.17,-1.68l-0.04,-0.13l-0.93,-1.53Z\", \"name\": \"Chad\"}, \"LY\": {\"path\": \"M457.99,226.38l-1.57,0.87l-1.25,-1.28l-0.13,-0.08l-3.85,-1.11l-1.04,-1.57l-0.09,-0.09l-1.98,-1.23l-0.27,-0.02l-0.93,0.39l-0.72,-1.2l-0.09,-1.07l-0.06,-0.16l-1.33,-1.75l0.83,-0.94l0.07,-0.24l-0.21,-1.64l0.31,-1.43l-0.17,-1.29l0.43,-2.26l-0.15,-1.33l-0.73,-2.18l0.99,-0.52l0.16,-0.21l0.22,-1.16l-0.22,-1.06l1.54,-0.95l0.81,-0.92l1.19,-0.78l0.14,-0.23l0.12,-1.76l2.57,0.84l0.16,0.01l0.99,-0.23l2.01,0.45l3.19,1.2l1.12,2.36l0.2,0.16l2.24,0.53l3.5,1.14l2.65,1.36l0.29,-0.01l1.22,-0.71l1.27,-1.32l0.07,-0.29l-0.55,-2.0l0.69,-1.19l1.7,-1.23l1.61,-0.35l3.2,0.54l0.78,1.14l0.24,0.13l0.85,0.01l0.84,0.47l2.35,0.31l0.42,0.63l-0.79,1.16l-0.04,0.26l0.35,1.08l-0.61,1.6l-0.0,0.2l0.73,2.16l0.0,24.24l-2.58,0.01l-0.3,0.29l-0.02,0.62l-19.55,-9.83l-0.28,0.01l-2.53,1.44Z\", \"name\": \"Libya\"}, \"AE\": {\"path\": \"M550.59,223.8l0.12,0.08l1.92,-0.41l3.54,0.15l0.23,-0.09l1.71,-1.79l1.86,-1.7l1.31,-1.36l0.26,0.5l0.28,1.72l-0.93,0.01l-0.3,0.26l-0.21,1.73l0.11,0.27l0.08,0.06l-0.7,0.32l-0.17,0.27l-0.01,0.99l-0.68,1.02l-0.05,0.15l-0.06,0.96l-0.32,0.36l-7.19,-1.27l-0.79,-2.22Z\", \"name\": \"United Arab Emirates\"}, \"VE\": {\"path\": \"M240.66,256.5l0.65,0.91l-0.03,1.13l-1.05,1.39l-0.03,0.31l0.95,2.0l0.32,0.17l1.08,-0.16l0.24,-0.21l0.56,-1.83l-0.06,-0.29l-0.71,-0.81l-0.1,-1.58l2.9,-0.96l0.19,-0.37l-0.29,-1.02l0.45,-0.41l0.72,1.43l0.26,0.16l1.65,0.04l1.46,1.27l0.08,0.72l0.3,0.27l2.28,0.02l2.55,-0.25l1.34,1.06l0.14,0.06l1.92,0.31l0.2,-0.03l1.4,-0.79l0.15,-0.25l0.02,-0.36l2.82,-0.14l1.17,-0.01l-0.41,0.14l-0.14,0.46l0.86,1.19l0.22,0.12l1.93,0.18l1.73,1.13l0.37,1.9l0.31,0.24l1.21,-0.05l0.52,0.32l-1.63,1.21l-0.11,0.17l-0.22,0.92l0.07,0.27l0.63,0.69l-0.31,0.24l-1.48,0.39l-0.22,0.3l0.04,1.03l-0.59,0.6l-0.01,0.41l1.67,1.87l0.23,0.48l-0.72,0.76l-2.71,0.91l-1.78,0.39l-0.13,0.06l-0.6,0.49l-1.84,-0.58l-1.89,-0.33l-0.18,0.03l-0.47,0.23l-0.02,0.53l0.96,0.56l-0.08,1.58l0.35,1.58l0.26,0.23l1.91,0.19l0.02,0.07l-1.54,0.62l-0.18,0.2l-0.25,0.92l-0.88,0.35l-1.85,0.58l-0.16,0.13l-0.4,0.64l-1.66,0.14l-1.22,-1.18l-0.79,-2.52l-0.67,-0.88l-0.66,-0.43l0.99,-0.98l0.09,-0.26l-0.09,-0.56l-0.08,-0.16l-0.66,-0.69l-0.47,-1.54l0.18,-1.67l0.55,-0.85l0.45,-1.35l-0.15,-0.36l-0.89,-0.43l-0.19,-0.02l-1.39,0.28l-1.76,-0.13l-0.92,0.23l-1.64,-2.01l-0.17,-0.1l-1.54,-0.33l-3.05,0.23l-0.5,-0.73l-0.15,-0.12l-0.45,-0.15l-0.05,-0.28l0.28,-0.86l0.01,-0.15l-0.2,-1.01l-0.08,-0.15l-0.5,-0.5l-0.3,-1.08l-0.25,-0.22l-0.89,-0.12l0.54,-1.18l0.29,-1.73l0.66,-0.85l0.94,-0.7l0.09,-0.11l0.3,-0.6Z\", \"name\": \"Venezuela\"}, \"AF\": {\"path\": \"M574.42,192.1l2.24,0.95l0.18,0.02l1.89,-0.38l0.22,-0.18l0.46,-1.14l1.82,-0.4l1.5,-0.91l0.14,-0.19l0.46,-2.12l1.93,-0.51l0.2,-0.18l0.26,-0.68l0.87,0.57l0.13,0.05l0.79,0.09l1.35,0.02l1.83,0.59l0.75,0.34l0.26,-0.01l1.66,-0.85l0.7,0.46l0.42,-0.09l0.72,-1.17l1.32,0.05l0.23,-0.1l0.39,-0.43l0.07,-0.14l0.24,-1.08l0.86,-0.81l0.94,0.46l-0.2,0.64l0.23,0.38l0.49,0.09l-0.21,2.15l0.09,0.25l0.99,0.94l0.38,0.03l0.83,-0.57l1.06,-0.27l0.12,-0.06l1.46,-1.21l1.63,0.2l2.4,0.0l0.17,0.32l-1.12,0.25l-1.23,0.52l-2.86,0.33l-2.69,0.6l-0.13,0.06l-1.46,1.25l-0.07,0.36l0.58,1.18l0.25,1.21l-1.13,1.08l-0.09,0.25l0.09,0.98l-0.53,0.79l-2.22,-0.08l-0.28,0.44l0.83,1.57l-1.3,0.58l-0.13,0.11l-1.06,1.69l-0.05,0.18l0.13,1.51l-0.73,0.58l-0.78,-0.22l-0.14,-0.01l-1.91,0.36l-0.23,0.19l-0.2,0.57l-1.65,-0.0l-0.22,0.1l-1.4,1.56l-0.08,0.19l-0.08,2.13l-2.99,1.05l-1.67,-0.23l-0.27,0.1l-0.39,0.46l-1.43,-0.31l-2.43,0.4l-3.69,-1.23l1.96,-2.15l0.08,-0.24l-0.21,-1.78l-0.23,-0.26l-1.69,-0.42l-0.19,-1.62l-0.77,-2.08l0.98,-1.41l-0.14,-0.45l-0.82,-0.31l0.6,-1.79l0.93,-3.21Z\", \"name\": \"Afghanistan\"}, \"IQ\": {\"path\": \"M534.42,190.89l0.13,0.14l1.5,0.78l0.15,1.34l-1.13,0.87l-0.11,0.16l-0.58,2.2l0.04,0.24l1.73,2.67l0.12,0.1l2.99,1.49l1.18,1.94l-0.39,1.89l0.29,0.36l0.5,-0.0l0.02,1.17l0.08,0.2l0.83,0.86l-2.36,-0.29l-0.29,0.13l-1.74,2.49l-4.4,-0.21l-7.03,-5.49l-3.73,-1.94l-2.92,-0.74l-0.89,-3.0l5.33,-2.81l0.15,-0.19l0.95,-3.43l-0.2,-2.0l1.19,-0.61l0.11,-0.09l1.23,-1.73l0.92,-0.38l2.75,0.35l0.81,0.68l0.31,0.05l0.94,-0.38l1.5,3.17Z\", \"name\": \"Iraq\"}, \"IS\": {\"path\": \"M384.26,87.96l-0.51,2.35l0.08,0.28l2.61,2.58l-2.99,2.83l-7.16,2.72l-2.08,0.7l-9.51,-1.71l1.89,-1.36l-0.07,-0.53l-4.4,-1.59l3.33,-0.59l0.25,-0.32l-0.11,-1.2l-0.25,-0.27l-4.82,-0.88l1.38,-2.2l3.54,-0.57l3.8,2.74l0.33,0.01l3.68,-2.18l3.02,1.12l0.25,-0.02l4.01,-2.18l3.72,0.27Z\", \"name\": \"Iceland\"}, \"IR\": {\"path\": \"M556.2,187.5l2.05,-0.52l0.13,-0.07l1.69,-1.57l1.55,0.08l0.15,-0.03l1.02,-0.5l1.64,0.25l2.82,1.48l1.91,0.3l2.8,2.49l0.18,0.08l1.61,0.09l0.19,2.09l-1.0,3.47l-0.69,2.04l0.18,0.38l0.73,0.28l-0.85,1.22l-0.04,0.28l0.81,2.19l0.19,1.72l0.23,0.26l1.69,0.42l0.17,1.43l-2.18,2.39l-0.01,0.4l1.22,1.42l1.0,1.62l0.12,0.11l2.23,1.11l0.06,2.2l0.2,0.27l1.03,0.38l0.14,0.83l-3.38,1.3l-0.18,0.19l-0.87,2.85l-4.44,-0.76l-2.75,-0.62l-2.64,-0.32l-1.01,-3.11l-0.17,-0.19l-1.2,-0.48l-0.18,-0.01l-1.99,0.51l-2.42,1.25l-2.89,-0.84l-2.48,-2.03l-2.41,-0.79l-1.61,-2.47l-1.84,-3.63l-0.36,-0.15l-1.22,0.4l-1.48,-0.84l-0.37,0.06l-0.72,0.82l-1.08,-1.12l-0.02,-1.35l-0.3,-0.29l-0.43,0.0l0.34,-1.64l-0.04,-0.22l-1.29,-2.11l-0.12,-0.11l-3.0,-1.49l-1.62,-2.49l0.52,-1.98l1.18,-0.92l0.11,-0.27l-0.19,-1.66l-0.16,-0.23l-1.55,-0.81l-1.58,-3.33l-1.3,-2.2l0.41,-0.75l0.03,-0.21l-0.73,-3.12l1.2,-0.59l0.35,0.9l1.26,1.35l0.15,0.09l1.81,0.39l0.91,-0.09l0.15,-0.06l2.9,-2.13l0.7,-0.16l0.48,0.56l-0.75,1.26l0.05,0.37l1.56,1.53l0.28,0.08l0.37,-0.09l0.7,1.89l0.21,0.19l2.31,0.59l1.69,1.4l0.15,0.07l3.66,0.49l3.91,-0.76l0.23,-0.19l0.19,-0.52Z\", \"name\": \"Iran\"}, \"AM\": {\"path\": \"M530.51,176.08l2.91,-0.39l0.41,0.63l0.11,0.1l0.66,0.36l-0.32,0.47l0.07,0.41l1.1,0.84l-0.53,0.7l0.06,0.42l1.06,0.8l1.01,0.44l0.04,1.56l-0.44,0.04l-0.88,-1.46l0.01,-0.37l-0.3,-0.31l-0.98,0.01l-0.65,-0.69l-0.26,-0.09l-0.38,0.06l-0.97,-0.82l-1.64,-0.65l0.2,-1.2l-0.02,-0.16l-0.28,-0.69Z\", \"name\": \"Armenia\"}, \"IT\": {\"path\": \"M451.68,158.58l0.2,0.16l3.3,0.75l-0.22,1.26l0.02,0.18l0.35,0.78l-1.4,-0.32l-0.21,0.03l-2.04,1.1l-0.16,0.29l0.13,1.47l-0.29,0.82l0.02,0.24l0.82,1.57l0.1,0.11l2.28,1.5l1.29,2.53l2.79,2.43l0.2,0.07l1.83,-0.02l0.31,0.34l-0.46,0.39l0.06,0.5l4.06,1.97l2.06,1.49l0.17,0.36l-0.24,0.53l-1.08,-1.07l-0.15,-0.08l-2.18,-0.49l-0.33,0.15l-1.05,1.91l0.11,0.4l1.63,0.98l-0.22,1.12l-0.84,0.14l-0.22,0.15l-1.27,2.38l-0.54,0.12l0.01,-0.47l0.48,-1.46l0.5,-0.58l0.03,-0.35l-0.97,-1.69l-0.76,-1.48l-0.17,-0.15l-0.94,-0.33l-0.68,-1.18l-0.16,-0.13l-1.53,-0.52l-1.03,-1.14l-0.19,-0.1l-1.78,-0.19l-1.88,-1.3l-2.27,-1.94l-1.64,-1.68l-0.76,-2.94l-0.21,-0.21l-1.22,-0.35l-2.01,-1.0l-0.24,-0.01l-1.15,0.42l-0.11,0.07l-1.38,1.36l-0.5,0.11l0.19,-0.87l-0.21,-0.35l-1.19,-0.34l-0.56,-2.06l0.76,-0.82l0.03,-0.36l-0.68,-1.08l0.04,-0.31l0.68,0.42l0.19,0.04l1.21,-0.15l0.14,-0.06l1.18,-0.89l0.25,0.29l0.25,0.1l1.19,-0.1l0.25,-0.18l0.45,-1.04l1.61,0.34l0.19,-0.02l1.1,-0.53l0.17,-0.22l0.15,-0.95l1.19,0.35l0.35,-0.16l0.23,-0.47l2.11,-0.47l0.45,0.89ZM459.35,184.63l-0.71,1.81l0.0,0.23l0.33,0.79l-0.37,1.03l-1.6,-0.91l-1.33,-0.34l-3.24,-1.36l0.23,-0.99l2.73,0.24l3.95,-0.5ZM443.95,175.91l1.26,1.77l-0.31,3.47l-0.82,-0.13l-0.26,0.08l-0.83,0.79l-0.64,-0.52l-0.1,-3.42l-0.44,-1.34l0.91,0.1l0.21,-0.06l1.01,-0.74Z\", \"name\": \"Italy\"}, \"VN\": {\"path\": \"M690.8,230.21l-2.86,1.93l-2.09,2.46l-0.06,0.11l-0.55,1.8l0.04,0.26l4.26,6.1l2.31,1.63l1.46,1.97l1.12,4.62l-0.32,4.3l-1.97,1.57l-2.85,1.62l-2.09,2.14l-2.83,2.13l-0.67,-1.19l0.65,-1.58l-0.09,-0.35l-1.47,-1.14l1.67,-0.79l2.57,-0.18l0.22,-0.47l-0.89,-1.24l3.88,-1.8l0.17,-0.24l0.31,-3.05l-0.01,-0.13l-0.56,-1.63l0.44,-2.48l-0.01,-0.15l-0.63,-1.81l-0.08,-0.12l-1.87,-1.77l-3.64,-5.3l-0.11,-0.1l-2.68,-1.39l0.45,-0.59l1.53,-0.65l0.16,-0.39l-0.97,-2.27l-0.27,-0.18l-2.89,-0.02l-1.04,-2.21l-1.28,-1.83l0.96,-0.46l1.97,0.01l2.43,-0.3l0.13,-0.05l1.95,-1.29l1.04,0.85l0.13,0.06l1.98,0.42l-0.32,1.21l0.09,0.3l1.19,1.07l0.12,0.07l1.88,0.51Z\", \"name\": \"Vietnam\"}, \"AR\": {\"path\": \"M258.11,341.34l1.4,1.81l0.51,-0.06l0.89,-1.94l2.51,0.1l0.36,0.49l4.6,4.31l0.15,0.08l1.99,0.39l3.01,1.93l2.5,1.01l0.28,0.91l-2.4,3.97l0.17,0.44l2.57,0.74l2.81,0.41l2.09,-0.44l0.14,-0.07l2.27,-2.06l0.09,-0.17l0.38,-2.2l0.88,-0.36l1.05,1.29l-0.04,1.88l-1.98,1.4l-1.72,1.13l-2.84,2.65l-3.34,3.73l-0.07,0.12l-0.63,2.22l-0.67,2.85l0.02,2.73l-0.47,0.54l-0.07,0.17l-0.36,3.28l0.12,0.27l3.03,2.32l-0.31,1.78l0.11,0.29l1.44,1.15l-0.11,1.17l-2.32,3.57l-3.59,1.51l-4.95,0.6l-2.72,-0.29l-0.32,0.38l0.5,1.67l-0.49,2.13l0.01,0.16l0.4,1.29l-1.27,0.88l-2.41,0.39l-2.33,-1.05l-0.31,0.04l-0.97,0.78l-0.11,0.27l0.35,2.98l0.16,0.23l1.69,0.91l0.31,-0.02l1.08,-0.75l0.46,0.96l-2.1,0.88l-2.01,1.89l-0.09,0.18l-0.36,3.05l-0.51,1.42l-2.16,0.01l-0.19,0.07l-1.96,1.59l-0.1,0.15l-0.72,2.34l0.08,0.31l2.46,2.31l0.13,0.07l2.09,0.56l-0.74,2.45l-2.86,1.75l-0.12,0.14l-1.59,3.71l-2.2,1.24l-0.1,0.09l-1.03,1.54l-0.04,0.23l0.81,3.45l0.06,0.13l1.13,1.32l-2.59,-0.57l-5.89,-0.44l-0.92,-1.73l0.05,-2.4l-0.34,-0.3l-1.49,0.19l-0.72,-0.98l-0.2,-3.21l1.79,-1.33l0.1,-0.13l0.79,-2.04l0.02,-0.16l-0.27,-1.52l1.31,-2.69l0.91,-4.15l-0.23,-1.72l0.91,-0.49l0.15,-0.33l-0.27,-1.16l-0.15,-0.2l-0.87,-0.46l0.65,-1.01l-0.04,-0.37l-1.06,-1.09l-0.54,-3.2l0.83,-0.51l0.14,-0.29l-0.42,-3.6l0.58,-2.98l0.64,-2.5l1.41,-1.0l0.12,-0.32l-0.75,-2.8l-0.01,-2.48l1.81,-1.78l0.09,-0.22l-0.06,-2.3l1.39,-2.69l0.03,-0.14l0.01,-2.58l-0.11,-0.24l-0.57,-0.45l-1.1,-4.59l1.49,-2.73l0.04,-0.17l-0.23,-2.59l0.86,-2.38l1.6,-2.48l1.74,-1.65l0.04,-0.39l-0.64,-0.89l0.42,-0.7l0.04,-0.16l-0.08,-4.26l2.55,-1.23l0.16,-0.18l0.86,-2.75l-0.01,-0.22l-0.22,-0.48l1.84,-2.1l3.0,0.59ZM256.77,438.98l-2.1,0.15l-1.18,-1.14l-0.19,-0.08l-1.53,-0.09l-2.38,-0.0l-0.0,-6.28l0.4,0.65l1.25,2.55l0.11,0.12l3.26,2.07l3.19,0.8l-0.82,1.26Z\", \"name\": \"Argentina\"}, \"AU\": {\"path\": \"M705.55,353.06l0.09,0.09l0.37,0.05l0.13,-0.35l-0.57,-1.69l0.48,0.3l0.71,0.99l0.34,0.11l0.2,-0.29l-0.04,-1.37l-0.04,-0.14l-1.22,-2.07l-0.28,-0.9l-0.51,-0.69l0.24,-1.33l0.52,-0.7l0.34,-1.32l0.01,-0.13l-0.25,-1.44l0.51,-0.94l0.1,1.03l0.23,0.26l0.32,-0.14l1.01,-1.72l1.94,-0.84l1.27,-1.14l1.84,-0.92l1.0,-0.18l0.6,0.28l0.26,-0.0l1.94,-0.96l1.48,-0.28l0.19,-0.13l0.32,-0.49l0.51,-0.18l1.42,0.05l2.63,-0.76l0.11,-0.06l1.36,-1.15l0.08,-0.1l0.61,-1.33l1.42,-1.27l0.1,-0.19l0.11,-1.03l0.06,-1.32l1.39,-1.74l0.85,1.79l0.4,0.14l1.07,-0.51l0.11,-0.45l-0.77,-1.05l0.53,-0.84l0.86,0.43l0.43,-0.22l0.29,-1.85l1.29,-1.19l0.6,-0.98l1.16,-0.4l0.2,-0.27l0.02,-0.34l0.74,0.2l0.38,-0.27l0.03,-0.44l1.98,-0.61l1.7,1.08l1.36,1.48l0.22,0.1l1.55,0.02l1.57,0.24l0.33,-0.4l-0.48,-1.27l1.09,-1.86l1.06,-0.63l0.1,-0.42l-0.28,-0.46l0.93,-1.24l1.36,-0.8l1.16,0.27l0.14,0.0l2.1,-0.48l0.23,-0.3l-0.05,-1.3l-0.18,-0.26l-1.08,-0.49l0.44,-0.12l1.52,0.58l1.39,1.06l2.11,0.65l0.19,-0.0l0.59,-0.21l1.44,0.72l0.27,0.0l1.37,-0.68l0.84,0.2l0.26,-0.06l0.37,-0.3l0.82,0.89l-0.56,1.14l-0.84,0.91l-0.75,0.07l-0.26,0.38l0.26,0.9l-0.67,1.15l-0.88,1.24l-0.05,0.25l0.18,0.72l0.12,0.17l1.99,1.42l1.96,0.84l1.25,0.86l1.8,1.51l0.19,0.07l0.63,-0.0l1.15,0.58l0.34,0.7l0.17,0.15l2.39,0.88l0.24,-0.02l1.65,-0.88l0.14,-0.16l0.49,-1.37l0.52,-1.19l0.31,-1.39l0.75,-2.02l0.01,-0.19l-0.33,-1.16l0.16,-0.67l0.0,-0.13l-0.28,-1.41l0.3,-1.78l0.42,-0.45l0.05,-0.33l-0.33,-0.73l0.56,-1.25l0.48,-1.39l0.07,-0.69l0.58,-0.59l0.48,0.84l0.17,1.53l0.17,0.24l0.47,0.23l0.09,0.9l0.05,0.14l0.87,1.23l0.17,1.33l-0.09,0.89l0.03,0.15l0.9,2.0l0.43,0.13l1.38,-0.83l0.71,0.92l1.06,0.88l-0.22,0.96l0.0,0.14l0.53,2.2l0.38,1.3l0.15,0.18l0.52,0.26l0.62,2.01l-0.23,1.27l0.02,0.18l0.81,1.76l0.14,0.14l2.69,1.35l3.21,2.21l-0.2,0.4l0.04,0.34l1.39,1.6l0.95,2.78l0.43,0.16l0.79,-0.46l0.85,0.96l0.39,0.05l0.22,-0.15l0.36,2.33l0.09,0.18l1.78,1.63l1.16,1.01l1.9,2.1l0.67,2.05l0.06,1.47l-0.17,1.64l0.03,0.17l1.16,2.22l-0.14,2.28l-0.43,1.24l-0.68,2.44l0.04,1.63l-0.48,1.92l-1.06,2.43l-1.79,1.32l-0.1,0.12l-0.91,2.15l-0.82,1.37l-0.76,2.47l-0.98,1.46l-0.63,2.14l-0.33,2.02l0.1,0.82l-1.21,0.85l-2.71,0.1l-0.13,0.03l-2.31,1.19l-1.21,1.17l-1.34,1.11l-1.89,-1.18l-1.33,-0.46l0.32,-1.24l-0.4,-0.35l-1.46,0.61l-2.06,1.98l-1.99,-0.73l-1.43,-0.46l-1.45,-0.22l-2.32,-0.81l-1.51,-1.67l-0.45,-2.11l-0.6,-1.5l-0.07,-0.11l-1.23,-1.16l-0.16,-0.08l-1.96,-0.28l0.59,-0.99l0.03,-0.24l-0.61,-2.1l-0.54,-0.08l-1.16,1.85l-1.23,0.29l0.73,-0.88l0.06,-0.12l0.37,-1.57l0.93,-1.33l0.05,-0.2l-0.2,-2.07l-0.53,-0.17l-2.01,2.35l-1.52,0.94l-0.12,0.14l-0.82,1.93l-1.5,-0.9l0.07,-1.32l-0.06,-0.2l-1.57,-2.04l-1.15,-0.92l0.3,-0.41l-0.1,-0.44l-3.21,-1.69l-0.13,-0.03l-1.69,-0.08l-2.35,-1.31l-0.16,-0.04l-4.55,0.27l-3.24,0.99l-2.8,0.91l-2.33,-0.18l-0.17,0.03l-2.63,1.41l-2.14,0.64l-0.2,0.19l-0.47,1.42l-0.8,0.99l-1.99,0.06l-1.55,0.24l-2.27,-0.5l-1.79,0.3l-1.71,0.13l-0.19,0.09l-1.38,1.39l-0.58,-0.1l-0.21,0.04l-1.26,0.8l-1.13,0.85l-1.72,-0.1l-1.6,-0.0l-2.58,-1.76l-1.21,-0.49l0.04,-1.19l1.04,-0.32l0.16,-0.12l0.42,-0.64l0.05,-0.19l-0.09,-0.97l0.3,-2.0l-0.28,-1.64l-1.34,-2.84l-0.39,-1.49l0.1,-1.51l-0.04,-0.17l-0.96,-1.72l-0.06,-0.73l-0.09,-0.19l-1.04,-1.01l-0.3,-2.02l-0.05,-0.12l-1.23,-1.83ZM784.95,393.35l2.39,1.01l0.2,0.01l3.26,-0.96l1.19,0.16l0.16,3.19l-0.78,0.95l-0.07,0.16l-0.19,1.83l-0.43,-0.41l-0.44,0.03l-1.61,1.96l-0.4,-0.12l-1.38,-0.09l-1.43,-2.42l-0.37,-2.03l-1.4,-2.53l0.04,-0.94l1.27,0.2Z\", \"name\": \"Australia\"}, \"IL\": {\"path\": \"M509.04,199.22l0.71,0.0l0.27,-0.17l0.15,-0.33l0.19,-0.01l0.02,0.73l-0.27,0.34l0.02,0.08l-0.32,0.62l-0.65,-0.27l-0.41,0.19l-0.52,1.85l0.16,0.35l0.14,0.07l-0.17,0.1l-0.14,0.21l-0.11,0.73l0.39,0.33l0.81,-0.26l0.03,0.64l-0.97,3.43l-1.28,-3.67l0.62,-0.78l-0.03,-0.41l0.58,-1.16l0.5,-2.07l0.27,-0.54Z\", \"name\": \"Israel\"}, \"IN\": {\"path\": \"M615.84,192.58l2.4,2.97l-0.24,2.17l0.05,0.2l0.94,1.35l-0.06,0.97l-1.46,-0.3l-0.35,0.36l0.7,3.06l0.12,0.18l2.46,1.75l3.11,1.72l-1.23,0.96l-0.1,0.13l-0.97,2.55l0.16,0.38l2.41,1.02l2.37,1.33l3.27,1.52l3.43,0.37l1.37,1.3l0.17,0.08l1.92,0.25l3.0,0.62l2.15,-0.04l0.28,-0.22l0.29,-1.06l0.0,-0.13l-0.32,-1.66l0.16,-0.94l1.0,-0.37l0.23,2.28l0.18,0.24l2.28,1.02l0.2,0.02l1.52,-0.41l2.06,0.18l2.08,-0.08l0.29,-0.27l0.18,-1.66l-0.1,-0.26l-0.53,-0.44l1.38,-0.23l0.15,-0.07l2.26,-2.0l2.75,-1.65l1.97,0.63l0.25,-0.03l1.54,-0.99l0.89,1.28l-0.72,0.97l0.2,0.48l2.49,0.37l0.11,0.61l-0.69,0.39l-0.15,0.3l0.15,1.22l-1.36,-0.37l-0.23,0.03l-3.24,1.86l-0.15,0.28l0.07,1.44l-1.33,2.16l-0.04,0.13l-0.12,1.24l-0.98,1.91l-1.72,-0.53l-0.39,0.28l-0.09,2.66l-0.52,0.83l-0.04,0.23l0.21,0.89l-0.71,0.36l-1.21,-3.85l-0.29,-0.21l-0.69,0.01l-0.29,0.23l-0.28,1.17l-0.84,-0.84l0.6,-1.17l0.97,-0.13l0.23,-0.16l1.15,-2.25l-0.18,-0.42l-1.54,-0.47l-2.3,0.04l-2.13,-0.33l-0.19,-1.63l-0.26,-0.26l-1.13,-0.13l-1.93,-1.13l-0.42,0.13l-0.88,1.82l0.08,0.37l1.47,1.15l-1.21,0.77l-0.1,0.1l-0.56,0.97l0.13,0.42l1.31,0.61l-0.36,1.35l0.01,0.2l0.85,1.95l0.37,2.05l-0.26,0.68l-1.55,-0.02l-3.09,0.54l-0.25,0.32l0.13,1.84l-1.21,1.4l-3.64,1.79l-2.79,3.04l-1.86,1.61l-2.48,1.68l-0.13,0.25l-0.0,1.0l-1.07,0.55l-2.21,0.9l-1.13,0.13l-0.25,0.19l-0.75,1.96l-0.02,0.15l0.52,3.31l0.13,2.03l-1.03,2.35l-0.03,0.12l-0.01,4.03l-1.02,0.1l-0.23,0.15l-1.14,1.93l0.04,0.36l0.44,0.48l-1.83,0.57l-0.18,0.15l-0.81,1.65l-0.74,0.53l-2.14,-2.12l-1.14,-3.47l-0.96,-2.57l-0.9,-1.26l-1.3,-2.38l-0.61,-3.14l-0.44,-1.62l-2.29,-3.56l-1.03,-4.94l-0.74,-3.29l0.01,-3.12l-0.49,-2.51l-0.41,-0.22l-3.56,1.53l-1.59,-0.28l-2.96,-2.87l0.94,-0.74l0.06,-0.41l-0.74,-1.03l-2.73,-2.1l1.35,-1.43l5.38,0.01l0.29,-0.36l-0.5,-2.29l-0.09,-0.15l-1.33,-1.28l-0.27,-1.96l-0.12,-0.2l-1.36,-1.0l2.42,-2.48l2.77,0.2l0.24,-0.1l2.62,-2.85l1.59,-2.8l2.41,-2.74l0.07,-0.2l-0.04,-1.82l2.01,-1.51l-0.01,-0.49l-1.95,-1.33l-0.83,-1.81l-0.82,-2.27l0.98,-0.97l3.64,0.66l2.89,-0.42l0.17,-0.08l2.18,-2.15Z\", \"name\": \"India\"}, \"TZ\": {\"path\": \"M505.77,287.58l0.36,0.23l8.95,5.03l0.15,1.3l0.13,0.21l3.4,2.37l-1.07,2.88l-0.02,0.14l0.15,1.42l0.15,0.23l1.47,0.84l0.05,0.42l-0.66,1.44l-0.02,0.18l0.13,0.72l-0.16,1.16l0.03,0.19l0.87,1.57l1.03,2.48l0.12,0.14l0.53,0.32l-1.59,1.18l-2.64,0.95l-1.45,-0.04l-0.2,0.07l-0.81,0.69l-1.64,0.06l-0.68,0.3l-2.9,-0.69l-1.71,0.17l-0.65,-3.18l-0.05,-0.12l-1.35,-1.88l-0.19,-0.12l-2.41,-0.46l-1.38,-0.74l-1.63,-0.44l-0.96,-0.41l-0.95,-0.58l-1.31,-3.09l-1.47,-1.46l-0.45,-1.31l0.24,-1.34l-0.39,-1.99l0.71,-0.08l0.18,-0.09l0.91,-0.91l0.98,-1.31l0.59,-0.5l0.11,-0.24l-0.02,-0.81l-0.08,-0.2l-0.47,-0.5l-0.1,-0.67l0.51,-0.23l0.18,-0.25l0.14,-1.47l-0.05,-0.2l-0.76,-1.09l0.45,-0.15l2.71,0.03l5.01,-0.19Z\", \"name\": \"Tanzania\"}, \"AZ\": {\"path\": \"M539.36,175.66l0.16,0.09l1.11,0.2l0.32,-0.15l0.4,-0.71l1.22,-0.99l1.11,1.33l1.26,2.09l0.22,0.14l1.06,0.13l0.28,0.29l-1.46,0.17l-0.26,0.24l-0.43,2.26l-0.39,0.92l-0.85,0.63l-0.12,0.25l0.06,1.2l-0.22,0.05l-1.28,-1.25l0.74,-1.25l-0.03,-0.35l-0.74,-0.86l-0.3,-0.1l-1.05,0.27l-2.49,1.82l-0.04,-1.46l-0.18,-0.27l-1.09,-0.47l-0.8,-0.6l0.53,-0.7l-0.06,-0.42l-1.11,-0.84l0.34,-0.51l-0.11,-0.43l-0.89,-0.48l-0.33,-0.49l0.25,-0.2l1.78,0.81l1.35,0.18l0.25,-0.09l0.34,-0.35l0.02,-0.39l-1.04,-1.36l0.28,-0.18l0.49,0.07l1.65,1.74ZM533.53,180.16l0.63,0.67l0.22,0.09l0.8,-0.0l0.04,0.31l0.66,1.09l-0.94,-0.21l-1.16,-1.24l-0.25,-0.71Z\", \"name\": \"Azerbaijan\"}, \"IE\": {\"path\": \"M405.17,135.35l0.36,2.16l-1.78,2.84l-4.28,1.91l-3.02,-0.43l1.81,-3.13l0.02,-0.26l-1.23,-3.26l3.24,-2.56l1.54,-1.32l0.37,1.33l-0.49,1.77l0.3,0.38l1.49,-0.05l1.68,0.63Z\", \"name\": \"Ireland\"}, \"ID\": {\"path\": \"M756.56,287.86l0.69,4.02l0.15,0.21l2.59,1.5l0.39,-0.07l2.05,-2.61l2.75,-1.45l2.09,-0.0l2.08,0.85l1.85,0.89l2.52,0.46l0.08,15.44l-1.72,-1.6l-0.15,-0.07l-2.54,-0.51l-0.29,0.1l-0.53,0.62l-2.53,0.06l0.78,-1.51l1.48,-0.66l0.17,-0.34l-0.65,-2.74l-1.23,-2.19l-0.14,-0.13l-4.85,-2.13l-2.09,-0.23l-3.7,-2.28l-0.41,0.1l-0.67,1.11l-0.63,0.14l-0.41,-0.67l-0.01,-1.01l-0.14,-0.25l-1.39,-0.89l2.05,-0.69l1.73,0.05l0.29,-0.39l-0.21,-0.66l-0.29,-0.21l-3.5,-0.0l-0.9,-1.36l-0.19,-0.13l-2.14,-0.44l-0.65,-0.76l2.86,-0.51l1.28,-0.79l3.75,0.96l0.32,0.76ZM758.01,300.37l-0.79,1.04l-0.14,-1.07l0.4,-0.81l0.29,-0.47l0.24,0.31l-0.0,1.0ZM747.45,292.9l0.48,1.02l-1.45,-0.69l-2.09,-0.21l-1.45,0.16l-1.28,-0.07l0.35,-0.81l2.86,-0.1l2.58,0.68ZM741.15,285.69l-0.16,-0.25l-0.72,-3.08l0.47,-1.86l0.35,-0.38l0.1,0.73l0.25,0.26l1.28,0.19l0.18,0.78l-0.11,1.8l-0.96,-0.18l-0.35,0.22l-0.38,1.52l0.05,0.24ZM741.19,285.75l0.76,0.97l-0.11,0.05l-0.65,-1.02ZM739.18,293.52l-0.61,0.54l-1.44,-0.38l-0.25,-0.55l1.93,-0.09l0.36,0.48ZM728.4,295.87l-0.27,-0.07l-2.26,0.89l-0.37,-0.41l0.27,-0.8l-0.09,-0.33l-1.68,-1.37l0.17,-2.29l-0.42,-0.3l-1.67,0.76l-0.17,0.29l0.21,2.92l0.09,3.34l-1.22,0.28l-0.78,-0.54l0.65,-2.1l0.01,-0.14l-0.39,-2.42l-0.29,-0.25l-0.86,-0.02l-0.63,-1.4l0.99,-1.61l0.35,-1.97l1.24,-3.73l0.49,-0.96l1.95,-1.7l1.86,0.69l3.16,0.35l2.92,-0.1l0.17,-0.06l2.24,-1.65l0.11,0.14l-1.8,2.22l-1.72,0.44l-2.41,-0.48l-4.21,0.13l-2.19,0.36l-0.25,0.24l-0.36,1.9l0.08,0.27l2.24,2.23l0.4,0.02l1.29,-1.08l3.19,-0.58l-0.19,0.06l-1.04,1.4l-2.13,0.94l-0.12,0.45l2.26,3.06l-0.37,0.69l0.03,0.32l1.51,1.95ZM728.48,295.97l0.59,0.76l-0.02,1.37l-1.0,0.55l-0.64,-0.58l1.09,-1.84l-0.02,-0.26ZM728.64,286.95l0.79,-0.14l-0.07,0.39l-0.72,-0.24ZM732.38,310.1l-1.89,0.49l-0.06,-0.06l0.17,-0.64l1.0,-1.42l2.14,-0.87l0.1,0.2l0.04,0.58l-1.49,1.72ZM728.26,305.71l-0.17,0.63l-3.53,0.67l-3.02,-0.28l-0.0,-0.42l1.66,-0.44l1.47,0.71l0.16,0.03l1.75,-0.21l1.69,-0.69ZM722.98,310.33l-0.74,0.03l-2.52,-1.35l1.42,-0.3l1.19,0.7l0.72,0.63l-0.06,0.28ZM716.24,305.63l0.66,0.49l0.22,0.06l1.35,-0.18l0.31,0.53l-4.18,0.77l-0.8,-0.01l0.51,-0.86l1.2,-0.02l0.24,-0.12l0.49,-0.65ZM715.84,280.21l0.09,0.34l2.25,1.86l-2.25,0.22l-0.24,0.17l-0.84,1.71l-0.03,0.15l0.1,2.11l-2.27,1.62l-0.13,0.24l-0.06,2.46l-0.74,2.92l-0.02,-0.05l-0.39,-0.16l-2.62,1.04l-0.86,-1.33l-0.23,-0.14l-1.71,-0.14l-1.19,-0.76l-0.25,-0.03l-2.78,0.84l-0.79,-1.05l-0.26,-0.12l-1.61,0.13l-1.8,-0.25l-0.36,-3.13l-0.15,-0.23l-1.18,-0.65l-1.13,-2.02l-0.33,-2.1l0.27,-2.19l1.05,-1.17l0.28,1.12l0.1,0.16l1.71,1.41l0.28,0.05l1.55,-0.49l1.54,0.17l0.23,-0.07l1.4,-1.21l1.05,-0.19l2.3,0.68l0.16,0.0l2.04,-0.53l0.21,-0.19l1.26,-3.41l0.91,-0.82l0.09,-0.14l0.8,-2.64l2.63,0.0l1.71,0.33l-1.19,1.89l0.02,0.34l1.74,2.24l-0.37,1.0ZM692.67,302.0l0.26,0.19l4.8,0.25l0.28,-0.16l0.44,-0.83l4.29,1.12l0.85,1.52l0.23,0.15l3.71,0.45l2.37,1.15l-2.06,0.69l-2.77,-1.0l-2.25,0.07l-2.57,-0.18l-2.31,-0.45l-2.94,-0.97l-1.84,-0.25l-0.13,0.01l-0.97,0.29l-4.34,-0.98l-0.38,-0.94l-0.25,-0.19l-1.76,-0.14l1.31,-1.84l2.81,0.14l1.97,0.96l0.95,0.19l0.28,0.74ZM685.63,299.27l-2.36,0.04l-2.07,-2.05l-3.17,-2.02l-1.06,-1.5l-1.88,-2.02l-1.22,-1.85l-1.9,-3.49l-2.2,-2.11l-0.71,-2.08l-0.94,-1.99l-0.1,-0.12l-2.21,-1.54l-1.35,-2.17l-1.86,-1.39l-2.53,-2.68l-0.14,-0.81l1.22,0.08l3.76,0.47l2.16,2.4l1.94,1.7l1.37,1.04l2.35,2.67l0.22,0.1l2.44,0.04l1.99,1.62l1.42,2.06l0.09,0.09l1.67,1.0l-0.88,1.8l0.11,0.39l1.44,0.87l0.13,0.04l0.68,0.05l0.41,1.62l0.87,1.4l0.22,0.14l1.71,0.21l1.06,1.38l-0.61,3.04l-0.09,3.6Z\", \"name\": \"Indonesia\"}, \"UA\": {\"path\": \"M500.54,141.42l0.9,0.13l0.27,-0.11l0.52,-0.62l0.68,0.13l2.43,-0.3l1.32,1.57l-0.45,0.48l-0.07,0.26l0.21,1.03l0.27,0.24l1.85,0.15l0.76,1.22l-0.05,0.55l0.2,0.31l3.18,1.15l0.18,0.01l1.75,-0.47l1.42,1.41l0.22,0.09l1.42,-0.03l3.44,0.99l0.02,0.65l-0.97,1.62l-0.03,0.24l0.52,1.67l-0.29,0.79l-2.24,0.22l-0.14,0.05l-1.29,0.89l-0.13,0.23l-0.07,1.16l-1.75,0.22l-0.12,0.04l-1.6,0.98l-2.27,0.16l-0.12,0.04l-2.16,1.17l-0.16,0.29l0.15,1.94l0.14,0.23l1.23,0.75l0.18,0.04l2.06,-0.15l-0.22,0.51l-2.67,0.54l-3.27,1.72l-1.0,-0.45l0.45,-1.19l-0.19,-0.39l-2.34,-0.78l0.15,-0.2l2.32,-1.0l0.09,-0.49l-0.73,-0.72l-0.15,-0.08l-3.69,-0.75l-0.14,-0.96l-0.35,-0.25l-2.32,0.39l-0.21,0.15l-0.91,1.7l-1.77,2.1l-0.93,-0.44l-0.24,-0.0l-1.05,0.45l-0.48,-0.25l0.13,-0.07l0.14,-0.15l0.43,-1.04l0.67,-0.97l0.04,-0.26l-0.1,-0.31l0.04,-0.02l0.11,0.19l0.24,0.15l1.48,0.09l0.78,-0.25l0.07,-0.53l-0.27,-0.19l0.09,-0.25l-0.08,-0.33l-0.81,-0.74l-0.34,-1.24l-0.14,-0.18l-0.73,-0.42l0.15,-0.87l-0.11,-0.29l-1.13,-0.86l-0.15,-0.06l-0.97,-0.11l-1.79,-0.97l-0.2,-0.03l-1.66,0.32l-0.13,0.06l-0.52,0.41l-0.95,-0.0l-0.23,0.11l-0.56,0.66l-1.74,0.29l-0.79,0.43l-1.01,-0.68l-0.16,-0.05l-1.57,-0.01l-1.52,-0.35l-0.23,0.04l-0.71,0.45l-0.09,-0.43l-0.13,-0.19l-1.18,-0.74l0.38,-1.02l0.53,-0.64l0.35,0.12l0.37,-0.41l-0.57,-1.29l2.1,-2.5l1.16,-0.36l0.2,-0.2l0.27,-0.92l-0.01,-0.2l-1.1,-2.52l0.79,-0.09l0.13,-0.05l1.3,-0.86l1.83,-0.07l2.48,0.26l2.84,0.8l1.91,0.06l0.88,0.45l0.29,-0.01l0.72,-0.44l0.49,0.58l0.25,0.11l2.2,-0.16l0.94,0.3l0.39,-0.26l0.15,-1.57l0.61,-0.59l2.01,-0.19Z\", \"name\": \"Ukraine\"}, \"QA\": {\"path\": \"M548.47,221.47l-0.15,-1.72l0.59,-1.23l0.38,-0.16l0.54,0.6l0.04,1.4l-0.47,1.37l-0.41,0.11l-0.53,-0.37Z\", \"name\": \"Qatar\"}, \"MZ\": {\"path\": \"M507.71,314.14l1.65,-0.18l2.96,0.7l0.2,-0.02l0.6,-0.29l1.68,-0.06l0.18,-0.07l0.8,-0.69l1.5,0.02l2.74,-0.98l1.74,-1.27l0.25,0.7l-0.1,2.47l0.31,2.27l0.1,3.97l0.42,1.24l-0.7,1.71l-0.94,1.73l-1.52,1.52l-5.06,2.21l-2.88,2.8l-1.01,0.51l-1.72,1.81l-0.99,0.58l-0.15,0.23l-0.21,1.86l0.04,0.19l1.17,1.95l0.47,1.47l0.03,0.74l0.39,0.28l0.05,-0.01l-0.06,2.13l-0.39,1.19l0.1,0.33l0.42,0.32l-0.28,0.83l-0.95,0.86l-2.03,0.88l-3.08,1.49l-1.1,0.99l-0.09,0.28l0.21,1.13l0.21,0.23l0.38,0.11l-0.14,0.89l-1.39,-0.02l-0.17,-0.94l-0.38,-1.23l-0.2,-0.89l0.44,-2.91l-0.01,-0.14l-0.65,-1.88l-1.15,-3.55l2.52,-2.85l0.68,-1.89l0.29,-0.18l0.14,-0.2l0.28,-1.53l-0.03,-0.19l-0.36,-0.7l0.1,-1.83l0.49,-1.84l-0.01,-3.26l-0.14,-0.25l-1.3,-0.83l-0.11,-0.04l-1.08,-0.17l-0.47,-0.55l-0.1,-0.08l-1.16,-0.54l-0.13,-0.03l-1.83,0.04l-0.32,-2.25l7.19,-1.99l1.32,1.12l0.29,0.06l0.55,-0.19l0.75,0.49l0.11,0.81l-0.49,1.11l-0.02,0.15l0.19,1.81l0.09,0.18l1.63,1.59l0.48,-0.1l0.72,-1.68l0.99,-0.49l0.17,-0.29l-0.21,-3.29l-0.04,-0.13l-1.11,-1.92l-0.9,-0.82l-0.21,-0.08l-0.62,0.03l-0.63,-2.98l0.61,-1.67Z\", \"name\": \"Mozambique\"}}, \"height\": 440.7063107441331, \"projection\": {\"type\": \"mill\", \"centralMeridian\": 11.5}, \"width\": 900.0});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/laydate/laydate.js",
    "content": "/*! laydate-v5.0.9 日期与时间组件 MIT License  http://www.layui.com/laydate/  By 贤心 */\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": "src/main/resources/static/js/plugins/laydate/theme/default/laydate.css",
    "content": "/*! laydate-v5.0.9 日期与时间组件 MIT License  http://www.layui.com/laydate/  By 贤心 */\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}@font-face{font-family:laydate-icon;src:url(font/iconfont.eot);src:url(font/iconfont.eot#iefix) format('embedded-opentype'),url(font/iconfont.svg#iconfont) format('svg'),url(font/iconfont.woff) format('woff'),url(font/iconfont.ttf) format('truetype')}.laydate-icon{font-family:laydate-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/extend/layer.ext.js",
    "content": "/*! layer弹层组件拓展类 */\n;!function(){layer.use(\"skin/layer.ext.css\",function(){layer.layui_layer_extendlayerextjs=!0});var a=layer.cache||{},b=function(b){return a.skin?\" \"+a.skin+\" \"+a.skin+\"-\"+b:\"\"};layer.prompt=function(a,c){a=a||{},\"function\"==typeof a&&(c=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 layer.open($.extend({btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:e,skin:\"layui-layer-prompt\"+b(\"prompt\"),success:function(a){d=a.find(\".layui-layer-input\"),d.focus()},yes:function(b){var e=d.val();\"\"===e?d.focus():e.length>(a.maxlength||500)?layer.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(a.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",d,{tips:1}):c&&c(e,b,d)}},a))},layer.tab=function(a){a=a||{};var c=a.tab||{};return layer.open($.extend({type:1,skin:\"layui-layer-tab\"+b(\"tab\"),title:function(){var a=c.length,b=1,d=\"\";if(a>0)for(d='<span class=\"layui-layer-tabnow\">'+c[0].title+\"</span>\";a>b;b++)d+=\"<span>\"+c[b].title+\"</span>\";return d}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var a=c.length,b=1,d=\"\";if(a>0)for(d='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(c[0].content||\"no content\")+\"</li>\";a>b;b++)d+='<li class=\"layui-layer-tabli\">'+(c[b].content||\"no  content\")+\"</li>\";return d}()+\"</ul>\",success:function(a){var b=a.find(\".layui-layer-title\").children(),c=a.find(\".layui-layer-tabmain\").children();b.on(\"mousedown\",function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0;var b=$(this),d=b.index();b.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),c.eq(d).show().siblings().hide()})}},a))},layer.photos=function(a,c,d){function e(a,b,c){var d=new Image;d.onload=function(){d.onload=null,b(d)},d.onerror=function(a){d.onerror=null,c(a)},d.src=a}var f={};if(a=a||{},a.photos){var g=a.photos.constructor===Object,h=g?a.photos:{},i=h.data||[],j=h.start||0;if(f.imgIndex=j+1,g){if(0===i.length)return void layer.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var k=$(a.photos),l=k.find(a.img||\"img\");if(0===l.length)return;if(c||k.find(h.img||\"img\").each(function(b){var c=$(this);i.push({alt:c.attr(\"alt\"),pid:c.attr(\"layer-pid\"),src:c.attr(\"layer-src\")||c.attr(\"src\"),thumb:c.attr(\"src\")}),c.on(\"click\",function(){layer.photos($.extend(a,{photos:{start:b,data:i,tab:a.tab},full:a.full}),!0)})}),!c)return}f.imgprev=function(a){f.imgIndex--,f.imgIndex<1&&(f.imgIndex=i.length),f.tabimg(a)},f.imgnext=function(a,b){f.imgIndex++,f.imgIndex>i.length&&(f.imgIndex=1,b)||f.tabimg(a)},f.keyup=function(a){if(!f.end){var b=a.keyCode;a.preventDefault(),37===b?f.imgprev(!0):39===b?f.imgnext(!0):27===b&&layer.close(f.index)}},f.tabimg=function(b){i.length<=1||(h.start=f.imgIndex-1,layer.close(f.index),layer.photos(a,!0,b))},f.event=function(){f.bigimg.hover(function(){f.imgsee.show()},function(){f.imgsee.hide()}),f.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(a){a.preventDefault(),f.imgprev()}),f.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(a){a.preventDefault(),f.imgnext()}),$(document).on(\"keyup\",f.keyup)},f.loadi=layer.load(1,{shade:\"shade\"in a?!1:.9,scrollbar:!1}),e(i[j].src,function(c){layer.close(f.loadi),f.index=layer.open($.extend({type:1,area:function(){var b=[c.width,c.height],d=[$(window).width()-100,$(window).height()-100];return!a.full&&b[0]>d[0]&&(b[0]=d[0],b[1]=b[0]*d[1]/b[0]),[b[0]+\"px\",b[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\"+b(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+i[j].src+'\" alt=\"'+(i[j].alt||\"\")+'\" layer-pid=\"'+i[j].pid+'\"><div class=\"layui-layer-imgsee\">'+(i.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:'+(d?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(i[j].alt||\"\")+\"</a><em>\"+f.imgIndex+\"/\"+i.length+\"</em></span></div></div></div>\",success:function(b,c){f.bigimg=b.find(\".layui-layer-phimg\"),f.imgsee=b.find(\".layui-layer-imguide,.layui-layer-imgbar\"),f.event(b),a.tab&&a.tab(i[j],b)},end:function(){f.end=!0,$(document).off(\"keyup\",f.keyup)}},a))},function(){layer.close(f.loadi),layer.msg(\"&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;\",{time:3e4,btn:[\"下一张\",\"不看了\"],yes:function(){i.length>1&&f.imgnext(!0,!0)}})})}}}();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/laydate/laydate.js",
    "content": "/**\n\n @Name : layDate v1.1 日期控件\n @author 郑保乐\n @Date: 2014-06-25\n @QQ群：176047195\n @Site：http://sentsin.com/layui/laydate\n\n */\n\n;!function(a){var b={path:\"\",defSkin:\"default\",format:\"YYYY-MM-DD\",min:\"1900-01-01 00:00:00\",max:\"2099-12-31 23:59:59\",isv:!1},c={},d=document,e=\"createElement\",f=\"getElementById\",g=\"getElementsByTagName\",h=[\"laydate_box\",\"laydate_void\",\"laydate_click\",\"LayDateSkin\",\"skins/\",\"/laydate.css\"];a.laydate=function(b){b=b||{};try{h.event=a.event?a.event:laydate.caller.arguments[0]}catch(d){}return c.run(b),laydate},laydate.v=\"1.1\",c.getPath=function(){var a=document.scripts,c=a[a.length-1].src;return b.path?b.path:c.substring(0,c.lastIndexOf(\"/\")+1)}(),c.use=function(a,b){var f=d[e](\"link\");f.type=\"text/css\",f.rel=\"stylesheet\",f.href=c.getPath+a+h[5],b&&(f.id=b),d[g](\"head\")[0].appendChild(f),f=null},c.trim=function(a){return a=a||\"\",a.replace(/^\\s|\\s$/g,\"\").replace(/\\s+/g,\" \")},c.digit=function(a){return 10>a?\"0\"+(0|a):a},c.stopmp=function(b){return b=b||a.event,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0,this},c.each=function(a,b){for(var c=0,d=a.length;d>c&&b(c,a[c])!==!1;c++);},c.hasClass=function(a,b){return a=a||{},new RegExp(\"\\\\b\"+b+\"\\\\b\").test(a.className)},c.addClass=function(a,b){return a=a||{},c.hasClass(a,b)||(a.className+=\" \"+b),a.className=c.trim(a.className),this},c.removeClass=function(a,b){if(a=a||{},c.hasClass(a,b)){var d=new RegExp(\"\\\\b\"+b+\"\\\\b\");a.className=a.className.replace(d,\"\")}return this},c.removeCssAttr=function(a,b){var c=a.style;c.removeProperty?c.removeProperty(b):c.removeAttribute(b)},c.shde=function(a,b){a.style.display=b?\"none\":\"block\"},c.query=function(a){var e,b,h,i,j;return a=c.trim(a).split(\" \"),b=d[f](a[0].substr(1)),b?a[1]?/^\\./.test(a[1])?(i=a[1].substr(1),j=new RegExp(\"\\\\b\"+i+\"\\\\b\"),e=[],h=d.getElementsByClassName?b.getElementsByClassName(i):b[g](\"*\"),c.each(h,function(a,b){j.test(b.className)&&e.push(b)}),e[0]?e:\"\"):(e=b[g](a[1]),e[0]?b[g](a[1]):\"\"):b:void 0},c.on=function(b,d,e){return b.attachEvent?b.attachEvent(\"on\"+d,function(){e.call(b,a.even)}):b.addEventListener(d,e,!1),c},c.stopMosup=function(a,b){\"mouseup\"!==a&&c.on(b,\"mouseup\",function(a){c.stopmp(a)})},c.run=function(a){var d,e,g,b=c.query,f=h.event;try{g=f.target||f.srcElement||{}}catch(i){g={}}if(d=a.elem?b(a.elem):g,f&&g.tagName){if(!d||d===c.elem)return;c.stopMosup(f.type,d),c.stopmp(f),c.view(d,a),c.reshow()}else e=a.event||\"click\",c.each((0|d.length)>0?d:[d],function(b,d){c.stopMosup(e,d),c.on(d,e,function(b){c.stopmp(b),d!==c.elem&&(c.view(d,a),c.reshow())})})},c.scroll=function(a){return a=a?\"scrollLeft\":\"scrollTop\",d.body[a]|d.documentElement[a]},c.winarea=function(a){return document.documentElement[a?\"clientWidth\":\"clientHeight\"]},c.isleap=function(a){return 0===a%4&&0!==a%100||0===a%400},c.checkVoid=function(a,b,d){var e=[];return a=0|a,b=0|b,d=0|d,a<c.mins[0]?e=[\"y\"]:a>c.maxs[0]?e=[\"y\",1]:a>=c.mins[0]&&a<=c.maxs[0]&&(a==c.mins[0]&&(b<c.mins[1]?e=[\"m\"]:b==c.mins[1]&&d<c.mins[2]&&(e=[\"d\"])),a==c.maxs[0]&&(b>c.maxs[1]?e=[\"m\",1]:b==c.maxs[1]&&d>c.maxs[2]&&(e=[\"d\",1]))),e},c.timeVoid=function(a,b){if(c.ymd[1]+1==c.mins[1]&&c.ymd[2]==c.mins[2]){if(0===b&&a<c.mins[3])return 1;if(1===b&&a<c.mins[4])return 1;if(2===b&&a<c.mins[5])return 1}else if(c.ymd[1]+1==c.maxs[1]&&c.ymd[2]==c.maxs[2]){if(0===b&&a>c.maxs[3])return 1;if(1===b&&a>c.maxs[4])return 1;if(2===b&&a>c.maxs[5])return 1}return a>(b?59:23)?1:void 0},c.check=function(){var a=c.options.format.replace(/YYYY|MM|DD|hh|mm|ss/g,\"\\\\d+\\\\\").replace(/\\\\$/g,\"\"),b=new RegExp(a),d=c.elem[h.elemv],e=d.match(/\\d+/g)||[],f=c.checkVoid(e[0],e[1],e[2]);if(\"\"!==d.replace(/\\s/g,\"\")){if(!b.test(d))return c.elem[h.elemv]=\"\",c.msg(\"日期不符合格式，请重新选择。\"),1;if(f[0])return c.elem[h.elemv]=\"\",c.msg(\"日期不在有效期内，请重新选择。\"),1;f.value=c.elem[h.elemv].match(b).join(),e=f.value.match(/\\d+/g),e[1]<1?(e[1]=1,f.auto=1):e[1]>12?(e[1]=12,f.auto=1):e[1].length<2&&(f.auto=1),e[2]<1?(e[2]=1,f.auto=1):e[2]>c.months[(0|e[1])-1]?(e[2]=31,f.auto=1):e[2].length<2&&(f.auto=1),e.length>3&&(c.timeVoid(e[3],0)&&(f.auto=1),c.timeVoid(e[4],1)&&(f.auto=1),c.timeVoid(e[5],2)&&(f.auto=1)),f.auto?c.creation([e[0],0|e[1],0|e[2]],1):f.value!==c.elem[h.elemv]&&(c.elem[h.elemv]=f.value)}},c.months=[31,null,31,30,31,30,31,31,30,31,30,31],c.viewDate=function(a,b,d){var f=(c.query,{}),g=new Date;a<(0|c.mins[0])&&(a=0|c.mins[0]),a>(0|c.maxs[0])&&(a=0|c.maxs[0]),g.setFullYear(a,b,d),f.ymd=[g.getFullYear(),g.getMonth(),g.getDate()],c.months[1]=c.isleap(f.ymd[0])?29:28,g.setFullYear(f.ymd[0],f.ymd[1],1),f.FDay=g.getDay(),f.PDay=c.months[0===b?11:b-1]-f.FDay+1,f.NDay=1,c.each(h.tds,function(a,b){var g,d=f.ymd[0],e=f.ymd[1]+1;b.className=\"\",a<f.FDay?(b.innerHTML=g=a+f.PDay,c.addClass(b,\"laydate_nothis\"),1===e&&(d-=1),e=1===e?12:e-1):a>=f.FDay&&a<f.FDay+c.months[f.ymd[1]]?(b.innerHTML=g=a-f.FDay+1,a-f.FDay+1===f.ymd[2]&&(c.addClass(b,h[2]),f.thisDay=b)):(b.innerHTML=g=f.NDay++,c.addClass(b,\"laydate_nothis\"),12===e&&(d+=1),e=12===e?1:e+1),c.checkVoid(d,e,g)[0]&&c.addClass(b,h[1]),c.options.festival&&c.festival(b,e+\".\"+g),b.setAttribute(\"y\",d),b.setAttribute(\"m\",e),b.setAttribute(\"d\",g),d=e=g=null}),c.valid=!c.hasClass(f.thisDay,h[1]),c.ymd=f.ymd,h.year.value=c.ymd[0]+\"年\",h.month.value=c.digit(c.ymd[1]+1)+\"月\",c.each(h.mms,function(a,b){var d=c.checkVoid(c.ymd[0],(0|b.getAttribute(\"m\"))+1);\"y\"===d[0]||\"m\"===d[0]?c.addClass(b,h[1]):c.removeClass(b,h[1]),c.removeClass(b,h[2]),d=null}),c.addClass(h.mms[c.ymd[1]],h[2]),f.times=[0|c.inymd[3]||0,0|c.inymd[4]||0,0|c.inymd[5]||0],c.each(new Array(3),function(a){c.hmsin[a].value=c.digit(c.timeVoid(f.times[a],a)?0|c.mins[a+3]:0|f.times[a])}),c[c.valid?\"removeClass\":\"addClass\"](h.ok,h[1])},c.festival=function(a,b){var c;switch(b){case\"1.1\":c=\"元旦\";break;case\"3.8\":c=\"妇女\";break;case\"4.5\":c=\"清明\";break;case\"5.1\":c=\"劳动\";break;case\"6.1\":c=\"儿童\";break;case\"9.10\":c=\"教师\";break;case\"10.1\":c=\"国庆\"}c&&(a.innerHTML=c),c=null},c.viewYears=function(a){var b=c.query,d=\"\";c.each(new Array(14),function(b){d+=7===b?\"<li \"+(parseInt(h.year.value)===a?'class=\"'+h[2]+'\"':\"\")+' y=\"'+a+'\">'+a+\"年</li>\":'<li y=\"'+(a-7+b)+'\">'+(a-7+b)+\"年</li>\"}),b(\"#laydate_ys\").innerHTML=d,c.each(b(\"#laydate_ys li\"),function(a,b){\"y\"===c.checkVoid(b.getAttribute(\"y\"))[0]?c.addClass(b,h[1]):c.on(b,\"click\",function(a){c.stopmp(a).reshow(),c.viewDate(0|this.getAttribute(\"y\"),c.ymd[1],c.ymd[2])})})},c.initDate=function(){var d=(c.query,new Date),e=c.elem[h.elemv].match(/\\d+/g)||[];e.length<3&&(e=c.options.start.match(/\\d+/g)||[],e.length<3&&(e=[d.getFullYear(),d.getMonth()+1,d.getDate()])),c.inymd=e,c.viewDate(e[0],e[1]-1,e[2])},c.iswrite=function(){var a=c.query,b={time:a(\"#laydate_hms\")};c.shde(b.time,!c.options.istime),c.shde(h.oclear,!(\"isclear\"in c.options?c.options.isclear:1)),c.shde(h.otoday,!(\"istoday\"in c.options?c.options.istoday:1)),c.shde(h.ok,!(\"issure\"in c.options?c.options.issure:1))},c.orien=function(a,b){var d,e=c.elem.getBoundingClientRect();a.style.left=e.left+(b?0:c.scroll(1))+\"px\",d=e.bottom+a.offsetHeight/1.5<=c.winarea()?e.bottom-1:e.top>a.offsetHeight/1.5?e.top-a.offsetHeight+1:c.winarea()-a.offsetHeight,a.style.top=d+(b?0:c.scroll())+\"px\"},c.follow=function(a){c.options.fixed?(a.style.position=\"fixed\",c.orien(a,1)):(a.style.position=\"absolute\",c.orien(a))},c.viewtb=function(){var a,b=[],f=[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],h={},i=d[e](\"table\"),j=d[e](\"thead\");return j.appendChild(d[e](\"tr\")),h.creath=function(a){var b=d[e](\"th\");b.innerHTML=f[a],j[g](\"tr\")[0].appendChild(b),b=null},c.each(new Array(6),function(d){b.push([]),a=i.insertRow(0),c.each(new Array(7),function(c){b[d][c]=0,0===d&&h.creath(c),a.insertCell(c)})}),i.insertBefore(j,i.children[0]),i.id=i.className=\"laydate_table\",a=b=null,i.outerHTML.toLowerCase()}(),c.view=function(a,f){var i,g=c.query,j={};f=f||a,c.elem=a,c.options=f,c.options.format||(c.options.format=b.format),c.options.start=c.options.start||\"\",c.mm=j.mm=[c.options.min||b.min,c.options.max||b.max],c.mins=j.mm[0].match(/\\d+/g),c.maxs=j.mm[1].match(/\\d+/g),h.elemv=/textarea|input/.test(c.elem.tagName.toLocaleLowerCase())?\"value\":\"innerHTML\",c.box?c.shde(c.box):(i=d[e](\"div\"),i.id=h[0],i.className=h[0],i.style.cssText=\"position: absolute;\",i.setAttribute(\"name\",\"laydate-v\"+laydate.v),i.innerHTML=j.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 a=\"\";return c.each(new Array(12),function(b){a+='<span m=\"'+b+'\">'+c.digit(b+1)+\"月</span>\"}),a}()+\"</div>\"+\"</div>\"+\"</div>\"+c.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>\"+(b.isv?'<a href=\"http://sentsin.com/layui/laydate/\" class=\"laydate_v\" target=\"_blank\">laydate-v'+laydate.v+\"</a>\":\"\")+\"</div>\",d.body.appendChild(i),c.box=g(\"#\"+h[0]),c.events(),i=null),c.follow(c.box),f.zIndex?c.box.style.zIndex=f.zIndex:c.removeCssAttr(c.box,\"z-index\"),c.stopMosup(\"click\",c.box),c.initDate(),c.iswrite(),c.check()},c.reshow=function(){return c.each(c.query(\"#\"+h[0]+\" .laydate_show\"),function(a,b){c.removeClass(b,\"laydate_show\")}),this},c.close=function(){c.reshow(),c.shde(c.query(\"#\"+h[0]),1),c.elem=null},c.parse=function(a,d,e){return a=a.concat(d),e=e||(c.options?c.options.format:b.format),e.replace(/YYYY|MM|DD|hh|mm|ss/g,function(){return a.index=0|++a.index,c.digit(a[a.index])})},c.creation=function(a,b){var e=(c.query,c.hmsin),f=c.parse(a,[e[0].value,e[1].value,e[2].value]);c.elem[h.elemv]=f,b||(c.close(),\"function\"==typeof c.options.choose&&c.options.choose(f))},c.events=function(){var b=c.query,e={box:\"#\"+h[0]};c.addClass(d.body,\"laydate_body\"),h.tds=b(\"#laydate_table td\"),h.mms=b(\"#laydate_ms span\"),h.year=b(\"#laydate_y\"),h.month=b(\"#laydate_m\"),c.each(b(e.box+\" .laydate_ym\"),function(a,b){c.on(b,\"click\",function(b){c.stopmp(b).reshow(),c.addClass(this[g](\"div\")[0],\"laydate_show\"),a||(e.YY=parseInt(h.year.value),c.viewYears(e.YY))})}),c.on(b(e.box),\"click\",function(){c.reshow()}),e.tabYear=function(a){0===a?c.ymd[0]--:1===a?c.ymd[0]++:2===a?e.YY-=14:e.YY+=14,2>a?(c.viewDate(c.ymd[0],c.ymd[1],c.ymd[2]),c.reshow()):c.viewYears(e.YY)},c.each(b(\"#laydate_YY .laydate_tab\"),function(a,b){c.on(b,\"click\",function(b){c.stopmp(b),e.tabYear(a)})}),e.tabMonth=function(a){a?(c.ymd[1]++,12===c.ymd[1]&&(c.ymd[0]++,c.ymd[1]=0)):(c.ymd[1]--,-1===c.ymd[1]&&(c.ymd[0]--,c.ymd[1]=11)),c.viewDate(c.ymd[0],c.ymd[1],c.ymd[2])},c.each(b(\"#laydate_MM .laydate_tab\"),function(a,b){c.on(b,\"click\",function(b){c.stopmp(b).reshow(),e.tabMonth(a)})}),c.each(b(\"#laydate_ms span\"),function(a,b){c.on(b,\"click\",function(a){c.stopmp(a).reshow(),c.hasClass(this,h[1])||c.viewDate(c.ymd[0],0|this.getAttribute(\"m\"),c.ymd[2])})}),c.each(b(\"#laydate_table td\"),function(a,b){c.on(b,\"click\",function(a){c.hasClass(this,h[1])||(c.stopmp(a),c.creation([0|this.getAttribute(\"y\"),0|this.getAttribute(\"m\"),0|this.getAttribute(\"d\")]))})}),h.oclear=b(\"#laydate_clear\"),c.on(h.oclear,\"click\",function(){c.elem[h.elemv]=\"\",c.close()}),h.otoday=b(\"#laydate_today\"),c.on(h.otoday,\"click\",function(){c.elem[h.elemv]=laydate.now(0,c.options.format),c.close()}),h.ok=b(\"#laydate_ok\"),c.on(h.ok,\"click\",function(){c.valid&&c.creation([c.ymd[0],c.ymd[1]+1,c.ymd[2]])}),e.times=b(\"#laydate_time\"),c.hmsin=e.hmsin=b(\"#laydate_hms input\"),e.hmss=[\"小时\",\"分钟\",\"秒数\"],e.hmsarr=[],c.msg=function(a,d){var f='<div class=\"laydte_hsmtex\">'+(d||\"提示\")+\"<span>×</span></div>\";\"string\"==typeof a?(f+=\"<p>\"+a+\"</p>\",c.shde(b(\"#\"+h[0])),c.removeClass(e.times,\"laydate_time1\").addClass(e.times,\"laydate_msg\")):(e.hmsarr[a]?f=e.hmsarr[a]:(f+='<div id=\"laydate_hmsno\" class=\"laydate_hmsno\">',c.each(new Array(0===a?24:60),function(a){f+=\"<span>\"+a+\"</span>\"}),f+=\"</div>\",e.hmsarr[a]=f),c.removeClass(e.times,\"laydate_msg\"),c[0===a?\"removeClass\":\"addClass\"](e.times,\"laydate_time1\")),c.addClass(e.times,\"laydate_show\"),e.times.innerHTML=f},e.hmson=function(a,d){var e=b(\"#laydate_hmsno span\"),f=c.valid?null:1;c.each(e,function(b,e){f?c.addClass(e,h[1]):c.timeVoid(b,d)?c.addClass(e,h[1]):c.on(e,\"click\",function(){c.hasClass(this,h[1])||(a.value=c.digit(0|this.innerHTML))})}),c.addClass(e[0|a.value],\"laydate_click\")},c.each(e.hmsin,function(a,b){c.on(b,\"click\",function(b){c.stopmp(b).reshow(),c.msg(a,e.hmss[a]),e.hmson(this,a)})}),c.on(d,\"mouseup\",function(){var a=b(\"#\"+h[0]);a&&\"none\"!==a.style.display&&(c.check()||c.close())}).on(d,\"keydown\",function(b){b=b||a.event;var d=b.keyCode;13===d&&c.creation([c.ymd[0],c.ymd[1]+1,c.ymd[2]])})},c.init=function(){c.use(\"need\"),c.use(h[4]+b.defSkin,h[3]),c.skinLink=c.query(\"#\"+h[3])}(),laydate.reset=function(){c.box&&c.elem&&c.follow(c.box)},laydate.now=function(a,b){var d=new Date(0|a?function(a){return 864e5>a?+new Date+864e5*a:a}(parseInt(a)):+new Date);return c.parse([d.getFullYear(),d.getMonth()+1,d.getDate()],[d.getHours(),d.getMinutes(),d.getSeconds()],b)},laydate.skin=function(a){c.skinLink.href=c.getPath+h[4]+a+h[5]}}(window);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/laydate/need/laydate.css",
    "content": "/**\n\n @Name： laydate 核心样式\n @author 郑保乐\n @Site：http://sentsin.com/layui/laydate\n\n**/\n\nhtml{_background-image:url(about:blank); _background-attachment:fixed;}\n.layer-date{display: inline-block!important;vertical-align:text-top;max-width:240px;}\n.laydate_body .laydate_box, .laydate_body .laydate_box *{margin:0; padding:0;}\n.laydate-icon,\n.laydate-icon-default,\n.laydate-icon-danlan,\n.laydate-icon-dahong,\n.laydate-icon-molv{height:34px; padding-right:20px;min-width:34px;vertical-align: text-top;border:1px solid #C6C6C6; background-repeat:no-repeat; background-position:right center;  background-color:#fff; outline:0;}\n.laydate-icon-default{ background-image:url(../skins/default/icon.png)}\n.laydate-icon-danlan{border:1px solid #B1D2EC; background-image:url(../skins/danlan/icon.png)}\n.laydate-icon-dahong{background-image:url(../skins/dahong/icon.png)}\n.laydate-icon-molv{background-image:url(../skins/molv/icon.png)}\n.laydate_body .laydate_box{width:240px; font:12px '\\5B8B\\4F53'; z-index:99999999; *margin:-2px 0 0 -2px; *overflow:hidden; _margin:0; _position:absolute!important; background-color:#fff;}\n.laydate_body .laydate_box li{list-style:none;}\n.laydate_body .laydate_box .laydate_void{cursor:text!important;}\n.laydate_body .laydate_box a, .laydate_body .laydate_box a:hover{text-decoration:none; blr:expression(this.onFocus=this.blur()); cursor:pointer;}\n.laydate_body .laydate_box a:hover{text-decoration:none;}\n.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;}\n.laydate_body .laydate_box .laydate_yms, .laydate_body .laydate_box .laydate_time{display:none;}\n.laydate_body .laydate_box .laydate_show{display:block;}\n.laydate_body .laydate_box input{outline:0; font-size:14px; background-color:#fff;}\n.laydate_body .laydate_top{position:relative; height:26px; padding:5px; *width:100%; z-index:99;}\n.laydate_body .laydate_ym{position:relative; float:left; height:24px; cursor:pointer;}\n.laydate_body .laydate_ym input{float:left; height:24px; line-height:24px; text-align:center; border:none; cursor:pointer;}\n.laydate_body .laydate_ym .laydate_yms{position:absolute; left: -1px; top: 24px; height:181px;}\n.laydate_body .laydate_y{width:121px;}\n.laydate_body .laydate_y input{width:64px; margin-right:15px;}\n.laydate_body .laydate_y .laydate_yms{width:121px; text-align:center;}\n.laydate_body .laydate_y .laydate_yms a{position:relative; display:block; height:20px;}\n.laydate_body .laydate_y .laydate_yms ul{height:139px; padding:0; *overflow:hidden;}\n.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;}\n.laydate_box *{box-sizing:content-box!important;}\n.laydate_body .laydate_m{width:99px;float: right;margin-right:-2px;}\n.laydate_body .laydate_m .laydate_yms{width:99px; padding:0;}\n.laydate_body .laydate_m input{width:42px; margin-right:15px;}\n.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;}\n.laydate_body .laydate_choose{display:block; float:left; position:relative; width:20px; height:24px;}\n.laydate_body .laydate_choose cite, .laydate_body .laydate_tab cite{left:50%; top:50%;}\n.laydate_body .laydate_chtop cite{margin:-7px 0 0 -5px; border-bottom-style:solid;}\n.laydate_body .laydate_chdown cite, .laydate_body .laydate_ym label{top:50%; margin:-2px 0 0 -5px; border-top-style:solid;}\n.laydate_body .laydate_chprev cite{margin:-5px 0 0 -7px;}\n.laydate_body .laydate_chnext cite{margin:-5px 0 0 -2px;}\n.laydate_body .laydate_ym label{right:28px;}\n.laydate_body .laydate_table{ width:230px; margin:0 5px; border-collapse:collapse; border-spacing:0px; }\n.laydate_body .laydate_table td{width:31px; height:19px; line-height:19px; text-align: center; cursor:pointer; font-size: 12px;}\n.laydate_body .laydate_table thead{height:22px; line-height:22px;}\n.laydate_body .laydate_table thead th{font-weight:400; font-size:12px; text-align:center;}\n.laydate_body .laydate_bottom{position:relative; height:22px; line-height:20px; padding:5px; font-size:12px;}\n.laydate_body .laydate_bottom #laydate_hms{position: relative; z-index: 1; float:left; }\n.laydate_body .laydate_time{ position:absolute; left:5px; bottom: 26px; width:129px; height:125px; *overflow:hidden;}\n.laydate_body .laydate_time .laydate_hmsno{ padding:5px 0 0 5px;}\n.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;}\n.laydate_body .laydate_time1{width:228px; height:154px;}\n.laydate_body .laydate_time1 .laydate_hmsno{padding: 6px 0 0 8px;}\n.laydate_body .laydate_time1 .laydate_hmsno span{width:21px; height:20px; line-height:20px;}\n.laydate_body .laydate_msg{left:49px; bottom:67px; width:141px; height:auto; overflow: hidden;}\n.laydate_body .laydate_msg p{padding:5px 10px;}\n.laydate_body .laydate_bottom li{float:left; height:20px; line-height:20px; border-right:none; font-weight:900;}\n.laydate_body .laydate_bottom .laydate_sj{width:33px; text-align:center; font-weight:400;}\n.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;}\n.laydate_body .laydate_bottom .laydte_hsmtex{height:20px; line-height:20px; text-align:center;}\n.laydate_body .laydate_bottom .laydte_hsmtex span{position:absolute; width:20px; top:0; right:0px; cursor:pointer;}\n.laydate_body .laydate_bottom .laydte_hsmtex span:hover{font-size:14px;}\n.laydate_body .laydate_bottom .laydate_btn{position:absolute; right:5px; top:5px;}\n.laydate_body .laydate_bottom .laydate_btn a{float:left; height:20px; padding:0 6px; _padding:0 5px;}\n.laydate_body .laydate_bottom .laydate_v{position:absolute; left:10px; top:6px; font-family:Courier; z-index:0;}\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/laydate/skins/default/laydate.css",
    "content": "/**\n\n @Name： laydate皮肤：墨绿\n @author 郑保乐\n @Site：http://sentsin.com/layui/laydate\n\n**/\n\n.laydate-icon{border:1px solid #ccc; background-image:url(icon.png)}\n\n.laydate_body .laydate_bottom #laydate_hms,\n.laydate_body .laydate_time{border:1px solid #ccc;}\n\n.laydate_body .laydate_box,\n.laydate_body .laydate_ym .laydate_yms,\n.laydate_body .laydate_time{box-shadow: 2px 2px 5px rgba(0,0,0,.1);}\n\n.laydate_body .laydate_box{border-top:none; border-bottom:none; background-color:#fff; color:#00625A;}\n.laydate_body .laydate_box input{background:none!important; color:#fff;}\n.laydate_body .laydate_box .laydate_void{color:#00E8D7!important;}\n.laydate_body .laydate_box a, .laydate_body .laydate_box a:hover{color:#00625A;}\n.laydate_body .laydate_box a:hover{color:#666;}\n.laydate_body .laydate_click{background-color:#009F95!important; color:#fff!important;}\n.laydate_body .laydate_top{border-top:1px solid #009F95; background-color:#009F95}\n.laydate_body .laydate_ym{border:1px solid #009F95; background-color:#009F95;}\n.laydate_body .laydate_ym .laydate_yms{border:1px solid #009F95; background-color:#009F95; color:#fff;}\n.laydate_body .laydate_y .laydate_yms a{border-bottom:1px solid #009F95;}\n.laydate_body .laydate_y .laydate_yms .laydate_chdown{border-top:1px solid #009F95; border-bottom:none;}\n.laydate_body .laydate_choose{border-left:1px solid #009F95;}\n.laydate_body .laydate_chprev{border-left:none; border-right:1px solid #009F95;}\n.laydate_body .laydate_choose:hover,\n.laydate_body .laydate_y .laydate_yms a:hover{background-color:#00C1B3;}\n.laydate_body .laydate_chtop cite{border-bottom-color:#fff;}\n.laydate_body .laydate_chdown cite, .laydate_body .laydate_ym label{border-top-color:#fff;}\n.laydate_body .laydate_chprev cite{border-right-style:solid; border-right-color:#fff;}\n.laydate_body .laydate_chnext cite{border-left-style:solid; border-left-color:#fff;}\n.laydate_body .laydate_table{width: 240px!important; margin: 0!important; border:1px solid #ccc; border-top:none; border-bottom:none;}\n.laydate_body .laydate_table td{border:none;  height:21px!important; line-height:21px!important; background-color:#fff; color:#00625A;}\n.laydate_body .laydate_table .laydate_nothis{color:#999;}\n.laydate_body .laydate_table thead{border-bottom:1px solid #ccc; height:21px!important; line-height:21px!important;}\n.laydate_body .laydate_table thead th{}\n.laydate_body .laydate_bottom{border:1px solid #ccc; border-top:none;}\n.laydate_body .laydate_bottom #laydate_hms{background-color:#fff;}\n.laydate_body .laydate_time{background-color:#fff;}\n.laydate_body .laydate_time1{width: 226px!important; height: 152px!important;}\n.laydate_body .laydate_bottom .laydate_sj{width:31px!important; border-right:1px solid #ccc; background-color:#fff;}\n.laydate_body .laydate_bottom input{background-color:#fff; color:#00625A;}\n.laydate_body .laydate_bottom .laydte_hsmtex{border-bottom:1px solid #ccc;}\n.laydate_body .laydate_bottom .laydate_btn{border-right:1px solid #ccc;}\n.laydate_body .laydate_bottom .laydate_v{color:#999}\n.laydate_body .laydate_bottom .laydate_btn a{border: 1px solid #ccc; border-right:none; background-color:#fff;}\n.laydate_body .laydate_bottom .laydate_btn a:hover{background-color:#F6F6F6; color:#00625A;}\n\n.laydate_body .laydate_m .laydate_yms span:hover,\n.laydate_body .laydate_time .laydate_hmsno span:hover,\n.laydate_body .laydate_y .laydate_yms ul li:hover,\n.laydate_body .laydate_table td:hover{background-color:#00C1B3; color:#fff;}\n\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layer.js",
    "content": "/*! layer-v3.1.0 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\"],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.0\",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": "src/main/resources/static/js/plugins/layer/layim/data/chatlog.json",
    "content": "{\n    \"status\": 1,\n    \"msg\": \"ok\",\n    \"data\": [\n        {\n            \"id\": \"100001\",\n            \"name\": \"Beaut-zihan\",\n            \"time\": \"10:23\",\n            \"face\": \"img/a1.jpg\"\n        },\n        {\n            \"id\": \"100002\",\n            \"name\": \"慕容晓晓\",\n            \"time\": \"昨天\",\n            \"face\": \"img/a2.jpg\"\n        },\n        {\n            \"id\": \"1000033\",\n            \"name\": \"乔峰\",\n            \"time\": \"2014-4.22\",\n            \"face\": \"img/a3.jpg\"\n        },\n        {\n            \"id\": \"10000333\",\n            \"name\": \"高圆圆\",\n            \"time\": \"2014-4.21\",\n            \"face\": \"img/a4.jpg\"\n        }\n    ]\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layim/data/friend.json",
    "content": "{\n    \"status\": 1,\n    \"msg\": \"ok\",\n    \"data\": [\n        {\n            \"name\": \"销售部\",\n            \"nums\": 36,\n            \"id\": 1,\n            \"item\": [\n                {\n                    \"id\": \"100001\",\n                    \"name\": \"郭敬明\",\n                    \"face\": \"img/a5.jpg\"\n                },\n                {\n                    \"id\": \"100002\",\n                    \"name\": \"作家崔成浩\",\n                    \"face\": \"img/a6.jpg\"\n                },\n                {\n                    \"id\": \"1000022\",\n                    \"name\": \"韩寒\",\n                    \"face\": \"img/a7.jpg\"\n                },\n                {\n                    \"id\": \"10000222\",\n                    \"name\": \"范爷\",\n                    \"face\": \"img/a8.jpg\"\n                },\n                {\n                    \"id\": \"100002222\",\n                    \"name\": \"小马哥\",\n                    \"face\": \"img/a9.jpg\"\n                }\n            ]\n        },\n        {\n            \"name\": \"大学同窗\",\n            \"nums\": 16,\n            \"id\": 2,\n            \"item\": [\n                {\n                    \"id\": \"1000033\",\n                    \"name\": \"苏醒\",\n                    \"face\": \"img/a9.jpg\"\n                },\n                {\n                    \"id\": \"10000333\",\n                    \"name\": \"马云\",\n                    \"face\": \"img/a8.jpg\"\n                },\n                {\n                    \"id\": \"100003\",\n                    \"name\": \"鬼脚七\",\n                    \"face\": \"img/a7.jpg\"\n                },\n                {\n                    \"id\": \"100004\",\n                    \"name\": \"谢楠\",\n                    \"face\": \"img/a6.jpg\"\n                },\n                {\n                    \"id\": \"100005\",\n                    \"name\": \"徐峥\",\n                    \"face\": \"img/a5.jpg\"\n                }\n            ]\n        },\n        {\n            \"name\": \"H+后台主题\",\n            \"nums\": 38,\n            \"id\": 3,\n            \"item\": [\n                {\n                    \"id\": \"100006\",\n                    \"name\": \"柏雪近在它香\",\n                    \"face\": \"img/a4.jpg\"\n                },\n                {\n                    \"id\": \"100007\",\n                    \"name\": \"罗昌平\",\n                    \"face\": \"img/a3.jpg\"\n                },\n                {\n                    \"id\": \"100008\",\n                    \"name\": \"Crystal影子\",\n                    \"face\": \"img/a2.jpg\"\n                },\n                {\n                    \"id\": \"100009\",\n                    \"name\": \"艺小想\",\n                    \"face\": \"img/a1.jpg\"\n                },\n                {\n                    \"id\": \"100010\",\n                    \"name\": \"天猫\",\n                    \"face\": \"img/a8.jpg\"\n                },\n                {\n                    \"id\": \"100011\",\n                    \"name\": \"张泉灵\",\n                    \"face\": \"img/a7.jpg\"\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layim/data/group.json",
    "content": "{\n    \"status\": 1,\n    \"msg\": \"ok\",\n    \"data\": [\n        {\n            \"name\": \"H+交流群\",\n            \"nums\": 36,\n            \"id\": 1,\n            \"item\": [\n                {\n                    \"id\": \"101\",\n                    \"name\": \"H+ Bug反馈\",\n                    \"face\": \"http://tp2.sinaimg.cn/2211874245/180/40050524279/0\"\n                },\n                {\n                    \"id\": \"102\",\n                    \"name\": \"H+ 技术交流\",\n                    \"face\": \"http://tp3.sinaimg.cn/1820711170/180/1286855219/1\"\n                }\n            ]\n        },\n        {\n            \"name\": \"Bootstrap\",\n            \"nums\": 16,\n            \"id\": 2,\n            \"item\": [\n                {\n                    \"id\": \"103\",\n                    \"name\": \"Bootstrap中文\",\n                    \"face\": \"http://tp2.sinaimg.cn/2211874245/180/40050524279/0\"\n                },\n                {\n                    \"id\": \"104\",\n                    \"name\": \"Bootstrap资源\",\n                    \"face\": \"http://tp3.sinaimg.cn/1820711170/180/1286855219/1\"\n                }\n            ]\n        },\n        {\n            \"name\": \"WebApp\",\n            \"nums\": 106,\n            \"id\": 3,\n            \"item\": [\n                {\n                    \"id\": \"105\",\n                    \"name\": \"移动开发\",\n                    \"face\": \"http://tp2.sinaimg.cn/2211874245/180/40050524279/0\"\n                },\n                {\n                    \"id\": \"106\",\n                    \"name\": \"H5前言\",\n                    \"face\": \"http://tp3.sinaimg.cn/1820711170/180/1286855219/1\"\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layim/data/groups.json",
    "content": "{\n    \"status\": 1,\n    \"msg\": \"ok\",\n    \"data\": [\n        {\n            \"id\": \"100001\",\n            \"name\": \"無言的蒁説\",\n            \"face\": \"img/a1.jpg\"\n        },\n        {\n            \"id\": \"100002\",\n            \"name\": \"婷宝奢侈品\",\n            \"face\": \"img/a2.jpg\"\n        },\n        {\n            \"id\": \"100003\",\n            \"name\": \"忆恨思爱\",\n            \"face\": \"img/a3.jpg\"\n        },\n        {\n            \"id\": \"100004\",\n            \"name\": \"天涯奥拓慢\",\n            \"face\": \"img/a4.jpg\"\n        },\n        {\n            \"id\": \"100005\",\n            \"name\": \"雨落无声的天空\",\n            \"face\": \"img/a5.jpg\"\n        },\n        {\n            \"id\": \"100006\",\n            \"name\": \"李越LycorisRadiate\",\n            \"face\": \"img/a6.jpg\"\n        },\n        {\n            \"id\": \"100007\",\n            \"name\": \"冯胖妞张直丑\",\n            \"face\": \"img/a7.jpg\"\n        },\n        {\n            \"id\": \"100008\",\n            \"name\": \"陈龙hmmm\",\n            \"face\": \"img/a8.jpg\"\n        },\n        {\n            \"id\": \"100009\",\n            \"name\": \"别闹哥胆儿小\",\n            \"face\": \"img/a9.jpg\"\n        },\n        {\n            \"id\": \"100010\",\n            \"name\": \"锅锅锅锅萌哒哒 \",\n            \"face\": \"img/a10.jpg\"\n        }\n    ]\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layim/layim.css",
    "content": "/*\n\n @Name: layim WebIM 1.0.0\n @author 郑保乐\n @Date: 2014-04-25\n @Blog: http://sentsin.com\n\n */\nbody,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,input,button,textarea,p,blockquote,th,td,form{margin:0; padding:0;}\ninput,button,textarea,select,optgroup,option{font-family:inherit; font-size:inherit; font-style:inherit; font-weight:inherit; outline: 0;}\nli{list-style:none;}\n.xxim_icon, .xxim_main i, .layim_chatbox i{position:absolute;}\n.loading{background:url(loading.gif) no-repeat center center;}\n.layim_chatbox a, .layim_chatbox a:hover{color:#343434; text-decoration:none; }\n.layim_zero{position:absolute; width:0; height:0; border-style:dashed; border-color:transparent; overflow:hidden;}\n\n.xxim_main{position:fixed; right:1px; bottom:1px; width:230px; border:1px solid #BEBEBE; background-color:#fff; font-size:12px; box-shadow: 0 0 10px rgba(0,0,0,.2); z-index:99999999}\n.layim_chatbox textarea{resize:none;}\n.xxim_main em, .xxim_main i, .layim_chatbox em, .layim_chatbox i{font-style:normal; font-weight:400;}\n.xxim_main h5{font-size:100%; font-weight:400;}\n\n/* 搜索栏 */\n.xxim_search{position:relative; padding-left:40px; height:40px; border-bottom:1px solid #DCDCDC; background-color:#fff;}\n.xxim_search i{left:10px; top:12px; width:16px; height:16px;font-size: 16px;color:#999;}\n.xxim_search input{border:none; background:none; width: 180px; margin-top:10px; line-height:20px;}\n.xxim_search span{display:none; position:absolute; right:10px; top:10px; height:18px; line-height:18px;width:18px;text-align: center;background-color:#AFAFAF; color:#fff; cursor:pointer; border-radius:2px; font-size:12px; font-weight:900;}\n.xxim_search span:hover{background-color:#FCBE00;}\n\n/* 主面板tab */\n.xxim_tabs{height:45px; border-bottom:1px solid #DBDBDB; background-color:#F4F4F4; font-size:0;}\n.xxim_tabs span{position:relative; display:inline-block; *display:inline; *zoom:1; vertical-align:top; width:76px; height:45px; border-right:1px solid #DBDBDB; cursor:pointer; font-size:12px;}\n.xxim_tabs span i{top:12px; left:50%; width:20px; margin-left:-10px; height:20px;font-size:20px;color:#ccc;}\n.xxim_tabs .xxim_tabnow{height:46px; background-color:#fff;}\n.xxim_tabs .xxim_tabnow i{color:#1ab394;}\n.xxim_tabs .xxim_latechat{border-right:none;}\n.xxim_tabs .xxim_tabfriend i{width:14px; margin-left:-7px;}\n\n/* 主面板列表 */\n.xxim_list{display:none; height:350px; padding:5px 0; overflow:hidden;}\n.xxim_list:hover{ overflow-y:auto;}\n.xxim_list h5{position:relative; padding-left:32px; height:26px; line-height:26px; cursor:pointer; color:#000; font-size:0;}\n.xxim_list h5 span{display:inline-block; *display:inline; *zoom:1; vertical-align:top; max-width:140px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap; font-size:12px;}\n.xxim_list h5 i{left:15px; top:8px; width:10px; height:10px;font-size:10px;color:#666;}\n.xxim_list h5 *{font-size:12px;}\n.xxim_list .xxim_chatlist{display:none;}\n.xxim_list .xxim_liston h5 i{width:8px; height:7px;}\n.xxim_list .xxim_liston .xxim_chatlist{display:block;}\n.xxim_chatlist {}\n.xxim_chatlist li{position:relative; height:40px; line-height:30px; padding:5px 10px; font-size:0; cursor:pointer;}\n.xxim_chatlist li:hover{background-color:#F2F4F8}\n.xxim_chatlist li *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}\n.xxim_chatlist li span{padding-left:10px; max-width:120px;  overflow:hidden; text-overflow: ellipsis; white-space:nowrap;}\n.xxim_chatlist li img{width:30px; height:30px;}\n.xxim_chatlist li .xxim_time{position:absolute; right:10px; color:#999;}\n.xxim_list .xxim_errormsg{text-align:center; margin:50px 0; color:#999;}\n.xxim_searchmain{position:absolute; width:230px; height:491px; left:0; top:41px; z-index:10; background-color:#fff;}\n\n/* 主面板底部 */\n.xxim_bottom{height:34px; border-top:1px solid #D0DCF3; background-color:#F2F4F8;}\n.xxim_expend{border-left:1px solid #D0DCF3; border-bottom:1px solid #D0DCF3;}\n.xxim_bottom li{position:relative; width:50px; height:32px; line-height:32px; float:left; border-right:1px solid #D0DCF3;  cursor:pointer;}\n.xxim_bottom li i{ top:9px;}\n.xxim_bottom .xxim_hide{border-right:none;}\n.xxim_bottom .xxim_online{width:72px; padding-left:35px;}\n.xxim_online i{left:13px; width:14px; height:14px;font-size:14px;color:#FFA00A;}\n.xxim_setonline{display:none; position:absolute; left:-79px; bottom:-1px;  border:1px solid #DCDCDC; background-color:#fff;}\n.xxim_setonline span{position:relative; display:block; width:32px;width: 77px; padding:0 10px 0 35px;}\n.xxim_setonline span:hover{background-color:#F2F4F8;}\n.xxim_offline .xxim_nowstate, .xxim_setoffline i{color:#999;}\n.xxim_mymsg i{left:18px; width:14px; height:14px;font-size: 14px;}\n.xxim_mymsg a{position:absolute; left:0; top:0; width:50px; height:32px;}\n.xxim_seter i{left:18px; width:14px; height:14px;font-size: 14px;}\n.xxim_hide i{left:18px; width:14px; height:14px;font-size: 14px;}\n.xxim_show i{}\n.xxim_bottom .xxim_on{position:absolute; left:-17px; top:50%; width:16px;text-align: center;color:#999;line-height: 97px; height:97px; margin-top:-49px;border:solid 1px #BEBEBE;border-right: none; background:#F2F4F8;}\n.xxim_bottom .xxim_off{}\n\n/* 聊天窗口 */\n.layim_chatbox{width:620px; border:1px solid #BEBEBE; background-color:#fff; font-size:12px; box-shadow: 0 0 10px rgba(0,0,0,.2);}\n.layim_chatbox h6{position:relative; height:40px; border-bottom:1px solid #D9D9D9; background-color:#FCFDFA}\n.layim_move{position:absolute; height:40px; width: 620px; z-index:0;}\n.layim_face{position:absolute; bottom:-1px; left:10px; width:64px; height:64px;padding:1px;background: #fff; border:1px solid #ccc;}\n.layim_face img{width:60px; height:60px;}\n.layim_names{position:absolute; left:90px; max-width:300px; line-height:40px; color:#000; overflow:hidden; text-overflow: ellipsis; white-space:nowrap; font-size:14px;}\n.layim_rightbtn{position:absolute; right:15px; top:12px; font-size:20px;}\n.layim_rightbtn i{position:relative; width:16px; height:16px; display:inline-block; *display:inline; *zoom:1; vertical-align:top; cursor:pointer; transition: all .3s;text-align: center;line-height: 16px;}\n.layim_rightbtn .layim_close{background: #FFA00A;color:#fff;}\n.layim_rightbtn .layim_close:hover{-webkit-transform: rotate(180deg); -moz-transform: rotate(180deg);}\n.layim_rightbtn .layer_setmin{margin-right:5px;color:#999;font-size:14px;font-weight: 700;}\n.layim_chat, .layim_chatmore,.layim_groups{height:450px; overflow:hidden;}\n.layim_chatmore{display:none; float:left; width:135px; border-right:1px solid #BEBEBE; background-color:#F2F2F2}\n.layim_chatlist li, .layim_groups li{position:relative; height:30px; line-height:30px; padding:0 10px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap; cursor:pointer;}\n.layim_chatlist li{padding:0 20px 0 10px;}\n.layim_chatlist li:hover{background-color:#E3E3E3;}\n.layim_chatlist li span{display:inline-block; *display:inline; *zoom:1; vertical-align:top; width:90px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap;}\n.layim_chatlist li em{display:none; position:absolute; top:6px; right:10px; height:18px; line-height:18px;width:18px;text-align: center;font-size:14px;font-weight:900; border-radius:3px;}\n.layim_chatlist li em:hover{background-color: #FCBE00; color:#fff;}\n.layim_chatlist .layim_chatnow,.layim_chatlist .layim_chatnow:hover{/*border-top:1px solid #D9D9D9; border-bottom:1px solid #D9D9D9;*/ background-color:#fff;}\n.layim_chat{}\n.layim_chatarea{height:280px;}\n.layim_chatview{display:none; height:280px; overflow:hidden;}\n.layim_chatmore:hover, .layim_groups:hover, .layim_chatview:hover{overflow-y:auto;}\n.layim_chatview li{margin-bottom:10px; clear:both; *zoom:1;}\n.layim_chatview li:after{content:'\\20'; clear:both; *zoom:1; display:block; height:0;}\n\n.layim_chatthis{display:block;}\n.layim_chatuser{float:left; padding:15px; font-size:0;}\n.layim_chatuser *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; line-height:30px; font-size:12px; padding-right:10px;}\n.layim_chatuser img{width:30px; height:30px;padding-right: 0;margin-right: 15px;}\n.layim_chatuser .layim_chatname{max-width:230px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap;}\n.layim_chatuser .layim_chattime{color:#999; padding-left:10px;}\n.layim_chatsay{position:relative; float:left; margin:0 15px; padding:10px; line-height:20px; background-color:#F3F3F3; border-radius:3px; clear:both;}\n.layim_chatsay .layim_zero{left:5px; top:-8px; border-width:8px; border-right-style:solid; border-right-color:#F3F3F3;}\n.layim_chateme .layim_chatuser{float:right;}\n.layim_chateme .layim_chatuser *{padding-right:0; padding-left:10px;}\n.layim_chateme .layim_chatuser img{margin-left:15px;padding-left: 0;}\n.layim_chateme .layim_chatsay .layim_zero{left:auto; right:10px;}\n.layim_chateme .layim_chatuser .layim_chattime{padding-left:0; padding-right:10px;}\n.layim_chateme .layim_chatsay{float:right; background-color:#EBFBE3}\n.layim_chateme .layim_zero{border-right-color:#EBFBE3;}\n.layim_groups{display:none; float:right; width:130px; border-left:1px solid #D9D9D9; background-color:#fff;}\n.layim_groups ul{display:none;}\n.layim_groups ul.layim_groupthis{display:block;}\n.layim_groups li *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; margin-right:10px;}\n.layim_groups li img{width:20px; height:20px; margin-top:5px;}\n.layim_groups li span{max-width:80px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap;}\n.layim_groups li:hover{background-color:#F3F3F3;}\n.layim_groups .layim_errors{text-align:center; color:#999;}\n.layim_tool{position:relative; height:35px; line-height:35px; padding-left:10px; background-color:#F3F3F3;}\n.layim_tool i{position:relative; top:10px; display:inline-block; *display:inline; *zoom:1; vertical-align:top; width:16px; height:16px; margin-right:10px; cursor:pointer;font-size:16px;color:#999;font-weight: 700;}\n.layim_tool i:hover{color:#FFA00A;}\n.layim_tool .layim_seechatlog{position:absolute; right:15px;}\n.layim_tool .layim_seechatlog i{}\n.layim_write{display:block; border:none; width:98%; height:90px; line-height:20px; margin:5px auto 0;}\n.layim_send{position:relative; height:40px; background-color:#F3F3F3;}\n.layim_sendbtn{position:absolute; height:26px; line-height:26px; right:10px; top:8px; padding:0 40px 0 20px; background-color:#FFA00A; color:#fff; border-radius:3px; cursor:pointer;}\n.layim_enter{position:absolute; right:0; border-left:1px solid #FFB94F; width:24px; height:26px;}\n.layim_enter:hover{background-color:#E68A00; border-radius:0 3px 3px 0;}\n.layim_enter .layim_zero{left:7px; top:11px; border-width:5px; border-top-style:solid; border-top-color:#FFE0B3;}\n.layim_sendtype{display:none; position:absolute; right:10px; bottom:37px; border:1px solid #D9D9D9; background-color:#fff; text-align:left;}\n.layim_sendtype span{display:block; line-height:24px; padding:0 10px 0 25px; cursor:pointer;}\n.layim_sendtype span:hover{background-color:#F3F3F3;}\n.layim_sendtype span i{left:5px;}\n\n.layim_min{display:none; position:absolute; left:-190px; bottom:-1px; width:160px; height:32px; line-height:32px; padding:0 10px; overflow:hidden; text-overflow: ellipsis; white-space:nowrap; border:1px solid #ccc; box-shadow: 0 0 5px rgba(0,0,75,.2); background-color:#FCFDFA; cursor:pointer;}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/layim/layim.js",
    "content": "/*\n\n @Name: layui WebIM 1.0.0\n @author 郑保乐\n @Date: 2014-04-25\n @Blog: http://sentsin.com\n\n */\n\n;!function(win, undefined){\n\nvar config = {\n    msgurl: 'mailbox.html?msg=',\n    chatlogurl: 'mailbox.html?user=',\n    aniTime: 200,\n    right: -232,\n    api: {\n        friend: 'js/plugins/layer/layim/data/friend.json', //好友列表接口\n        group: 'js/plugins/layer/layim/data/group.json', //群组列表接口\n        chatlog: 'js/plugins/layer/layim/data/chatlog.json', //聊天记录接口\n        groups: 'js/plugins/layer/layim/data/groups.json', //群组成员接口\n        sendurl: '' //发送消息接口\n    },\n    user: { //当前用户信息\n        name: '游客',\n        face: 'img/a1.jpg'\n    },\n\n    //自动回复内置文案，也可动态读取数据库配置\n    autoReplay: [\n        '您好，我现在有事不在，一会再和您联系。',\n        '你没发错吧？',\n        '洗澡中，请勿打扰，偷窥请购票，个体四十，团体八折，订票电话：一般人我不告诉他！',\n        '你好，我是主人的美女秘书，有什么事就跟我说吧，等他回来我会转告他的。',\n        '我正在拉磨，没法招呼您，因为我们家毛驴去动物保护协会把我告了，说我剥夺它休产假的权利。',\n        '<（@￣︶￣@）>',\n        '你要和我说话？你真的要和我说话？你确定自己想说吗？你一定非说不可吗？那你说吧，这是自动回复。',\n        '主人正在开机自检，键盘鼠标看好机会出去凉快去了，我是他的电冰箱，我打字比较慢，你慢慢说，别急……',\n        '(*^__^*) 嘻嘻，是贤心吗？'\n    ],\n\n\n    chating: {},\n    hosts: (function(){\n        var dk = location.href.match(/\\:\\d+/);\n        dk = dk ? dk[0] : '';\n        return 'http://' + document.domain + dk + '/';\n    })(),\n    json: function(url, data, callback, error){\n        return $.ajax({\n            type: 'POST',\n            url: url,\n            data: data,\n            dataType: 'json',\n            success: callback,\n            error: error\n        });\n    },\n    stopMP: function(e){\n        e ? e.stopPropagation() : e.cancelBubble = true;\n    }\n}, dom = [$(window), $(document), $('html'), $('body')], xxim = {};\n\n//主界面tab\nxxim.tabs = function(index){\n    var node = xxim.node;\n    node.tabs.eq(index).addClass('xxim_tabnow').siblings().removeClass('xxim_tabnow');\n    node.list.eq(index).show().siblings('.xxim_list').hide();\n    if(node.list.eq(index).find('li').length === 0){\n        xxim.getDates(index);\n    }\n};\n\n//节点\nxxim.renode = function(){\n    var node = xxim.node = {\n        tabs: $('#xxim_tabs>span'),\n        list: $('.xxim_list'),\n        online: $('.xxim_online'),\n        setonline: $('.xxim_setonline'),\n        onlinetex: $('#xxim_onlinetex'),\n        xximon: $('#xxim_on'),\n        layimFooter: $('#xxim_bottom'),\n        xximHide: $('#xxim_hide'),\n        xximSearch: $('#xxim_searchkey'),\n        searchMian: $('#xxim_searchmain'),\n        closeSearch: $('#xxim_closesearch'),\n        layimMin: $('#layim_min')\n    };\n};\n\n//主界面缩放\nxxim.expend = function(){\n    var node = xxim.node;\n    if(xxim.layimNode.attr('state') !== '1'){\n        xxim.layimNode.stop().animate({right: config.right}, config.aniTime, function(){\n            node.xximon.addClass('xxim_off');\n            try{\n                localStorage.layimState = 1;\n            }catch(e){}\n            xxim.layimNode.attr({state: 1});\n            node.layimFooter.addClass('xxim_expend').stop().animate({marginLeft: config.right}, config.aniTime/2);\n            node.xximHide.addClass('xxim_show');\n        });\n    } else {\n        xxim.layimNode.stop().animate({right: 1}, config.aniTime, function(){\n            node.xximon.removeClass('xxim_off');\n            try{\n                localStorage.layimState = 2;\n            }catch(e){}\n            xxim.layimNode.removeAttr('state');\n            node.layimFooter.removeClass('xxim_expend');\n            node.xximHide.removeClass('xxim_show');\n        });\n        node.layimFooter.stop().animate({marginLeft: 0}, config.aniTime);\n    }\n};\n\n//初始化窗口格局\nxxim.layinit = function(){\n    var node = xxim.node;\n\n    //主界面\n    try{\n        /*\n        if(!localStorage.layimState){\n            config.aniTime = 0;\n            localStorage.layimState = 1;\n        }\n        */\n        if(localStorage.layimState === '1'){\n            xxim.layimNode.attr({state: 1}).css({right: config.right});\n            node.xximon.addClass('xxim_off');\n            node.layimFooter.addClass('xxim_expend').css({marginLeft: config.right});\n            node.xximHide.addClass('xxim_show');\n        }\n    }catch(e){\n        //layer.msg(e.message, 5, -1);\n    }\n};\n\n//聊天窗口\nxxim.popchat = function(param){\n    var node = xxim.node, log = {};\n\n    log.success = function(layero){\n        layer.setMove();\n\n        xxim.chatbox = layero.find('#layim_chatbox');\n        log.chatlist = xxim.chatbox.find('.layim_chatmore>ul');\n\n        log.chatlist.html('<li data-id=\"'+ param.id +'\" type=\"'+ param.type +'\"  id=\"layim_user'+ param.type + param.id +'\"><span>'+ param.name +'</span><em>×</em></li>')\n        xxim.tabchat(param, xxim.chatbox);\n\n        //最小化聊天窗\n        xxim.chatbox.find('.layer_setmin').on('click', function(){\n            var indexs = layero.attr('times');\n            layero.hide();\n            node.layimMin.text(xxim.nowchat.name).show();\n        });\n\n        //关闭窗口\n        xxim.chatbox.find('.layim_close').on('click', function(){\n            var indexs = layero.attr('times');\n            layer.close(indexs);\n            xxim.chatbox = null;\n            config.chating = {};\n            config.chatings = 0;\n        });\n\n        //关闭某个聊天\n        log.chatlist.on('mouseenter', 'li', function(){\n            $(this).find('em').show();\n        }).on('mouseleave', 'li', function(){\n            $(this).find('em').hide();\n        });\n        log.chatlist.on('click', 'li em', function(e){\n            var parents = $(this).parent(), dataType = parents.attr('type');\n            var dataId = parents.attr('data-id'), index = parents.index();\n            var chatlist = log.chatlist.find('li'), indexs;\n\n            config.stopMP(e);\n\n            delete config.chating[dataType + dataId];\n            config.chatings--;\n\n            parents.remove();\n            $('#layim_area'+ dataType + dataId).remove();\n            if(dataType === 'group'){\n                $('#layim_group'+ dataType + dataId).remove();\n            }\n\n            if(parents.hasClass('layim_chatnow')){\n                if(index === config.chatings){\n                    indexs = index - 1;\n                } else {\n                    indexs = index + 1;\n                }\n                xxim.tabchat(config.chating[chatlist.eq(indexs).attr('type') + chatlist.eq(indexs).attr('data-id')]);\n            }\n\n            if(log.chatlist.find('li').length === 1){\n                log.chatlist.parent().hide();\n            }\n        });\n\n        //聊天选项卡\n        log.chatlist.on('click', 'li', function(){\n            var othis = $(this), dataType = othis.attr('type'), dataId = othis.attr('data-id');\n            xxim.tabchat(config.chating[dataType + dataId]);\n        });\n\n        //发送热键切换\n        log.sendType = $('#layim_sendtype'), log.sendTypes = log.sendType.find('span');\n        $('#layim_enter').on('click', function(e){\n            config.stopMP(e);\n            log.sendType.show();\n        });\n        log.sendTypes.on('click', function(){\n            log.sendTypes.find('i').text('')\n            $(this).find('i').text('√');\n        });\n\n        xxim.transmit();\n    };\n\n    log.html = '<div class=\"layim_chatbox\" id=\"layim_chatbox\">'\n            +'<h6>'\n            +'<span class=\"layim_move\"></span>'\n            +'    <a href=\"'+ param.url +'\" class=\"layim_face\" target=\"_blank\"><img src=\"'+ param.face +'\" ></a>'\n            +'    <a href=\"'+ param.url +'\" class=\"layim_names\" target=\"_blank\">'+ param.name +'</a>'\n            +'    <span class=\"layim_rightbtn\">'\n            +'        <i class=\"layer_setmin\">—</i>'\n            +'        <i class=\"layim_close\">&times;</i>'\n            +'    </span>'\n            +'</h6>'\n            +'<div class=\"layim_chatmore\" id=\"layim_chatmore\">'\n            +'    <ul class=\"layim_chatlist\"></ul>'\n            +'</div>'\n            +'<div class=\"layim_groups\" id=\"layim_groups\"></div>'\n            +'<div class=\"layim_chat\">'\n            +'    <div class=\"layim_chatarea\" id=\"layim_chatarea\">'\n            +'        <ul class=\"layim_chatview layim_chatthis\"  id=\"layim_area'+ param.type + param.id +'\"></ul>'\n            +'    </div>'\n            +'    <div class=\"layim_tool\">'\n            +'        <i class=\"layim_addface fa fa-meh-o\" title=\"发送表情\"></i>'\n            +'        <a href=\"javascript:;\"><i class=\"layim_addimage fa fa-picture-o\" title=\"上传图片\"></i></a>'\n            +'        <a href=\"javascript:;\"><i class=\"layim_addfile fa fa-paperclip\" title=\"上传附件\"></i></a>'\n            +'        <a href=\"\" target=\"_blank\" class=\"layim_seechatlog\"><i class=\"fa fa-comment-o\"></i>聊天记录</a>'\n            +'    </div>'\n            +'    <textarea class=\"layim_write\" id=\"layim_write\"></textarea>'\n            +'    <div class=\"layim_send\">'\n            +'        <div class=\"layim_sendbtn\" id=\"layim_sendbtn\">发送<span class=\"layim_enter\" id=\"layim_enter\"><em class=\"layim_zero\"></em></span></div>'\n            +'        <div class=\"layim_sendtype\" id=\"layim_sendtype\">'\n            +'            <span><i>√</i>按Enter键发送</span>'\n            +'            <span><i></i>按Ctrl+Enter键发送</span>'\n            +'        </div>'\n            +'    </div>'\n            +'</div>'\n            +'</div>';\n\n    if(config.chatings < 1){\n        $.layer({\n            type: 1,\n            border: [0],\n            title: false,\n            shade: [0],\n            area: ['620px', '493px'],\n            move: '.layim_chatbox .layim_move',\n            moveType: 1,\n            closeBtn: false,\n            offset: [(($(window).height() - 493)/2)+'px', ''],\n            page: {\n                html: log.html\n            }, success: function(layero){\n                log.success(layero);\n            }\n        })\n    } else {\n        log.chatmore = xxim.chatbox.find('#layim_chatmore');\n        log.chatarea = xxim.chatbox.find('#layim_chatarea');\n\n        log.chatmore.show();\n\n        log.chatmore.find('ul>li').removeClass('layim_chatnow');\n        log.chatmore.find('ul').append('<li data-id=\"'+ param.id +'\" type=\"'+ param.type +'\" id=\"layim_user'+ param.type + param.id +'\" class=\"layim_chatnow\"><span>'+ param.name +'</span><em>×</em></li>');\n\n        log.chatarea.find('.layim_chatview').removeClass('layim_chatthis');\n        log.chatarea.append('<ul class=\"layim_chatview layim_chatthis\" id=\"layim_area'+ param.type + param.id +'\"></ul>');\n\n        xxim.tabchat(param);\n    }\n\n    //群组\n    log.chatgroup = xxim.chatbox.find('#layim_groups');\n    if(param.type === 'group'){\n        log.chatgroup.find('ul').removeClass('layim_groupthis');\n        log.chatgroup.append('<ul class=\"layim_groupthis\" id=\"layim_group'+ param.type + param.id +'\"></ul>');\n        xxim.getGroups(param);\n    }\n    //点击群员切换聊天窗\n    log.chatgroup.on('click', 'ul>li', function(){\n        xxim.popchatbox($(this));\n    });\n};\n\n//定位到某个聊天队列\nxxim.tabchat = function(param){\n    var node = xxim.node, log = {}, keys = param.type + param.id;\n    xxim.nowchat = param;\n\n    xxim.chatbox.find('#layim_user'+ keys).addClass('layim_chatnow').siblings().removeClass('layim_chatnow');\n    xxim.chatbox.find('#layim_area'+ keys).addClass('layim_chatthis').siblings().removeClass('layim_chatthis');\n    xxim.chatbox.find('#layim_group'+ keys).addClass('layim_groupthis').siblings().removeClass('layim_groupthis');\n\n    xxim.chatbox.find('.layim_face>img').attr('src', param.face);\n    xxim.chatbox.find('.layim_face, .layim_names').attr('href', param.href);\n    xxim.chatbox.find('.layim_names').text(param.name);\n\n    xxim.chatbox.find('.layim_seechatlog').attr('href', config.chatlogurl + param.id);\n\n    log.groups = xxim.chatbox.find('.layim_groups');\n    if(param.type === 'group'){\n        log.groups.show();\n    } else {\n        log.groups.hide();\n    }\n\n    $('#layim_write').focus();\n\n};\n\n//弹出聊天窗\nxxim.popchatbox = function(othis){\n    var node = xxim.node, dataId = othis.attr('data-id'), param = {\n        id: dataId, //用户ID\n        type: othis.attr('type'),\n        name: othis.find('.xxim_onename').text(),  //用户名\n        face: othis.find('.xxim_oneface').attr('src'),  //用户头像\n        href: 'profile.html?user=' + dataId //用户主页\n    }, key = param.type + dataId;\n    if(!config.chating[key]){\n        xxim.popchat(param);\n        config.chatings++;\n    } else {\n        xxim.tabchat(param);\n    }\n    config.chating[key] = param;\n\n    var chatbox = $('#layim_chatbox');\n    if(chatbox[0]){\n        node.layimMin.hide();\n        chatbox.parents('.xubox_layer').show();\n    }\n};\n\n//请求群员\nxxim.getGroups = function(param){\n    var keys = param.type + param.id, str = '',\n    groupss = xxim.chatbox.find('#layim_group'+ keys);\n    groupss.addClass('loading');\n    config.json(config.api.groups, {}, function(datas){\n        if(datas.status === 1){\n            var ii = 0, lens = datas.data.length;\n            if(lens > 0){\n                for(; ii < lens; ii++){\n                    str += '<li data-id=\"'+ datas.data[ii].id +'\" type=\"one\"><img src=\"'+ datas.data[ii].face +'\" class=\"xxim_oneface\"><span class=\"xxim_onename\">'+ datas.data[ii].name +'</span></li>';\n                }\n            } else {\n                str = '<li class=\"layim_errors\">没有群员</li>';\n            }\n\n        } else {\n            str = '<li class=\"layim_errors\">'+ datas.msg +'</li>';\n        }\n        groupss.removeClass('loading');\n        groupss.html(str);\n    }, function(){\n        groupss.removeClass('loading');\n        groupss.html('<li class=\"layim_errors\">请求异常</li>');\n    });\n};\n\n//消息传输\nxxim.transmit = function(){\n    var node = xxim.node, log = {};\n    node.sendbtn = $('#layim_sendbtn');\n    node.imwrite = $('#layim_write');\n\n    //发送\n    log.send = function(){\n        var data = {\n            content: node.imwrite.val(),\n            id: xxim.nowchat.id,\n            sign_key: '', //密匙\n            _: +new Date\n        };\n\n        if(data.content.replace(/\\s/g, '') === ''){\n            layer.tips('说点啥呗！', '#layim_write', 2);\n            node.imwrite.focus();\n        } else {\n            //此处皆为模拟\n            var keys = xxim.nowchat.type + xxim.nowchat.id;\n\n            //聊天模版\n            log.html = function(param, type){\n                return '<li class=\"'+ (type === 'me' ? 'layim_chateme' : '') +'\">'\n                    +'<div class=\"layim_chatuser\">'\n                        + function(){\n                            if(type === 'me'){\n                                return '<span class=\"layim_chattime\">'+ param.time +'</span>'\n                                       +'<span class=\"layim_chatname\">'+ param.name +'</span>'\n                                       +'<img src=\"'+ param.face +'\" >';\n                            } else {\n                                return '<img src=\"'+ param.face +'\" >'\n                                       +'<span class=\"layim_chatname\">'+ param.name +'</span>'\n                                       +'<span class=\"layim_chattime\">'+ param.time +'</span>';\n                            }\n                        }()\n                    +'</div>'\n                    +'<div class=\"layim_chatsay\">'+ param.content +'<em class=\"layim_zero\"></em></div>'\n                +'</li>';\n            };\n\n            log.imarea = xxim.chatbox.find('#layim_area'+ keys);\n\n            log.imarea.append(log.html({\n                time: '2014-04-26 0:37',\n                name: config.user.name,\n                face: config.user.face,\n                content: data.content\n            }, 'me'));\n            node.imwrite.val('').focus();\n            log.imarea.scrollTop(log.imarea[0].scrollHeight);\n\n            setTimeout(function(){\n                log.imarea.append(log.html({\n                    time: '2014-04-26 0:38',\n                    name: xxim.nowchat.name,\n                    face: xxim.nowchat.face,\n                    content: config.autoReplay[(Math.random()*config.autoReplay.length) | 0]\n                }));\n                log.imarea.scrollTop(log.imarea[0].scrollHeight);\n            }, 500);\n\n            /*\n            that.json(config.api.sendurl, data, function(datas){\n\n            });\n            */\n        }\n\n    };\n    node.sendbtn.on('click', log.send);\n\n    node.imwrite.keyup(function(e){\n        if(e.keyCode === 13){\n            log.send();\n        }\n    });\n};\n\n//事件\nxxim.event = function(){\n    var node = xxim.node;\n\n    //主界面tab\n    node.tabs.eq(0).addClass('xxim_tabnow');\n    node.tabs.on('click', function(){\n        var othis = $(this), index = othis.index();\n        xxim.tabs(index);\n    });\n\n    //列表展收\n    node.list.on('click', 'h5', function(){\n        var othis = $(this), chat = othis.siblings('.xxim_chatlist'), parentss = othis.find(\"i\");\n        if(parentss.hasClass('fa-caret-down')){\n            chat.hide();\n            parentss.attr('class','fa fa-caret-right');\n        } else {\n            chat.show();\n            parentss.attr('class','fa fa-caret-down');\n        }\n    });\n\n    //设置在线隐身\n    node.online.on('click', function(e){\n        config.stopMP(e);\n        node.setonline.show();\n    });\n    node.setonline.find('span').on('click', function(e){\n        var index = $(this).index();\n        config.stopMP(e);\n        if(index === 0){\n            node.onlinetex.html('在线');\n            node.online.removeClass('xxim_offline');\n        } else if(index === 1) {\n            node.onlinetex.html('隐身');\n            node.online.addClass('xxim_offline');\n        }\n        node.setonline.hide();\n    });\n\n    node.xximon.on('click', xxim.expend);\n    node.xximHide.on('click', xxim.expend);\n\n    //搜索\n    node.xximSearch.keyup(function(){\n        var val = $(this).val().replace(/\\s/g, '');\n        if(val !== ''){\n            node.searchMian.show();\n            node.closeSearch.show();\n            //此处的搜索ajax参考xxim.getDates\n            node.list.eq(3).html('<li class=\"xxim_errormsg\">没有符合条件的结果</li>');\n        } else {\n            node.searchMian.hide();\n            node.closeSearch.hide();\n        }\n    });\n    node.closeSearch.on('click', function(){\n        $(this).hide();\n        node.searchMian.hide();\n        node.xximSearch.val('').focus();\n    });\n\n    //弹出聊天窗\n    config.chatings = 0;\n    node.list.on('click', '.xxim_childnode', function(){\n        var othis = $(this);\n        xxim.popchatbox(othis);\n    });\n\n    //点击最小化栏\n    node.layimMin.on('click', function(){\n        $(this).hide();\n        $('#layim_chatbox').parents('.xubox_layer').show();\n    });\n\n\n    //document事件\n    dom[1].on('click', function(){\n        node.setonline.hide();\n        $('#layim_sendtype').hide();\n    });\n};\n\n//请求列表数据\nxxim.getDates = function(index){\n    var api = [config.api.friend, config.api.group, config.api.chatlog],\n        node = xxim.node, myf = node.list.eq(index);\n    myf.addClass('loading');\n    config.json(api[index], {}, function(datas){\n        if(datas.status === 1){\n            var i = 0, myflen = datas.data.length, str = '', item;\n            if(myflen > 1){\n                if(index !== 2){\n                    for(; i < myflen; i++){\n                        str += '<li data-id=\"'+ datas.data[i].id +'\" class=\"xxim_parentnode\">'\n                            +'<h5><i class=\"fa fa-caret-right\"></i><span class=\"xxim_parentname\">'+ datas.data[i].name +'</span><em class=\"xxim_nums\">（'+ datas.data[i].nums +'）</em></h5>'\n                            +'<ul class=\"xxim_chatlist\">';\n                        item = datas.data[i].item;\n                        for(var j = 0; j < item.length; j++){\n                            str += '<li data-id=\"'+ item[j].id +'\" class=\"xxim_childnode\" type=\"'+ (index === 0 ? 'one' : 'group') +'\"><img src=\"'+ item[j].face +'\" class=\"xxim_oneface\"><span class=\"xxim_onename\">'+ item[j].name +'</span></li>';\n                        }\n                        str += '</ul></li>';\n                    }\n                } else {\n                    str += '<li class=\"xxim_liston\">'\n                        +'<ul class=\"xxim_chatlist\">';\n                    for(; i < myflen; i++){\n                        str += '<li data-id=\"'+ datas.data[i].id +'\" class=\"xxim_childnode\" type=\"one\"><img src=\"'+ datas.data[i].face +'\"  class=\"xxim_oneface\"><span  class=\"xxim_onename\">'+ datas.data[i].name +'</span><em class=\"xxim_time\">'+ datas.data[i].time +'</em></li>';\n                    }\n                    str += '</ul></li>';\n                }\n                myf.html(str);\n            } else {\n                myf.html('<li class=\"xxim_errormsg\">没有任何数据</li>');\n            }\n            myf.removeClass('loading');\n        } else {\n            myf.html('<li class=\"xxim_errormsg\">'+ datas.msg +'</li>');\n        }\n    }, function(){\n        myf.html('<li class=\"xxim_errormsg\">请求失败</li>');\n        myf.removeClass('loading');\n    });\n};\n\n//渲染骨架\nxxim.view = (function(){\n    var xximNode = xxim.layimNode = $('<div id=\"xximmm\" class=\"xxim_main\">'\n            +'<div class=\"xxim_top\" id=\"xxim_top\">'\n            +'  <div class=\"xxim_search\"><i class=\"fa fa-search\"></i><input id=\"xxim_searchkey\" /><span id=\"xxim_closesearch\">×</span></div>'\n            +'  <div class=\"xxim_tabs\" id=\"xxim_tabs\"><span class=\"xxim_tabfriend\" title=\"好友\"><i class=\"fa fa-user\"></i></span><span class=\"xxim_tabgroup\" title=\"群组\"><i class=\"fa fa-users\"></i></span><span class=\"xxim_latechat\"  title=\"最近聊天\"><i class=\"fa fa-clock-o\"></i></span></div>'\n            +'  <ul class=\"xxim_list\" style=\"display:block\"></ul>'\n            +'  <ul class=\"xxim_list\"></ul>'\n            +'  <ul class=\"xxim_list\"></ul>'\n            +'  <ul class=\"xxim_list xxim_searchmain\" id=\"xxim_searchmain\"></ul>'\n            +'</div>'\n            +'<ul class=\"xxim_bottom\" id=\"xxim_bottom\">'\n            +'<li class=\"xxim_online\" id=\"xxim_online\">'\n                +'<i class=\"xxim_nowstate fa fa-check-circle\"></i><span id=\"xxim_onlinetex\">在线</span>'\n                +'<div class=\"xxim_setonline\">'\n                    +'<span><i class=\"fa fa-check-circle\"></i>在线</span>'\n                    +'<span class=\"xxim_setoffline\"><i class=\"fa fa-check-circle\"></i>隐身</span>'\n                +'</div>'\n            +'</li>'\n            +'<li class=\"xxim_mymsg\" id=\"xxim_mymsg\" title=\"我的私信\"><i class=\"fa fa-comment\"></i><a href=\"'+ config.msgurl +'\" target=\"_blank\"></a></li>'\n            +'<li class=\"xxim_seter\" id=\"xxim_seter\" title=\"设置\">'\n                +'<i class=\"fa fa-gear\"></i>'\n                +'<div>'\n\n                +'</div>'\n            +'</li>'\n            +'<li class=\"xxim_hide\" id=\"xxim_hide\"><i class=\"fa fa-exchange\"></i></li>'\n            +'<li id=\"xxim_on\" class=\"xxim_icon xxim_on fa fa-ellipsis-v\"></li>'\n            +'<div class=\"layim_min\" id=\"layim_min\"></div>'\n        +'</ul>'\n    +'</div>');\n    dom[3].append(xximNode);\n\n    xxim.renode();\n    xxim.getDates(0);\n    xxim.event();\n    xxim.layinit();\n}());\n\n}(window);\n\n"
  },
  {
    "path": "src/main/resources/static/js/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": "src/main/resources/static/js/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": "src/main/resources/static/js/plugins/layer/skin/layer.css",
    "content": "/*!\n\n @Name: layer's style\n @author 郑保乐\n @Blog： sentsin.com\n\n */*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{top:150px;left:50%;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)}}.layui-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)}}.layui-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}}.layui-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)}}.layui-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}}.layui-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)}}.layui-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-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)}}.layui-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;text-overflow:ellipsis;white-space:nowrap;background-color:#F8F8F8}.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:-150px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-181px -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;font-size:14px;overflow: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-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}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/skin/layer.ext.css",
    "content": "/*!\n\n @Name: layer拓展样式\n @Date: 2012.12.13\n @author 郑保乐\n @blog: sentsin.com\n\n */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.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;background:url(default/xubox_loading1.gif) center center no-repeat #000}.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}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/layer/skin/moon/style.css",
    "content": "/*\n * layer皮肤\n * 作者：一☆隐☆一\n * QQ:9073194\n * 请保留这里的信息 谢谢！虽然你不保留我也不能把你怎么样！\n */\n\nhtml #layui_layer_skinmoonstylecss {\n\tdisplay: none;\n\tposition: absolute;\n\twidth: 1989px;\n}\nbody .layer-ext-moon[type=\"dialog\"] {\n\tmin-width: 320px;\n}\nbody .layer-ext-moon-msg[type=\"dialog\"]{min-width:200px;}\nbody .layer-ext-moon .layui-layer-title {\n\tbackground: #f6f6f6;\n\tcolor: #212a31;\n\tfont-size: 16px;\n\tfont-weight: bold;\n\theight: 46px;\n\tline-height: 46px;\n}\n\n\n\nbody .layer-ext-moon .layui-layer-content .layui-layer-ico {\n\theight: 32px;\n\twidth: 32px;\n\ttop:18.5px;\n}\nbody .layer-ext-moon .layui-layer-ico0 {\n\tbackground: url(default.png) no-repeat -96px 0;\n\t;\n}\nbody .layer-ext-moon .layui-layer-ico1 {\n\tbackground: url(default.png) no-repeat -224px 0;\n\t;\n}\nbody .layer-ext-moon .layui-layer-ico2 {\n\tbackground: url(default.png) no-repeat -192px 0;\n}\nbody .layer-ext-moon .layui-layer-ico3 {\n\tbackground: url(default.png) no-repeat -160px 0;\n}\nbody .layer-ext-moon .layui-layer-ico4 {\n\tbackground: url(default.png) no-repeat -320px 0;\n}\nbody .layer-ext-moon .layui-layer-ico5 {\n\tbackground: url(default.png) no-repeat -288px 0;\n}\nbody .layer-ext-moon .layui-layer-ico6 {\n\tbackground: url(default.png) -256px 0;\n}\nbody .layer-ext-moon .layui-layer-ico7 {\n\tbackground: url(default.png) no-repeat -128px 0;\n}\nbody .layer-ext-moon .layui-layer-setwin {\n\ttop: 15px;\n\tright: 15px;\n}\nbody .layer-ext-moon .layui-layer-setwin a {\n\twidth: 16px;\n\theight: 16px;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover {\n\tbackground-color: #56abe4;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-max {\n\tbackground: url(default.png) no-repeat -80px 0;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover {\n\tbackground: url(default.png) no-repeat -64px 0;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin {\n\tbackground: url(default.png) no-repeat -32px 0;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover {\n\tbackground: url(default.png) no-repeat -16px 0;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2 {\n\tbackground: url(default.png) 0 0;\n}\nbody .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover {\n\tbackground: url(default.png) -48px 0;\n}\nbody .layer-ext-moon .layui-layer-padding{padding-top: 24px;}\nbody .layer-ext-moon .layui-layer-btn {\n\tpadding: 15px 0;\n\tbackground: #f0f4f7;\n\tborder-top: 1px #c7c7c7 solid;\n}\nbody .layer-ext-moon .layui-layer-btn a {\n\tfont-size: 12px;\n\tfont-weight: normal;\n\tmargin: 0 3px;\n\tmargin-right: 7px;\n\tmargin-left: 7px;\n\tpadding: 6px 20px;\n\tcolor: #fff;\n\tborder: 1px solid #0064b6;\n\tbackground: #0071ce;\n\tborder-radius: 3px;\n\tdisplay: inline-block;\n\theight: 20px;\n\tline-height: 20px;\n\ttext-align: center;\n\tvertical-align: middle;\n\tbackground-repeat: no-repeat;\n\ttext-decoration: none;\n\toutline: none;\n\t-moz-box-sizing: content-box;\n\t-webkit-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\nbody .layer-ext-moon .layui-layer-btn .layui-layer-btn0 {\n\tbackground: #0071ce;\n}\nbody .layer-ext-moon .layui-layer-btn .layui-layer-btn1 {\n\tbackground: #fff;\n\tcolor: #404a58;\n\tborder: 1px solid #c0c4cd;\n\tborder-radius: 3px;\n}\nbody .layer-ext-moon .layui-layer-btn .layui-layer-btn2 {\n\tbackground: #f60;\n\tcolor: #fff;\n\tborder: 1px solid #f60;\n\tborder-radius: 3px;\n}\nbody .layer-ext-moon .layui-layer-btn .layui-layer-btn3 {\n\tbackground: #f00;\n\tcolor: #fff;\n\tborder: 1px solid #f00;\n\tborder-radius: 3px;\n}\n\nbody .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{\n\theight:46px;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/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": "src/main/resources/static/js/plugins/markdown/bootstrap-markdown.js",
    "content": "/* ===================================================\n * bootstrap-markdown.js v2.7.0\n * http://github.com/toopay/bootstrap-markdown\n * ===================================================\n * Copyright 2013-2014 Taufan Aditya\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    /* MARKDOWN CLASS DEFINITION\n     * ========================== */\n\n    var Markdown = function (element, options) {\n        // Class Properties\n        this.$ns = 'bootstrap-markdown'\n        this.$element = $(element)\n        this.$editable = {\n            el: null,\n            type: null,\n            attrKeys: [],\n            attrValues: [],\n            content: null\n        }\n        this.$options = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data(), this.$element.data('options'))\n        this.$oldContent = null\n        this.$isPreview = false\n        this.$isFullscreen = false\n        this.$editor = null\n        this.$textarea = null\n        this.$handler = []\n        this.$callback = []\n        this.$nextTab = []\n\n        this.showEditor()\n    }\n\n    Markdown.prototype = {\n\n        constructor: Markdown\n\n        ,\n        __alterButtons: function (name, alter) {\n            var handler = this.$handler,\n                isAll = (name == 'all'),\n                that = this\n\n            $.each(handler, function (k, v) {\n                var halt = true\n                if (isAll) {\n                    halt = false\n                } else {\n                    halt = v.indexOf(name) < 0\n                }\n\n                if (halt == false) {\n                    alter(that.$editor.find('button[data-handler=\"' + v + '\"]'))\n                }\n            })\n        }\n\n        ,\n        __buildButtons: function (buttonsArray, container) {\n            var i,\n                ns = this.$ns,\n                handler = this.$handler,\n                callback = this.$callback\n\n            for (i = 0; i < buttonsArray.length; i++) {\n                // Build each group container\n                var y, btnGroups = buttonsArray[i]\n                for (y = 0; y < btnGroups.length; y++) {\n                    // Build each button group\n                    var z,\n                        buttons = btnGroups[y].data,\n                        btnGroupContainer = $('<div/>', {\n                            'class': 'btn-group'\n                        })\n\n                    for (z = 0; z < buttons.length; z++) {\n                        var button = buttons[z],\n                            buttonContainer, buttonIconContainer,\n                            buttonHandler = ns + '-' + button.name,\n                            buttonIcon = this.__getIcon(button.icon),\n                            btnText = button.btnText ? button.btnText : '',\n                            btnClass = button.btnClass ? button.btnClass : 'btn',\n                            tabIndex = button.tabIndex ? button.tabIndex : '-1',\n                            hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',\n                            hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' (' + hotkey + ')' : ''\n\n                        // Construct the button object\n                        buttonContainer = $('<button></button>');\n                        buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-white btn-sm').addClass(btnClass);\n                        if (btnClass.match(/btn\\-(primary|success|info|warning|danger|link)/)) {\n                            buttonContainer.removeClass('btn-default');\n                        }\n                        buttonContainer.attr({\n                            'type': 'button',\n                            'title': this.__localize(button.title) + hotkeyCaption,\n                            'tabindex': tabIndex,\n                            'data-provider': ns,\n                            'data-handler': buttonHandler,\n                            'data-hotkey': hotkey\n                        });\n                        if (button.toggle == true) {\n                            buttonContainer.attr('data-toggle', 'button');\n                        }\n                        buttonIconContainer = $('<span/>');\n                        buttonIconContainer.addClass(buttonIcon);\n                        buttonIconContainer.prependTo(buttonContainer);\n\n                        // Attach the button object\n                        btnGroupContainer.append(buttonContainer);\n\n                        // Register handler and callback\n                        handler.push(buttonHandler);\n                        callback.push(button.callback);\n                    }\n\n                    // Attach the button group into container dom\n                    container.append(btnGroupContainer);\n                }\n            }\n\n            return container;\n        },\n        __setListener: function () {\n            // Set size and resizable Properties\n            var hasRows = typeof this.$textarea.attr('rows') != 'undefined',\n                maxRows = this.$textarea.val().split(\"\\n\").length > 5 ? this.$textarea.val().split(\"\\n\").length : '5',\n                rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows\n\n            this.$textarea.attr('rows', rowsVal)\n            if (this.$options.resize) {\n                this.$textarea.css('resize', this.$options.resize)\n            }\n\n            this.$textarea\n                .on('focus', $.proxy(this.focus, this))\n                .on('keypress', $.proxy(this.keypress, this))\n                .on('keyup', $.proxy(this.keyup, this))\n                .on('change', $.proxy(this.change, this))\n\n            if (this.eventSupported('keydown')) {\n                this.$textarea.on('keydown', $.proxy(this.keydown, this))\n            }\n\n            // Re-attach markdown data\n            this.$textarea.data('markdown', this)\n        }\n\n        ,\n        __handle: function (e) {\n            var target = $(e.currentTarget),\n                handler = this.$handler,\n                callback = this.$callback,\n                handlerName = target.attr('data-handler'),\n                callbackIndex = handler.indexOf(handlerName),\n                callbackHandler = callback[callbackIndex]\n\n            // Trigger the focusin\n            $(e.currentTarget).focus()\n\n            callbackHandler(this)\n\n            // Trigger onChange for each button handle\n            this.change(this);\n\n            // Unless it was the save handler,\n            // focusin the textarea\n            if (handlerName.indexOf('cmdSave') < 0) {\n                this.$textarea.focus()\n            }\n\n            e.preventDefault()\n        }\n\n        ,\n        __localize: function (string) {\n            var messages = $.fn.markdown.messages,\n                language = this.$options.language\n            if (\n                typeof messages !== 'undefined' &&\n                typeof messages[language] !== 'undefined' &&\n                typeof messages[language][string] !== 'undefined'\n            ) {\n                return messages[language][string];\n            }\n            return string;\n        }\n\n        ,\n        __getIcon: function (src) {\n            return typeof src == 'object' ? src[this.$options.iconlibrary] : src;\n        }\n\n        ,\n        setFullscreen: function (mode) {\n            var $editor = this.$editor,\n                $textarea = this.$textarea\n\n            if (mode === true) {\n                $editor.addClass('md-fullscreen-mode')\n                $('body').addClass('md-nooverflow')\n                this.$options.onFullscreen(this)\n            } else {\n                $editor.removeClass('md-fullscreen-mode')\n                $('body').removeClass('md-nooverflow')\n            }\n\n            this.$isFullscreen = mode;\n            $textarea.focus()\n        }\n\n        ,\n        showEditor: function () {\n            var instance = this,\n                textarea,\n                ns = this.$ns,\n                container = this.$element,\n                originalHeigth = container.css('height'),\n                originalWidth = container.css('width'),\n                editable = this.$editable,\n                handler = this.$handler,\n                callback = this.$callback,\n                options = this.$options,\n                editor = $('<div/>', {\n                    'class': 'md-editor',\n                    click: function () {\n                        instance.focus()\n                    }\n                })\n\n            // Prepare the editor\n            if (this.$editor == null) {\n                // Create the panel\n                var editorHeader = $('<div/>', {\n                    'class': 'md-header btn-toolbar'\n                })\n\n                // Merge the main & additional button groups together\n                var allBtnGroups = []\n                if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0])\n                if (options.additionalButtons.length > 0) allBtnGroups = allBtnGroups.concat(options.additionalButtons[0])\n\n                // Reduce and/or reorder the button groups\n                if (options.reorderButtonGroups.length > 0) {\n                    allBtnGroups = allBtnGroups\n                        .filter(function (btnGroup) {\n                            return options.reorderButtonGroups.indexOf(btnGroup.name) > -1\n                        })\n                        .sort(function (a, b) {\n                            if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1\n                            if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1\n                            return 0\n                        })\n                }\n\n                // Build the buttons\n                if (allBtnGroups.length > 0) {\n                    editorHeader = this.__buildButtons([allBtnGroups], editorHeader)\n                }\n\n                if (options.fullscreen.enable) {\n                    editorHeader.append('<div class=\"md-controls\"><a class=\"md-control md-control-fullscreen\" href=\"#\"><span class=\"' + this.__getIcon(options.fullscreen.icons.fullscreenOn) + '\"></span></a></div>').on('click', '.md-control-fullscreen', function (e) {\n                        e.preventDefault();\n                        instance.setFullscreen(true)\n                    })\n                }\n\n                editor.append(editorHeader)\n\n                // Wrap the textarea\n                if (container.is('textarea')) {\n                    container.before(editor)\n                    textarea = container\n                    textarea.addClass('md-input')\n                    editor.append(textarea)\n                } else {\n                    var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),\n                        currentContent = $.trim(rawContent)\n\n                    // This is some arbitrary content that could be edited\n                    textarea = $('<textarea/>', {\n                        'class': 'md-input',\n                        'val': currentContent\n                    })\n\n                    editor.append(textarea)\n\n                    // Save the editable\n                    editable.el = container\n                    editable.type = container.prop('tagName').toLowerCase()\n                    editable.content = container.html()\n\n                    $(container[0].attributes).each(function () {\n                        editable.attrKeys.push(this.nodeName)\n                        editable.attrValues.push(this.nodeValue)\n                    })\n\n                    // Set editor to blocked the original container\n                    container.replaceWith(editor)\n                }\n\n                var editorFooter = $('<div/>', {\n                        'class': 'md-footer'\n                    }),\n                    createFooter = false,\n                    footer = ''\n                    // Create the footer if savable\n                if (options.savable) {\n                    createFooter = true;\n                    var saveHandler = 'cmdSave'\n\n                    // Register handler and callback\n                    handler.push(saveHandler)\n                    callback.push(options.onSave)\n\n                    editorFooter.append('<button class=\"btn btn-success\" data-provider=\"' + ns + '\" data-handler=\"' + saveHandler + '\"><i class=\"icon icon-white icon-ok\"></i> ' + this.__localize('Save') + '</button>')\n\n\n                }\n\n                footer = typeof options.footer === 'function' ? options.footer(this) : options.footer\n\n                if ($.trim(footer) !== '') {\n                    createFooter = true;\n                    editorFooter.append(footer);\n                }\n\n                if (createFooter) editor.append(editorFooter)\n\n                // Set width\n                if (options.width && options.width !== 'inherit') {\n                    if (jQuery.isNumeric(options.width)) {\n                        editor.css('display', 'table')\n                        textarea.css('width', options.width + 'px')\n                    } else {\n                        editor.addClass(options.width)\n                    }\n                }\n\n                // Set height\n                if (options.height && options.height !== 'inherit') {\n                    if (jQuery.isNumeric(options.height)) {\n                        var height = options.height\n                        if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight())\n                        if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight())\n                        textarea.css('height', height + 'px')\n                    } else {\n                        editor.addClass(options.height)\n                    }\n                }\n\n                // Reference\n                this.$editor = editor\n                this.$textarea = textarea\n                this.$editable = editable\n                this.$oldContent = this.getContent()\n\n                this.__setListener()\n\n                // Set editor attributes, data short-hand API and listener\n                this.$editor.attr('id', (new Date).getTime())\n                this.$editor.on('click', '[data-provider=\"bootstrap-markdown\"]', $.proxy(this.__handle, this))\n\n                if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {\n                    this.$editor.addClass('md-editor-disabled');\n                    this.disableButtons('all');\n                }\n\n                if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {\n                    editorHeader.find('[data-provider=\"bootstrap-markdown\"]').each(function () {\n                        var $button = $(this),\n                            hotkey = $button.attr('data-hotkey')\n                        if (hotkey.toLowerCase() !== '') {\n                            textarea.bind('keydown', hotkey, function () {\n                                $button.trigger('click')\n                                return false;\n                            })\n                        }\n                    })\n                }\n\n                if (options.initialstate === 'preview') {\n                    this.showPreview();\n                } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {\n                    this.setFullscreen(true)\n                }\n\n            } else {\n                this.$editor.show()\n            }\n\n            if (options.autofocus) {\n                this.$textarea.focus()\n                this.$editor.addClass('active')\n            }\n\n            if (options.fullscreen.enable && options.fullscreen !== false) {\n                this.$editor.append('\\\n          <div class=\"md-fullscreen-controls\">\\\n            <a href=\"#\" class=\"exit-fullscreen\" title=\"Exit fullscreen\"><span class=\"' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '\"></span></a>\\\n          </div>')\n\n                this.$editor.on('click', '.exit-fullscreen', function (e) {\n                    e.preventDefault()\n                    instance.setFullscreen(false)\n                })\n            }\n\n            // hide hidden buttons from options\n            this.hideButtons(options.hiddenButtons)\n\n            // disable disabled buttons from options\n            this.disableButtons(options.disabledButtons)\n\n            // Trigger the onShow hook\n            options.onShow(this)\n\n            return this\n        }\n\n        ,\n        parseContent: function () {\n            var content,\n                callbackContent = this.$options.onPreview(this) // Try to get the content from callback\n\n            if (typeof callbackContent == 'string') {\n                // Set the content based by callback content\n                content = callbackContent\n            } else {\n                // Set the content\n                var val = this.$textarea.val();\n                if (typeof markdown == 'object') {\n                    content = markdown.toHTML(val);\n                } else if (typeof marked == 'function') {\n                    content = marked(val);\n                } else {\n                    content = val;\n                }\n            }\n\n            return content;\n        }\n\n        ,\n        showPreview: function () {\n            var options = this.$options,\n                container = this.$textarea,\n                afterContainer = container.next(),\n                replacementContainer = $('<div/>', {\n                    'class': 'md-preview',\n                    'data-provider': 'markdown-preview'\n                }),\n                content\n\n            // Give flag that tell the editor enter preview mode\n            this.$isPreview = true\n            // Disable all buttons\n            this.disableButtons('all').enableButtons('cmdPreview')\n\n            content = this.parseContent()\n\n            // Build preview element\n            replacementContainer.html(content)\n\n            if (afterContainer && afterContainer.attr('class') == 'md-footer') {\n                // If there is footer element, insert the preview container before it\n                replacementContainer.insertBefore(afterContainer)\n            } else {\n                // Otherwise, just append it after textarea\n                container.parent().append(replacementContainer)\n            }\n\n            // Set the preview element dimensions\n            replacementContainer.css({\n                width: container.outerWidth() + 'px',\n                height: container.outerHeight() + 'px'\n            })\n\n            if (this.$options.resize) {\n                replacementContainer.css('resize', this.$options.resize)\n            }\n\n            // Hide the last-active textarea\n            container.hide()\n\n            // Attach the editor instances\n            replacementContainer.data('markdown', this)\n\n            if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {\n                this.$editor.addClass('md-editor-disabled');\n                this.disableButtons('all');\n            }\n\n            return this\n        }\n\n        ,\n        hidePreview: function () {\n            // Give flag that tell the editor quit preview mode\n            this.$isPreview = false\n\n            // Obtain the preview container\n            var container = this.$editor.find('div[data-provider=\"markdown-preview\"]')\n\n            // Remove the preview container\n            container.remove()\n\n            // Enable all buttons\n            this.enableButtons('all')\n            // Disable configured disabled buttons\n            this.disableButtons(this.$options.disabledButtons)\n\n            // Back to the editor\n            this.$textarea.show()\n            this.__setListener()\n\n            return this\n        }\n\n        ,\n        isDirty: function () {\n            return this.$oldContent != this.getContent()\n        }\n\n        ,\n        getContent: function () {\n            return this.$textarea.val()\n        }\n\n        ,\n        setContent: function (content) {\n            this.$textarea.val(content)\n\n            return this\n        }\n\n        ,\n        findSelection: function (chunk) {\n            var content = this.getContent(),\n                startChunkPosition\n\n            if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {\n                var oldSelection = this.getSelection(),\n                    selection\n\n                this.setSelection(startChunkPosition, startChunkPosition + chunk.length)\n                selection = this.getSelection()\n\n                this.setSelection(oldSelection.start, oldSelection.end)\n\n                return selection\n            } else {\n                return null\n            }\n        }\n\n        ,\n        getSelection: function () {\n\n            var e = this.$textarea[0]\n\n            return (\n\n                ('selectionStart' in e && function () {\n                    var l = e.selectionEnd - e.selectionStart\n                    return {\n                        start: e.selectionStart,\n                        end: e.selectionEnd,\n                        length: l,\n                        text: e.value.substr(e.selectionStart, l)\n                    }\n                }) ||\n\n                /* browser not supported */\n                function () {\n                    return null\n                }\n\n            )()\n\n        }\n\n        ,\n        setSelection: function (start, end) {\n\n            var e = this.$textarea[0]\n\n            return (\n\n                ('selectionStart' in e && function () {\n                    e.selectionStart = start\n                    e.selectionEnd = end\n                    return\n                }) ||\n\n                /* browser not supported */\n                function () {\n                    return null\n                }\n\n            )()\n\n        }\n\n        ,\n        replaceSelection: function (text) {\n\n            var e = this.$textarea[0]\n\n            return (\n\n                ('selectionStart' in e && function () {\n                    e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length)\n                    // Set cursor to the last replacement end\n                    e.selectionStart = e.value.length\n                    return this\n                }) ||\n\n                /* browser not supported */\n                function () {\n                    e.value += text\n                    return jQuery(e)\n                }\n\n            )()\n\n        }\n\n        ,\n        getNextTab: function () {\n            // Shift the nextTab\n            if (this.$nextTab.length == 0) {\n                return null\n            } else {\n                var nextTab, tab = this.$nextTab.shift()\n\n                if (typeof tab == 'function') {\n                    nextTab = tab()\n                } else if (typeof tab == 'object' && tab.length > 0) {\n                    nextTab = tab\n                }\n\n                return nextTab\n            }\n        }\n\n        ,\n        setNextTab: function (start, end) {\n            // Push new selection into nextTab collections\n            if (typeof start == 'string') {\n                var that = this\n                this.$nextTab.push(function () {\n                    return that.findSelection(start)\n                })\n            } else if (typeof start == 'number' && typeof end == 'number') {\n                var oldSelection = this.getSelection()\n\n                this.setSelection(start, end)\n                this.$nextTab.push(this.getSelection())\n\n                this.setSelection(oldSelection.start, oldSelection.end)\n            }\n\n            return\n        }\n\n        ,\n        __parseButtonNameParam: function (nameParam) {\n            var buttons = []\n\n            if (typeof nameParam == 'string') {\n                buttons.push(nameParam)\n            } else {\n                buttons = nameParam\n            }\n\n            return buttons\n        }\n\n        ,\n        enableButtons: function (name) {\n            var buttons = this.__parseButtonNameParam(name),\n                that = this\n\n            $.each(buttons, function (i, v) {\n                that.__alterButtons(buttons[i], function (el) {\n                    el.removeAttr('disabled')\n                });\n            })\n\n            return this;\n        }\n\n        ,\n        disableButtons: function (name) {\n            var buttons = this.__parseButtonNameParam(name),\n                that = this\n\n            $.each(buttons, function (i, v) {\n                that.__alterButtons(buttons[i], function (el) {\n                    el.attr('disabled', 'disabled')\n                });\n            })\n\n            return this;\n        }\n\n        ,\n        hideButtons: function (name) {\n            var buttons = this.__parseButtonNameParam(name),\n                that = this\n\n            $.each(buttons, function (i, v) {\n                that.__alterButtons(buttons[i], function (el) {\n                    el.addClass('hidden');\n                });\n            })\n\n            return this;\n\n        }\n\n        ,\n        showButtons: function (name) {\n            var buttons = this.__parseButtonNameParam(name),\n                that = this\n\n            $.each(buttons, function (i, v) {\n                that.__alterButtons(buttons[i], function (el) {\n                    el.removeClass('hidden');\n                });\n            })\n\n            return this;\n\n        }\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        ,\n        keyup: function (e) {\n            var blocked = false\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                var nextTab\n                if (nextTab = this.getNextTab(), nextTab != null) {\n                    // Get the nextTab if exists\n                    var that = this\n                    setTimeout(function () {\n                        that.setSelection(nextTab.start, nextTab.end)\n                    }, 500)\n\n                    blocked = true\n                } else {\n                    // The next tab memory contains nothing...\n                    // check the cursor position to determine tab action\n                    var cursor = this.getSelection()\n\n                    if (cursor.start == cursor.end && cursor.end == this.getContent().length) {\n                        // The cursor already reach the end of the content\n                        blocked = false\n\n                    } else {\n                        // Put the cursor to the end\n                        this.setSelection(this.getContent().length, this.getContent().length)\n\n                        blocked = true\n                    }\n                }\n\n                break\n\n            case 13: // enter\n                blocked = false\n                break\n            case 27: // escape\n                if (this.$isFullscreen) this.setFullscreen(false)\n                blocked = false\n                break\n\n            default:\n                blocked = false\n            }\n\n            if (blocked) {\n                e.stopPropagation()\n                e.preventDefault()\n            }\n\n            this.$options.onChange(this)\n        }\n\n        ,\n        change: function (e) {\n            this.$options.onChange(this);\n            return this;\n        }\n\n        ,\n        focus: function (e) {\n            var options = this.$options,\n                isHideable = options.hideable,\n                editor = this.$editor\n\n            editor.addClass('active')\n\n            // Blur other markdown(s)\n            $(document).find('.md-editor').each(function () {\n                if ($(this).attr('id') != editor.attr('id')) {\n                    var attachedMarkdown\n\n                    if (attachedMarkdown = $(this).find('textarea').data('markdown'),\n                        attachedMarkdown == null) {\n                        attachedMarkdown = $(this).find('div[data-provider=\"markdown-preview\"]').data('markdown')\n                    }\n\n                    if (attachedMarkdown) {\n                        attachedMarkdown.blur()\n                    }\n                }\n            })\n\n            // Trigger the onFocus hook\n            options.onFocus(this);\n\n            return this\n        }\n\n        ,\n        blur: function (e) {\n            var options = this.$options,\n                isHideable = options.hideable,\n                editor = this.$editor,\n                editable = this.$editable\n\n            if (editor.hasClass('active') || this.$element.parent().length == 0) {\n                editor.removeClass('active')\n\n                if (isHideable) {\n\n                    // Check for editable elements\n                    if (editable.el != null) {\n                        // Build the original element\n                        var oldElement = $('<' + editable.type + '/>'),\n                            content = this.getContent(),\n                            currentContent = (typeof markdown == 'object') ? markdown.toHTML(content) : content\n\n                        $(editable.attrKeys).each(function (k, v) {\n                            oldElement.attr(editable.attrKeys[k], editable.attrValues[k])\n                        })\n\n                        // Get the editor content\n                        oldElement.html(currentContent)\n\n                        editor.replaceWith(oldElement)\n                    } else {\n                        editor.hide()\n\n                    }\n                }\n\n                // Trigger the onBlur hook\n                options.onBlur(this)\n            }\n\n            return this\n        }\n\n    }\n\n    /* MARKDOWN PLUGIN DEFINITION\n     * ========================== */\n\n    var old = $.fn.markdown\n\n    $.fn.markdown = function (option) {\n        return this.each(function () {\n            var $this = $(this),\n                data = $this.data('markdown'),\n                options = typeof option == 'object' && option\n            if (!data) $this.data('markdown', (data = new Markdown(this, options)))\n        })\n    }\n\n    $.fn.markdown.messages = {}\n\n    $.fn.markdown.defaults = {\n        /* Editor Properties */\n        autofocus: false,\n        hideable: false,\n        savable: false,\n        width: 'inherit',\n        height: 'inherit',\n        resize: 'none',\n        iconlibrary: 'glyph',\n        language: 'zh',\n        initialstate: 'editor',\n\n        /* Buttons Properties */\n        buttons: [\n      [{\n                name: 'groupFont',\n                data: [{\n                    name: 'cmdBold',\n                    hotkey: 'Ctrl+B',\n                    title: 'Bold',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-bold',\n                        fa: 'fa fa-bold',\n                        'fa-3': 'icon-bold'\n                    },\n                    callback: function (e) {\n                        // Give/remove ** surround the selection\n                        var chunk, cursor, selected = e.getSelection(),\n                            content = e.getContent()\n\n                        if (selected.length == 0) {\n                            // Give extra word\n                            chunk = e.__localize('strong text')\n                        } else {\n                            chunk = selected.text\n                        }\n\n                        // transform selection and set the cursor into chunked text\n                        if (content.substr(selected.start - 2, 2) == '**' && content.substr(selected.end, 2) == '**') {\n                            e.setSelection(selected.start - 2, selected.end + 2)\n                            e.replaceSelection(chunk)\n                            cursor = selected.start - 2\n                        } else {\n                            e.replaceSelection('**' + chunk + '**')\n                            cursor = selected.start + 2\n                        }\n\n                        // Set the cursor\n                        e.setSelection(cursor, cursor + chunk.length)\n                    }\n        }, {\n                    name: 'cmdItalic',\n                    title: 'Italic',\n                    hotkey: 'Ctrl+I',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-italic',\n                        fa: 'fa fa-italic',\n                        'fa-3': 'icon-italic'\n                    },\n                    callback: function (e) {\n                        // Give/remove * surround the selection\n                        var chunk, cursor, selected = e.getSelection(),\n                            content = e.getContent()\n\n                        if (selected.length == 0) {\n                            // Give extra word\n                            chunk = e.__localize('emphasized text')\n                        } else {\n                            chunk = selected.text\n                        }\n\n                        // transform selection and set the cursor into chunked text\n                        if (content.substr(selected.start - 1, 1) == '_' && content.substr(selected.end, 1) == '_') {\n                            e.setSelection(selected.start - 1, selected.end + 1)\n                            e.replaceSelection(chunk)\n                            cursor = selected.start - 1\n                        } else {\n                            e.replaceSelection('_' + chunk + '_')\n                            cursor = selected.start + 1\n                        }\n\n                        // Set the cursor\n                        e.setSelection(cursor, cursor + chunk.length)\n                    }\n        }, {\n                    name: 'cmdHeading',\n                    title: 'Heading',\n                    hotkey: 'Ctrl+H',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-header',\n                        fa: 'fa fa-header',\n                        'fa-3': 'icon-font'\n                    },\n                    callback: function (e) {\n                        // Append/remove ### surround the selection\n                        var chunk, cursor, selected = e.getSelection(),\n                            content = e.getContent(),\n                            pointer, prevChar\n\n                        if (selected.length == 0) {\n                            // Give extra word\n                            chunk = e.__localize('heading text')\n                        } else {\n                            chunk = selected.text + '\\n';\n                        }\n\n                        // transform selection and set the cursor into chunked text\n                        if ((pointer = 4, content.substr(selected.start - pointer, pointer) == '### ') || (pointer = 3, content.substr(selected.start - pointer, pointer) == '###')) {\n                            e.setSelection(selected.start - pointer, selected.end)\n                            e.replaceSelection(chunk)\n                            cursor = selected.start - pointer\n                        } else if (selected.start > 0 && (prevChar = content.substr(selected.start - 1, 1), !!prevChar && prevChar != '\\n')) {\n                            e.replaceSelection('\\n\\n### ' + chunk)\n                            cursor = selected.start + 6\n                        } else {\n                            // Empty string before element\n                            e.replaceSelection('### ' + chunk)\n                            cursor = selected.start + 4\n                        }\n\n                        // Set the cursor\n                        e.setSelection(cursor, cursor + chunk.length)\n                    }\n        }]\n      }, {\n                name: 'groupLink',\n                data: [{\n                    name: 'cmdUrl',\n                    title: 'URL/Link',\n                    hotkey: 'Ctrl+L',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-link',\n                        fa: 'fa fa-link',\n                        'fa-3': 'icon-link'\n                    },\n                    callback: function (e) {\n                        // Give [] surround the selection and prepend the link\n                        var chunk, cursor, selected = e.getSelection(),\n                            content = e.getContent(),\n                            link\n\n                        if (selected.length == 0) {\n                            // Give extra word\n                            chunk = e.__localize('enter link description here')\n                        } else {\n                            chunk = selected.text\n                        }\n\n                        link = prompt(e.__localize('Insert Hyperlink'), 'http://')\n\n                        if (link != null && link != '' && link != 'http://' && link.substr(0, 4) == 'http') {\n                            var sanitizedLink = $('<div>' + link + '</div>').text()\n\n                            // transform selection and set the cursor into chunked text\n                            e.replaceSelection('[' + chunk + '](' + sanitizedLink + ')')\n                            cursor = selected.start + 1\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n                    }\n        }, {\n                    name: 'cmdImage',\n                    title: 'Image',\n                    hotkey: 'Ctrl+G',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-picture',\n                        fa: 'fa fa-picture-o',\n                        'fa-3': 'icon-picture'\n                    },\n                    callback: function (e) {\n                        // Give ![] surround the selection and prepend the image link\n                        var chunk, cursor, selected = e.getSelection(),\n                            content = e.getContent(),\n                            link\n\n                        if (selected.length == 0) {\n                            // Give extra word\n                            chunk = e.__localize('enter image description here')\n                        } else {\n                            chunk = selected.text\n                        }\n\n                        link = prompt(e.__localize('Insert Image Hyperlink'), 'http://')\n\n                        if (link != null && link != '' && link != 'http://' && link.substr(0, 4) == 'http') {\n                            var sanitizedLink = $('<div>' + link + '</div>').text()\n\n                            // transform selection and set the cursor into chunked text\n                            e.replaceSelection('![' + chunk + '](' + sanitizedLink + ' \"' + e.__localize('enter image title here') + '\")')\n                            cursor = selected.start + 2\n\n                            // Set the next tab\n                            e.setNextTab(e.__localize('enter image title here'))\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n                    }\n        }]\n      }, {\n                name: 'groupMisc',\n                data: [{\n                        name: 'cmdList',\n                        hotkey: 'Ctrl+U',\n                        title: 'Unordered List',\n                        icon: {\n                            glyph: 'glyphicon glyphicon-list',\n                            fa: 'fa fa-list',\n                            'fa-3': 'icon-list-ul'\n                        },\n                        callback: function (e) {\n                            // Prepend/Give - surround the selection\n                            var chunk, cursor, selected = e.getSelection(),\n                                content = e.getContent()\n\n                            // transform selection and set the cursor into chunked text\n                            if (selected.length == 0) {\n                                // Give extra word\n                                chunk = e.__localize('list text here')\n\n                                e.replaceSelection('- ' + chunk)\n                                // Set the cursor\n                                cursor = selected.start + 2\n\n                            } else {\n                                if (selected.text.indexOf('\\n') < 0) {\n                                    chunk = selected.text\n\n                                    e.replaceSelection('- ' + chunk)\n\n                                    // Set the cursor\n                                    cursor = selected.start + 2\n                                } else {\n                                    var list = []\n\n                                    list = selected.text.split('\\n')\n                                    chunk = list[0]\n\n                                    $.each(list, function (k, v) {\n                                        list[k] = '- ' + v\n                                    })\n\n                                    e.replaceSelection('\\n\\n' + list.join('\\n'))\n\n                                    // Set the cursor\n                                    cursor = selected.start + 4\n                                }\n                            }\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n        },\n                    {\n                        name: 'cmdListO',\n                        hotkey: 'Ctrl+O',\n                        title: 'Ordered List',\n                        icon: {\n                            glyph: 'glyphicon glyphicon-th-list',\n                            fa: 'fa fa-list-ol',\n                            'fa-3': 'icon-list-ol'\n                        },\n                        callback: function (e) {\n\n                            // Prepend/Give - surround the selection\n                            var chunk, cursor, selected = e.getSelection(),\n                                content = e.getContent()\n\n                            // transform selection and set the cursor into chunked text\n                            if (selected.length == 0) {\n                                // Give extra word\n                                chunk = e.__localize('list text here')\n                                e.replaceSelection('1. ' + chunk)\n                                // Set the cursor\n                                cursor = selected.start + 3\n\n                            } else {\n                                if (selected.text.indexOf('\\n') < 0) {\n                                    chunk = selected.text\n\n                                    e.replaceSelection('1. ' + chunk)\n\n                                    // Set the cursor\n                                    cursor = selected.start + 3\n                                } else {\n                                    var list = []\n\n                                    list = selected.text.split('\\n')\n                                    chunk = list[0]\n\n                                    $.each(list, function (k, v) {\n                                        list[k] = '1. ' + v\n                                    })\n\n                                    e.replaceSelection('\\n\\n' + list.join('\\n'))\n\n                                    // Set the cursor\n                                    cursor = selected.start + 5\n                                }\n                            }\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n        },\n                    {\n                        name: 'cmdCode',\n                        hotkey: 'Ctrl+K',\n                        title: 'Code',\n                        icon: {\n                            glyph: 'glyphicon glyphicon-asterisk',\n                            fa: 'fa fa-code',\n                            'fa-3': 'icon-code'\n                        },\n                        callback: function (e) {\n\n                            // Give/remove ** surround the selection\n                            var chunk, cursor, selected = e.getSelection(),\n                                content = e.getContent()\n\n                            if (selected.length == 0) {\n                                // Give extra word\n                                chunk = e.__localize('code text here')\n                            } else {\n                                chunk = selected.text\n                            }\n\n                            // transform selection and set the cursor into chunked text\n                            if (content.substr(selected.start - 1, 1) == '`' && content.substr(selected.end, 1) == '`') {\n                                e.setSelection(selected.start - 1, selected.end + 1)\n                                e.replaceSelection(chunk)\n                                cursor = selected.start - 1\n                            } else {\n                                e.replaceSelection('`' + chunk + '`')\n                                cursor = selected.start + 1\n                            }\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n        },\n                    {\n                        name: 'cmdQuote',\n                        hotkey: 'Ctrl+Q',\n                        title: 'Quote',\n                        icon: {\n                            glyph: 'glyphicon glyphicon-comment',\n                            fa: 'fa fa-quote-left',\n                            'fa-3': 'icon-quote-left'\n                        },\n                        callback: function (e) {\n                            // Prepend/Give - surround the selection\n                            var chunk, cursor, selected = e.getSelection(),\n                                content = e.getContent()\n\n                            // transform selection and set the cursor into chunked text\n                            if (selected.length == 0) {\n                                // Give extra word\n                                chunk = e.__localize('quote here')\n                                e.replaceSelection('> ' + chunk)\n                                // Set the cursor\n                                cursor = selected.start + 2\n\n                            } else {\n                                if (selected.text.indexOf('\\n') < 0) {\n                                    chunk = selected.text\n\n                                    e.replaceSelection('> ' + chunk)\n\n                                    // Set the cursor\n                                    cursor = selected.start + 2\n                                } else {\n                                    var list = []\n\n                                    list = selected.text.split('\\n')\n                                    chunk = list[0]\n\n                                    $.each(list, function (k, v) {\n                                        list[k] = '> ' + v\n                                    })\n\n                                    e.replaceSelection('\\n\\n' + list.join('\\n'))\n\n                                    // Set the cursor\n                                    cursor = selected.start + 4\n                                }\n                            }\n\n                            // Set the cursor\n                            e.setSelection(cursor, cursor + chunk.length)\n                        }\n        }]\n      }, {\n                name: 'groupUtil',\n                data: [{\n                    name: 'cmdPreview',\n                    toggle: true,\n                    hotkey: 'Ctrl+P',\n                    title: 'Preview',\n                    btnText: 'Preview',\n                    btnClass: 'btn btn-sm',\n                    icon: {\n                        glyph: 'glyphicon glyphicon-search',\n                        fa: 'fa fa-search',\n                        'fa-3': 'icon-search'\n                    },\n                    callback: function (e) {\n                        // Check the preview mode and toggle based on this flag\n                        var isPreview = e.$isPreview,\n                            content\n\n                        if (isPreview == false) {\n                            // Give flag that tell the editor enter preview mode\n                            e.showPreview()\n                        } else {\n                            e.hidePreview()\n                        }\n                    }\n        }]\n      }]\n    ],\n        additionalButtons: [], // Place to hook more buttons by code\n        reorderButtonGroups: [],\n        hiddenButtons: [], // Default hidden buttons\n        disabledButtons: [], // Default disabled buttons\n        footer: '',\n        fullscreen: {\n            enable: true,\n            icons: {\n                fullscreenOn: {\n                    fa: 'fa fa-expand',\n                    glyph: 'glyphicon glyphicon-fullscreen',\n                    'fa-3': 'icon-resize-full'\n                },\n                fullscreenOff: {\n                    fa: 'fa fa-compress',\n                    glyph: 'glyphicon glyphicon-fullscreen',\n                    'fa-3': 'icon-resize-small'\n                }\n            }\n        },\n\n        /* Events hook */\n        onShow: function (e) {},\n        onPreview: function (e) {},\n        onSave: function (e) {},\n        onBlur: function (e) {},\n        onFocus: function (e) {},\n        onChange: function (e) {},\n        onFullscreen: function (e) {}\n    }\n\n    $.fn.markdown.Constructor = Markdown\n\n\n    /* MARKDOWN NO CONFLICT\n     * ==================== */\n\n    $.fn.markdown.noConflict = function () {\n        $.fn.markdown = old\n        return this\n    }\n\n    /* MARKDOWN GLOBAL FUNCTION & DATA-API\n     * ==================================== */\n    var initMarkdown = function (el) {\n        var $this = el\n\n        if ($this.data('markdown')) {\n            $this.data('markdown').showEditor()\n            return\n        }\n\n        $this.markdown()\n    }\n\n    var blurNonFocused = function (e) {\n        var $activeElement = $(document.activeElement)\n\n        // Blur event\n        $(document).find('.md-editor').each(function () {\n            var $this = $(this),\n                focused = $activeElement.closest('.md-editor')[0] === this,\n                attachedMarkdown = $this.find('textarea').data('markdown') ||\n                $this.find('div[data-provider=\"markdown-preview\"]').data('markdown')\n\n            if (attachedMarkdown && !focused) {\n                attachedMarkdown.blur()\n            }\n        })\n    }\n\n    $(document)\n        .on('click.markdown.data-api', '[data-provide=\"markdown-editable\"]', function (e) {\n            initMarkdown($(this))\n            e.preventDefault()\n        })\n        .on('click focusin', function (e) {\n            blurNonFocused(e)\n        })\n        .ready(function () {\n            $('textarea[data-provide=\"markdown\"]').each(function () {\n                initMarkdown($(this))\n            })\n        })\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/markdown/bootstrap-markdown.zh.js",
    "content": "/**\n * Chinese translation for bootstrap-markdown\n * benhaile <denghaier@163.com>\n */\n(function ($) {\n  $.fn.markdown.messages.zh = {\n    'Bold': \"粗体\",\n    'Italic': \"斜体\",\n    'Heading': \"标题\",\n    'URL/Link': \"链接\",\n    'Image': \"图片\",\n    'List': \"列表\",\n    'Unordered List': \"无序列表\",\n    'Ordered List': \"有序列表\",\n    'Code': \"代码\",\n    'Quote': \"引用\",\n    'Preview': \"预览\",\n    'strong text': \"粗体\",\n    'emphasized text': \"强调\",\n    'heading text': \"标题\",\n    'enter link description here': \"输入链接说明\",\n    'Insert Hyperlink': \"URL地址\",\n    'enter image description here': \"输入图片说明\",\n    'Insert Image Hyperlink': \"图片URL地址\",\n    'enter image title here': \"在这里输入图片标题\",\n    'list text here': \"这里是列表文本\",\n    'code text here': \"这里输入代码\",\n    'quote here': \"这里输入引用文本\"\n\n\n  };\n}(jQuery));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/markdown/markdown.js",
    "content": "// Released under MIT license\n// Copyright (c) 2009-2010 Dominic Baggott\n// Copyright (c) 2009-2010 Ash Berlin\n// Copyright (c) 2011 Christoph Dorn <christoph@christophdorn.com> (http://www.christophdorn.com)\n\n(function( expose ) {\n\n/**\n *  class Markdown\n *\n *  Markdown processing in Javascript done right. We have very particular views\n *  on what constitutes 'right' which include:\n *\n *  - produces well-formed HTML (this means that em and strong nesting is\n *    important)\n *\n *  - has an intermediate representation to allow processing of parsed data (We\n *    in fact have two, both as [JsonML]: a markdown tree and an HTML tree).\n *\n *  - is easily extensible to add new dialects without having to rewrite the\n *    entire parsing mechanics\n *\n *  - has a good test suite\n *\n *  This implementation fulfills all of these (except that the test suite could\n *  do with expanding to automatically run all the fixtures from other Markdown\n *  implementations.)\n *\n *  ##### Intermediate Representation\n *\n *  *TODO* Talk about this :) Its JsonML, but document the node names we use.\n *\n *  [JsonML]: http://jsonml.org/ \"JSON Markup Language\"\n **/\nvar Markdown = expose.Markdown = function Markdown(dialect) {\n  switch (typeof dialect) {\n    case \"undefined\":\n      this.dialect = Markdown.dialects.Gruber;\n      break;\n    case \"object\":\n      this.dialect = dialect;\n      break;\n    default:\n      if (dialect in Markdown.dialects) {\n        this.dialect = Markdown.dialects[dialect];\n      }\n      else {\n        throw new Error(\"Unknown Markdown dialect '\" + String(dialect) + \"'\");\n      }\n      break;\n  }\n  this.em_state = [];\n  this.strong_state = [];\n  this.debug_indent = \"\";\n};\n\n/**\n *  parse( markdown, [dialect] ) -> JsonML\n *  - markdown (String): markdown string to parse\n *  - dialect (String | Dialect): the dialect to use, defaults to gruber\n *\n *  Parse `markdown` and return a markdown document as a Markdown.JsonML tree.\n **/\nexpose.parse = function( source, dialect ) {\n  // dialect will default if undefined\n  var md = new Markdown( dialect );\n  return md.toTree( source );\n};\n\n/**\n *  toHTML( markdown, [dialect]  ) -> String\n *  toHTML( md_tree ) -> String\n *  - markdown (String): markdown string to parse\n *  - md_tree (Markdown.JsonML): parsed markdown tree\n *\n *  Take markdown (either as a string or as a JsonML tree) and run it through\n *  [[toHTMLTree]] then turn it into a well-formated HTML fragment.\n **/\nexpose.toHTML = function toHTML( source , dialect , options ) {\n  var input = expose.toHTMLTree( source , dialect , options );\n\n  return expose.renderJsonML( input );\n};\n\n/**\n *  toHTMLTree( markdown, [dialect] ) -> JsonML\n *  toHTMLTree( md_tree ) -> JsonML\n *  - markdown (String): markdown string to parse\n *  - dialect (String | Dialect): the dialect to use, defaults to gruber\n *  - md_tree (Markdown.JsonML): parsed markdown tree\n *\n *  Turn markdown into HTML, represented as a JsonML tree. If a string is given\n *  to this function, it is first parsed into a markdown tree by calling\n *  [[parse]].\n **/\nexpose.toHTMLTree = function toHTMLTree( input, dialect , options ) {\n  // convert string input to an MD tree\n  if ( typeof input ===\"string\" ) input = this.parse( input, dialect );\n\n  // Now convert the MD tree to an HTML tree\n\n  // remove references from the tree\n  var attrs = extract_attr( input ),\n      refs = {};\n\n  if ( attrs && attrs.references ) {\n    refs = attrs.references;\n  }\n\n  var html = convert_tree_to_html( input, refs , options );\n  merge_text_nodes( html );\n  return html;\n};\n\n// For Spidermonkey based engines\nfunction mk_block_toSource() {\n  return \"Markdown.mk_block( \" +\n          uneval(this.toString()) +\n          \", \" +\n          uneval(this.trailing) +\n          \", \" +\n          uneval(this.lineNumber) +\n          \" )\";\n}\n\n// node\nfunction mk_block_inspect() {\n  var util = require('util');\n  return \"Markdown.mk_block( \" +\n          util.inspect(this.toString()) +\n          \", \" +\n          util.inspect(this.trailing) +\n          \", \" +\n          util.inspect(this.lineNumber) +\n          \" )\";\n\n}\n\nvar mk_block = Markdown.mk_block = function(block, trail, line) {\n  // Be helpful for default case in tests.\n  if ( arguments.length == 1 ) trail = \"\\n\\n\";\n\n  var s = new String(block);\n  s.trailing = trail;\n  // To make it clear its not just a string\n  s.inspect = mk_block_inspect;\n  s.toSource = mk_block_toSource;\n\n  if (line != undefined)\n    s.lineNumber = line;\n\n  return s;\n};\n\nfunction count_lines( str ) {\n  var n = 0, i = -1;\n  while ( ( i = str.indexOf('\\n', i+1) ) !== -1) n++;\n  return n;\n}\n\n// Internal - split source into rough blocks\nMarkdown.prototype.split_blocks = function splitBlocks( input, startLine ) {\n  // [\\s\\S] matches _anything_ (newline or space)\n  var re = /([\\s\\S]+?)($|\\n(?:\\s*\\n|$)+)/g,\n      blocks = [],\n      m;\n\n  var line_no = 1;\n\n  if ( ( m = /^(\\s*\\n)/.exec(input) ) != null ) {\n    // skip (but count) leading blank lines\n    line_no += count_lines( m[0] );\n    re.lastIndex = m[0].length;\n  }\n\n  while ( ( m = re.exec(input) ) !== null ) {\n    blocks.push( mk_block( m[1], m[2], line_no ) );\n    line_no += count_lines( m[0] );\n  }\n\n  return blocks;\n};\n\n/**\n *  Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]\n *  - block (String): the block to process\n *  - next (Array): the following blocks\n *\n * Process `block` and return an array of JsonML nodes representing `block`.\n *\n * It does this by asking each block level function in the dialect to process\n * the block until one can. Succesful handling is indicated by returning an\n * array (with zero or more JsonML nodes), failure by a false value.\n *\n * Blocks handlers are responsible for calling [[Markdown#processInline]]\n * themselves as appropriate.\n *\n * If the blocks were split incorrectly or adjacent blocks need collapsing you\n * can adjust `next` in place using shift/splice etc.\n *\n * If any of this default behaviour is not right for the dialect, you can\n * define a `__call__` method on the dialect that will get invoked to handle\n * the block processing.\n */\nMarkdown.prototype.processBlock = function processBlock( block, next ) {\n  var cbs = this.dialect.block,\n      ord = cbs.__order__;\n\n  if ( \"__call__\" in cbs ) {\n    return cbs.__call__.call(this, block, next);\n  }\n\n  for ( var i = 0; i < ord.length; i++ ) {\n    //D:this.debug( \"Testing\", ord[i] );\n    var res = cbs[ ord[i] ].call( this, block, next );\n    if ( res ) {\n      //D:this.debug(\"  matched\");\n      if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )\n        this.debug(ord[i], \"didn't return a proper array\");\n      //D:this.debug( \"\" );\n      return res;\n    }\n  }\n\n  // Uhoh! no match! Should we throw an error?\n  return [];\n};\n\nMarkdown.prototype.processInline = function processInline( block ) {\n  return this.dialect.inline.__call__.call( this, String( block ) );\n};\n\n/**\n *  Markdown#toTree( source ) -> JsonML\n *  - source (String): markdown source to parse\n *\n *  Parse `source` into a JsonML tree representing the markdown document.\n **/\n// custom_tree means set this.tree to `custom_tree` and restore old value on return\nMarkdown.prototype.toTree = function toTree( source, custom_root ) {\n  var blocks = source instanceof Array ? source : this.split_blocks( source );\n\n  // Make tree a member variable so its easier to mess with in extensions\n  var old_tree = this.tree;\n  try {\n    this.tree = custom_root || this.tree || [ \"markdown\" ];\n\n    blocks:\n    while ( blocks.length ) {\n      var b = this.processBlock( blocks.shift(), blocks );\n\n      // Reference blocks and the like won't return any content\n      if ( !b.length ) continue blocks;\n\n      this.tree.push.apply( this.tree, b );\n    }\n    return this.tree;\n  }\n  finally {\n    if ( custom_root ) {\n      this.tree = old_tree;\n    }\n  }\n};\n\n// Noop by default\nMarkdown.prototype.debug = function () {\n  var args = Array.prototype.slice.call( arguments);\n  args.unshift(this.debug_indent);\n  if (typeof print !== \"undefined\")\n      print.apply( print, args );\n  if (typeof console !== \"undefined\" && typeof console.log !== \"undefined\")\n      console.log.apply( null, args );\n}\n\nMarkdown.prototype.loop_re_over_block = function( re, block, cb ) {\n  // Dont use /g regexps with this\n  var m,\n      b = block.valueOf();\n\n  while ( b.length && (m = re.exec(b) ) != null) {\n    b = b.substr( m[0].length );\n    cb.call(this, m);\n  }\n  return b;\n};\n\n/**\n * Markdown.dialects\n *\n * Namespace of built-in dialects.\n **/\nMarkdown.dialects = {};\n\n/**\n * Markdown.dialects.Gruber\n *\n * The default dialect that follows the rules set out by John Gruber's\n * markdown.pl as closely as possible. Well actually we follow the behaviour of\n * that script which in some places is not exactly what the syntax web page\n * says.\n **/\nMarkdown.dialects.Gruber = {\n  block: {\n    atxHeader: function atxHeader( block, next ) {\n      var m = block.match( /^(#{1,6})\\s*(.*?)\\s*#*\\s*(?:\\n|$)/ );\n\n      if ( !m ) return undefined;\n\n      var header = [ \"header\", { level: m[ 1 ].length } ];\n      Array.prototype.push.apply(header, this.processInline(m[ 2 ]));\n\n      if ( m[0].length < block.length )\n        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );\n\n      return [ header ];\n    },\n\n    setextHeader: function setextHeader( block, next ) {\n      var m = block.match( /^(.*)\\n([-=])\\2\\2+(?:\\n|$)/ );\n\n      if ( !m ) return undefined;\n\n      var level = ( m[ 2 ] === \"=\" ) ? 1 : 2;\n      var header = [ \"header\", { level : level }, m[ 1 ] ];\n\n      if ( m[0].length < block.length )\n        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );\n\n      return [ header ];\n    },\n\n    code: function code( block, next ) {\n      // |    Foo\n      // |bar\n      // should be a code block followed by a paragraph. Fun\n      //\n      // There might also be adjacent code block to merge.\n\n      var ret = [],\n          re = /^(?: {0,3}\\t| {4})(.*)\\n?/,\n          lines;\n\n      // 4 spaces + content\n      if ( !block.match( re ) ) return undefined;\n\n      block_search:\n      do {\n        // Now pull out the rest of the lines\n        var b = this.loop_re_over_block(\n                  re, block.valueOf(), function( m ) { ret.push( m[1] ); } );\n\n        if (b.length) {\n          // Case alluded to in first comment. push it back on as a new block\n          next.unshift( mk_block(b, block.trailing) );\n          break block_search;\n        }\n        else if (next.length) {\n          // Check the next block - it might be code too\n          if ( !next[0].match( re ) ) break block_search;\n\n          // Pull how how many blanks lines follow - minus two to account for .join\n          ret.push ( block.trailing.replace(/[^\\n]/g, '').substring(2) );\n\n          block = next.shift();\n        }\n        else {\n          break block_search;\n        }\n      } while (true);\n\n      return [ [ \"code_block\", ret.join(\"\\n\") ] ];\n    },\n\n    horizRule: function horizRule( block, next ) {\n      // this needs to find any hr in the block to handle abutting blocks\n      var m = block.match( /^(?:([\\s\\S]*?)\\n)?[ \\t]*([-_*])(?:[ \\t]*\\2){2,}[ \\t]*(?:\\n([\\s\\S]*))?$/ );\n\n      if ( !m ) {\n        return undefined;\n      }\n\n      var jsonml = [ [ \"hr\" ] ];\n\n      // if there's a leading abutting block, process it\n      if ( m[ 1 ] ) {\n        jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );\n      }\n\n      // if there's a trailing abutting block, stick it into next\n      if ( m[ 3 ] ) {\n        next.unshift( mk_block( m[ 3 ] ) );\n      }\n\n      return jsonml;\n    },\n\n    // There are two types of lists. Tight and loose. Tight lists have no whitespace\n    // between the items (and result in text just in the <li>) and loose lists,\n    // which have an empty line between list items, resulting in (one or more)\n    // paragraphs inside the <li>.\n    //\n    // There are all sorts weird edge cases about the original markdown.pl's\n    // handling of lists:\n    //\n    // * Nested lists are supposed to be indented by four chars per level. But\n    //   if they aren't, you can get a nested list by indenting by less than\n    //   four so long as the indent doesn't match an indent of an existing list\n    //   item in the 'nest stack'.\n    //\n    // * The type of the list (bullet or number) is controlled just by the\n    //    first item at the indent. Subsequent changes are ignored unless they\n    //    are for nested lists\n    //\n    lists: (function( ) {\n      // Use a closure to hide a few variables.\n      var any_list = \"[*+-]|\\\\d+\\\\.\",\n          bullet_list = /[*+-]/,\n          number_list = /\\d+\\./,\n          // Capture leading indent as it matters for determining nested lists.\n          is_list_re = new RegExp( \"^( {0,3})(\" + any_list + \")[ \\t]+\" ),\n          indent_re = \"(?: {0,3}\\\\t| {4})\";\n\n      // TODO: Cache this regexp for certain depths.\n      // Create a regexp suitable for matching an li for a given stack depth\n      function regex_for_depth( depth ) {\n\n        return new RegExp(\n          // m[1] = indent, m[2] = list_type\n          \"(?:^(\" + indent_re + \"{0,\" + depth + \"} {0,3})(\" + any_list + \")\\\\s+)|\" +\n          // m[3] = cont\n          \"(^\" + indent_re + \"{0,\" + (depth-1) + \"}[ ]{0,4})\"\n        );\n      }\n      function expand_tab( input ) {\n        return input.replace( / {0,3}\\t/g, \"    \" );\n      }\n\n      // Add inline content `inline` to `li`. inline comes from processInline\n      // so is an array of content\n      function add(li, loose, inline, nl) {\n        if (loose) {\n          li.push( [ \"para\" ].concat(inline) );\n          return;\n        }\n        // Hmmm, should this be any block level element or just paras?\n        var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == \"para\"\n                   ? li[li.length -1]\n                   : li;\n\n        // If there is already some content in this list, add the new line in\n        if (nl && li.length > 1) inline.unshift(nl);\n\n        for (var i=0; i < inline.length; i++) {\n          var what = inline[i],\n              is_str = typeof what == \"string\";\n          if (is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == \"string\" ) {\n            add_to[ add_to.length-1 ] += what;\n          }\n          else {\n            add_to.push( what );\n          }\n        }\n      }\n\n      // contained means have an indent greater than the current one. On\n      // *every* line in the block\n      function get_contained_blocks( depth, blocks ) {\n\n        var re = new RegExp( \"^(\" + indent_re + \"{\" + depth + \"}.*?\\\\n?)*$\" ),\n            replace = new RegExp(\"^\" + indent_re + \"{\" + depth + \"}\", \"gm\"),\n            ret = [];\n\n        while ( blocks.length > 0 ) {\n          if ( re.exec( blocks[0] ) ) {\n            var b = blocks.shift(),\n                // Now remove that indent\n                x = b.replace( replace, \"\");\n\n            ret.push( mk_block( x, b.trailing, b.lineNumber ) );\n          }\n          break;\n        }\n        return ret;\n      }\n\n      // passed to stack.forEach to turn list items up the stack into paras\n      function paragraphify(s, i, stack) {\n        var list = s.list;\n        var last_li = list[list.length-1];\n\n        if (last_li[1] instanceof Array && last_li[1][0] == \"para\") {\n          return;\n        }\n        if (i+1 == stack.length) {\n          // Last stack frame\n          // Keep the same array, but replace the contents\n          last_li.push( [\"para\"].concat( last_li.splice(1) ) );\n        }\n        else {\n          var sublist = last_li.pop();\n          last_li.push( [\"para\"].concat( last_li.splice(1) ), sublist );\n        }\n      }\n\n      // The matcher function\n      return function( block, next ) {\n        var m = block.match( is_list_re );\n        if ( !m ) return undefined;\n\n        function make_list( m ) {\n          var list = bullet_list.exec( m[2] )\n                   ? [\"bulletlist\"]\n                   : [\"numberlist\"];\n\n          stack.push( { list: list, indent: m[1] } );\n          return list;\n        }\n\n\n        var stack = [], // Stack of lists for nesting.\n            list = make_list( m ),\n            last_li,\n            loose = false,\n            ret = [ stack[0].list ],\n            i;\n\n        // Loop to search over block looking for inner block elements and loose lists\n        loose_search:\n        while( true ) {\n          // Split into lines preserving new lines at end of line\n          var lines = block.split( /(?=\\n)/ );\n\n          // We have to grab all lines for a li and call processInline on them\n          // once as there are some inline things that can span lines.\n          var li_accumulate = \"\";\n\n          // Loop over the lines in this block looking for tight lists.\n          tight_search:\n          for (var line_no=0; line_no < lines.length; line_no++) {\n            var nl = \"\",\n                l = lines[line_no].replace(/^\\n/, function(n) { nl = n; return \"\"; });\n\n            // TODO: really should cache this\n            var line_re = regex_for_depth( stack.length );\n\n            m = l.match( line_re );\n            //print( \"line:\", uneval(l), \"\\nline match:\", uneval(m) );\n\n            // We have a list item\n            if ( m[1] !== undefined ) {\n              // Process the previous list item, if any\n              if ( li_accumulate.length ) {\n                add( last_li, loose, this.processInline( li_accumulate ), nl );\n                // Loose mode will have been dealt with. Reset it\n                loose = false;\n                li_accumulate = \"\";\n              }\n\n              m[1] = expand_tab( m[1] );\n              var wanted_depth = Math.floor(m[1].length/4)+1;\n              //print( \"want:\", wanted_depth, \"stack:\", stack.length);\n              if ( wanted_depth > stack.length ) {\n                // Deep enough for a nested list outright\n                //print ( \"new nested list\" );\n                list = make_list( m );\n                last_li.push( list );\n                last_li = list[1] = [ \"listitem\" ];\n              }\n              else {\n                // We aren't deep enough to be strictly a new level. This is\n                // where Md.pl goes nuts. If the indent matches a level in the\n                // stack, put it there, else put it one deeper then the\n                // wanted_depth deserves.\n                var found = false;\n                for (i = 0; i < stack.length; i++) {\n                  if ( stack[ i ].indent != m[1] ) continue;\n                  list = stack[ i ].list;\n                  stack.splice( i+1 );\n                  found = true;\n                  break;\n                }\n\n                if (!found) {\n                  //print(\"not found. l:\", uneval(l));\n                  wanted_depth++;\n                  if (wanted_depth <= stack.length) {\n                    stack.splice(wanted_depth);\n                    //print(\"Desired depth now\", wanted_depth, \"stack:\", stack.length);\n                    list = stack[wanted_depth-1].list;\n                    //print(\"list:\", uneval(list) );\n                  }\n                  else {\n                    //print (\"made new stack for messy indent\");\n                    list = make_list(m);\n                    last_li.push(list);\n                  }\n                }\n\n                //print( uneval(list), \"last\", list === stack[stack.length-1].list );\n                last_li = [ \"listitem\" ];\n                list.push(last_li);\n              } // end depth of shenegains\n              nl = \"\";\n            }\n\n            // Add content\n            if (l.length > m[0].length) {\n              li_accumulate += nl + l.substr( m[0].length );\n            }\n          } // tight_search\n\n          if ( li_accumulate.length ) {\n            add( last_li, loose, this.processInline( li_accumulate ), nl );\n            // Loose mode will have been dealt with. Reset it\n            loose = false;\n            li_accumulate = \"\";\n          }\n\n          // Look at the next block - we might have a loose list. Or an extra\n          // paragraph for the current li\n          var contained = get_contained_blocks( stack.length, next );\n\n          // Deal with code blocks or properly nested lists\n          if (contained.length > 0) {\n            // Make sure all listitems up the stack are paragraphs\n            forEach( stack, paragraphify, this);\n\n            last_li.push.apply( last_li, this.toTree( contained, [] ) );\n          }\n\n          var next_block = next[0] && next[0].valueOf() || \"\";\n\n          if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {\n            block = next.shift();\n\n            // Check for an HR following a list: features/lists/hr_abutting\n            var hr = this.dialect.block.horizRule( block, next );\n\n            if (hr) {\n              ret.push.apply(ret, hr);\n              break;\n            }\n\n            // Make sure all listitems up the stack are paragraphs\n            forEach( stack, paragraphify, this);\n\n            loose = true;\n            continue loose_search;\n          }\n          break;\n        } // loose_search\n\n        return ret;\n      };\n    })(),\n\n    blockquote: function blockquote( block, next ) {\n      if ( !block.match( /^>/m ) )\n        return undefined;\n\n      var jsonml = [];\n\n      // separate out the leading abutting block, if any\n      if ( block[ 0 ] != \">\" ) {\n        var lines = block.split( /\\n/ ),\n            prev = [];\n\n        // keep shifting lines until you find a crotchet\n        while ( lines.length && lines[ 0 ][ 0 ] != \">\" ) {\n            prev.push( lines.shift() );\n        }\n\n        // reassemble!\n        block = lines.join( \"\\n\" );\n        jsonml.push.apply( jsonml, this.processBlock( prev.join( \"\\n\" ), [] ) );\n      }\n\n      // if the next block is also a blockquote merge it in\n      while ( next.length && next[ 0 ][ 0 ] == \">\" ) {\n        var b = next.shift();\n        block = new String(block + block.trailing + b);\n        block.trailing = b.trailing;\n      }\n\n      // Strip off the leading \"> \" and re-process as a block.\n      var input = block.replace( /^> ?/gm, '' ),\n          old_tree = this.tree;\n      jsonml.push( this.toTree( input, [ \"blockquote\" ] ) );\n\n      return jsonml;\n    },\n\n    referenceDefn: function referenceDefn( block, next) {\n      var re = /^\\s*\\[(.*?)\\]:\\s*(\\S+)(?:\\s+(?:(['\"])(.*?)\\3|\\((.*?)\\)))?\\n?/;\n      // interesting matches are [ , ref_id, url, , title, title ]\n\n      if ( !block.match(re) )\n        return undefined;\n\n      // make an attribute node if it doesn't exist\n      if ( !extract_attr( this.tree ) ) {\n        this.tree.splice( 1, 0, {} );\n      }\n\n      var attrs = extract_attr( this.tree );\n\n      // make a references hash if it doesn't exist\n      if ( attrs.references === undefined ) {\n        attrs.references = {};\n      }\n\n      var b = this.loop_re_over_block(re, block, function( m ) {\n\n        if ( m[2] && m[2][0] == '<' && m[2][m[2].length-1] == '>' )\n          m[2] = m[2].substring( 1, m[2].length - 1 );\n\n        var ref = attrs.references[ m[1].toLowerCase() ] = {\n          href: m[2]\n        };\n\n        if (m[4] !== undefined)\n          ref.title = m[4];\n        else if (m[5] !== undefined)\n          ref.title = m[5];\n\n      } );\n\n      if (b.length)\n        next.unshift( mk_block( b, block.trailing ) );\n\n      return [];\n    },\n\n    para: function para( block, next ) {\n      // everything's a para!\n      return [ [\"para\"].concat( this.processInline( block ) ) ];\n    }\n  }\n};\n\nMarkdown.dialects.Gruber.inline = {\n\n    __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {\n      var m,\n          res,\n          lastIndex = 0;\n\n      patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;\n      var re = new RegExp( \"([\\\\s\\\\S]*?)(\" + (patterns_or_re.source || patterns_or_re) + \")\" );\n\n      m = re.exec( text );\n      if (!m) {\n        // Just boring text\n        return [ text.length, text ];\n      }\n      else if ( m[1] ) {\n        // Some un-interesting text matched. Return that first\n        return [ m[1].length, m[1] ];\n      }\n\n      var res;\n      if ( m[2] in this.dialect.inline ) {\n        res = this.dialect.inline[ m[2] ].call(\n                  this,\n                  text.substr( m.index ), m, previous_nodes || [] );\n      }\n      // Default for now to make dev easier. just slurp special and output it.\n      res = res || [ m[2].length, m[2] ];\n      return res;\n    },\n\n    __call__: function inline( text, patterns ) {\n\n      var out = [],\n          res;\n\n      function add(x) {\n        //D:self.debug(\"  adding output\", uneval(x));\n        if (typeof x == \"string\" && typeof out[out.length-1] == \"string\")\n          out[ out.length-1 ] += x;\n        else\n          out.push(x);\n      }\n\n      while ( text.length > 0 ) {\n        res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );\n        text = text.substr( res.shift() );\n        forEach(res, add )\n      }\n\n      return out;\n    },\n\n    // These characters are intersting elsewhere, so have rules for them so that\n    // chunks of plain text blocks don't include them\n    \"]\": function () {},\n    \"}\": function () {},\n\n    \"\\\\\": function escaped( text ) {\n      // [ length of input processed, node/children to add... ]\n      // Only esacape: \\ ` * _ { } [ ] ( ) # * + - . !\n      if ( text.match( /^\\\\[\\\\`\\*_{}\\[\\]()#\\+.!\\-]/ ) )\n        return [ 2, text[1] ];\n      else\n        // Not an esacpe\n        return [ 1, \"\\\\\" ];\n    },\n\n    \"![\": function image( text ) {\n\n      // Unlike images, alt text is plain text only. no other elements are\n      // allowed in there\n\n      // ![Alt text](/path/to/img.jpg \"Optional title\")\n      //      1          2            3       4         <--- captures\n      var m = text.match( /^!\\[(.*?)\\][ \\t]*\\([ \\t]*(\\S*)(?:[ \\t]+([\"'])(.*?)\\3)?[ \\t]*\\)/ );\n\n      if ( m ) {\n        if ( m[2] && m[2][0] == '<' && m[2][m[2].length-1] == '>' )\n          m[2] = m[2].substring( 1, m[2].length - 1 );\n\n        m[2] = this.dialect.inline.__call__.call( this, m[2], /\\\\/ )[0];\n\n        var attrs = { alt: m[1], href: m[2] || \"\" };\n        if ( m[4] !== undefined)\n          attrs.title = m[4];\n\n        return [ m[0].length, [ \"img\", attrs ] ];\n      }\n\n      // ![Alt text][id]\n      m = text.match( /^!\\[(.*?)\\][ \\t]*\\[(.*?)\\]/ );\n\n      if ( m ) {\n        // We can't check if the reference is known here as it likely wont be\n        // found till after. Check it in md tree->hmtl tree conversion\n        return [ m[0].length, [ \"img_ref\", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];\n      }\n\n      // Just consume the '!['\n      return [ 2, \"![\" ];\n    },\n\n    \"[\": function link( text ) {\n\n      var orig = String(text);\n      // Inline content is possible inside `link text`\n      var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), ']' );\n\n      // No closing ']' found. Just consume the [\n      if ( !res ) return [ 1, '[' ];\n\n      var consumed = 1 + res[ 0 ],\n          children = res[ 1 ],\n          link,\n          attrs;\n\n      // At this point the first [...] has been parsed. See what follows to find\n      // out which kind of link we are (reference or direct url)\n      text = text.substr( consumed );\n\n      // [link text](/path/to/img.jpg \"Optional title\")\n      //                 1            2       3         <--- captures\n      // This will capture up to the last paren in the block. We then pull\n      // back based on if there a matching ones in the url\n      //    ([here](/url/(test))\n      // The parens have to be balanced\n      var m = text.match( /^\\s*\\([ \\t]*(\\S+)(?:[ \\t]+([\"'])(.*?)\\2)?[ \\t]*\\)/ );\n      if ( m ) {\n        var url = m[1];\n        consumed += m[0].length;\n\n        if ( url && url[0] == '<' && url[url.length-1] == '>' )\n          url = url.substring( 1, url.length - 1 );\n\n        // If there is a title we don't have to worry about parens in the url\n        if ( !m[3] ) {\n          var open_parens = 1; // One open that isn't in the capture\n          for (var len = 0; len < url.length; len++) {\n            switch ( url[len] ) {\n            case '(':\n              open_parens++;\n              break;\n            case ')':\n              if ( --open_parens == 0) {\n                consumed -= url.length - len;\n                url = url.substring(0, len);\n              }\n              break;\n            }\n          }\n        }\n\n        // Process escapes only\n        url = this.dialect.inline.__call__.call( this, url, /\\\\/ )[0];\n\n        attrs = { href: url || \"\" };\n        if ( m[3] !== undefined)\n          attrs.title = m[3];\n\n        link = [ \"link\", attrs ].concat( children );\n        return [ consumed, link ];\n      }\n\n      // [Alt text][id]\n      // [Alt text] [id]\n      m = text.match( /^\\s*\\[(.*?)\\]/ );\n\n      if ( m ) {\n\n        consumed += m[ 0 ].length;\n\n        // [links][] uses links as its reference\n        attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(),  original: orig.substr( 0, consumed ) };\n\n        link = [ \"link_ref\", attrs ].concat( children );\n\n        // We can't check if the reference is known here as it likely wont be\n        // found till after. Check it in md tree->hmtl tree conversion.\n        // Store the original so that conversion can revert if the ref isn't found.\n        return [ consumed, link ];\n      }\n\n      // [id]\n      // Only if id is plain (no formatting.)\n      if ( children.length == 1 && typeof children[0] == \"string\" ) {\n\n        attrs = { ref: children[0].toLowerCase(),  original: orig.substr( 0, consumed ) };\n        link = [ \"link_ref\", attrs, children[0] ];\n        return [ consumed, link ];\n      }\n\n      // Just consume the '['\n      return [ 1, \"[\" ];\n    },\n\n\n    \"<\": function autoLink( text ) {\n      var m;\n\n      if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\\.[a-zA-Z]+))>/ ) ) != null ) {\n        if ( m[3] ) {\n          return [ m[0].length, [ \"link\", { href: \"mailto:\" + m[3] }, m[3] ] ];\n\n        }\n        else if ( m[2] == \"mailto\" ) {\n          return [ m[0].length, [ \"link\", { href: m[1] }, m[1].substr(\"mailto:\".length ) ] ];\n        }\n        else\n          return [ m[0].length, [ \"link\", { href: m[1] }, m[1] ] ];\n      }\n\n      return [ 1, \"<\" ];\n    },\n\n    \"`\": function inlineCode( text ) {\n      // Inline code block. as many backticks as you like to start it\n      // Always skip over the opening ticks.\n      var m = text.match( /(`+)(([\\s\\S]*?)\\1)/ );\n\n      if ( m && m[2] )\n        return [ m[1].length + m[2].length, [ \"inlinecode\", m[3] ] ];\n      else {\n        // TODO: No matching end code found - warn!\n        return [ 1, \"`\" ];\n      }\n    },\n\n    \"  \\n\": function lineBreak( text ) {\n      return [ 3, [ \"linebreak\" ] ];\n    }\n\n};\n\n// Meta Helper/generator method for em and strong handling\nfunction strong_em( tag, md ) {\n\n  var state_slot = tag + \"_state\",\n      other_slot = tag == \"strong\" ? \"em_state\" : \"strong_state\";\n\n  function CloseTag(len) {\n    this.len_after = len;\n    this.name = \"close_\" + md;\n  }\n\n  return function ( text, orig_match ) {\n\n    if (this[state_slot][0] == md) {\n      // Most recent em is of this type\n      //D:this.debug(\"closing\", md);\n      this[state_slot].shift();\n\n      // \"Consume\" everything to go back to the recrusion in the else-block below\n      return[ text.length, new CloseTag(text.length-md.length) ];\n    }\n    else {\n      // Store a clone of the em/strong states\n      var other = this[other_slot].slice(),\n          state = this[state_slot].slice();\n\n      this[state_slot].unshift(md);\n\n      //D:this.debug_indent += \"  \";\n\n      // Recurse\n      var res = this.processInline( text.substr( md.length ) );\n      //D:this.debug_indent = this.debug_indent.substr(2);\n\n      var last = res[res.length - 1];\n\n      //D:this.debug(\"processInline from\", tag + \": \", uneval( res ) );\n\n      var check = this[state_slot].shift();\n      if (last instanceof CloseTag) {\n        res.pop();\n        // We matched! Huzzah.\n        var consumed = text.length - last.len_after;\n        return [ consumed, [ tag ].concat(res) ];\n      }\n      else {\n        // Restore the state of the other kind. We might have mistakenly closed it.\n        this[other_slot] = other;\n        this[state_slot] = state;\n\n        // We can't reuse the processed result as it could have wrong parsing contexts in it.\n        return [ md.length, md ];\n      }\n    }\n  }; // End returned function\n}\n\nMarkdown.dialects.Gruber.inline[\"**\"] = strong_em(\"strong\", \"**\");\nMarkdown.dialects.Gruber.inline[\"__\"] = strong_em(\"strong\", \"__\");\nMarkdown.dialects.Gruber.inline[\"*\"]  = strong_em(\"em\", \"*\");\nMarkdown.dialects.Gruber.inline[\"_\"]  = strong_em(\"em\", \"_\");\n\n\n// Build default order from insertion order.\nMarkdown.buildBlockOrder = function(d) {\n  var ord = [];\n  for ( var i in d ) {\n    if ( i == \"__order__\" || i == \"__call__\" ) continue;\n    ord.push( i );\n  }\n  d.__order__ = ord;\n};\n\n// Build patterns for inline matcher\nMarkdown.buildInlinePatterns = function(d) {\n  var patterns = [];\n\n  for ( var i in d ) {\n    // __foo__ is reserved and not a pattern\n    if ( i.match( /^__.*__$/) ) continue;\n    var l = i.replace( /([\\\\.*+?|()\\[\\]{}])/g, \"\\\\$1\" )\n             .replace( /\\n/, \"\\\\n\" );\n    patterns.push( i.length == 1 ? l : \"(?:\" + l + \")\" );\n  }\n\n  patterns = patterns.join(\"|\");\n  d.__patterns__ = patterns;\n  //print(\"patterns:\", uneval( patterns ) );\n\n  var fn = d.__call__;\n  d.__call__ = function(text, pattern) {\n    if (pattern != undefined) {\n      return fn.call(this, text, pattern);\n    }\n    else\n    {\n      return fn.call(this, text, patterns);\n    }\n  };\n};\n\nMarkdown.DialectHelpers = {};\nMarkdown.DialectHelpers.inline_until_char = function( text, want ) {\n  var consumed = 0,\n      nodes = [];\n\n  while ( true ) {\n    if ( text[ consumed ] == want ) {\n      // Found the character we were looking for\n      consumed++;\n      return [ consumed, nodes ];\n    }\n\n    if ( consumed >= text.length ) {\n      // No closing char found. Abort.\n      return null;\n    }\n\n    var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );\n    consumed += res[ 0 ];\n    // Add any returned nodes.\n    nodes.push.apply( nodes, res.slice( 1 ) );\n  }\n}\n\n// Helper function to make sub-classing a dialect easier\nMarkdown.subclassDialect = function( d ) {\n  function Block() {}\n  Block.prototype = d.block;\n  function Inline() {}\n  Inline.prototype = d.inline;\n\n  return { block: new Block(), inline: new Inline() };\n};\n\nMarkdown.buildBlockOrder ( Markdown.dialects.Gruber.block );\nMarkdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );\n\nMarkdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );\n\nMarkdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {\n  var meta = split_meta_hash( meta_string ),\n      attr = {};\n\n  for ( var i = 0; i < meta.length; ++i ) {\n    // id: #foo\n    if ( /^#/.test( meta[ i ] ) ) {\n      attr.id = meta[ i ].substring( 1 );\n    }\n    // class: .foo\n    else if ( /^\\./.test( meta[ i ] ) ) {\n      // if class already exists, append the new one\n      if ( attr['class'] ) {\n        attr['class'] = attr['class'] + meta[ i ].replace( /./, \" \" );\n      }\n      else {\n        attr['class'] = meta[ i ].substring( 1 );\n      }\n    }\n    // attribute: foo=bar\n    else if ( /\\=/.test( meta[ i ] ) ) {\n      var s = meta[ i ].split( /\\=/ );\n      attr[ s[ 0 ] ] = s[ 1 ];\n    }\n  }\n\n  return attr;\n}\n\nfunction split_meta_hash( meta_string ) {\n  var meta = meta_string.split( \"\" ),\n      parts = [ \"\" ],\n      in_quotes = false;\n\n  while ( meta.length ) {\n    var letter = meta.shift();\n    switch ( letter ) {\n      case \" \" :\n        // if we're in a quoted section, keep it\n        if ( in_quotes ) {\n          parts[ parts.length - 1 ] += letter;\n        }\n        // otherwise make a new part\n        else {\n          parts.push( \"\" );\n        }\n        break;\n      case \"'\" :\n      case '\"' :\n        // reverse the quotes and move straight on\n        in_quotes = !in_quotes;\n        break;\n      case \"\\\\\" :\n        // shift off the next letter to be used straight away.\n        // it was escaped so we'll keep it whatever it is\n        letter = meta.shift();\n      default :\n        parts[ parts.length - 1 ] += letter;\n        break;\n    }\n  }\n\n  return parts;\n}\n\nMarkdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {\n  // we're only interested in the first block\n  if ( block.lineNumber > 1 ) return undefined;\n\n  // document_meta blocks consist of one or more lines of `Key: Value\\n`\n  if ( ! block.match( /^(?:\\w+:.*\\n)*\\w+:.*$/ ) ) return undefined;\n\n  // make an attribute node if it doesn't exist\n  if ( !extract_attr( this.tree ) ) {\n    this.tree.splice( 1, 0, {} );\n  }\n\n  var pairs = block.split( /\\n/ );\n  for ( p in pairs ) {\n    var m = pairs[ p ].match( /(\\w+):\\s*(.*)$/ ),\n        key = m[ 1 ].toLowerCase(),\n        value = m[ 2 ];\n\n    this.tree[ 1 ][ key ] = value;\n  }\n\n  // document_meta produces no content!\n  return [];\n};\n\nMarkdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {\n  // check if the last line of the block is an meta hash\n  var m = block.match( /(^|\\n) {0,3}\\{:\\s*((?:\\\\\\}|[^\\}])*)\\s*\\}$/ );\n  if ( !m ) return undefined;\n\n  // process the meta hash\n  var attr = this.dialect.processMetaHash( m[ 2 ] );\n\n  var hash;\n\n  // if we matched ^ then we need to apply meta to the previous block\n  if ( m[ 1 ] === \"\" ) {\n    var node = this.tree[ this.tree.length - 1 ];\n    hash = extract_attr( node );\n\n    // if the node is a string (rather than JsonML), bail\n    if ( typeof node === \"string\" ) return undefined;\n\n    // create the attribute hash if it doesn't exist\n    if ( !hash ) {\n      hash = {};\n      node.splice( 1, 0, hash );\n    }\n\n    // add the attributes in\n    for ( a in attr ) {\n      hash[ a ] = attr[ a ];\n    }\n\n    // return nothing so the meta hash is removed\n    return [];\n  }\n\n  // pull the meta hash off the block and process what's left\n  var b = block.replace( /\\n.*$/, \"\" ),\n      result = this.processBlock( b, [] );\n\n  // get or make the attributes hash\n  hash = extract_attr( result[ 0 ] );\n  if ( !hash ) {\n    hash = {};\n    result[ 0 ].splice( 1, 0, hash );\n  }\n\n  // attach the attributes to the block\n  for ( a in attr ) {\n    hash[ a ] = attr[ a ];\n  }\n\n  return result;\n};\n\nMarkdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {\n  // one or more terms followed by one or more definitions, in a single block\n  var tight = /^((?:[^\\s:].*\\n)+):\\s+([\\s\\S]+)$/,\n      list = [ \"dl\" ],\n      i;\n\n  // see if we're dealing with a tight or loose block\n  if ( ( m = block.match( tight ) ) ) {\n    // pull subsequent tight DL blocks out of `next`\n    var blocks = [ block ];\n    while ( next.length && tight.exec( next[ 0 ] ) ) {\n      blocks.push( next.shift() );\n    }\n\n    for ( var b = 0; b < blocks.length; ++b ) {\n      var m = blocks[ b ].match( tight ),\n          terms = m[ 1 ].replace( /\\n$/, \"\" ).split( /\\n/ ),\n          defns = m[ 2 ].split( /\\n:\\s+/ );\n\n      // print( uneval( m ) );\n\n      for ( i = 0; i < terms.length; ++i ) {\n        list.push( [ \"dt\", terms[ i ] ] );\n      }\n\n      for ( i = 0; i < defns.length; ++i ) {\n        // run inline processing over the definition\n        list.push( [ \"dd\" ].concat( this.processInline( defns[ i ].replace( /(\\n)\\s+/, \"$1\" ) ) ) );\n      }\n    }\n  }\n  else {\n    return undefined;\n  }\n\n  return [ list ];\n};\n\nMarkdown.dialects.Maruku.inline[ \"{:\" ] = function inline_meta( text, matches, out ) {\n  if ( !out.length ) {\n    return [ 2, \"{:\" ];\n  }\n\n  // get the preceeding element\n  var before = out[ out.length - 1 ];\n\n  if ( typeof before === \"string\" ) {\n    return [ 2, \"{:\" ];\n  }\n\n  // match a meta hash\n  var m = text.match( /^\\{:\\s*((?:\\\\\\}|[^\\}])*)\\s*\\}/ );\n\n  // no match, false alarm\n  if ( !m ) {\n    return [ 2, \"{:\" ];\n  }\n\n  // attach the attributes to the preceeding element\n  var meta = this.dialect.processMetaHash( m[ 1 ] ),\n      attr = extract_attr( before );\n\n  if ( !attr ) {\n    attr = {};\n    before.splice( 1, 0, attr );\n  }\n\n  for ( var k in meta ) {\n    attr[ k ] = meta[ k ];\n  }\n\n  // cut out the string and replace it with nothing\n  return [ m[ 0 ].length, \"\" ];\n};\n\nMarkdown.buildBlockOrder ( Markdown.dialects.Maruku.block );\nMarkdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );\n\nvar isArray = Array.isArray || function(obj) {\n  return Object.prototype.toString.call(obj) == '[object Array]';\n};\n\nvar forEach;\n// Don't mess with Array.prototype. Its not friendly\nif ( Array.prototype.forEach ) {\n  forEach = function( arr, cb, thisp ) {\n    return arr.forEach( cb, thisp );\n  };\n}\nelse {\n  forEach = function(arr, cb, thisp) {\n    for (var i = 0; i < arr.length; i++) {\n      cb.call(thisp || arr, arr[i], i, arr);\n    }\n  }\n}\n\nfunction extract_attr( jsonml ) {\n  return isArray(jsonml)\n      && jsonml.length > 1\n      && typeof jsonml[ 1 ] === \"object\"\n      && !( isArray(jsonml[ 1 ]) )\n      ? jsonml[ 1 ]\n      : undefined;\n}\n\n\n\n/**\n *  renderJsonML( jsonml[, options] ) -> String\n *  - jsonml (Array): JsonML array to render to XML\n *  - options (Object): options\n *\n *  Converts the given JsonML into well-formed XML.\n *\n *  The options currently understood are:\n *\n *  - root (Boolean): wether or not the root node should be included in the\n *    output, or just its children. The default `false` is to not include the\n *    root itself.\n */\nexpose.renderJsonML = function( jsonml, options ) {\n  options = options || {};\n  // include the root element in the rendered output?\n  options.root = options.root || false;\n\n  var content = [];\n\n  if ( options.root ) {\n    content.push( render_tree( jsonml ) );\n  }\n  else {\n    jsonml.shift(); // get rid of the tag\n    if ( jsonml.length && typeof jsonml[ 0 ] === \"object\" && !( jsonml[ 0 ] instanceof Array ) ) {\n      jsonml.shift(); // get rid of the attributes\n    }\n\n    while ( jsonml.length ) {\n      content.push( render_tree( jsonml.shift() ) );\n    }\n  }\n\n  return content.join( \"\\n\\n\" );\n};\n\nfunction escapeHTML( text ) {\n  return text.replace( /&/g, \"&amp;\" )\n             .replace( /</g, \"&lt;\" )\n             .replace( />/g, \"&gt;\" )\n             .replace( /\"/g, \"&quot;\" )\n             .replace( /'/g, \"&#39;\" );\n}\n\nfunction render_tree( jsonml ) {\n  // basic case\n  if ( typeof jsonml === \"string\" ) {\n    return escapeHTML( jsonml );\n  }\n\n  var tag = jsonml.shift(),\n      attributes = {},\n      content = [];\n\n  if ( jsonml.length && typeof jsonml[ 0 ] === \"object\" && !( jsonml[ 0 ] instanceof Array ) ) {\n    attributes = jsonml.shift();\n  }\n\n  while ( jsonml.length ) {\n    content.push( arguments.callee( jsonml.shift() ) );\n  }\n\n  var tag_attrs = \"\";\n  for ( var a in attributes ) {\n    tag_attrs += \" \" + a + '=\"' + escapeHTML( attributes[ a ] ) + '\"';\n  }\n\n  // be careful about adding whitespace here for inline elements\n  if ( tag == \"img\" || tag == \"br\" || tag == \"hr\" ) {\n    return \"<\"+ tag + tag_attrs + \"/>\";\n  }\n  else {\n    return \"<\"+ tag + tag_attrs + \">\" + content.join( \"\" ) + \"</\" + tag + \">\";\n  }\n}\n\nfunction convert_tree_to_html( tree, references, options ) {\n  var i;\n  options = options || {};\n\n  // shallow clone\n  var jsonml = tree.slice( 0 );\n\n  if (typeof options.preprocessTreeNode === \"function\") {\n      jsonml = options.preprocessTreeNode(jsonml, references);\n  }\n\n  // Clone attributes if they exist\n  var attrs = extract_attr( jsonml );\n  if ( attrs ) {\n    jsonml[ 1 ] = {};\n    for ( i in attrs ) {\n      jsonml[ 1 ][ i ] = attrs[ i ];\n    }\n    attrs = jsonml[ 1 ];\n  }\n\n  // basic case\n  if ( typeof jsonml === \"string\" ) {\n    return jsonml;\n  }\n\n  // convert this node\n  switch ( jsonml[ 0 ] ) {\n    case \"header\":\n      jsonml[ 0 ] = \"h\" + jsonml[ 1 ].level;\n      delete jsonml[ 1 ].level;\n      break;\n    case \"bulletlist\":\n      jsonml[ 0 ] = \"ul\";\n      break;\n    case \"numberlist\":\n      jsonml[ 0 ] = \"ol\";\n      break;\n    case \"listitem\":\n      jsonml[ 0 ] = \"li\";\n      break;\n    case \"para\":\n      jsonml[ 0 ] = \"p\";\n      break;\n    case \"markdown\":\n      jsonml[ 0 ] = \"html\";\n      if ( attrs ) delete attrs.references;\n      break;\n    case \"code_block\":\n      jsonml[ 0 ] = \"pre\";\n      i = attrs ? 2 : 1;\n      var code = [ \"code\" ];\n      code.push.apply( code, jsonml.splice( i ) );\n      jsonml[ i ] = code;\n      break;\n    case \"inlinecode\":\n      jsonml[ 0 ] = \"code\";\n      break;\n    case \"img\":\n      jsonml[ 1 ].src = jsonml[ 1 ].href;\n      delete jsonml[ 1 ].href;\n      break;\n    case \"linebreak\":\n      jsonml[ 0 ] = \"br\";\n    break;\n    case \"link\":\n      jsonml[ 0 ] = \"a\";\n      break;\n    case \"link_ref\":\n      jsonml[ 0 ] = \"a\";\n\n      // grab this ref and clean up the attribute node\n      var ref = references[ attrs.ref ];\n\n      // if the reference exists, make the link\n      if ( ref ) {\n        delete attrs.ref;\n\n        // add in the href and title, if present\n        attrs.href = ref.href;\n        if ( ref.title ) {\n          attrs.title = ref.title;\n        }\n\n        // get rid of the unneeded original text\n        delete attrs.original;\n      }\n      // the reference doesn't exist, so revert to plain text\n      else {\n        return attrs.original;\n      }\n      break;\n    case \"img_ref\":\n      jsonml[ 0 ] = \"img\";\n\n      // grab this ref and clean up the attribute node\n      var ref = references[ attrs.ref ];\n\n      // if the reference exists, make the link\n      if ( ref ) {\n        delete attrs.ref;\n\n        // add in the href and title, if present\n        attrs.src = ref.href;\n        if ( ref.title ) {\n          attrs.title = ref.title;\n        }\n\n        // get rid of the unneeded original text\n        delete attrs.original;\n      }\n      // the reference doesn't exist, so revert to plain text\n      else {\n        return attrs.original;\n      }\n      break;\n  }\n\n  // convert all the children\n  i = 1;\n\n  // deal with the attribute node, if it exists\n  if ( attrs ) {\n    // if there are keys, skip over it\n    for ( var key in jsonml[ 1 ] ) {\n      i = 2;\n    }\n    // if there aren't, remove it\n    if ( i === 1 ) {\n      jsonml.splice( i, 1 );\n    }\n  }\n\n  for ( ; i < jsonml.length; ++i ) {\n    jsonml[ i ] = arguments.callee( jsonml[ i ], references, options );\n  }\n\n  return jsonml;\n}\n\n\n// merges adjacent text nodes into a single node\nfunction merge_text_nodes( jsonml ) {\n  // skip the tag name and attribute hash\n  var i = extract_attr( jsonml ) ? 2 : 1;\n\n  while ( i < jsonml.length ) {\n    // if it's a string check the next item too\n    if ( typeof jsonml[ i ] === \"string\" ) {\n      if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === \"string\" ) {\n        // merge the second string into the first and remove it\n        jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];\n      }\n      else {\n        ++i;\n      }\n    }\n    // if it's not a string recurse\n    else {\n      arguments.callee( jsonml[ i ] );\n      ++i;\n    }\n  }\n}\n\n} )( (function() {\n  if ( typeof exports === \"undefined\" ) {\n    window.markdown = {};\n    return window.markdown;\n  }\n  else {\n    return exports;\n  }\n} )() );\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/markdown/to-markdown.js",
    "content": "/*\n * to-markdown - an HTML to Markdown converter\n *\n * Copyright 2011, Dom Christie\n * Licenced under the MIT licence\n *\n */\n\nvar toMarkdown = function(string) {\n\n  var ELEMENTS = [\n    {\n      patterns: 'p',\n      replacement: function(str, attrs, innerHTML) {\n        return innerHTML ? '\\n\\n' + innerHTML + '\\n' : '';\n      }\n    },\n    {\n      patterns: 'br',\n      type: 'void',\n      replacement: '\\n'\n    },\n    {\n      patterns: 'h([1-6])',\n      replacement: function(str, hLevel, attrs, innerHTML) {\n        var hPrefix = '';\n        for(var i = 0; i < hLevel; i++) {\n          hPrefix += '#';\n        }\n        return '\\n\\n' + hPrefix + ' ' + innerHTML + '\\n';\n      }\n    },\n    {\n      patterns: 'hr',\n      type: 'void',\n      replacement: '\\n\\n* * *\\n'\n    },\n    {\n      patterns: 'a',\n      replacement: function(str, attrs, innerHTML) {\n        var href = attrs.match(attrRegExp('href')),\n            title = attrs.match(attrRegExp('title'));\n        return href ? '[' + innerHTML + ']' + '(' + href[1] + (title && title[1] ? ' \"' + title[1] + '\"' : '') + ')' : str;\n      }\n    },\n    {\n      patterns: ['b', 'strong'],\n      replacement: function(str, attrs, innerHTML) {\n        return innerHTML ? '**' + innerHTML + '**' : '';\n      }\n    },\n    {\n      patterns: ['i', 'em'],\n      replacement: function(str, attrs, innerHTML) {\n        return innerHTML ? '_' + innerHTML + '_' : '';\n      }\n    },\n    {\n      patterns: 'code',\n      replacement: function(str, attrs, innerHTML) {\n        return innerHTML ? '`' + innerHTML + '`' : '';\n      }\n    },\n    {\n      patterns: 'img',\n      type: 'void',\n      replacement: function(str, attrs, innerHTML) {\n        var src = attrs.match(attrRegExp('src')),\n            alt = attrs.match(attrRegExp('alt')),\n            title = attrs.match(attrRegExp('title'));\n        return '![' + (alt && alt[1] ? alt[1] : '') + ']' + '(' + src[1] + (title && title[1] ? ' \"' + title[1] + '\"' : '') + ')';\n      }\n    }\n  ];\n\n  for(var i = 0, len = ELEMENTS.length; i < len; i++) {\n    if(typeof ELEMENTS[i].patterns === 'string') {\n      string = replaceEls(string, { tag: ELEMENTS[i].patterns, replacement: ELEMENTS[i].replacement, type:  ELEMENTS[i].type });\n    }\n    else {\n      for(var j = 0, pLen = ELEMENTS[i].patterns.length; j < pLen; j++) {\n        string = replaceEls(string, { tag: ELEMENTS[i].patterns[j], replacement: ELEMENTS[i].replacement, type:  ELEMENTS[i].type });\n      }\n    }\n  }\n\n  function replaceEls(html, elProperties) {\n    var pattern = elProperties.type === 'void' ? '<' + elProperties.tag + '\\\\b([^>]*)\\\\/?>' : '<' + elProperties.tag + '\\\\b([^>]*)>([\\\\s\\\\S]*?)<\\\\/' + elProperties.tag + '>',\n        regex = new RegExp(pattern, 'gi'),\n        markdown = '';\n    if(typeof elProperties.replacement === 'string') {\n      markdown = html.replace(regex, elProperties.replacement);\n    }\n    else {\n      markdown = html.replace(regex, function(str, p1, p2, p3) {\n        return elProperties.replacement.call(this, str, p1, p2, p3);\n      });\n    }\n    return markdown;\n  }\n\n  function attrRegExp(attr) {\n    return new RegExp(attr + '\\\\s*=\\\\s*[\"\\']?([^\"\\']*)[\"\\']?', 'i');\n  }\n\n  // Pre code blocks\n\n  string = string.replace(/<pre\\b[^>]*>`([\\s\\S]*)`<\\/pre>/gi, function(str, innerHTML) {\n    innerHTML = innerHTML.replace(/^\\t+/g, '  '); // convert tabs to spaces (you know it makes sense)\n    innerHTML = innerHTML.replace(/\\n/g, '\\n    ');\n    return '\\n\\n    ' + innerHTML + '\\n';\n  });\n\n  // Lists\n\n  // Escape numbers that could trigger an ol\n  // If there are more than three spaces before the code, it would be in a pre tag\n  // Make sure we are escaping the period not matching any character\n  string = string.replace(/^(\\s{0,3}\\d+)\\. /g, '$1\\\\. ');\n\n  // Converts lists that have no child lists (of same type) first, then works it's way up\n  var noChildrenRegex = /<(ul|ol)\\b[^>]*>(?:(?!<ul|<ol)[\\s\\S])*?<\\/\\1>/gi;\n  while(string.match(noChildrenRegex)) {\n    string = string.replace(noChildrenRegex, function(str) {\n      return replaceLists(str);\n    });\n  }\n\n  function replaceLists(html) {\n\n    html = html.replace(/<(ul|ol)\\b[^>]*>([\\s\\S]*?)<\\/\\1>/gi, function(str, listType, innerHTML) {\n      var lis = innerHTML.split('</li>');\n      lis.splice(lis.length - 1, 1);\n\n      for(i = 0, len = lis.length; i < len; i++) {\n        if(lis[i]) {\n          var prefix = (listType === 'ol') ? (i + 1) + \".  \" : \"*   \";\n          lis[i] = lis[i].replace(/\\s*<li[^>]*>([\\s\\S]*)/i, function(str, innerHTML) {\n\n            innerHTML = innerHTML.replace(/^\\s+/, '');\n            innerHTML = innerHTML.replace(/\\n\\n/g, '\\n\\n    ');\n            // indent nested lists\n            innerHTML = innerHTML.replace(/\\n([ ]*)+(\\*|\\d+\\.) /g, '\\n$1    $2 ');\n            return prefix + innerHTML;\n          });\n        }\n      }\n      return lis.join('\\n');\n    });\n    return '\\n\\n' + html.replace(/[ \\t]+\\n|\\s+$/g, '');\n  }\n\n  // Blockquotes\n  var deepest = /<blockquote\\b[^>]*>((?:(?!<blockquote)[\\s\\S])*?)<\\/blockquote>/gi;\n  while(string.match(deepest)) {\n    string = string.replace(deepest, function(str) {\n      return replaceBlockquotes(str);\n    });\n  }\n\n  function replaceBlockquotes(html) {\n    html = html.replace(/<blockquote\\b[^>]*>([\\s\\S]*?)<\\/blockquote>/gi, function(str, inner) {\n      inner = inner.replace(/^\\s+|\\s+$/g, '');\n      inner = cleanUp(inner);\n      inner = inner.replace(/^/gm, '> ');\n      inner = inner.replace(/^(>([ \\t]{2,}>)+)/gm, '> >');\n      return inner;\n    });\n    return html;\n  }\n\n  function cleanUp(string) {\n    string = string.replace(/^[\\t\\r\\n]+|[\\t\\r\\n]+$/g, ''); // trim leading/trailing whitespace\n    string = string.replace(/\\n\\s+\\n/g, '\\n\\n');\n    string = string.replace(/\\n{3,}/g, '\\n\\n'); // limit consecutive linebreaks to 2\n    return string;\n  }\n\n  return cleanUp(string);\n};\n\nif (typeof exports === 'object') {\n  exports.toMarkdown = toMarkdown;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/metisMenu/jquery.metisMenu.js",
    "content": "/*\n * metismenu - v1.1.3\n * Easy menu jQuery plugin for Twitter Bootstrap 3\n * https://github.com/onokumus/metisMenu\n *\n * Made by Osman Nuri Okumus\n * Under MIT License\n */\n;(function($, window, document, undefined) {\n\n    var pluginName = \"metisMenu\",\n        defaults = {\n            toggle: true,\n            doubleTapToGo: false\n        };\n\n    function Plugin(element, options) {\n        this.element = $(element);\n        this.settings = $.extend({}, defaults, options);\n        this._defaults = defaults;\n        this._name = pluginName;\n        this.init();\n    }\n\n    Plugin.prototype = {\n        init: function() {\n\n            var $this = this.element,\n                $toggle = this.settings.toggle,\n                obj = this;\n\n            if (this.isIE() <= 9) {\n                $this.find(\"li.active\").has(\"ul\").children(\"ul\").collapse(\"show\");\n                $this.find(\"li\").not(\".active\").has(\"ul\").children(\"ul\").collapse(\"hide\");\n            } else {\n                $this.find(\"li.active\").has(\"ul\").children(\"ul\").addClass(\"collapse in\");\n                $this.find(\"li\").not(\".active\").has(\"ul\").children(\"ul\").addClass(\"collapse\");\n            }\n\n            //add the \"doubleTapToGo\" class to active items if needed\n            if (obj.settings.doubleTapToGo) {\n                $this.find(\"li.active\").has(\"ul\").children(\"a\").addClass(\"doubleTapToGo\");\n            }\n\n            $this.find(\"li\").has(\"ul\").children(\"a\").on(\"click\" + \".\" + pluginName, function(e) {\n                e.preventDefault();\n\n                //Do we need to enable the double tap\n                if (obj.settings.doubleTapToGo) {\n\n                    //if we hit a second time on the link and the href is valid, navigate to that url\n                    if (obj.doubleTapToGo($(this)) && $(this).attr(\"href\") !== \"#\" && $(this).attr(\"href\") !== \"\") {\n                        e.stopPropagation();\n                        document.location = $(this).attr(\"href\");\n                        return;\n                    }\n                }\n\n                $(this).parent(\"li\").toggleClass(\"active\").children(\"ul\").collapse(\"toggle\");\n\n                if ($toggle) {\n                    $(this).parent(\"li\").siblings().removeClass(\"active\").children(\"ul.in\").collapse(\"hide\");\n                }\n\n            });\n        },\n\n        isIE: function() { //https://gist.github.com/padolsey/527683\n            var undef,\n                v = 3,\n                div = document.createElement(\"div\"),\n                all = div.getElementsByTagName(\"i\");\n\n            while (\n                div.innerHTML = \"<!--[if gt IE \" + (++v) + \"]><i></i><![endif]-->\",\n                    all[0]\n                ) {\n                return v > 4 ? v : undef;\n            }\n        },\n\n        //Enable the link on the second click.\n        doubleTapToGo: function(elem) {\n            var $this = this.element;\n\n            //if the class \"doubleTapToGo\" exists, remove it and return\n            if (elem.hasClass(\"doubleTapToGo\")) {\n                elem.removeClass(\"doubleTapToGo\");\n                return true;\n            }\n\n            //does not exists, add a new class and return false\n            if (elem.parent().children(\"ul\").length) {\n                //first remove all other class\n                $this.find(\".doubleTapToGo\").removeClass(\"doubleTapToGo\");\n                //add the class on the current element\n                elem.addClass(\"doubleTapToGo\");\n                return false;\n            }\n        },\n\n        remove: function() {\n            this.element.off(\".\" + pluginName);\n            this.element.removeData(pluginName);\n        }\n\n    };\n\n    $.fn[pluginName] = function(options) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data(pluginName)) {\n                el.data(pluginName).remove();\n            }\n            el.data(pluginName, new Plugin(this, options));\n        });\n        return this;\n    };\n\n})(jQuery, window, document);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/morris/morris.js",
    "content": "(function() {\n  var $, Morris, minutesSpecHelper, secondsSpecHelper,\n    __slice = [].slice,\n    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n    __hasProp = {}.hasOwnProperty,\n    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\n  Morris = window.Morris = {};\n\n  $ = jQuery;\n\n  Morris.EventEmitter = (function() {\n    function EventEmitter() {}\n\n    EventEmitter.prototype.on = function(name, handler) {\n      if (this.handlers == null) {\n        this.handlers = {};\n      }\n      if (this.handlers[name] == null) {\n        this.handlers[name] = [];\n      }\n      this.handlers[name].push(handler);\n      return this;\n    };\n\n    EventEmitter.prototype.fire = function() {\n      var args, handler, name, _i, _len, _ref, _results;\n      name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n      if ((this.handlers != null) && (this.handlers[name] != null)) {\n        _ref = this.handlers[name];\n        _results = [];\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          handler = _ref[_i];\n          _results.push(handler.apply(null, args));\n        }\n        return _results;\n      }\n    };\n\n    return EventEmitter;\n\n  })();\n\n  Morris.commas = function(num) {\n    var absnum, intnum, ret, strabsnum;\n    if (num != null) {\n      ret = num < 0 ? \"-\" : \"\";\n      absnum = Math.abs(num);\n      intnum = Math.floor(absnum).toFixed(0);\n      ret += intnum.replace(/(?=(?:\\d{3})+$)(?!^)/g, ',');\n      strabsnum = absnum.toString();\n      if (strabsnum.length > intnum.length) {\n        ret += strabsnum.slice(intnum.length);\n      }\n      return ret;\n    } else {\n      return '-';\n    }\n  };\n\n  Morris.pad2 = function(number) {\n    return (number < 10 ? '0' : '') + number;\n  };\n\n  Morris.Grid = (function(_super) {\n    __extends(Grid, _super);\n\n    function Grid(options) {\n      this.resizeHandler = __bind(this.resizeHandler, this);\n      var _this = this;\n      if (typeof options.element === 'string') {\n        this.el = $(document.getElementById(options.element));\n      } else {\n        this.el = $(options.element);\n      }\n      if ((this.el == null) || this.el.length === 0) {\n        throw new Error(\"Graph container element not found\");\n      }\n      if (this.el.css('position') === 'static') {\n        this.el.css('position', 'relative');\n      }\n      this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options);\n      if (typeof this.options.units === 'string') {\n        this.options.postUnits = options.units;\n      }\n      this.raphael = new Raphael(this.el[0]);\n      this.elementWidth = null;\n      this.elementHeight = null;\n      this.dirty = false;\n      this.selectFrom = null;\n      if (this.init) {\n        this.init();\n      }\n      this.setData(this.options.data);\n      this.el.bind('mousemove', function(evt) {\n        var left, offset, right, width, x;\n        offset = _this.el.offset();\n        x = evt.pageX - offset.left;\n        if (_this.selectFrom) {\n          left = _this.data[_this.hitTest(Math.min(x, _this.selectFrom))]._x;\n          right = _this.data[_this.hitTest(Math.max(x, _this.selectFrom))]._x;\n          width = right - left;\n          return _this.selectionRect.attr({\n            x: left,\n            width: width\n          });\n        } else {\n          return _this.fire('hovermove', x, evt.pageY - offset.top);\n        }\n      });\n      this.el.bind('mouseleave', function(evt) {\n        if (_this.selectFrom) {\n          _this.selectionRect.hide();\n          _this.selectFrom = null;\n        }\n        return _this.fire('hoverout');\n      });\n      this.el.bind('touchstart touchmove touchend', function(evt) {\n        var offset, touch;\n        touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];\n        offset = _this.el.offset();\n        _this.fire('hover', touch.pageX - offset.left, touch.pageY - offset.top);\n        return touch;\n      });\n      this.el.bind('click', function(evt) {\n        var offset;\n        offset = _this.el.offset();\n        return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top);\n      });\n      if (this.options.rangeSelect) {\n        this.selectionRect = this.raphael.rect(0, 0, 0, this.el.innerHeight()).attr({\n          fill: this.options.rangeSelectColor,\n          stroke: false\n        }).toBack().hide();\n        this.el.bind('mousedown', function(evt) {\n          var offset;\n          offset = _this.el.offset();\n          return _this.startRange(evt.pageX - offset.left);\n        });\n        this.el.bind('mouseup', function(evt) {\n          var offset;\n          offset = _this.el.offset();\n          _this.endRange(evt.pageX - offset.left);\n          return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);\n        });\n      }\n      if (this.options.resize) {\n        $(window).bind('resize', function(evt) {\n          if (_this.timeoutId != null) {\n            window.clearTimeout(_this.timeoutId);\n          }\n          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);\n        });\n      }\n      if (this.postInit) {\n        this.postInit();\n      }\n    }\n\n    Grid.prototype.gridDefaults = {\n      dateFormat: null,\n      axes: true,\n      grid: true,\n      gridLineColor: '#aaa',\n      gridStrokeWidth: 0.5,\n      gridTextColor: '#888',\n      gridTextSize: 12,\n      gridTextFamily: 'sans-serif',\n      gridTextWeight: 'normal',\n      hideHover: false,\n      yLabelFormat: null,\n      xLabelAngle: 0,\n      numLines: 5,\n      padding: 25,\n      parseTime: true,\n      postUnits: '',\n      preUnits: '',\n      ymax: 'auto',\n      ymin: 'auto 0',\n      goals: [],\n      goalStrokeWidth: 1.0,\n      goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'],\n      events: [],\n      eventStrokeWidth: 1.0,\n      eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'],\n      rangeSelect: null,\n      rangeSelectColor: '#eef',\n      resize: false\n    };\n\n    Grid.prototype.setData = function(data, redraw) {\n      var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval, _ref;\n      if (redraw == null) {\n        redraw = true;\n      }\n      this.options.data = data;\n      if ((data == null) || data.length === 0) {\n        this.data = [];\n        this.raphael.clear();\n        if (this.hover != null) {\n          this.hover.hide();\n        }\n        return;\n      }\n      ymax = this.cumulative ? 0 : null;\n      ymin = this.cumulative ? 0 : null;\n      if (this.options.goals.length > 0) {\n        minGoal = Math.min.apply(Math, this.options.goals);\n        maxGoal = Math.max.apply(Math, this.options.goals);\n        ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;\n        ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;\n      }\n      this.data = (function() {\n        var _i, _len, _results;\n        _results = [];\n        for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) {\n          row = data[index];\n          ret = {\n            src: row\n          };\n          ret.label = row[this.options.xkey];\n          if (this.options.parseTime) {\n            ret.x = Morris.parseDate(ret.label);\n            if (this.options.dateFormat) {\n              ret.label = this.options.dateFormat(ret.x);\n            } else if (typeof ret.label === 'number') {\n              ret.label = new Date(ret.label).toString();\n            }\n          } else {\n            ret.x = index;\n            if (this.options.xLabelFormat) {\n              ret.label = this.options.xLabelFormat(ret);\n            }\n          }\n          total = 0;\n          ret.y = (function() {\n            var _j, _len1, _ref, _results1;\n            _ref = this.options.ykeys;\n            _results1 = [];\n            for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) {\n              ykey = _ref[idx];\n              yval = row[ykey];\n              if (typeof yval === 'string') {\n                yval = parseFloat(yval);\n              }\n              if ((yval != null) && typeof yval !== 'number') {\n                yval = null;\n              }\n              if (yval != null) {\n                if (this.cumulative) {\n                  total += yval;\n                } else {\n                  if (ymax != null) {\n                    ymax = Math.max(yval, ymax);\n                    ymin = Math.min(yval, ymin);\n                  } else {\n                    ymax = ymin = yval;\n                  }\n                }\n              }\n              if (this.cumulative && (total != null)) {\n                ymax = Math.max(total, ymax);\n                ymin = Math.min(total, ymin);\n              }\n              _results1.push(yval);\n            }\n            return _results1;\n          }).call(this);\n          _results.push(ret);\n        }\n        return _results;\n      }).call(this);\n      if (this.options.parseTime) {\n        this.data = this.data.sort(function(a, b) {\n          return (a.x > b.x) - (b.x > a.x);\n        });\n      }\n      this.xmin = this.data[0].x;\n      this.xmax = this.data[this.data.length - 1].x;\n      this.events = [];\n      if (this.options.events.length > 0) {\n        if (this.options.parseTime) {\n          this.events = (function() {\n            var _i, _len, _ref, _results;\n            _ref = this.options.events;\n            _results = [];\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n              e = _ref[_i];\n              _results.push(Morris.parseDate(e));\n            }\n            return _results;\n          }).call(this);\n        } else {\n          this.events = this.options.events;\n        }\n        this.xmax = Math.max(this.xmax, Math.max.apply(Math, this.events));\n        this.xmin = Math.min(this.xmin, Math.min.apply(Math, this.events));\n      }\n      if (this.xmin === this.xmax) {\n        this.xmin -= 1;\n        this.xmax += 1;\n      }\n      this.ymin = this.yboundary('min', ymin);\n      this.ymax = this.yboundary('max', ymax);\n      if (this.ymin === this.ymax) {\n        if (ymin) {\n          this.ymin -= 1;\n        }\n        this.ymax += 1;\n      }\n      if (((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') || this.options.grid === true) {\n        if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) {\n          this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines);\n          this.ymin = Math.min(this.ymin, this.grid[0]);\n          this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]);\n        } else {\n          step = (this.ymax - this.ymin) / (this.options.numLines - 1);\n          this.grid = (function() {\n            var _i, _ref1, _ref2, _results;\n            _results = [];\n            for (y = _i = _ref1 = this.ymin, _ref2 = this.ymax; step > 0 ? _i <= _ref2 : _i >= _ref2; y = _i += step) {\n              _results.push(y);\n            }\n            return _results;\n          }).call(this);\n        }\n      }\n      this.dirty = true;\n      if (redraw) {\n        return this.redraw();\n      }\n    };\n\n    Grid.prototype.yboundary = function(boundaryType, currentValue) {\n      var boundaryOption, suggestedValue;\n      boundaryOption = this.options[\"y\" + boundaryType];\n      if (typeof boundaryOption === 'string') {\n        if (boundaryOption.slice(0, 4) === 'auto') {\n          if (boundaryOption.length > 5) {\n            suggestedValue = parseInt(boundaryOption.slice(5), 10);\n            if (currentValue == null) {\n              return suggestedValue;\n            }\n            return Math[boundaryType](currentValue, suggestedValue);\n          } else {\n            if (currentValue != null) {\n              return currentValue;\n            } else {\n              return 0;\n            }\n          }\n        } else {\n          return parseInt(boundaryOption, 10);\n        }\n      } else {\n        return boundaryOption;\n      }\n    };\n\n    Grid.prototype.autoGridLines = function(ymin, ymax, nlines) {\n      var gmax, gmin, grid, smag, span, step, unit, y, ymag;\n      span = ymax - ymin;\n      ymag = Math.floor(Math.log(span) / Math.log(10));\n      unit = Math.pow(10, ymag);\n      gmin = Math.floor(ymin / unit) * unit;\n      gmax = Math.ceil(ymax / unit) * unit;\n      step = (gmax - gmin) / (nlines - 1);\n      if (unit === 1 && step > 1 && Math.ceil(step) !== step) {\n        step = Math.ceil(step);\n        gmax = gmin + step * (nlines - 1);\n      }\n      if (gmin < 0 && gmax > 0) {\n        gmin = Math.floor(ymin / step) * step;\n        gmax = Math.ceil(ymax / step) * step;\n      }\n      if (step < 1) {\n        smag = Math.floor(Math.log(step) / Math.log(10));\n        grid = (function() {\n          var _i, _results;\n          _results = [];\n          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {\n            _results.push(parseFloat(y.toFixed(1 - smag)));\n          }\n          return _results;\n        })();\n      } else {\n        grid = (function() {\n          var _i, _results;\n          _results = [];\n          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {\n            _results.push(y);\n          }\n          return _results;\n        })();\n      }\n      return grid;\n    };\n\n    Grid.prototype._calc = function() {\n      var bottomOffsets, gridLine, h, i, w, yLabelWidths, _ref, _ref1;\n      w = this.el.width();\n      h = this.el.height();\n      if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) {\n        this.elementWidth = w;\n        this.elementHeight = h;\n        this.dirty = false;\n        this.left = this.options.padding;\n        this.right = this.elementWidth - this.options.padding;\n        this.top = this.options.padding;\n        this.bottom = this.elementHeight - this.options.padding;\n        if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') {\n          yLabelWidths = (function() {\n            var _i, _len, _ref1, _results;\n            _ref1 = this.grid;\n            _results = [];\n            for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n              gridLine = _ref1[_i];\n              _results.push(this.measureText(this.yAxisFormat(gridLine)).width);\n            }\n            return _results;\n          }).call(this);\n          this.left += Math.max.apply(Math, yLabelWidths);\n        }\n        if ((_ref1 = this.options.axes) === true || _ref1 === 'both' || _ref1 === 'x') {\n          bottomOffsets = (function() {\n            var _i, _ref2, _results;\n            _results = [];\n            for (i = _i = 0, _ref2 = this.data.length; 0 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 0 <= _ref2 ? ++_i : --_i) {\n              _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height);\n            }\n            return _results;\n          }).call(this);\n          this.bottom -= Math.max.apply(Math, bottomOffsets);\n        }\n        this.width = Math.max(1, this.right - this.left);\n        this.height = Math.max(1, this.bottom - this.top);\n        this.dx = this.width / (this.xmax - this.xmin);\n        this.dy = this.height / (this.ymax - this.ymin);\n        if (this.calc) {\n          return this.calc();\n        }\n      }\n    };\n\n    Grid.prototype.transY = function(y) {\n      return this.bottom - (y - this.ymin) * this.dy;\n    };\n\n    Grid.prototype.transX = function(x) {\n      if (this.data.length === 1) {\n        return (this.left + this.right) / 2;\n      } else {\n        return this.left + (x - this.xmin) * this.dx;\n      }\n    };\n\n    Grid.prototype.redraw = function() {\n      this.raphael.clear();\n      this._calc();\n      this.drawGrid();\n      this.drawGoals();\n      this.drawEvents();\n      if (this.draw) {\n        return this.draw();\n      }\n    };\n\n    Grid.prototype.measureText = function(text, angle) {\n      var ret, tt;\n      if (angle == null) {\n        angle = 0;\n      }\n      tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle);\n      ret = tt.getBBox();\n      tt.remove();\n      return ret;\n    };\n\n    Grid.prototype.yAxisFormat = function(label) {\n      return this.yLabelFormat(label);\n    };\n\n    Grid.prototype.yLabelFormat = function(label) {\n      if (typeof this.options.yLabelFormat === 'function') {\n        return this.options.yLabelFormat(label);\n      } else {\n        return \"\" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;\n      }\n    };\n\n    Grid.prototype.drawGrid = function() {\n      var lineY, y, _i, _len, _ref, _ref1, _ref2, _results;\n      if (this.options.grid === false && ((_ref = this.options.axes) !== true && _ref !== 'both' && _ref !== 'y')) {\n        return;\n      }\n      _ref1 = this.grid;\n      _results = [];\n      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n        lineY = _ref1[_i];\n        y = this.transY(lineY);\n        if ((_ref2 = this.options.axes) === true || _ref2 === 'both' || _ref2 === 'y') {\n          this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY));\n        }\n        if (this.options.grid) {\n          _results.push(this.drawGridLine(\"M\" + this.left + \",\" + y + \"H\" + (this.left + this.width)));\n        } else {\n          _results.push(void 0);\n        }\n      }\n      return _results;\n    };\n\n    Grid.prototype.drawGoals = function() {\n      var color, goal, i, _i, _len, _ref, _results;\n      _ref = this.options.goals;\n      _results = [];\n      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n        goal = _ref[i];\n        color = this.options.goalLineColors[i % this.options.goalLineColors.length];\n        _results.push(this.drawGoal(goal, color));\n      }\n      return _results;\n    };\n\n    Grid.prototype.drawEvents = function() {\n      var color, event, i, _i, _len, _ref, _results;\n      _ref = this.events;\n      _results = [];\n      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n        event = _ref[i];\n        color = this.options.eventLineColors[i % this.options.eventLineColors.length];\n        _results.push(this.drawEvent(event, color));\n      }\n      return _results;\n    };\n\n    Grid.prototype.drawGoal = function(goal, color) {\n      return this.raphael.path(\"M\" + this.left + \",\" + (this.transY(goal)) + \"H\" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth);\n    };\n\n    Grid.prototype.drawEvent = function(event, color) {\n      return this.raphael.path(\"M\" + (this.transX(event)) + \",\" + this.bottom + \"V\" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth);\n    };\n\n    Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) {\n      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');\n    };\n\n    Grid.prototype.drawGridLine = function(path) {\n      return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);\n    };\n\n    Grid.prototype.startRange = function(x) {\n      this.hover.hide();\n      this.selectFrom = x;\n      return this.selectionRect.attr({\n        x: x,\n        width: 0\n      }).show();\n    };\n\n    Grid.prototype.endRange = function(x) {\n      var end, start;\n      if (this.selectFrom) {\n        start = Math.min(this.selectFrom, x);\n        end = Math.max(this.selectFrom, x);\n        this.options.rangeSelect.call(this.el, {\n          start: this.data[this.hitTest(start)].x,\n          end: this.data[this.hitTest(end)].x\n        });\n        return this.selectFrom = null;\n      }\n    };\n\n    Grid.prototype.resizeHandler = function() {\n      this.timeoutId = null;\n      this.raphael.setSize(this.el.width(), this.el.height());\n      return this.redraw();\n    };\n\n    return Grid;\n\n  })(Morris.EventEmitter);\n\n  Morris.parseDate = function(date) {\n    var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs;\n    if (typeof date === 'number') {\n      return date;\n    }\n    m = date.match(/^(\\d+) Q(\\d)$/);\n    n = date.match(/^(\\d+)-(\\d+)$/);\n    o = date.match(/^(\\d+)-(\\d+)-(\\d+)$/);\n    p = date.match(/^(\\d+) W(\\d+)$/);\n    q = date.match(/^(\\d+)-(\\d+)-(\\d+)[ T](\\d+):(\\d+)(Z|([+-])(\\d\\d):?(\\d\\d))?$/);\n    r = date.match(/^(\\d+)-(\\d+)-(\\d+)[ T](\\d+):(\\d+):(\\d+(\\.\\d+)?)(Z|([+-])(\\d\\d):?(\\d\\d))?$/);\n    if (m) {\n      return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime();\n    } else if (n) {\n      return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime();\n    } else if (o) {\n      return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime();\n    } else if (p) {\n      ret = new Date(parseInt(p[1], 10), 0, 1);\n      if (ret.getDay() !== 4) {\n        ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);\n      }\n      return ret.getTime() + parseInt(p[2], 10) * 604800000;\n    } else if (q) {\n      if (!q[6]) {\n        return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime();\n      } else {\n        offsetmins = 0;\n        if (q[6] !== 'Z') {\n          offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10);\n          if (q[7] === '+') {\n            offsetmins = 0 - offsetmins;\n          }\n        }\n        return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins);\n      }\n    } else if (r) {\n      secs = parseFloat(r[6]);\n      isecs = Math.floor(secs);\n      msecs = Math.round((secs - isecs) * 1000);\n      if (!r[8]) {\n        return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime();\n      } else {\n        offsetmins = 0;\n        if (r[8] !== 'Z') {\n          offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);\n          if (r[9] === '+') {\n            offsetmins = 0 - offsetmins;\n          }\n        }\n        return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs);\n      }\n    } else {\n      return new Date(parseInt(date, 10), 0, 1).getTime();\n    }\n  };\n\n  Morris.Hover = (function() {\n    Hover.defaults = {\n      \"class\": 'morris-hover morris-default-style'\n    };\n\n    function Hover(options) {\n      if (options == null) {\n        options = {};\n      }\n      this.options = $.extend({}, Morris.Hover.defaults, options);\n      this.el = $(\"<div class='\" + this.options[\"class\"] + \"'></div>\");\n      this.el.hide();\n      this.options.parent.append(this.el);\n    }\n\n    Hover.prototype.update = function(html, x, y) {\n      this.html;\n      this.show();\n      return this.moveTo(x, y);\n    };\n\n    Hover.prototype.html = function(content) {\n      return this.el.html(content);\n    };\n\n    Hover.prototype.moveTo = function(x, y) {\n      var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top;\n      parentWidth = this.options.parent.innerWidth();\n      parentHeight = this.options.parent.innerHeight();\n      hoverWidth = this.el.outerWidth();\n      hoverHeight = this.el.outerHeight();\n      left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth);\n      if (y != null) {\n        top = y - hoverHeight - 10;\n        if (top < 0) {\n          top = y + 10;\n          if (top + hoverHeight > parentHeight) {\n            top = parentHeight / 2 - hoverHeight / 2;\n          }\n        }\n      } else {\n        top = parentHeight / 2 - hoverHeight / 2;\n      }\n      return this.el.css({\n        left: left + \"px\",\n        top: parseInt(top) + \"px\"\n      });\n    };\n\n    Hover.prototype.show = function() {\n      return this.el.show();\n    };\n\n    Hover.prototype.hide = function() {\n      return this.el.hide();\n    };\n\n    return Hover;\n\n  })();\n\n  Morris.Line = (function(_super) {\n    __extends(Line, _super);\n\n    function Line(options) {\n      this.hilight = __bind(this.hilight, this);\n      this.onHoverOut = __bind(this.onHoverOut, this);\n      this.onHoverMove = __bind(this.onHoverMove, this);\n      this.onGridClick = __bind(this.onGridClick, this);\n      if (!(this instanceof Morris.Line)) {\n        return new Morris.Line(options);\n      }\n      Line.__super__.constructor.call(this, options);\n    }\n\n    Line.prototype.init = function() {\n      if (this.options.hideHover !== 'always') {\n        this.hover = new Morris.Hover({\n          parent: this.el\n        });\n        this.on('hovermove', this.onHoverMove);\n        this.on('hoverout', this.onHoverOut);\n        return this.on('gridclick', this.onGridClick);\n      }\n    };\n\n    Line.prototype.defaults = {\n      lineWidth: 3,\n      pointSize: 4,\n      lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],\n      pointStrokeWidths: [1],\n      pointStrokeColors: ['#ffffff'],\n      pointFillColors: [],\n      smooth: true,\n      xLabels: 'auto',\n      xLabelFormat: null,\n      xLabelMargin: 24,\n      continuousLine: true,\n      hideHover: false\n    };\n\n    Line.prototype.calc = function() {\n      this.calcPoints();\n      return this.generatePaths();\n    };\n\n    Line.prototype.calcPoints = function() {\n      var row, y, _i, _len, _ref, _results;\n      _ref = this.data;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        row = _ref[_i];\n        row._x = this.transX(row.x);\n        row._y = (function() {\n          var _j, _len1, _ref1, _results1;\n          _ref1 = row.y;\n          _results1 = [];\n          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n            y = _ref1[_j];\n            if (y != null) {\n              _results1.push(this.transY(y));\n            } else {\n              _results1.push(y);\n            }\n          }\n          return _results1;\n        }).call(this);\n        _results.push(row._ymax = Math.min.apply(Math, [this.bottom].concat((function() {\n          var _j, _len1, _ref1, _results1;\n          _ref1 = row._y;\n          _results1 = [];\n          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n            y = _ref1[_j];\n            if (y != null) {\n              _results1.push(y);\n            }\n          }\n          return _results1;\n        })())));\n      }\n      return _results;\n    };\n\n    Line.prototype.hitTest = function(x) {\n      var index, r, _i, _len, _ref;\n      if (this.data.length === 0) {\n        return null;\n      }\n      _ref = this.data.slice(1);\n      for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {\n        r = _ref[index];\n        if (x < (r._x + this.data[index]._x) / 2) {\n          break;\n        }\n      }\n      return index;\n    };\n\n    Line.prototype.onGridClick = function(x, y) {\n      var index;\n      index = this.hitTest(x);\n      return this.fire('click', index, this.data[index].src, x, y);\n    };\n\n    Line.prototype.onHoverMove = function(x, y) {\n      var index;\n      index = this.hitTest(x);\n      return this.displayHoverForRow(index);\n    };\n\n    Line.prototype.onHoverOut = function() {\n      if (this.options.hideHover !== false) {\n        return this.displayHoverForRow(null);\n      }\n    };\n\n    Line.prototype.displayHoverForRow = function(index) {\n      var _ref;\n      if (index != null) {\n        (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));\n        return this.hilight(index);\n      } else {\n        this.hover.hide();\n        return this.hilight();\n      }\n    };\n\n    Line.prototype.hoverContentForRow = function(index) {\n      var content, j, row, y, _i, _len, _ref;\n      row = this.data[index];\n      content = \"<div class='morris-hover-row-label'>\" + row.label + \"</div>\";\n      _ref = row.y;\n      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {\n        y = _ref[j];\n        content += \"<div class='morris-hover-point' style='color: \" + (this.colorFor(row, j, 'label')) + \"'>\\n  \" + this.options.labels[j] + \":\\n  \" + (this.yLabelFormat(y)) + \"\\n</div>\";\n      }\n      if (typeof this.options.hoverCallback === 'function') {\n        content = this.options.hoverCallback(index, this.options, content, row.src);\n      }\n      return [content, row._x, row._ymax];\n    };\n\n    Line.prototype.generatePaths = function() {\n      var c, coords, i, r, smooth;\n      return this.paths = (function() {\n        var _i, _ref, _ref1, _results;\n        _results = [];\n        for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n          smooth = typeof this.options.smooth === \"boolean\" ? this.options.smooth : (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0);\n          coords = (function() {\n            var _j, _len, _ref2, _results1;\n            _ref2 = this.data;\n            _results1 = [];\n            for (_j = 0, _len = _ref2.length; _j < _len; _j++) {\n              r = _ref2[_j];\n              if (r._y[i] !== void 0) {\n                _results1.push({\n                  x: r._x,\n                  y: r._y[i]\n                });\n              }\n            }\n            return _results1;\n          }).call(this);\n          if (this.options.continuousLine) {\n            coords = (function() {\n              var _j, _len, _results1;\n              _results1 = [];\n              for (_j = 0, _len = coords.length; _j < _len; _j++) {\n                c = coords[_j];\n                if (c.y !== null) {\n                  _results1.push(c);\n                }\n              }\n              return _results1;\n            })();\n          }\n          if (coords.length > 1) {\n            _results.push(Morris.Line.createPath(coords, smooth, this.bottom));\n          } else {\n            _results.push(null);\n          }\n        }\n        return _results;\n      }).call(this);\n    };\n\n    Line.prototype.draw = function() {\n      var _ref;\n      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {\n        this.drawXAxis();\n      }\n      this.drawSeries();\n      if (this.options.hideHover === false) {\n        return this.displayHoverForRow(this.data.length - 1);\n      }\n    };\n\n    Line.prototype.drawXAxis = function() {\n      var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results,\n        _this = this;\n      ypos = this.bottom + this.options.padding / 2;\n      prevLabelMargin = null;\n      prevAngleMargin = null;\n      drawLabel = function(labelText, xpos) {\n        var label, labelBox, margin, offset, textBox;\n        label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText);\n        textBox = label.getBBox();\n        label.transform(\"r\" + (-_this.options.xLabelAngle));\n        labelBox = label.getBBox();\n        label.transform(\"t0,\" + (labelBox.height / 2) + \"...\");\n        if (_this.options.xLabelAngle !== 0) {\n          offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0);\n          label.transform(\"t\" + offset + \",0...\");\n        }\n        labelBox = label.getBBox();\n        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) {\n          if (_this.options.xLabelAngle !== 0) {\n            margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0);\n            prevAngleMargin = labelBox.x - margin;\n          }\n          return prevLabelMargin = labelBox.x - _this.options.xLabelMargin;\n        } else {\n          return label.remove();\n        }\n      };\n      if (this.options.parseTime) {\n        if (this.data.length === 1 && this.options.xLabels === 'auto') {\n          labels = [[this.data[0].label, this.data[0].x]];\n        } else {\n          labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);\n        }\n      } else {\n        labels = (function() {\n          var _i, _len, _ref, _results;\n          _ref = this.data;\n          _results = [];\n          for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            row = _ref[_i];\n            _results.push([row.label, row.x]);\n          }\n          return _results;\n        }).call(this);\n      }\n      labels.reverse();\n      _results = [];\n      for (_i = 0, _len = labels.length; _i < _len; _i++) {\n        l = labels[_i];\n        _results.push(drawLabel(l[0], l[1]));\n      }\n      return _results;\n    };\n\n    Line.prototype.drawSeries = function() {\n      var i, _i, _j, _ref, _ref1, _results;\n      this.seriesPoints = [];\n      for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {\n        this._drawLineFor(i);\n      }\n      _results = [];\n      for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {\n        _results.push(this._drawPointFor(i));\n      }\n      return _results;\n    };\n\n    Line.prototype._drawPointFor = function(index) {\n      var circle, row, _i, _len, _ref, _results;\n      this.seriesPoints[index] = [];\n      _ref = this.data;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        row = _ref[_i];\n        circle = null;\n        if (row._y[index] != null) {\n          circle = this.drawLinePoint(row._x, row._y[index], this.colorFor(row, index, 'point'), index);\n        }\n        _results.push(this.seriesPoints[index].push(circle));\n      }\n      return _results;\n    };\n\n    Line.prototype._drawLineFor = function(index) {\n      var path;\n      path = this.paths[index];\n      if (path !== null) {\n        return this.drawLinePath(path, this.colorFor(null, index, 'line'), index);\n      }\n    };\n\n    Line.createPath = function(coords, smooth, bottom) {\n      var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;\n      path = \"\";\n      if (smooth) {\n        grads = Morris.Line.gradients(coords);\n      }\n      prevCoord = {\n        y: null\n      };\n      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {\n        coord = coords[i];\n        if (coord.y != null) {\n          if (prevCoord.y != null) {\n            if (smooth) {\n              g = grads[i];\n              lg = grads[i - 1];\n              ix = (coord.x - prevCoord.x) / 4;\n              x1 = prevCoord.x + ix;\n              y1 = Math.min(bottom, prevCoord.y + ix * lg);\n              x2 = coord.x - ix;\n              y2 = Math.min(bottom, coord.y - ix * g);\n              path += \"C\" + x1 + \",\" + y1 + \",\" + x2 + \",\" + y2 + \",\" + coord.x + \",\" + coord.y;\n            } else {\n              path += \"L\" + coord.x + \",\" + coord.y;\n            }\n          } else {\n            if (!smooth || (grads[i] != null)) {\n              path += \"M\" + coord.x + \",\" + coord.y;\n            }\n          }\n        }\n        prevCoord = coord;\n      }\n      return path;\n    };\n\n    Line.gradients = function(coords) {\n      var coord, grad, i, nextCoord, prevCoord, _i, _len, _results;\n      grad = function(a, b) {\n        return (a.y - b.y) / (a.x - b.x);\n      };\n      _results = [];\n      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {\n        coord = coords[i];\n        if (coord.y != null) {\n          nextCoord = coords[i + 1] || {\n            y: null\n          };\n          prevCoord = coords[i - 1] || {\n            y: null\n          };\n          if ((prevCoord.y != null) && (nextCoord.y != null)) {\n            _results.push(grad(prevCoord, nextCoord));\n          } else if (prevCoord.y != null) {\n            _results.push(grad(prevCoord, coord));\n          } else if (nextCoord.y != null) {\n            _results.push(grad(coord, nextCoord));\n          } else {\n            _results.push(null);\n          }\n        } else {\n          _results.push(null);\n        }\n      }\n      return _results;\n    };\n\n    Line.prototype.hilight = function(index) {\n      var i, _i, _j, _ref, _ref1;\n      if (this.prevHilight !== null && this.prevHilight !== index) {\n        for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {\n          if (this.seriesPoints[i][this.prevHilight]) {\n            this.seriesPoints[i][this.prevHilight].animate(this.pointShrinkSeries(i));\n          }\n        }\n      }\n      if (index !== null && this.prevHilight !== index) {\n        for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n          if (this.seriesPoints[i][index]) {\n            this.seriesPoints[i][index].animate(this.pointGrowSeries(i));\n          }\n        }\n      }\n      return this.prevHilight = index;\n    };\n\n    Line.prototype.colorFor = function(row, sidx, type) {\n      if (typeof this.options.lineColors === 'function') {\n        return this.options.lineColors.call(this, row, sidx, type);\n      } else if (type === 'point') {\n        return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length];\n      } else {\n        return this.options.lineColors[sidx % this.options.lineColors.length];\n      }\n    };\n\n    Line.prototype.drawXAxisLabel = function(xPos, yPos, text) {\n      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);\n    };\n\n    Line.prototype.drawLinePath = function(path, lineColor, lineIndex) {\n      return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.lineWidthForSeries(lineIndex));\n    };\n\n    Line.prototype.drawLinePoint = function(xPos, yPos, pointColor, lineIndex) {\n      return this.raphael.circle(xPos, yPos, this.pointSizeForSeries(lineIndex)).attr('fill', pointColor).attr('stroke-width', this.pointStrokeWidthForSeries(lineIndex)).attr('stroke', this.pointStrokeColorForSeries(lineIndex));\n    };\n\n    Line.prototype.pointStrokeWidthForSeries = function(index) {\n      return this.options.pointStrokeWidths[index % this.options.pointStrokeWidths.length];\n    };\n\n    Line.prototype.pointStrokeColorForSeries = function(index) {\n      return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length];\n    };\n\n    Line.prototype.lineWidthForSeries = function(index) {\n      if (this.options.lineWidth instanceof Array) {\n        return this.options.lineWidth[index % this.options.lineWidth.length];\n      } else {\n        return this.options.lineWidth;\n      }\n    };\n\n    Line.prototype.pointSizeForSeries = function(index) {\n      if (this.options.pointSize instanceof Array) {\n        return this.options.pointSize[index % this.options.pointSize.length];\n      } else {\n        return this.options.pointSize;\n      }\n    };\n\n    Line.prototype.pointGrowSeries = function(index) {\n      return Raphael.animation({\n        r: this.pointSizeForSeries(index) + 3\n      }, 25, 'linear');\n    };\n\n    Line.prototype.pointShrinkSeries = function(index) {\n      return Raphael.animation({\n        r: this.pointSizeForSeries(index)\n      }, 25, 'linear');\n    };\n\n    return Line;\n\n  })(Morris.Grid);\n\n  Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) {\n    var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;\n    ddensity = 200 * (dmax - dmin) / pxwidth;\n    d0 = new Date(dmin);\n    spec = Morris.LABEL_SPECS[specName];\n    if (spec === void 0) {\n      _ref = Morris.AUTO_LABEL_ORDER;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        name = _ref[_i];\n        s = Morris.LABEL_SPECS[name];\n        if (ddensity >= s.span) {\n          spec = s;\n          break;\n        }\n      }\n    }\n    if (spec === void 0) {\n      spec = Morris.LABEL_SPECS[\"second\"];\n    }\n    if (xLabelFormat) {\n      spec = $.extend({}, spec, {\n        fmt: xLabelFormat\n      });\n    }\n    d = spec.start(d0);\n    ret = [];\n    while ((t = d.getTime()) <= dmax) {\n      if (t >= dmin) {\n        ret.push([spec.fmt(d), t]);\n      }\n      spec.incr(d);\n    }\n    return ret;\n  };\n\n  minutesSpecHelper = function(interval) {\n    return {\n      span: interval * 60 * 1000,\n      start: function(d) {\n        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());\n      },\n      fmt: function(d) {\n        return \"\" + (Morris.pad2(d.getHours())) + \":\" + (Morris.pad2(d.getMinutes()));\n      },\n      incr: function(d) {\n        return d.setUTCMinutes(d.getUTCMinutes() + interval);\n      }\n    };\n  };\n\n  secondsSpecHelper = function(interval) {\n    return {\n      span: interval * 1000,\n      start: function(d) {\n        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());\n      },\n      fmt: function(d) {\n        return \"\" + (Morris.pad2(d.getHours())) + \":\" + (Morris.pad2(d.getMinutes())) + \":\" + (Morris.pad2(d.getSeconds()));\n      },\n      incr: function(d) {\n        return d.setUTCSeconds(d.getUTCSeconds() + interval);\n      }\n    };\n  };\n\n  Morris.LABEL_SPECS = {\n    \"decade\": {\n      span: 172800000000,\n      start: function(d) {\n        return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1);\n      },\n      fmt: function(d) {\n        return \"\" + (d.getFullYear());\n      },\n      incr: function(d) {\n        return d.setFullYear(d.getFullYear() + 10);\n      }\n    },\n    \"year\": {\n      span: 17280000000,\n      start: function(d) {\n        return new Date(d.getFullYear(), 0, 1);\n      },\n      fmt: function(d) {\n        return \"\" + (d.getFullYear());\n      },\n      incr: function(d) {\n        return d.setFullYear(d.getFullYear() + 1);\n      }\n    },\n    \"month\": {\n      span: 2419200000,\n      start: function(d) {\n        return new Date(d.getFullYear(), d.getMonth(), 1);\n      },\n      fmt: function(d) {\n        return \"\" + (d.getFullYear()) + \"-\" + (Morris.pad2(d.getMonth() + 1));\n      },\n      incr: function(d) {\n        return d.setMonth(d.getMonth() + 1);\n      }\n    },\n    \"week\": {\n      span: 604800000,\n      start: function(d) {\n        return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n      },\n      fmt: function(d) {\n        return \"\" + (d.getFullYear()) + \"-\" + (Morris.pad2(d.getMonth() + 1)) + \"-\" + (Morris.pad2(d.getDate()));\n      },\n      incr: function(d) {\n        return d.setDate(d.getDate() + 7);\n      }\n    },\n    \"day\": {\n      span: 86400000,\n      start: function(d) {\n        return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n      },\n      fmt: function(d) {\n        return \"\" + (d.getFullYear()) + \"-\" + (Morris.pad2(d.getMonth() + 1)) + \"-\" + (Morris.pad2(d.getDate()));\n      },\n      incr: function(d) {\n        return d.setDate(d.getDate() + 1);\n      }\n    },\n    \"hour\": minutesSpecHelper(60),\n    \"30min\": minutesSpecHelper(30),\n    \"15min\": minutesSpecHelper(15),\n    \"10min\": minutesSpecHelper(10),\n    \"5min\": minutesSpecHelper(5),\n    \"minute\": minutesSpecHelper(1),\n    \"30sec\": secondsSpecHelper(30),\n    \"15sec\": secondsSpecHelper(15),\n    \"10sec\": secondsSpecHelper(10),\n    \"5sec\": secondsSpecHelper(5),\n    \"second\": secondsSpecHelper(1)\n  };\n\n  Morris.AUTO_LABEL_ORDER = [\"decade\", \"year\", \"month\", \"week\", \"day\", \"hour\", \"30min\", \"15min\", \"10min\", \"5min\", \"minute\", \"30sec\", \"15sec\", \"10sec\", \"5sec\", \"second\"];\n\n  Morris.Area = (function(_super) {\n    var areaDefaults;\n\n    __extends(Area, _super);\n\n    areaDefaults = {\n      fillOpacity: 'auto',\n      behaveLikeLine: false\n    };\n\n    function Area(options) {\n      var areaOptions;\n      if (!(this instanceof Morris.Area)) {\n        return new Morris.Area(options);\n      }\n      areaOptions = $.extend({}, areaDefaults, options);\n      this.cumulative = !areaOptions.behaveLikeLine;\n      if (areaOptions.fillOpacity === 'auto') {\n        areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;\n      }\n      Area.__super__.constructor.call(this, areaOptions);\n    }\n\n    Area.prototype.calcPoints = function() {\n      var row, total, y, _i, _len, _ref, _results;\n      _ref = this.data;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        row = _ref[_i];\n        row._x = this.transX(row.x);\n        total = 0;\n        row._y = (function() {\n          var _j, _len1, _ref1, _results1;\n          _ref1 = row.y;\n          _results1 = [];\n          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n            y = _ref1[_j];\n            if (this.options.behaveLikeLine) {\n              _results1.push(this.transY(y));\n            } else {\n              total += y || 0;\n              _results1.push(this.transY(total));\n            }\n          }\n          return _results1;\n        }).call(this);\n        _results.push(row._ymax = Math.max.apply(Math, row._y));\n      }\n      return _results;\n    };\n\n    Area.prototype.drawSeries = function() {\n      var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;\n      this.seriesPoints = [];\n      if (this.options.behaveLikeLine) {\n        range = (function() {\n          _results = [];\n          for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }\n          return _results;\n        }).apply(this);\n      } else {\n        range = (function() {\n          _results1 = [];\n          for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }\n          return _results1;\n        }).apply(this);\n      }\n      _results2 = [];\n      for (_k = 0, _len = range.length; _k < _len; _k++) {\n        i = range[_k];\n        this._drawFillFor(i);\n        this._drawLineFor(i);\n        _results2.push(this._drawPointFor(i));\n      }\n      return _results2;\n    };\n\n    Area.prototype._drawFillFor = function(index) {\n      var path;\n      path = this.paths[index];\n      if (path !== null) {\n        path = path + (\"L\" + (this.transX(this.xmax)) + \",\" + this.bottom + \"L\" + (this.transX(this.xmin)) + \",\" + this.bottom + \"Z\");\n        return this.drawFilledPath(path, this.fillForSeries(index));\n      }\n    };\n\n    Area.prototype.fillForSeries = function(i) {\n      var color;\n      color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));\n      return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));\n    };\n\n    Area.prototype.drawFilledPath = function(path, fill) {\n      return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke', 'none');\n    };\n\n    return Area;\n\n  })(Morris.Line);\n\n  Morris.Bar = (function(_super) {\n    __extends(Bar, _super);\n\n    function Bar(options) {\n      this.onHoverOut = __bind(this.onHoverOut, this);\n      this.onHoverMove = __bind(this.onHoverMove, this);\n      this.onGridClick = __bind(this.onGridClick, this);\n      if (!(this instanceof Morris.Bar)) {\n        return new Morris.Bar(options);\n      }\n      Bar.__super__.constructor.call(this, $.extend({}, options, {\n        parseTime: false\n      }));\n    }\n\n    Bar.prototype.init = function() {\n      this.cumulative = this.options.stacked;\n      if (this.options.hideHover !== 'always') {\n        this.hover = new Morris.Hover({\n          parent: this.el\n        });\n        this.on('hovermove', this.onHoverMove);\n        this.on('hoverout', this.onHoverOut);\n        return this.on('gridclick', this.onGridClick);\n      }\n    };\n\n    Bar.prototype.defaults = {\n      barSizeRatio: 0.75,\n      barGap: 3,\n      barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],\n      barOpacity: 1.0,\n      barRadius: [0, 0, 0, 0],\n      xLabelMargin: 50\n    };\n\n    Bar.prototype.calc = function() {\n      var _ref;\n      this.calcBars();\n      if (this.options.hideHover === false) {\n        return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1));\n      }\n    };\n\n    Bar.prototype.calcBars = function() {\n      var idx, row, y, _i, _len, _ref, _results;\n      _ref = this.data;\n      _results = [];\n      for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {\n        row = _ref[idx];\n        row._x = this.left + this.width * (idx + 0.5) / this.data.length;\n        _results.push(row._y = (function() {\n          var _j, _len1, _ref1, _results1;\n          _ref1 = row.y;\n          _results1 = [];\n          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n            y = _ref1[_j];\n            if (y != null) {\n              _results1.push(this.transY(y));\n            } else {\n              _results1.push(null);\n            }\n          }\n          return _results1;\n        }).call(this));\n      }\n      return _results;\n    };\n\n    Bar.prototype.draw = function() {\n      var _ref;\n      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {\n        this.drawXAxis();\n      }\n      return this.drawSeries();\n    };\n\n    Bar.prototype.drawXAxis = function() {\n      var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;\n      ypos = this.bottom + (this.options.xAxisLabelTopPadding || this.options.padding / 2);\n      prevLabelMargin = null;\n      prevAngleMargin = null;\n      _results = [];\n      for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n        row = this.data[this.data.length - 1 - i];\n        label = this.drawXAxisLabel(row._x, ypos, row.label);\n        textBox = label.getBBox();\n        label.transform(\"r\" + (-this.options.xLabelAngle));\n        labelBox = label.getBBox();\n        label.transform(\"t0,\" + (labelBox.height / 2) + \"...\");\n        if (this.options.xLabelAngle !== 0) {\n          offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0);\n          label.transform(\"t\" + offset + \",0...\");\n        }\n        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) {\n          if (this.options.xLabelAngle !== 0) {\n            margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0);\n            prevAngleMargin = labelBox.x - margin;\n          }\n          _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin);\n        } else {\n          _results.push(label.remove());\n        }\n      }\n      return _results;\n    };\n\n    Bar.prototype.drawSeries = function() {\n      var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, top, ypos, zeroPos;\n      groupWidth = this.width / this.options.data.length;\n      numBars = this.options.stacked != null ? 1 : this.options.ykeys.length;\n      barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;\n      leftPadding = groupWidth * (1 - this.options.barSizeRatio) / 2;\n      zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;\n      return this.bars = (function() {\n        var _i, _len, _ref, _results;\n        _ref = this.data;\n        _results = [];\n        for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {\n          row = _ref[idx];\n          lastTop = 0;\n          _results.push((function() {\n            var _j, _len1, _ref1, _results1;\n            _ref1 = row._y;\n            _results1 = [];\n            for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {\n              ypos = _ref1[sidx];\n              if (ypos !== null) {\n                if (zeroPos) {\n                  top = Math.min(ypos, zeroPos);\n                  bottom = Math.max(ypos, zeroPos);\n                } else {\n                  top = ypos;\n                  bottom = this.bottom;\n                }\n                left = this.left + idx * groupWidth + leftPadding;\n                if (!this.options.stacked) {\n                  left += sidx * (barWidth + this.options.barGap);\n                }\n                size = bottom - top;\n                if (this.options.stacked) {\n                  top -= lastTop;\n                }\n                this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius);\n                _results1.push(lastTop += size);\n              } else {\n                _results1.push(null);\n              }\n            }\n            return _results1;\n          }).call(this));\n        }\n        return _results;\n      }).call(this);\n    };\n\n    Bar.prototype.colorFor = function(row, sidx, type) {\n      var r, s;\n      if (typeof this.options.barColors === 'function') {\n        r = {\n          x: row.x,\n          y: row.y[sidx],\n          label: row.label\n        };\n        s = {\n          index: sidx,\n          key: this.options.ykeys[sidx],\n          label: this.options.labels[sidx]\n        };\n        return this.options.barColors.call(this, r, s, type);\n      } else {\n        return this.options.barColors[sidx % this.options.barColors.length];\n      }\n    };\n\n    Bar.prototype.hitTest = function(x) {\n      if (this.data.length === 0) {\n        return null;\n      }\n      x = Math.max(Math.min(x, this.right), this.left);\n      return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length)));\n    };\n\n    Bar.prototype.onGridClick = function(x, y) {\n      var index;\n      index = this.hitTest(x);\n      return this.fire('click', index, this.data[index].src, x, y);\n    };\n\n    Bar.prototype.onHoverMove = function(x, y) {\n      var index, _ref;\n      index = this.hitTest(x);\n      return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));\n    };\n\n    Bar.prototype.onHoverOut = function() {\n      if (this.options.hideHover !== false) {\n        return this.hover.hide();\n      }\n    };\n\n    Bar.prototype.hoverContentForRow = function(index) {\n      var content, j, row, x, y, _i, _len, _ref;\n      row = this.data[index];\n      content = \"<div class='morris-hover-row-label'>\" + row.label + \"</div>\";\n      _ref = row.y;\n      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {\n        y = _ref[j];\n        content += \"<div class='morris-hover-point' style='color: \" + (this.colorFor(row, j, 'label')) + \"'>\\n  \" + this.options.labels[j] + \":\\n  \" + (this.yLabelFormat(y)) + \"\\n</div>\";\n      }\n      if (typeof this.options.hoverCallback === 'function') {\n        content = this.options.hoverCallback(index, this.options, content, row.src);\n      }\n      x = this.left + (index + 0.5) * this.width / this.data.length;\n      return [content, x];\n    };\n\n    Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) {\n      var label;\n      return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);\n    };\n\n    Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor, opacity, radiusArray) {\n      var maxRadius, path;\n      maxRadius = Math.max.apply(Math, radiusArray);\n      if (maxRadius === 0 || maxRadius > height) {\n        path = this.raphael.rect(xPos, yPos, width, height);\n      } else {\n        path = this.raphael.path(this.roundedRect(xPos, yPos, width, height, radiusArray));\n      }\n      return path.attr('fill', barColor).attr('fill-opacity', opacity).attr('stroke', 'none');\n    };\n\n    Bar.prototype.roundedRect = function(x, y, w, h, r) {\n      if (r == null) {\n        r = [0, 0, 0, 0];\n      }\n      return [\"M\", x, r[0] + y, \"Q\", x, y, x + r[0], y, \"L\", x + w - r[1], y, \"Q\", x + w, y, x + w, y + r[1], \"L\", x + w, y + h - r[2], \"Q\", x + w, y + h, x + w - r[2], y + h, \"L\", x + r[3], y + h, \"Q\", x, y + h, x, y + h - r[3], \"Z\"];\n    };\n\n    return Bar;\n\n  })(Morris.Grid);\n\n  Morris.Donut = (function(_super) {\n    __extends(Donut, _super);\n\n    Donut.prototype.defaults = {\n      colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],\n      backgroundColor: '#FFFFFF',\n      labelColor: '#000000',\n      formatter: Morris.commas,\n      resize: false\n    };\n\n    function Donut(options) {\n      this.resizeHandler = __bind(this.resizeHandler, this);\n      this.select = __bind(this.select, this);\n      this.click = __bind(this.click, this);\n      var _this = this;\n      if (!(this instanceof Morris.Donut)) {\n        return new Morris.Donut(options);\n      }\n      this.options = $.extend({}, this.defaults, options);\n      if (typeof options.element === 'string') {\n        this.el = $(document.getElementById(options.element));\n      } else {\n        this.el = $(options.element);\n      }\n      if (this.el === null || this.el.length === 0) {\n        throw new Error(\"Graph placeholder not found.\");\n      }\n      if (options.data === void 0 || options.data.length === 0) {\n        return;\n      }\n      this.raphael = new Raphael(this.el[0]);\n      if (this.options.resize) {\n        $(window).bind('resize', function(evt) {\n          if (_this.timeoutId != null) {\n            window.clearTimeout(_this.timeoutId);\n          }\n          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);\n        });\n      }\n      this.setData(options.data);\n    }\n\n    Donut.prototype.redraw = function() {\n      var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;\n      this.raphael.clear();\n      cx = this.el.width() / 2;\n      cy = this.el.height() / 2;\n      w = (Math.min(cx, cy) - 10) / 3;\n      total = 0;\n      _ref = this.values;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        value = _ref[_i];\n        total += value;\n      }\n      min = 5 / (2 * w);\n      C = 1.9999 * Math.PI - min * this.data.length;\n      last = 0;\n      idx = 0;\n      this.segments = [];\n      _ref1 = this.values;\n      for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {\n        value = _ref1[i];\n        next = last + min + C * (value / total);\n        seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);\n        seg.render();\n        this.segments.push(seg);\n        seg.on('hover', this.select);\n        seg.on('click', this.click);\n        last = next;\n        idx += 1;\n      }\n      this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);\n      this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);\n      max_value = Math.max.apply(Math, this.values);\n      idx = 0;\n      _ref2 = this.values;\n      _results = [];\n      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {\n        value = _ref2[_k];\n        if (value === max_value) {\n          this.select(idx);\n          break;\n        }\n        _results.push(idx += 1);\n      }\n      return _results;\n    };\n\n    Donut.prototype.setData = function(data) {\n      var row;\n      this.data = data;\n      this.values = (function() {\n        var _i, _len, _ref, _results;\n        _ref = this.data;\n        _results = [];\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          row = _ref[_i];\n          _results.push(parseFloat(row.value));\n        }\n        return _results;\n      }).call(this);\n      return this.redraw();\n    };\n\n    Donut.prototype.click = function(idx) {\n      return this.fire('click', idx, this.data[idx]);\n    };\n\n    Donut.prototype.select = function(idx) {\n      var row, s, segment, _i, _len, _ref;\n      _ref = this.segments;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        s = _ref[_i];\n        s.deselect();\n      }\n      segment = this.segments[idx];\n      segment.select();\n      row = this.data[idx];\n      return this.setLabels(row.label, this.options.formatter(row.value, row));\n    };\n\n    Donut.prototype.setLabels = function(label1, label2) {\n      var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale;\n      inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3;\n      maxWidth = 1.8 * inner;\n      maxHeightTop = inner / 2;\n      maxHeightBottom = inner / 3;\n      this.text1.attr({\n        text: label1,\n        transform: ''\n      });\n      text1bbox = this.text1.getBBox();\n      text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height);\n      this.text1.attr({\n        transform: \"S\" + text1scale + \",\" + text1scale + \",\" + (text1bbox.x + text1bbox.width / 2) + \",\" + (text1bbox.y + text1bbox.height)\n      });\n      this.text2.attr({\n        text: label2,\n        transform: ''\n      });\n      text2bbox = this.text2.getBBox();\n      text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height);\n      return this.text2.attr({\n        transform: \"S\" + text2scale + \",\" + text2scale + \",\" + (text2bbox.x + text2bbox.width / 2) + \",\" + text2bbox.y\n      });\n    };\n\n    Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) {\n      var text;\n      text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color);\n      if (fontWeight != null) {\n        text.attr('font-weight', fontWeight);\n      }\n      return text;\n    };\n\n    Donut.prototype.resizeHandler = function() {\n      this.timeoutId = null;\n      this.raphael.setSize(this.el.width(), this.el.height());\n      return this.redraw();\n    };\n\n    return Donut;\n\n  })(Morris.EventEmitter);\n\n  Morris.DonutSegment = (function(_super) {\n    __extends(DonutSegment, _super);\n\n    function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) {\n      this.cx = cx;\n      this.cy = cy;\n      this.inner = inner;\n      this.outer = outer;\n      this.color = color;\n      this.backgroundColor = backgroundColor;\n      this.index = index;\n      this.raphael = raphael;\n      this.deselect = __bind(this.deselect, this);\n      this.select = __bind(this.select, this);\n      this.sin_p0 = Math.sin(p0);\n      this.cos_p0 = Math.cos(p0);\n      this.sin_p1 = Math.sin(p1);\n      this.cos_p1 = Math.cos(p1);\n      this.is_long = (p1 - p0) > Math.PI ? 1 : 0;\n      this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5);\n      this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer);\n      this.hilight = this.calcArc(this.inner);\n    }\n\n    DonutSegment.prototype.calcArcPoints = function(r) {\n      return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1];\n    };\n\n    DonutSegment.prototype.calcSegment = function(r1, r2) {\n      var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1;\n      _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];\n      _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3];\n      return (\"M\" + ix0 + \",\" + iy0) + (\"A\" + r1 + \",\" + r1 + \",0,\" + this.is_long + \",0,\" + ix1 + \",\" + iy1) + (\"L\" + ox1 + \",\" + oy1) + (\"A\" + r2 + \",\" + r2 + \",0,\" + this.is_long + \",1,\" + ox0 + \",\" + oy0) + \"Z\";\n    };\n\n    DonutSegment.prototype.calcArc = function(r) {\n      var ix0, ix1, iy0, iy1, _ref;\n      _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];\n      return (\"M\" + ix0 + \",\" + iy0) + (\"A\" + r + \",\" + r + \",0,\" + this.is_long + \",0,\" + ix1 + \",\" + iy1);\n    };\n\n    DonutSegment.prototype.render = function() {\n      var _this = this;\n      this.arc = this.drawDonutArc(this.hilight, this.color);\n      return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() {\n        return _this.fire('hover', _this.index);\n      }, function() {\n        return _this.fire('click', _this.index);\n      });\n    };\n\n    DonutSegment.prototype.drawDonutArc = function(path, color) {\n      return this.raphael.path(path).attr({\n        stroke: color,\n        'stroke-width': 2,\n        opacity: 0\n      });\n    };\n\n    DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) {\n      return this.raphael.path(path).attr({\n        fill: fillColor,\n        stroke: strokeColor,\n        'stroke-width': 3\n      }).hover(hoverFunction).click(clickFunction);\n    };\n\n    DonutSegment.prototype.select = function() {\n      if (!this.selected) {\n        this.seg.animate({\n          path: this.selectedPath\n        }, 150, '<>');\n        this.arc.animate({\n          opacity: 1\n        }, 150, '<>');\n        return this.selected = true;\n      }\n    };\n\n    DonutSegment.prototype.deselect = function() {\n      if (this.selected) {\n        this.seg.animate({\n          path: this.path\n        }, 150, '<>');\n        this.arc.animate({\n          opacity: 0\n        }, 150, '<>');\n        return this.selected = false;\n      }\n    };\n\n    return DonutSegment;\n\n  })(Morris.EventEmitter);\n\n}).call(this);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/multiselect/bootstrap-multiselect.js",
    "content": "/**\n * Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect)\n *\n * Apache License, Version 2.0:\n * Copyright (c) 2012 - 2015 David Stutz\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * 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\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, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n *\n * BSD 3-Clause License:\n * Copyright (c) 2012 - 2015 David Stutz\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *    - Redistributions of source code must retain the above copyright notice,\n *      this list of conditions and the following disclaimer.\n *    - Redistributions in binary form must reproduce the above copyright notice,\n *      this list of conditions and the following disclaimer in the documentation\n *      and/or other materials provided with the distribution.\n *    - Neither the name of David Stutz nor the names of its contributors may be\n *      used to endorse or promote products derived from this software without\n *      specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n!function ($) {\n    \"use strict\";// jshint ;_;\n\n    if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {\n        ko.bindingHandlers.multiselect = {\n            after: ['options', 'value', 'selectedOptions'],\n\n            init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n                var $element = $(element);\n                var config = ko.toJS(valueAccessor());\n\n                $element.multiselect(config);\n\n                if (allBindings.has('options')) {\n                    var options = allBindings.get('options');\n                    if (ko.isObservable(options)) {\n                        ko.computed({\n                            read: function() {\n                                options();\n                                setTimeout(function() {\n                                    var ms = $element.data('multiselect');\n                                    if (ms)\n                                        ms.updateOriginalOptions();//Not sure how beneficial this is.\n                                    $element.multiselect('rebuild');\n                                }, 1);\n                            },\n                            disposeWhenNodeIsRemoved: element\n                        });\n                    }\n                }\n\n                //value and selectedOptions are two-way, so these will be triggered even by our own actions.\n                //It needs some way to tell if they are triggered because of us or because of outside change.\n                //It doesn't loop but it's a waste of processing.\n                if (allBindings.has('value')) {\n                    var value = allBindings.get('value');\n                    if (ko.isObservable(value)) {\n                        ko.computed({\n                            read: function() {\n                                value();\n                                setTimeout(function() {\n                                    $element.multiselect('refresh');\n                                }, 1);\n                            },\n                            disposeWhenNodeIsRemoved: element\n                        }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\n                    }\n                }\n\n                //Switched from arrayChange subscription to general subscription using 'refresh'.\n                //Not sure performance is any better using 'select' and 'deselect'.\n                if (allBindings.has('selectedOptions')) {\n                    var selectedOptions = allBindings.get('selectedOptions');\n                    if (ko.isObservable(selectedOptions)) {\n                        ko.computed({\n                            read: function() {\n                                selectedOptions();\n                                setTimeout(function() {\n                                    $element.multiselect('refresh');\n                                }, 1);\n                            },\n                            disposeWhenNodeIsRemoved: element\n                        }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\n                    }\n                }\n\n                ko.utils.domNodeDisposal.addDisposeCallback(element, function() {\n                    $element.multiselect('destroy');\n                });\n            },\n\n            update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n                var $element = $(element);\n                var config = ko.toJS(valueAccessor());\n\n                $element.multiselect('setOptions', config);\n                $element.multiselect('rebuild');\n            }\n        };\n    }\n\n    function forEach(array, callback) {\n        for (var index = 0; index < array.length; ++index) {\n            callback(array[index], index);\n        }\n    }\n\n    /**\n     * Constructor to create a new multiselect using the given select.\n     *\n     * @param {jQuery} select\n     * @param {Object} options\n     * @returns {Multiselect}\n     */\n    function Multiselect(select, options) {\n\n        this.$select = $(select);\n        this.options = this.mergeOptions($.extend({}, options, this.$select.data()));\n\n        // Initialization.\n        // We have to clone to create a new reference.\n        this.originalOptions = this.$select.clone()[0].options;\n        this.query = '';\n        this.searchTimeout = null;\n        this.lastToggledInput = null\n\n        this.options.multiple = this.$select.attr('multiple') === \"multiple\";\n        this.options.onChange = $.proxy(this.options.onChange, this);\n        this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);\n        this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);\n        this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this);\n        this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this);\n\n        // Build select all if enabled.\n        this.buildContainer();\n        this.buildButton();\n        this.buildDropdown();\n        this.buildSelectAll();\n        this.buildDropdownOptions();\n        this.buildFilter();\n\n        this.updateButtonText();\n        this.updateSelectAll();\n\n        if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {\n            this.disable();\n        }\n\n        this.$select.hide().after(this.$container);\n    };\n\n    Multiselect.prototype = {\n\n        defaults: {\n            /**\n             * Default text function will either print 'None selected' in case no\n             * option is selected or a list of the selected options up to a length\n             * of 3 selected options.\n             *\n             * @param {jQuery} options\n             * @param {jQuery} select\n             * @returns {String}\n             */\n            buttonText: function(options, select) {\n                if (options.length === 0) {\n                    return this.nonSelectedText;\n                }\n                else if (this.allSelectedText && options.length == $('option', $(select)).length) {\n                    if (this.selectAllNumber) {\n                        return this.allSelectedText + ' (' + options.length + ')';\n                    }\n                    else {\n                        return this.allSelectedText;\n                    }\n                }\n                else if (options.length > this.numberDisplayed) {\n                    return options.length + ' ' + this.nSelectedText;\n                }\n                else {\n                    var selected = '';\n                    options.each(function() {\n                        var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();\n\n                        selected += label + ', ';\n                    });\n\n                    return selected.substr(0, selected.length - 2);\n                }\n            },\n            /**\n             * Updates the title of the button similar to the buttonText function.\n             *\n             * @param {jQuery} options\n             * @param {jQuery} select\n             * @returns {@exp;selected@call;substr}\n             */\n            buttonTitle: function(options, select) {\n                if (options.length === 0) {\n                    return this.nonSelectedText;\n                }\n                else {\n                    var selected = '';\n                    options.each(function () {\n                        selected += $(this).text() + ', ';\n                    });\n                    return selected.substr(0, selected.length - 2);\n                }\n            },\n            /**\n             * Create a label.\n             *\n             * @param {jQuery} element\n             * @returns {String}\n             */\n            optionLabel: function(element){\n                return $(element).attr('label') || $(element).text();\n            },\n            /**\n             * Triggered on change of the multiselect.\n             *\n             * Not triggered when selecting/deselecting options manually.\n             *\n             * @param {jQuery} option\n             * @param {Boolean} checked\n             */\n            onChange : function(option, checked) {\n\n            },\n            /**\n             * Triggered when the dropdown is shown.\n             *\n             * @param {jQuery} event\n             */\n            onDropdownShow: function(event) {\n\n            },\n            /**\n             * Triggered when the dropdown is hidden.\n             *\n             * @param {jQuery} event\n             */\n            onDropdownHide: function(event) {\n\n            },\n            /**\n             * Triggered after the dropdown is shown.\n             *\n             * @param {jQuery} event\n             */\n            onDropdownShown: function(event) {\n\n            },\n            /**\n             * Triggered after the dropdown is hidden.\n             *\n             * @param {jQuery} event\n             */\n            onDropdownHidden: function(event) {\n\n            },\n            /**\n             * Triggered on select all.\n             */\n            onSelectAll: function() {\n\n            },\n            enableHTML: false,\n            buttonClass: 'btn btn-default',\n            inheritClass: false,\n            buttonWidth: 'auto',\n            buttonContainer: '<div class=\"btn-group\" />',\n            dropRight: false,\n            selectedClass: 'active',\n            // Maximum height of the dropdown menu.\n            // If maximum height is exceeded a scrollbar will be displayed.\n            maxHeight: false,\n            checkboxName: false,\n            includeSelectAllOption: false,\n            includeSelectAllIfMoreThan: 0,\n            selectAllText: ' Select all',\n            selectAllValue: 'multiselect-all',\n            selectAllName: false,\n            selectAllNumber: true,\n            enableFiltering: false,\n            enableCaseInsensitiveFiltering: false,\n            enableClickableOptGroups: false,\n            filterPlaceholder: 'Search',\n            // possible options: 'text', 'value', 'both'\n            filterBehavior: 'text',\n            includeFilterClearBtn: true,\n            preventInputChangeEvent: false,\n            nonSelectedText: 'None selected',\n            nSelectedText: 'selected',\n            allSelectedText: 'All selected',\n            numberDisplayed: 3,\n            disableIfEmpty: false,\n            templates: {\n                button: '<button type=\"button\" class=\"multiselect dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"multiselect-selected-text\"></span> <b class=\"caret\"></b></button>',\n                ul: '<ul class=\"multiselect-container dropdown-menu\"></ul>',\n                filter: '<li class=\"multiselect-item filter\"><div class=\"input-group\"><span class=\"input-group-addon\"><i class=\"glyphicon glyphicon-search\"></i></span><input class=\"form-control multiselect-search\" type=\"text\"></div></li>',\n                filterClearBtn: '<span class=\"input-group-btn\"><button class=\"btn btn-default multiselect-clear-filter\" type=\"button\"><i class=\"glyphicon glyphicon-remove-circle\"></i></button></span>',\n                li: '<li><a tabindex=\"0\"><label></label></a></li>',\n                divider: '<li class=\"multiselect-item divider\"></li>',\n                liGroup: '<li class=\"multiselect-item multiselect-group\"><label></label></li>'\n            }\n        },\n\n        constructor: Multiselect,\n\n        /**\n         * Builds the container of the multiselect.\n         */\n        buildContainer: function() {\n            this.$container = $(this.options.buttonContainer);\n            this.$container.on('show.bs.dropdown', this.options.onDropdownShow);\n            this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);\n            this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);\n            this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);\n        },\n\n        /**\n         * Builds the button of the multiselect.\n         */\n        buildButton: function() {\n            this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);\n            if (this.$select.attr('class') && this.options.inheritClass) {\n                this.$button.addClass(this.$select.attr('class'));\n            }\n            // Adopt active state.\n            if (this.$select.prop('disabled')) {\n                this.disable();\n            }\n            else {\n                this.enable();\n            }\n\n            // Manually add button width if set.\n            if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {\n                this.$button.css({\n                    'width' : this.options.buttonWidth,\n                    'overflow' : 'hidden',\n                    'text-overflow' : 'ellipsis'\n                });\n                this.$container.css({\n                    'width': this.options.buttonWidth\n                });\n            }\n\n            // Keep the tab index from the select.\n            var tabindex = this.$select.attr('tabindex');\n            if (tabindex) {\n                this.$button.attr('tabindex', tabindex);\n            }\n\n            this.$container.prepend(this.$button);\n        },\n\n        /**\n         * Builds the ul representing the dropdown menu.\n         */\n        buildDropdown: function() {\n\n            // Build ul.\n            this.$ul = $(this.options.templates.ul);\n\n            if (this.options.dropRight) {\n                this.$ul.addClass('pull-right');\n            }\n\n            // Set max height of dropdown menu to activate auto scrollbar.\n            if (this.options.maxHeight) {\n                // TODO: Add a class for this option to move the css declarations.\n                this.$ul.css({\n                    'max-height': this.options.maxHeight + 'px',\n                    'overflow-y': 'auto',\n                    'overflow-x': 'hidden'\n                });\n            }\n\n            this.$container.append(this.$ul);\n        },\n\n        /**\n         * Build the dropdown options and binds all nessecary events.\n         *\n         * Uses createDivider and createOptionValue to create the necessary options.\n         */\n        buildDropdownOptions: function() {\n\n            this.$select.children().each($.proxy(function(index, element) {\n\n                var $element = $(element);\n                // Support optgroups and options without a group simultaneously.\n                var tag = $element.prop('tagName')\n                    .toLowerCase();\n\n                if ($element.prop('value') === this.options.selectAllValue) {\n                    return;\n                }\n\n                if (tag === 'optgroup') {\n                    this.createOptgroup(element);\n                }\n                else if (tag === 'option') {\n\n                    if ($element.data('role') === 'divider') {\n                        this.createDivider();\n                    }\n                    else {\n                        this.createOptionValue(element);\n                    }\n\n                }\n\n                // Other illegal tags will be ignored.\n            }, this));\n\n            // Bind the change event on the dropdown elements.\n            $('li input', this.$ul).on('change', $.proxy(function(event) {\n                var $target = $(event.target);\n\n                var checked = $target.prop('checked') || false;\n                var isSelectAllOption = $target.val() === this.options.selectAllValue;\n\n                // Apply or unapply the configured selected class.\n                if (this.options.selectedClass) {\n                    if (checked) {\n                        $target.closest('li')\n                            .addClass(this.options.selectedClass);\n                    }\n                    else {\n                        $target.closest('li')\n                            .removeClass(this.options.selectedClass);\n                    }\n                }\n\n                // Get the corresponding option.\n                var value = $target.val();\n                var $option = this.getOptionByValue(value);\n\n                var $optionsNotThis = $('option', this.$select).not($option);\n                var $checkboxesNotThis = $('input', this.$container).not($target);\n\n                if (isSelectAllOption) {\n                    if (checked) {\n                        this.selectAll();\n                    }\n                    else {\n                        this.deselectAll();\n                    }\n                }\n\n                if(!isSelectAllOption){\n                    if (checked) {\n                        $option.prop('selected', true);\n\n                        if (this.options.multiple) {\n                            // Simply select additional option.\n                            $option.prop('selected', true);\n                        }\n                        else {\n                            // Unselect all other options and corresponding checkboxes.\n                            if (this.options.selectedClass) {\n                                $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass);\n                            }\n\n                            $($checkboxesNotThis).prop('checked', false);\n                            $optionsNotThis.prop('selected', false);\n\n                            // It's a single selection, so close.\n                            this.$button.click();\n                        }\n\n                        if (this.options.selectedClass === \"active\") {\n                            $optionsNotThis.closest(\"a\").css(\"outline\", \"\");\n                        }\n                    }\n                    else {\n                        // Unselect option.\n                        $option.prop('selected', false);\n                    }\n                }\n\n                this.$select.change();\n\n                this.updateButtonText();\n                this.updateSelectAll();\n\n                this.options.onChange($option, checked);\n\n                if(this.options.preventInputChangeEvent) {\n                    return false;\n                }\n            }, this));\n\n            $('li a', this.$ul).on('mousedown', function(e) {\n                if (e.shiftKey) {\n                    // Prevent selecting text by Shift+click\n                    return false;\n                }\n            });\n\n            $('li a', this.$ul).on('touchstart click', $.proxy(function(event) {\n                event.stopPropagation();\n\n                var $target = $(event.target);\n\n                if (event.shiftKey && this.options.multiple) {\n                    if($target.is(\"label\")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)\n                        event.preventDefault();\n                        $target = $target.find(\"input\");\n                        $target.prop(\"checked\", !$target.prop(\"checked\"));\n                    }\n                    var checked = $target.prop('checked') || false;\n\n                    if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range\n                        var from = $target.closest(\"li\").index();\n                        var to = this.lastToggledInput.closest(\"li\").index();\n\n                        if (from > to) { // Swap the indices\n                            var tmp = to;\n                            to = from;\n                            from = tmp;\n                        }\n\n                        // Make sure we grab all elements since slice excludes the last index\n                        ++to;\n\n                        // Change the checkboxes and underlying options\n                        var range = this.$ul.find(\"li\").slice(from, to).find(\"input\");\n\n                        range.prop('checked', checked);\n\n                        if (this.options.selectedClass) {\n                            range.closest('li')\n                                .toggleClass(this.options.selectedClass, checked);\n                        }\n\n                        for (var i = 0, j = range.length; i < j; i++) {\n                            var $checkbox = $(range[i]);\n\n                            var $option = this.getOptionByValue($checkbox.val());\n\n                            $option.prop('selected', checked);\n                        }\n                    }\n\n                    // Trigger the select \"change\" event\n                    $target.trigger(\"change\");\n                }\n\n                // Remembers last clicked option\n                if($target.is(\"input\") && !$target.closest(\"li\").is(\".multiselect-item\")){\n                    this.lastToggledInput = $target;\n                }\n\n                $target.blur();\n            }, this));\n\n            // Keyboard support.\n            this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {\n                if ($('input[type=\"text\"]', this.$container).is(':focus')) {\n                    return;\n                }\n\n                if (event.keyCode === 9 && this.$container.hasClass('open')) {\n                    this.$button.click();\n                }\n                else {\n                    var $items = $(this.$container).find(\"li:not(.divider):not(.disabled) a\").filter(\":visible\");\n\n                    if (!$items.length) {\n                        return;\n                    }\n\n                    var index = $items.index($items.filter(':focus'));\n\n                    // Navigation up.\n                    if (event.keyCode === 38 && index > 0) {\n                        index--;\n                    }\n                    // Navigate down.\n                    else if (event.keyCode === 40 && index < $items.length - 1) {\n                        index++;\n                    }\n                    else if (!~index) {\n                        index = 0;\n                    }\n\n                    var $current = $items.eq(index);\n                    $current.focus();\n\n                    if (event.keyCode === 32 || event.keyCode === 13) {\n                        var $checkbox = $current.find('input');\n\n                        $checkbox.prop(\"checked\", !$checkbox.prop(\"checked\"));\n                        $checkbox.change();\n                    }\n\n                    event.stopPropagation();\n                    event.preventDefault();\n                }\n            }, this));\n\n            if(this.options.enableClickableOptGroups && this.options.multiple) {\n                $('li.multiselect-group', this.$ul).on('click', $.proxy(function(event) {\n                    event.stopPropagation();\n\n                    var group = $(event.target).parent();\n\n                    // Search all option in optgroup\n                    var $options = group.nextUntil('li.multiselect-group');\n                    var $visibleOptions = $options.filter(\":visible:not(.disabled)\");\n\n                    // check or uncheck items\n                    var allChecked = true;\n                    var optionInputs = $visibleOptions.find('input');\n                    optionInputs.each(function() {\n                        allChecked = allChecked && $(this).prop('checked');\n                    });\n\n                    optionInputs.prop('checked', !allChecked).trigger('change');\n               }, this));\n            }\n        },\n\n        /**\n         * Create an option using the given select option.\n         *\n         * @param {jQuery} element\n         */\n        createOptionValue: function(element) {\n            var $element = $(element);\n            if ($element.is(':selected')) {\n                $element.prop('selected', true);\n            }\n\n            // Support the label attribute on options.\n            var label = this.options.optionLabel(element);\n            var value = $element.val();\n            var inputType = this.options.multiple ? \"checkbox\" : \"radio\";\n\n            var $li = $(this.options.templates.li);\n            var $label = $('label', $li);\n            $label.addClass(inputType);\n\n            if (this.options.enableHTML) {\n                $label.html(\" \" + label);\n            }\n            else {\n                $label.text(\" \" + label);\n            }\n\n            var $checkbox = $('<input/>').attr('type', inputType);\n\n            if (this.options.checkboxName) {\n                $checkbox.attr('name', this.options.checkboxName);\n            }\n            $label.prepend($checkbox);\n\n            var selected = $element.prop('selected') || false;\n            $checkbox.val(value);\n\n            if (value === this.options.selectAllValue) {\n                $li.addClass(\"multiselect-item multiselect-all\");\n                $checkbox.parent().parent()\n                    .addClass('multiselect-all');\n            }\n\n            $label.attr('title', $element.attr('title'));\n\n            this.$ul.append($li);\n\n            if ($element.is(':disabled')) {\n                $checkbox.attr('disabled', 'disabled')\n                    .prop('disabled', true)\n                    .closest('a')\n                    .attr(\"tabindex\", \"-1\")\n                    .closest('li')\n                    .addClass('disabled');\n            }\n\n            $checkbox.prop('checked', selected);\n\n            if (selected && this.options.selectedClass) {\n                $checkbox.closest('li')\n                    .addClass(this.options.selectedClass);\n            }\n        },\n\n        /**\n         * Creates a divider using the given select option.\n         *\n         * @param {jQuery} element\n         */\n        createDivider: function(element) {\n            var $divider = $(this.options.templates.divider);\n            this.$ul.append($divider);\n        },\n\n        /**\n         * Creates an optgroup.\n         *\n         * @param {jQuery} group\n         */\n        createOptgroup: function(group) {\n            var groupName = $(group).prop('label');\n\n            // Add a header for the group.\n            var $li = $(this.options.templates.liGroup);\n\n            if (this.options.enableHTML) {\n                $('label', $li).html(groupName);\n            }\n            else {\n                $('label', $li).text(groupName);\n            }\n\n            if (this.options.enableClickableOptGroups) {\n                $li.addClass('multiselect-group-clickable');\n            }\n\n            this.$ul.append($li);\n\n            if ($(group).is(':disabled')) {\n                $li.addClass('disabled');\n            }\n\n            // Add the options of the group.\n            $('option', group).each($.proxy(function(index, element) {\n                this.createOptionValue(element);\n            }, this));\n        },\n\n        /**\n         * Build the selct all.\n         *\n         * Checks if a select all has already been created.\n         */\n        buildSelectAll: function() {\n            if (typeof this.options.selectAllValue === 'number') {\n                this.options.selectAllValue = this.options.selectAllValue.toString();\n            }\n\n            var alreadyHasSelectAll = this.hasSelectAll();\n\n            if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple\n                    && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {\n\n                // Check whether to add a divider after the select all.\n                if (this.options.includeSelectAllDivider) {\n                    this.$ul.prepend($(this.options.templates.divider));\n                }\n\n                var $li = $(this.options.templates.li);\n                $('label', $li).addClass(\"checkbox\");\n\n                if (this.options.enableHTML) {\n                    $('label', $li).html(\" \" + this.options.selectAllText);\n                }\n                else {\n                    $('label', $li).text(\" \" + this.options.selectAllText);\n                }\n\n                if (this.options.selectAllName) {\n                    $('label', $li).prepend('<input type=\"checkbox\" name=\"' + this.options.selectAllName + '\" />');\n                }\n                else {\n                    $('label', $li).prepend('<input type=\"checkbox\" />');\n                }\n\n                var $checkbox = $('input', $li);\n                $checkbox.val(this.options.selectAllValue);\n\n                $li.addClass(\"multiselect-item multiselect-all\");\n                $checkbox.parent().parent()\n                    .addClass('multiselect-all');\n\n                this.$ul.prepend($li);\n\n                $checkbox.prop('checked', false);\n            }\n        },\n\n        /**\n         * Builds the filter.\n         */\n        buildFilter: function() {\n\n            // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.\n            if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {\n                var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);\n\n                if (this.$select.find('option').length >= enableFilterLength) {\n\n                    this.$filter = $(this.options.templates.filter);\n                    $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);\n\n                    // Adds optional filter clear button\n                    if(this.options.includeFilterClearBtn){\n                        var clearBtn = $(this.options.templates.filterClearBtn);\n                        clearBtn.on('click', $.proxy(function(event){\n                            clearTimeout(this.searchTimeout);\n                            this.$filter.find('.multiselect-search').val('');\n                            $('li', this.$ul).show().removeClass(\"filter-hidden\");\n                            this.updateSelectAll();\n                        }, this));\n                        this.$filter.find('.input-group').append(clearBtn);\n                    }\n\n                    this.$ul.prepend(this.$filter);\n\n                    this.$filter.val(this.query).on('click', function(event) {\n                        event.stopPropagation();\n                    }).on('input keydown', $.proxy(function(event) {\n                        // Cancel enter key default behaviour\n                        if (event.which === 13) {\n                          event.preventDefault();\n                        }\n\n                        // This is useful to catch \"keydown\" events after the browser has updated the control.\n                        clearTimeout(this.searchTimeout);\n\n                        this.searchTimeout = this.asyncFunction($.proxy(function() {\n\n                            if (this.query !== event.target.value) {\n                                this.query = event.target.value;\n\n                                var currentGroup, currentGroupVisible;\n                                $.each($('li', this.$ul), $.proxy(function(index, element) {\n                                    var value = $('input', element).length > 0 ? $('input', element).val() : \"\";\n                                    var text = $('label', element).text();\n\n                                    var filterCandidate = '';\n                                    if ((this.options.filterBehavior === 'text')) {\n                                        filterCandidate = text;\n                                    }\n                                    else if ((this.options.filterBehavior === 'value')) {\n                                        filterCandidate = value;\n                                    }\n                                    else if (this.options.filterBehavior === 'both') {\n                                        filterCandidate = text + '\\n' + value;\n                                    }\n\n                                    if (value !== this.options.selectAllValue && text) {\n                                        // By default lets assume that element is not\n                                        // interesting for this search.\n                                        var showElement = false;\n\n                                        if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {\n                                            showElement = true;\n                                        }\n                                        else if (filterCandidate.indexOf(this.query) > -1) {\n                                            showElement = true;\n                                        }\n\n                                        // Toggle current element (group or group item) according to showElement boolean.\n                                        $(element).toggle(showElement).toggleClass('filter-hidden', !showElement);\n\n                                        // Differentiate groups and group items.\n                                        if ($(element).hasClass('multiselect-group')) {\n                                            // Remember group status.\n                                            currentGroup = element;\n                                            currentGroupVisible = showElement;\n                                        }\n                                        else {\n                                            // Show group name when at least one of its items is visible.\n                                            if (showElement) {\n                                                $(currentGroup).show().removeClass('filter-hidden');\n                                            }\n\n                                            // Show all group items when group name satisfies filter.\n                                            if (!showElement && currentGroupVisible) {\n                                                $(element).show().removeClass('filter-hidden');\n                                            }\n                                        }\n                                    }\n                                }, this));\n                            }\n\n                            this.updateSelectAll();\n                        }, this), 300, this);\n                    }, this));\n                }\n            }\n        },\n\n        /**\n         * Unbinds the whole plugin.\n         */\n        destroy: function() {\n            this.$container.remove();\n            this.$select.show();\n            this.$select.data('multiselect', null);\n        },\n\n        /**\n         * Refreshs the multiselect based on the selected options of the select.\n         */\n        refresh: function() {\n            $('option', this.$select).each($.proxy(function(index, element) {\n                var $input = $('li input', this.$ul).filter(function() {\n                    return $(this).val() === $(element).val();\n                });\n\n                if ($(element).is(':selected')) {\n                    $input.prop('checked', true);\n\n                    if (this.options.selectedClass) {\n                        $input.closest('li')\n                            .addClass(this.options.selectedClass);\n                    }\n                }\n                else {\n                    $input.prop('checked', false);\n\n                    if (this.options.selectedClass) {\n                        $input.closest('li')\n                            .removeClass(this.options.selectedClass);\n                    }\n                }\n\n                if ($(element).is(\":disabled\")) {\n                    $input.attr('disabled', 'disabled')\n                        .prop('disabled', true)\n                        .closest('li')\n                        .addClass('disabled');\n                }\n                else {\n                    $input.prop('disabled', false)\n                        .closest('li')\n                        .removeClass('disabled');\n                }\n            }, this));\n\n            this.updateButtonText();\n            this.updateSelectAll();\n        },\n\n        /**\n         * Select all options of the given values.\n         *\n         * If triggerOnChange is set to true, the on change event is triggered if\n         * and only if one value is passed.\n         *\n         * @param {Array} selectValues\n         * @param {Boolean} triggerOnChange\n         */\n        select: function(selectValues, triggerOnChange) {\n            if(!$.isArray(selectValues)) {\n                selectValues = [selectValues];\n            }\n\n            for (var i = 0; i < selectValues.length; i++) {\n                var value = selectValues[i];\n\n                if (value === null || value === undefined) {\n                    continue;\n                }\n\n                var $option = this.getOptionByValue(value);\n                var $checkbox = this.getInputByValue(value);\n\n                if($option === undefined || $checkbox === undefined) {\n                    continue;\n                }\n\n                if (!this.options.multiple) {\n                    this.deselectAll(false);\n                }\n\n                if (this.options.selectedClass) {\n                    $checkbox.closest('li')\n                        .addClass(this.options.selectedClass);\n                }\n\n                $checkbox.prop('checked', true);\n                $option.prop('selected', true);\n            }\n\n            this.updateButtonText();\n            this.updateSelectAll();\n\n            if (triggerOnChange && selectValues.length === 1) {\n                this.options.onChange($option, true);\n            }\n        },\n\n        /**\n         * Clears all selected items.\n         */\n        clearSelection: function () {\n            this.deselectAll(false);\n            this.updateButtonText();\n            this.updateSelectAll();\n        },\n\n        /**\n         * Deselects all options of the given values.\n         *\n         * If triggerOnChange is set to true, the on change event is triggered, if\n         * and only if one value is passed.\n         *\n         * @param {Array} deselectValues\n         * @param {Boolean} triggerOnChange\n         */\n        deselect: function(deselectValues, triggerOnChange) {\n            if(!$.isArray(deselectValues)) {\n                deselectValues = [deselectValues];\n            }\n\n            for (var i = 0; i < deselectValues.length; i++) {\n                var value = deselectValues[i];\n\n                if (value === null || value === undefined) {\n                    continue;\n                }\n\n                var $option = this.getOptionByValue(value);\n                var $checkbox = this.getInputByValue(value);\n\n                if($option === undefined || $checkbox === undefined) {\n                    continue;\n                }\n\n                if (this.options.selectedClass) {\n                    $checkbox.closest('li')\n                        .removeClass(this.options.selectedClass);\n                }\n\n                $checkbox.prop('checked', false);\n                $option.prop('selected', false);\n            }\n\n            this.updateButtonText();\n            this.updateSelectAll();\n\n            if (triggerOnChange && deselectValues.length === 1) {\n                this.options.onChange($option, false);\n            }\n        },\n\n        /**\n         * Selects all enabled & visible options.\n         *\n         * If justVisible is true or not specified, only visible options are selected.\n         *\n         * @param {Boolean} justVisible\n         * @param {Boolean} triggerOnSelectAll\n         */\n        selectAll: function (justVisible, triggerOnSelectAll) {\n            var justVisible = typeof justVisible === 'undefined' ? true : justVisible;\n            var allCheckboxes = $(\"li input[type='checkbox']:enabled\", this.$ul);\n            var visibleCheckboxes = allCheckboxes.filter(\":visible\");\n            var allCheckboxesCount = allCheckboxes.length;\n            var visibleCheckboxesCount = visibleCheckboxes.length;\n\n            if(justVisible) {\n                visibleCheckboxes.prop('checked', true);\n                $(\"li:not(.divider):not(.disabled)\", this.$ul).filter(\":visible\").addClass(this.options.selectedClass);\n            }\n            else {\n                allCheckboxes.prop('checked', true);\n                $(\"li:not(.divider):not(.disabled)\", this.$ul).addClass(this.options.selectedClass);\n            }\n\n            if (allCheckboxesCount === visibleCheckboxesCount || justVisible === false) {\n                $(\"option:enabled\", this.$select).prop('selected', true);\n            }\n            else {\n                var values = visibleCheckboxes.map(function() {\n                    return $(this).val();\n                }).get();\n\n                $(\"option:enabled\", this.$select).filter(function(index) {\n                    return $.inArray($(this).val(), values) !== -1;\n                }).prop('selected', true);\n            }\n\n            if (triggerOnSelectAll) {\n                this.options.onSelectAll();\n            }\n        },\n\n        /**\n         * Deselects all options.\n         *\n         * If justVisible is true or not specified, only visible options are deselected.\n         *\n         * @param {Boolean} justVisible\n         */\n        deselectAll: function (justVisible) {\n            var justVisible = typeof justVisible === 'undefined' ? true : justVisible;\n\n            if(justVisible) {\n                var visibleCheckboxes = $(\"li input[type='checkbox']:not(:disabled)\", this.$ul).filter(\":visible\");\n                visibleCheckboxes.prop('checked', false);\n\n                var values = visibleCheckboxes.map(function() {\n                    return $(this).val();\n                }).get();\n\n                $(\"option:enabled\", this.$select).filter(function(index) {\n                    return $.inArray($(this).val(), values) !== -1;\n                }).prop('selected', false);\n\n                if (this.options.selectedClass) {\n                    $(\"li:not(.divider):not(.disabled)\", this.$ul).filter(\":visible\").removeClass(this.options.selectedClass);\n                }\n            }\n            else {\n                $(\"li input[type='checkbox']:enabled\", this.$ul).prop('checked', false);\n                $(\"option:enabled\", this.$select).prop('selected', false);\n\n                if (this.options.selectedClass) {\n                    $(\"li:not(.divider):not(.disabled)\", this.$ul).removeClass(this.options.selectedClass);\n                }\n            }\n        },\n\n        /**\n         * Rebuild the plugin.\n         *\n         * Rebuilds the dropdown, the filter and the select all option.\n         */\n        rebuild: function() {\n            this.$ul.html('');\n\n            // Important to distinguish between radios and checkboxes.\n            this.options.multiple = this.$select.attr('multiple') === \"multiple\";\n\n            this.buildSelectAll();\n            this.buildDropdownOptions();\n            this.buildFilter();\n\n            this.updateButtonText();\n            this.updateSelectAll();\n\n            if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {\n                this.disable();\n            }\n            else {\n                this.enable();\n            }\n\n            if (this.options.dropRight) {\n                this.$ul.addClass('pull-right');\n            }\n        },\n\n        /**\n         * The provided data will be used to build the dropdown.\n         */\n        dataprovider: function(dataprovider) {\n\n            var groupCounter = 0;\n            var $select = this.$select.empty();\n\n            $.each(dataprovider, function (index, option) {\n                var $tag;\n\n                if ($.isArray(option.children)) { // create optiongroup tag\n                    groupCounter++;\n\n                    $tag = $('<optgroup/>').attr({\n                        label: option.label || 'Group ' + groupCounter,\n                        disabled: !!option.disabled\n                    });\n\n                    forEach(option.children, function(subOption) { // add children option tags\n                        $tag.append($('<option/>').attr({\n                            value: subOption.value,\n                            label: subOption.label || subOption.value,\n                            title: subOption.title,\n                            selected: !!subOption.selected,\n                            disabled: !!subOption.disabled\n                        }));\n                    });\n                }\n                else {\n                    $tag = $('<option/>').attr({\n                        value: option.value,\n                        label: option.label || option.value,\n                        title: option.title,\n                        selected: !!option.selected,\n                        disabled: !!option.disabled\n                    });\n                }\n\n                $select.append($tag);\n            });\n\n            this.rebuild();\n        },\n\n        /**\n         * Enable the multiselect.\n         */\n        enable: function() {\n            this.$select.prop('disabled', false);\n            this.$button.prop('disabled', false)\n                .removeClass('disabled');\n        },\n\n        /**\n         * Disable the multiselect.\n         */\n        disable: function() {\n            this.$select.prop('disabled', true);\n            this.$button.prop('disabled', true)\n                .addClass('disabled');\n        },\n\n        /**\n         * Set the options.\n         *\n         * @param {Array} options\n         */\n        setOptions: function(options) {\n            this.options = this.mergeOptions(options);\n        },\n\n        /**\n         * Merges the given options with the default options.\n         *\n         * @param {Array} options\n         * @returns {Array}\n         */\n        mergeOptions: function(options) {\n            return $.extend(true, {}, this.defaults, this.options, options);\n        },\n\n        /**\n         * Checks whether a select all checkbox is present.\n         *\n         * @returns {Boolean}\n         */\n        hasSelectAll: function() {\n            return $('li.multiselect-all', this.$ul).length > 0;\n        },\n\n        /**\n         * Updates the select all checkbox based on the currently displayed and selected checkboxes.\n         */\n        updateSelectAll: function() {\n            if (this.hasSelectAll()) {\n                var allBoxes = $(\"li:not(.multiselect-item):not(.filter-hidden) input:enabled\", this.$ul);\n                var allBoxesLength = allBoxes.length;\n                var checkedBoxesLength = allBoxes.filter(\":checked\").length;\n                var selectAllLi  = $(\"li.multiselect-all\", this.$ul);\n                var selectAllInput = selectAllLi.find(\"input\");\n\n                if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {\n                    selectAllInput.prop(\"checked\", true);\n                    selectAllLi.addClass(this.options.selectedClass);\n                    this.options.onSelectAll();\n                }\n                else {\n                    selectAllInput.prop(\"checked\", false);\n                    selectAllLi.removeClass(this.options.selectedClass);\n                }\n            }\n        },\n\n        /**\n         * Update the button text and its title based on the currently selected options.\n         */\n        updateButtonText: function() {\n            var options = this.getSelected();\n\n            // First update the displayed button text.\n            if (this.options.enableHTML) {\n                $('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));\n            }\n            else {\n                $('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));\n            }\n\n            // Now update the title attribute of the button.\n            $('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));\n        },\n\n        /**\n         * Get all selected options.\n         *\n         * @returns {jQUery}\n         */\n        getSelected: function() {\n            return $('option', this.$select).filter(\":selected\");\n        },\n\n        /**\n         * Gets a select option by its value.\n         *\n         * @param {String} value\n         * @returns {jQuery}\n         */\n        getOptionByValue: function (value) {\n\n            var options = $('option', this.$select);\n            var valueToCompare = value.toString();\n\n            for (var i = 0; i < options.length; i = i + 1) {\n                var option = options[i];\n                if (option.value === valueToCompare) {\n                    return $(option);\n                }\n            }\n        },\n\n        /**\n         * Get the input (radio/checkbox) by its value.\n         *\n         * @param {String} value\n         * @returns {jQuery}\n         */\n        getInputByValue: function (value) {\n\n            var checkboxes = $('li input', this.$ul);\n            var valueToCompare = value.toString();\n\n            for (var i = 0; i < checkboxes.length; i = i + 1) {\n                var checkbox = checkboxes[i];\n                if (checkbox.value === valueToCompare) {\n                    return $(checkbox);\n                }\n            }\n        },\n\n        /**\n         * Used for knockout integration.\n         */\n        updateOriginalOptions: function() {\n            this.originalOptions = this.$select.clone()[0].options;\n        },\n\n        asyncFunction: function(callback, timeout, self) {\n            var args = Array.prototype.slice.call(arguments, 3);\n            return setTimeout(function() {\n                callback.apply(self || window, args);\n            }, timeout);\n        },\n\n        setAllSelectedText: function(allSelectedText) {\n            this.options.allSelectedText = allSelectedText;\n            this.updateButtonText();\n        }\n    };\n\n    $.fn.multiselect = function(option, parameter, extraOptions) {\n        return this.each(function() {\n            var data = $(this).data('multiselect');\n            var options = typeof option === 'object' && option;\n\n            // Initialize the multiselect.\n            if (!data) {\n                data = new Multiselect(this, options);\n                $(this).data('multiselect', data);\n            }\n\n            // Call multiselect method.\n            if (typeof option === 'string') {\n                data[option](parameter, extraOptions);\n\n                if (option === 'destroy') {\n                    $(this).data('multiselect', false);\n                }\n            }\n        });\n    };\n\n    $.fn.multiselect.Constructor = Multiselect;\n\n    $(function() {\n        $(\"select[data-role=multiselect]\").multiselect();\n    });\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/nestable/jquery.nestable.js",
    "content": "/*!\n * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/\n * Dual-licensed under the BSD or MIT licenses\n */\n;(function($, window, document, undefined)\n{\n    var hasTouch = 'ontouchstart' in document;\n\n    /**\n     * Detect CSS pointer-events property\n     * events are normally disabled on the dragging element to avoid conflicts\n     * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js\n     */\n    var hasPointerEvents = (function()\n    {\n        var el    = document.createElement('div'),\n            docEl = document.documentElement;\n        if (!('pointerEvents' in el.style)) {\n            return false;\n        }\n        el.style.pointerEvents = 'auto';\n        el.style.pointerEvents = 'x';\n        docEl.appendChild(el);\n        var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';\n        docEl.removeChild(el);\n        return !!supports;\n    })();\n\n    var defaults = {\n        listNodeName    : 'ol',\n        itemNodeName    : 'li',\n        rootClass       : 'dd',\n        listClass       : 'dd-list',\n        itemClass       : 'dd-item',\n        dragClass       : 'dd-dragel',\n        handleClass     : 'dd-handle',\n        collapsedClass  : 'dd-collapsed',\n        placeClass      : 'dd-placeholder',\n        noDragClass     : 'dd-nodrag',\n        emptyClass      : 'dd-empty',\n        expandBtnHTML   : '<button data-action=\"expand\" type=\"button\">展开</button>',\n        collapseBtnHTML : '<button data-action=\"collapse\" type=\"button\">关闭</button>',\n        group           : 0,\n        maxDepth        : 5,\n        threshold       : 20\n    };\n\n    function Plugin(element, options)\n    {\n        this.w  = $(document);\n        this.el = $(element);\n        this.options = $.extend({}, defaults, options);\n        this.init();\n    }\n\n    Plugin.prototype = {\n\n        init: function()\n        {\n            var list = this;\n\n            list.reset();\n\n            list.el.data('nestable-group', this.options.group);\n\n            list.placeEl = $('<div class=\"' + list.options.placeClass + '\"/>');\n\n            $.each(this.el.find(list.options.itemNodeName), function(k, el) {\n                list.setParent($(el));\n            });\n\n            list.el.on('click', 'button', function(e) {\n                if (list.dragEl) {\n                    return;\n                }\n                var target = $(e.currentTarget),\n                    action = target.data('action'),\n                    item   = target.parent(list.options.itemNodeName);\n                if (action === 'collapse') {\n                    list.collapseItem(item);\n                }\n                if (action === 'expand') {\n                    list.expandItem(item);\n                }\n            });\n\n            var onStartEvent = function(e)\n            {\n                var handle = $(e.target);\n                if (!handle.hasClass(list.options.handleClass)) {\n                    if (handle.closest('.' + list.options.noDragClass).length) {\n                        return;\n                    }\n                    handle = handle.closest('.' + list.options.handleClass);\n                }\n\n                if (!handle.length || list.dragEl) {\n                    return;\n                }\n\n                list.isTouch = /^touch/.test(e.type);\n                if (list.isTouch && e.touches.length !== 1) {\n                    return;\n                }\n\n                e.preventDefault();\n                list.dragStart(e.touches ? e.touches[0] : e);\n            };\n\n            var onMoveEvent = function(e)\n            {\n                if (list.dragEl) {\n                    e.preventDefault();\n                    list.dragMove(e.touches ? e.touches[0] : e);\n                }\n            };\n\n            var onEndEvent = function(e)\n            {\n                if (list.dragEl) {\n                    e.preventDefault();\n                    list.dragStop(e.touches ? e.touches[0] : e);\n                }\n            };\n\n            if (hasTouch) {\n                list.el[0].addEventListener('touchstart', onStartEvent, false);\n                window.addEventListener('touchmove', onMoveEvent, false);\n                window.addEventListener('touchend', onEndEvent, false);\n                window.addEventListener('touchcancel', onEndEvent, false);\n            }\n\n            list.el.on('mousedown', onStartEvent);\n            list.w.on('mousemove', onMoveEvent);\n            list.w.on('mouseup', onEndEvent);\n\n        },\n\n        serialize: function()\n        {\n            var data,\n                depth = 0,\n                list  = this;\n            step  = function(level, depth)\n            {\n                var array = [ ],\n                    items = level.children(list.options.itemNodeName);\n                items.each(function()\n                {\n                    var li   = $(this),\n                        item = $.extend({}, li.data()),\n                        sub  = li.children(list.options.listNodeName);\n                    if (sub.length) {\n                        item.children = step(sub, depth + 1);\n                    }\n                    array.push(item);\n                });\n                return array;\n            };\n            data = step(list.el.find(list.options.listNodeName).first(), depth);\n            return data;\n        },\n\n        serialise: function()\n        {\n            return this.serialize();\n        },\n\n        reset: function()\n        {\n            this.mouse = {\n                offsetX   : 0,\n                offsetY   : 0,\n                startX    : 0,\n                startY    : 0,\n                lastX     : 0,\n                lastY     : 0,\n                nowX      : 0,\n                nowY      : 0,\n                distX     : 0,\n                distY     : 0,\n                dirAx     : 0,\n                dirX      : 0,\n                dirY      : 0,\n                lastDirX  : 0,\n                lastDirY  : 0,\n                distAxX   : 0,\n                distAxY   : 0\n            };\n            this.isTouch    = false;\n            this.moving     = false;\n            this.dragEl     = null;\n            this.dragRootEl = null;\n            this.dragDepth  = 0;\n            this.hasNewRoot = false;\n            this.pointEl    = null;\n        },\n\n        expandItem: function(li)\n        {\n            li.removeClass(this.options.collapsedClass);\n            li.children('[data-action=\"expand\"]').hide();\n            li.children('[data-action=\"collapse\"]').show();\n            li.children(this.options.listNodeName).show();\n        },\n\n        collapseItem: function(li)\n        {\n            var lists = li.children(this.options.listNodeName);\n            if (lists.length) {\n                li.addClass(this.options.collapsedClass);\n                li.children('[data-action=\"collapse\"]').hide();\n                li.children('[data-action=\"expand\"]').show();\n                li.children(this.options.listNodeName).hide();\n            }\n        },\n\n        expandAll: function()\n        {\n            var list = this;\n            list.el.find(list.options.itemNodeName).each(function() {\n                list.expandItem($(this));\n            });\n        },\n\n        collapseAll: function()\n        {\n            var list = this;\n            list.el.find(list.options.itemNodeName).each(function() {\n                list.collapseItem($(this));\n            });\n        },\n\n        setParent: function(li)\n        {\n            if (li.children(this.options.listNodeName).length) {\n                li.prepend($(this.options.expandBtnHTML));\n                li.prepend($(this.options.collapseBtnHTML));\n            }\n            li.children('[data-action=\"expand\"]').hide();\n        },\n\n        unsetParent: function(li)\n        {\n            li.removeClass(this.options.collapsedClass);\n            li.children('[data-action]').remove();\n            li.children(this.options.listNodeName).remove();\n        },\n\n        dragStart: function(e)\n        {\n            var mouse    = this.mouse,\n                target   = $(e.target),\n                dragItem = target.closest(this.options.itemNodeName);\n\n            this.placeEl.css('height', dragItem.height());\n\n            mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;\n            mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;\n            mouse.startX = mouse.lastX = e.pageX;\n            mouse.startY = mouse.lastY = e.pageY;\n\n            this.dragRootEl = this.el;\n\n            this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);\n            this.dragEl.css('width', dragItem.width());\n\n            dragItem.after(this.placeEl);\n            dragItem[0].parentNode.removeChild(dragItem[0]);\n            dragItem.appendTo(this.dragEl);\n\n            $(document.body).append(this.dragEl);\n            this.dragEl.css({\n                'left' : e.pageX - mouse.offsetX,\n                'top'  : e.pageY - mouse.offsetY\n            });\n            // total depth of dragging item\n            var i, depth,\n                items = this.dragEl.find(this.options.itemNodeName);\n            for (i = 0; i < items.length; i++) {\n                depth = $(items[i]).parents(this.options.listNodeName).length;\n                if (depth > this.dragDepth) {\n                    this.dragDepth = depth;\n                }\n            }\n        },\n\n        dragStop: function(e)\n        {\n            var el = this.dragEl.children(this.options.itemNodeName).first();\n            el[0].parentNode.removeChild(el[0]);\n            this.placeEl.replaceWith(el);\n\n            this.dragEl.remove();\n            this.el.trigger('change');\n            if (this.hasNewRoot) {\n                this.dragRootEl.trigger('change');\n            }\n            this.reset();\n        },\n\n        dragMove: function(e)\n        {\n            var list, parent, prev, next, depth,\n                opt   = this.options,\n                mouse = this.mouse;\n\n            this.dragEl.css({\n                'left' : e.pageX - mouse.offsetX,\n                'top'  : e.pageY - mouse.offsetY\n            });\n\n            // mouse position last events\n            mouse.lastX = mouse.nowX;\n            mouse.lastY = mouse.nowY;\n            // mouse position this events\n            mouse.nowX  = e.pageX;\n            mouse.nowY  = e.pageY;\n            // distance mouse moved between events\n            mouse.distX = mouse.nowX - mouse.lastX;\n            mouse.distY = mouse.nowY - mouse.lastY;\n            // direction mouse was moving\n            mouse.lastDirX = mouse.dirX;\n            mouse.lastDirY = mouse.dirY;\n            // direction mouse is now moving (on both axis)\n            mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;\n            mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;\n            // axis mouse is now moving on\n            var newAx   = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;\n\n            // do nothing on first move\n            if (!mouse.moving) {\n                mouse.dirAx  = newAx;\n                mouse.moving = true;\n                return;\n            }\n\n            // calc distance moved on this axis (and direction)\n            if (mouse.dirAx !== newAx) {\n                mouse.distAxX = 0;\n                mouse.distAxY = 0;\n            } else {\n                mouse.distAxX += Math.abs(mouse.distX);\n                if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {\n                    mouse.distAxX = 0;\n                }\n                mouse.distAxY += Math.abs(mouse.distY);\n                if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {\n                    mouse.distAxY = 0;\n                }\n            }\n            mouse.dirAx = newAx;\n\n            /**\n             * move horizontal\n             */\n            if (mouse.dirAx && mouse.distAxX >= opt.threshold) {\n                // reset move distance on x-axis for new phase\n                mouse.distAxX = 0;\n                prev = this.placeEl.prev(opt.itemNodeName);\n                // increase horizontal level if previous sibling exists and is not collapsed\n                if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {\n                    // cannot increase level when item above is collapsed\n                    list = prev.find(opt.listNodeName).last();\n                    // check if depth limit has reached\n                    depth = this.placeEl.parents(opt.listNodeName).length;\n                    if (depth + this.dragDepth <= opt.maxDepth) {\n                        // create new sub-level if one doesn't exist\n                        if (!list.length) {\n                            list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);\n                            list.append(this.placeEl);\n                            prev.append(list);\n                            this.setParent(prev);\n                        } else {\n                            // else append to next level up\n                            list = prev.children(opt.listNodeName).last();\n                            list.append(this.placeEl);\n                        }\n                    }\n                }\n                // decrease horizontal level\n                if (mouse.distX < 0) {\n                    // we can't decrease a level if an item preceeds the current one\n                    next = this.placeEl.next(opt.itemNodeName);\n                    if (!next.length) {\n                        parent = this.placeEl.parent();\n                        this.placeEl.closest(opt.itemNodeName).after(this.placeEl);\n                        if (!parent.children().length) {\n                            this.unsetParent(parent.parent());\n                        }\n                    }\n                }\n            }\n\n            var isEmpty = false;\n\n            // find list item under cursor\n            if (!hasPointerEvents) {\n                this.dragEl[0].style.visibility = 'hidden';\n            }\n            this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));\n            if (!hasPointerEvents) {\n                this.dragEl[0].style.visibility = 'visible';\n            }\n            if (this.pointEl.hasClass(opt.handleClass)) {\n                this.pointEl = this.pointEl.parent(opt.itemNodeName);\n            }\n            if (this.pointEl.hasClass(opt.emptyClass)) {\n                isEmpty = true;\n            }\n            else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {\n                return;\n            }\n\n            // find parent list of item under cursor\n            var pointElRoot = this.pointEl.closest('.' + opt.rootClass),\n                isNewRoot   = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');\n\n            /**\n             * move vertical\n             */\n            if (!mouse.dirAx || isNewRoot || isEmpty) {\n                // check if groups match if dragging over new root\n                if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {\n                    return;\n                }\n                // check depth limit\n                depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;\n                if (depth > opt.maxDepth) {\n                    return;\n                }\n                var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);\n                parent = this.placeEl.parent();\n                // if empty create new list to replace empty placeholder\n                if (isEmpty) {\n                    list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);\n                    list.append(this.placeEl);\n                    this.pointEl.replaceWith(list);\n                }\n                else if (before) {\n                    this.pointEl.before(this.placeEl);\n                }\n                else {\n                    this.pointEl.after(this.placeEl);\n                }\n                if (!parent.children().length) {\n                    this.unsetParent(parent.parent());\n                }\n                if (!this.dragRootEl.find(opt.itemNodeName).length) {\n                    this.dragRootEl.append('<div class=\"' + opt.emptyClass + '\"/>');\n                }\n                // parent root list has changed\n                if (isNewRoot) {\n                    this.dragRootEl = pointElRoot;\n                    this.hasNewRoot = this.el[0] !== this.dragRootEl[0];\n                }\n            }\n        }\n\n    };\n\n    $.fn.nestable = function(params)\n    {\n        var lists  = this,\n            retval = this;\n\n        lists.each(function()\n        {\n            var plugin = $(this).data(\"nestable\");\n\n            if (!plugin) {\n                $(this).data(\"nestable\", new Plugin(this, params));\n                $(this).data(\"nestable-id\", new Date().getTime());\n            } else {\n                if (typeof params === 'string' && typeof plugin[params] === 'function') {\n                    retval = plugin[params]();\n                }\n            }\n        });\n\n        return retval || lists;\n    };\n\n})(window.jQuery || window.Zepto, window, document);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/plyr/plyr.js",
    "content": "// ==========================================================================\n// Plyr\n// plyr.js v1.3.6\n// https://github.com/selz/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n// Credits: http://paypal.github.io/accessible-html5-video-player/\n// ==========================================================================\n\n(function (api) {\n    'use strict';\n    /*global YT*/\n\n    // Globals\n    var fullscreen, config, callbacks = {\n        youtube: []\n    };\n\n    // Default config\n    var defaults = {\n        enabled: true,\n        debug: false,\n        seekTime: 10,\n        volume: 5,\n        click: true,\n        tooltips: true,\n        displayDuration: true,\n        iconPrefix: 'icon',\n        selectors: {\n            container: '.player',\n            controls: '.player-controls',\n            labels: '[data-player] .sr-only, label .sr-only',\n            buttons: {\n                seek: '[data-player=\"seek\"]',\n                play: '[data-player=\"play\"]',\n                pause: '[data-player=\"pause\"]',\n                restart: '[data-player=\"restart\"]',\n                rewind: '[data-player=\"rewind\"]',\n                forward: '[data-player=\"fast-forward\"]',\n                mute: '[data-player=\"mute\"]',\n                volume: '[data-player=\"volume\"]',\n                captions: '[data-player=\"captions\"]',\n                fullscreen: '[data-player=\"fullscreen\"]'\n            },\n            progress: {\n                container: '.player-progress',\n                buffer: '.player-progress-buffer',\n                played: '.player-progress-played'\n            },\n            captions: '.player-captions',\n            currentTime: '.player-current-time',\n            duration: '.player-duration'\n        },\n        classes: {\n            videoWrapper: 'player-video-wrapper',\n            embedWrapper: 'player-video-embed',\n            type: 'player-{0}',\n            stopped: 'stopped',\n            playing: 'playing',\n            muted: 'muted',\n            loading: 'loading',\n            tooltip: 'player-tooltip',\n            hidden: 'sr-only',\n            hover: 'player-hover',\n            captions: {\n                enabled: 'captions-enabled',\n                active: 'captions-active'\n            },\n            fullscreen: {\n                enabled: 'fullscreen-enabled',\n                active: 'fullscreen-active',\n                hideControls: 'fullscreen-hide-controls'\n            }\n        },\n        captions: {\n            defaultActive: false\n        },\n        fullscreen: {\n            enabled: true,\n            fallback: true,\n            hideControls: true\n        },\n        storage: {\n            enabled: true,\n            key: 'plyr_volume'\n        },\n        controls: ['restart', 'rewind', 'play', 'fast-forward', 'current-time', 'duration', 'mute', 'volume', /*'captions',*/ 'fullscreen'],\n        i18n: {\n            restart: '重新播放',\n            rewind: '后退{seektime}秒',\n            play: '播放',\n            pause: '暂停',\n            forward: '快进{seektime}秒',\n            played: '播放中',\n            buffered: '缓冲中',\n            currentTime: '当前时间',\n            duration: '持续时间',\n            volume: '音量',\n            toggleMute: '静音',\n            toggleCaptions: '字幕',\n            toggleFullscreen: '全屏'\n        }\n    };\n\n    // Build the default HTML\n    function _buildControls() {\n        // Open and add the progress and seek elements\n        var html = [\n        '<div class=\"player-controls\">',\n            '<div class=\"player-progress\">',\n                '<label for=\"seek{id}\" class=\"sr-only\">Seek</label>',\n                '<input id=\"seek{id}\" class=\"player-progress-seek\" type=\"range\" min=\"0\" max=\"100\" step=\"0.5\" value=\"0\" data-player=\"seek\">',\n                '<progress class=\"player-progress-played\" max=\"100\" value=\"0\">',\n                    '<span>0</span>% ' + config.i18n.played,\n                '</progress>',\n                '<progress class=\"player-progress-buffer\" max=\"100\" value=\"0\">',\n                    '<span>0</span>% ' + config.i18n.buffered,\n                '</progress>',\n            '</div>',\n            '<span class=\"player-controls-left\">'];\n\n        // Restart button\n        if (_inArray(config.controls, 'restart')) {\n            html.push(\n                '<button type=\"button\" data-player=\"restart\">',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-restart\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.restart + '</span>',\n                '</button>'\n            );\n        }\n\n        // Rewind button\n        if (_inArray(config.controls, 'rewind')) {\n            html.push(\n                '<button type=\"button\" data-player=\"rewind\">',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-rewind\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.rewind + '</span>',\n                '</button>'\n            );\n        }\n\n        // Play/pause button\n        if (_inArray(config.controls, 'play')) {\n            html.push(\n                '<button type=\"button\" data-player=\"play\">',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-play\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.play + '</span>',\n                '</button>',\n                '<button type=\"button\" data-player=\"pause\">',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-pause\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.pause + '</span>',\n                '</button>'\n            );\n        }\n\n        // Fast forward button\n        if (_inArray(config.controls, 'fast-forward')) {\n            html.push(\n                '<button type=\"button\" data-player=\"fast-forward\">',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-fast-forward\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.forward + '</span>',\n                '</button>'\n            );\n        }\n\n        // Media current time display\n        if (_inArray(config.controls, 'current-time')) {\n            html.push(\n                '<span class=\"player-time\">',\n                '<span class=\"sr-only\">' + config.i18n.currentTime + '</span>',\n                '<span class=\"player-current-time\">00:00</span>',\n                '</span>'\n            );\n        }\n\n        // Media duration display\n        if (_inArray(config.controls, 'duration')) {\n            html.push(\n                '<span class=\"player-time\">',\n                '<span class=\"sr-only\">' + config.i18n.duration + '</span>',\n                '<span class=\"player-duration\">00:00</span>',\n                '</span>'\n            );\n        }\n\n        // Close left controls\n        html.push(\n            '</span>',\n            '<span class=\"player-controls-right\">'\n        );\n\n        // Toggle mute button\n        if (_inArray(config.controls, 'mute')) {\n            html.push(\n                '<button type=\"button\" data-player=\"mute\">',\n                '<svg class=\"icon-muted\"><use xlink:href=\"#' + config.iconPrefix + '-muted\" /></svg>',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-volume\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.toggleMute + '</span>',\n                '</button>'\n            );\n        }\n\n        // Volume range control\n        if (_inArray(config.controls, 'volume')) {\n            html.push(\n                '<label for=\"volume{id}\" class=\"sr-only\">' + config.i18n.volume + '</label>',\n                '<input id=\"volume{id}\" class=\"player-volume\" type=\"range\" min=\"0\" max=\"10\" value=\"5\" data-player=\"volume\">'\n            );\n        }\n\n        // Toggle captions button\n        if (_inArray(config.controls, 'captions')) {\n            html.push(\n                '<button type=\"button\" data-player=\"captions\">',\n                '<svg class=\"icon-captions-on\"><use xlink:href=\"#' + config.iconPrefix + '-captions-on\" /></svg>',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-captions-off\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.toggleCaptions + '</span>',\n                '</button>'\n            );\n        }\n\n        // Toggle fullscreen button\n        if (_inArray(config.controls, 'fullscreen')) {\n            html.push(\n                '<button type=\"button\" data-player=\"fullscreen\">',\n                '<svg class=\"icon-exit-fullscreen\"><use xlink:href=\"#' + config.iconPrefix + '-exit-fullscreen\" /></svg>',\n                '<svg><use xlink:href=\"#' + config.iconPrefix + '-enter-fullscreen\" /></svg>',\n                '<span class=\"sr-only\">' + config.i18n.toggleFullscreen + '</span>',\n                '</button>'\n            );\n        }\n\n        // Close everything\n        html.push(\n            '</span>',\n            '</div>'\n        );\n\n        return html.join('');\n    }\n\n    // Debugging\n    function _log(text, error) {\n        if (config.debug && window.console) {\n            console[(error ? 'error' : 'log')](text);\n        }\n    }\n\n    // Credits: http://paypal.github.io/accessible-html5-video-player/\n    // Unfortunately, due to mixed support, UA sniffing is required\n    function _browserSniff() {\n        var nAgt = navigator.userAgent,\n            name = navigator.appName,\n            fullVersion = '' + parseFloat(navigator.appVersion),\n            majorVersion = parseInt(navigator.appVersion, 10),\n            nameOffset,\n            verOffset,\n            ix;\n\n        // MSIE 11\n        if ((navigator.appVersion.indexOf('Windows NT') !== -1) && (navigator.appVersion.indexOf('rv:11') !== -1)) {\n            name = 'IE';\n            fullVersion = '11;';\n        }\n        // MSIE\n        else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) {\n            name = 'IE';\n            fullVersion = nAgt.substring(verOffset + 5);\n        }\n        // Chrome\n        else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) {\n            name = 'Chrome';\n            fullVersion = nAgt.substring(verOffset + 7);\n        }\n        // Safari\n        else if ((verOffset = nAgt.indexOf('Safari')) !== -1) {\n            name = 'Safari';\n            fullVersion = nAgt.substring(verOffset + 7);\n            if ((verOffset = nAgt.indexOf('Version')) !== -1) {\n                fullVersion = nAgt.substring(verOffset + 8);\n            }\n        }\n        // Firefox\n        else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) {\n            name = 'Firefox';\n            fullVersion = nAgt.substring(verOffset + 8);\n        }\n        // In most other browsers, 'name/version' is at the end of userAgent\n        else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {\n            name = nAgt.substring(nameOffset, verOffset);\n            fullVersion = nAgt.substring(verOffset + 1);\n\n            if (name.toLowerCase() == name.toUpperCase()) {\n                name = navigator.appName;\n            }\n        }\n        // Trim the fullVersion string at semicolon/space if present\n        if ((ix = fullVersion.indexOf(';')) !== -1) {\n            fullVersion = fullVersion.substring(0, ix);\n        }\n        if ((ix = fullVersion.indexOf(' ')) !== -1) {\n            fullVersion = fullVersion.substring(0, ix);\n        }\n        // Get major version\n        majorVersion = parseInt('' + fullVersion, 10);\n        if (isNaN(majorVersion)) {\n            fullVersion = '' + parseFloat(navigator.appVersion);\n            majorVersion = parseInt(navigator.appVersion, 10);\n        }\n\n        // Return data\n        return {\n            name: name,\n            version: majorVersion,\n            ios: /(iPad|iPhone|iPod)/g.test(navigator.platform)\n        };\n    }\n\n    // Check for mime type support against a player instance\n    // Credits: http://diveintohtml5.info/everything.html\n    // Related: http://www.leanbackplayer.com/test/h5mt.html\n    function _supportMime(player, mimeType) {\n        var media = player.media;\n\n        // Only check video types for video players\n        if (player.type == 'video') {\n            // Check type\n            switch (mimeType) {\n            case 'video/webm':\n                return !!(media.canPlayType && media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, ''));\n            case 'video/mp4':\n                return !!(media.canPlayType && media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, ''));\n            case 'video/ogg':\n                return !!(media.canPlayType && media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, ''));\n            }\n        }\n\n        // Only check audio types for audio players\n        else if (player.type == 'audio') {\n            // Check type\n            switch (mimeType) {\n            case 'audio/mpeg':\n                return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, ''));\n            case 'audio/ogg':\n                return !!(media.canPlayType && media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, ''));\n            case 'audio/wav':\n                return !!(media.canPlayType && media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, ''));\n            }\n        }\n\n        // If we got this far, we're stuffed\n        return false;\n    }\n\n    // Inject a script\n    function _injectScript(source) {\n        if (document.querySelectorAll('script[src=\"' + source + '\"]').length) {\n            return;\n        }\n\n        var tag = document.createElement('script');\n        tag.src = source;\n        var firstScriptTag = document.getElementsByTagName('script')[0];\n        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n    }\n\n    // Element exists in an array\n    function _inArray(haystack, needle) {\n        return Array.prototype.indexOf && (haystack.indexOf(needle) != -1);\n    }\n\n    // Replace all\n    function _replaceAll(string, find, replace) {\n        return string.replace(new RegExp(find.replace(/([.*+?\\^=!:${}()|\\[\\]\\/\\\\])/g, '\\\\$1'), 'g'), replace);\n    }\n\n    // Wrap an element\n    function _wrap(elements, wrapper) {\n        // Convert `elements` to an array, if necessary.\n        if (!elements.length) {\n            elements = [elements];\n        }\n\n        // Loops backwards to prevent having to clone the wrapper on the\n        // first element (see `child` below).\n        for (var i = elements.length - 1; i >= 0; i--) {\n            var child = (i > 0) ? wrapper.cloneNode(true) : wrapper;\n            var element = elements[i];\n\n            // Cache the current parent and sibling.\n            var parent = element.parentNode;\n            var sibling = element.nextSibling;\n\n            // Wrap the element (is automatically removed from its current\n            // parent).\n            child.appendChild(element);\n\n            // If the element had a sibling, insert the wrapper before\n            // the sibling to maintain the HTML structure; otherwise, just\n            // append it to the parent.\n            if (sibling) {\n                parent.insertBefore(child, sibling);\n            } else {\n                parent.appendChild(child);\n            }\n        }\n    }\n\n    // Unwrap an element\n    // http://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/\n    function _unwrap(wrapper) {\n        // Get the element's parent node\n        var parent = wrapper.parentNode;\n\n        // Move all children out of the element\n        while (wrapper.firstChild) {\n            parent.insertBefore(wrapper.firstChild, wrapper);\n        }\n\n        // Remove the empty element\n        parent.removeChild(wrapper);\n    }\n\n    // Remove an element\n    function _remove(element) {\n        element.parentNode.removeChild(element);\n    }\n\n    // Prepend child\n    function _prependChild(parent, element) {\n        parent.insertBefore(element, parent.firstChild);\n    }\n\n    // Set attributes\n    function _setAttributes(element, attributes) {\n        for (var key in attributes) {\n            element.setAttribute(key, attributes[key]);\n        }\n    }\n\n    // Toggle class on an element\n    function _toggleClass(element, name, state) {\n        if (element) {\n            if (element.classList) {\n                element.classList[state ? 'add' : 'remove'](name);\n            } else {\n                var className = (' ' + element.className + ' ').replace(/\\s+/g, ' ').replace(' ' + name + ' ', '');\n                element.className = className + (state ? ' ' + name : '');\n            }\n        }\n    }\n\n    // Toggle event\n    function _toggleHandler(element, events, callback, toggle) {\n        var eventList = events.split(' ');\n\n        // If a nodelist is passed, call itself on each node\n        if (element instanceof NodeList) {\n            for (var x = 0; x < element.length; x++) {\n                if (element[x] instanceof Node) {\n                    _toggleHandler(element[x], arguments[1], arguments[2], arguments[3]);\n                }\n            }\n            return;\n        }\n\n        // If a single node is passed, bind the event listener\n        for (var i = 0; i < eventList.length; i++) {\n            element[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, false);\n        }\n    }\n\n    // Bind event\n    function _on(element, events, callback) {\n        if (element) {\n            _toggleHandler(element, events, callback, true);\n        }\n    }\n\n    // Unbind event\n    function _off(element, events, callback) {\n        if (element) {\n            _toggleHandler(element, events, callback, false);\n        }\n    }\n\n    // Trigger event\n    function _triggerEvent(element, event) {\n        // Create faux event\n        var fauxEvent = document.createEvent('MouseEvents');\n\n        // Set the event type\n        fauxEvent.initEvent(event, true, true);\n\n        // Dispatch the event\n        element.dispatchEvent(fauxEvent);\n    }\n\n    // Toggle aria-pressed state on a toggle button\n    function _toggleState(target, state) {\n        // Get state\n        state = (typeof state === 'boolean' ? state : !target.getAttribute('aria-pressed'));\n\n        // Set the attribute on target\n        target.setAttribute('aria-pressed', state);\n\n        return state;\n    }\n\n    // Get percentage\n    function _getPercentage(current, max) {\n        if (current === 0 || max === 0 || isNaN(current) || isNaN(max)) {\n            return 0;\n        }\n        return ((current / max) * 100).toFixed(2);\n    }\n\n    // Deep extend/merge two Objects\n    // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/\n    // Removed call to arguments.callee (used explicit function name instead)\n    function _extend(destination, source) {\n        for (var property in source) {\n            if (source[property] && source[property].constructor && source[property].constructor === Object) {\n                destination[property] = destination[property] || {};\n                _extend(destination[property], source[property]);\n            } else {\n                destination[property] = source[property];\n            }\n        }\n        return destination;\n    }\n\n    // Fullscreen API\n    function _fullscreen() {\n        var fullscreen = {\n                supportsFullScreen: false,\n                isFullScreen: function () {\n                    return false;\n                },\n                requestFullScreen: function () {},\n                cancelFullScreen: function () {},\n                fullScreenEventName: '',\n                element: null,\n                prefix: ''\n            },\n            browserPrefixes = 'webkit moz o ms khtml'.split(' ');\n\n        // Check for native support\n        if (typeof document.cancelFullScreen !== 'undefined') {\n            fullscreen.supportsFullScreen = true;\n        } else {\n            // Check for fullscreen support by vendor prefix\n            for (var i = 0, il = browserPrefixes.length; i < il; i++) {\n                fullscreen.prefix = browserPrefixes[i];\n\n                if (typeof document[fullscreen.prefix + 'CancelFullScreen'] !== 'undefined') {\n                    fullscreen.supportsFullScreen = true;\n                    break;\n                }\n                // Special case for MS (when isn't it?)\n                else if (typeof document.msExitFullscreen !== 'undefined' && document.msFullscreenEnabled) {\n                    fullscreen.prefix = 'ms';\n                    fullscreen.supportsFullScreen = true;\n                    break;\n                }\n            }\n        }\n\n        // Update methods to do something useful\n        if (fullscreen.supportsFullScreen) {\n            // Yet again Microsoft awesomeness,\n            // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n            fullscreen.fullScreenEventName = (fullscreen.prefix == 'ms' ? 'MSFullscreenChange' : fullscreen.prefix + 'fullscreenchange');\n\n            fullscreen.isFullScreen = function (element) {\n                if (typeof element === 'undefined') {\n                    element = document.body;\n                }\n                switch (this.prefix) {\n                case '':\n                    return document.fullscreenElement == element;\n                case 'moz':\n                    return document.mozFullScreenElement == element;\n                default:\n                    return document[this.prefix + 'FullscreenElement'] == element;\n                }\n            };\n            fullscreen.requestFullScreen = function (element) {\n                if (typeof element === 'undefined') {\n                    element = document.body;\n                }\n                return (this.prefix === '') ? element.requestFullScreen() : element[this.prefix + (this.prefix == 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n            };\n            fullscreen.cancelFullScreen = function () {\n                return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + (this.prefix == 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n            };\n            fullscreen.element = function () {\n                return (this.prefix === '') ? document.fullscreenElement : document[this.prefix + 'FullscreenElement'];\n            };\n        }\n\n        return fullscreen;\n    }\n\n    // Local storage\n    function _storage() {\n        var storage = {\n            supported: (function () {\n                try {\n                    return 'localStorage' in window && window.localStorage !== null;\n                } catch (e) {\n                    return false;\n                }\n            })()\n        };\n        return storage;\n    }\n\n    // Player instance\n    function Plyr(container) {\n        var player = this;\n        player.container = container;\n\n        // Captions functions\n        // Seek the manual caption time and update UI\n        function _seekManualCaptions(time) {\n            // If it's not video, or we're using textTracks, bail.\n            if (player.usingTextTracks || player.type !== 'video' || !player.supported.full) {\n                return;\n            }\n\n            // Reset subcount\n            player.subcount = 0;\n\n            // Check time is a number, if not use currentTime\n            // IE has a bug where currentTime doesn't go to 0\n            // https://twitter.com/Sam_Potts/status/573715746506731521\n            time = typeof time === 'number' ? time : player.media.currentTime;\n\n            while (_timecodeMax(player.captions[player.subcount][0]) < time.toFixed(1)) {\n                player.subcount++;\n                if (player.subcount > player.captions.length - 1) {\n                    player.subcount = player.captions.length - 1;\n                    break;\n                }\n            }\n\n            // Check if the next caption is in the current time range\n            if (player.media.currentTime.toFixed(1) >= _timecodeMin(player.captions[player.subcount][0]) &&\n                player.media.currentTime.toFixed(1) <= _timecodeMax(player.captions[player.subcount][0])) {\n                player.currentCaption = player.captions[player.subcount][1];\n\n                // Trim caption text\n                var content = player.currentCaption.trim();\n\n                // Render the caption (only if changed)\n                if (player.captionsContainer.innerHTML != content) {\n                    // Empty caption\n                    // Otherwise NVDA reads it twice\n                    player.captionsContainer.innerHTML = '';\n\n                    // Set new caption text\n                    player.captionsContainer.innerHTML = content;\n                }\n            } else {\n                player.captionsContainer.innerHTML = '';\n            }\n        }\n\n        // Display captions container and button (for initialization)\n        function _showCaptions() {\n            // If there's no caption toggle, bail\n            if (!player.buttons.captions) {\n                return;\n            }\n\n            _toggleClass(player.container, config.classes.captions.enabled, true);\n\n            if (config.captions.defaultActive) {\n                _toggleClass(player.container, config.classes.captions.active, true);\n                _toggleState(player.buttons.captions, true);\n            }\n        }\n\n        // Utilities for caption time codes\n        function _timecodeMin(tc) {\n            var tcpair = [];\n            tcpair = tc.split(' --> ');\n            return _subTcSecs(tcpair[0]);\n        }\n\n        function _timecodeMax(tc) {\n            var tcpair = [];\n            tcpair = tc.split(' --> ');\n            return _subTcSecs(tcpair[1]);\n        }\n\n        function _subTcSecs(tc) {\n            if (tc === null || tc === undefined) {\n                return 0;\n            } else {\n                var tc1 = [],\n                    tc2 = [],\n                    seconds;\n                tc1 = tc.split(',');\n                tc2 = tc1[0].split(':');\n                seconds = Math.floor(tc2[0] * 60 * 60) + Math.floor(tc2[1] * 60) + Math.floor(tc2[2]);\n                return seconds;\n            }\n        }\n\n        // Find all elements\n        function _getElements(selector) {\n            return player.container.querySelectorAll(selector);\n        }\n\n        // Find a single element\n        function _getElement(selector) {\n            return _getElements(selector)[0];\n        }\n\n        // Determine if we're in an iframe\n        function _inFrame() {\n            try {\n                return window.self !== window.top;\n            } catch (e) {\n                return true;\n            }\n        }\n\n        // Insert controls\n        function _injectControls() {\n            // Make a copy of the html\n            var html = config.html;\n\n            // Insert custom video controls\n            _log('Injecting custom controls.');\n\n            // If no controls are specified, create default\n            if (!html) {\n                html = _buildControls();\n            }\n\n            // Replace seek time instances\n            html = _replaceAll(html, '{seektime}', config.seekTime);\n\n            // Replace all id references with random numbers\n            html = _replaceAll(html, '{id}', Math.floor(Math.random() * (10000)));\n\n            // Inject into the container\n            player.container.insertAdjacentHTML('beforeend', html);\n\n            // Setup tooltips\n            if (config.tooltips) {\n                var labels = _getElements(config.selectors.labels);\n\n                for (var i = labels.length - 1; i >= 0; i--) {\n                    var label = labels[i];\n\n                    _toggleClass(label, config.classes.hidden, false);\n                    _toggleClass(label, config.classes.tooltip, true);\n                }\n            }\n        }\n\n        // Find the UI controls and store references\n        function _findElements() {\n            try {\n                player.controls = _getElement(config.selectors.controls);\n\n                // Buttons\n                player.buttons = {};\n                player.buttons.seek = _getElement(config.selectors.buttons.seek);\n                player.buttons.play = _getElement(config.selectors.buttons.play);\n                player.buttons.pause = _getElement(config.selectors.buttons.pause);\n                player.buttons.restart = _getElement(config.selectors.buttons.restart);\n                player.buttons.rewind = _getElement(config.selectors.buttons.rewind);\n                player.buttons.forward = _getElement(config.selectors.buttons.forward);\n                player.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen);\n\n                // Inputs\n                player.buttons.mute = _getElement(config.selectors.buttons.mute);\n                player.buttons.captions = _getElement(config.selectors.buttons.captions);\n                player.checkboxes = _getElements('[type=\"checkbox\"]');\n\n                // Progress\n                player.progress = {};\n                player.progress.container = _getElement(config.selectors.progress.container);\n\n                // Progress - Buffering\n                player.progress.buffer = {};\n                player.progress.buffer.bar = _getElement(config.selectors.progress.buffer);\n                player.progress.buffer.text = player.progress.buffer.bar && player.progress.buffer.bar.getElementsByTagName('span')[0];\n\n                // Progress - Played\n                player.progress.played = {};\n                player.progress.played.bar = _getElement(config.selectors.progress.played);\n                player.progress.played.text = player.progress.played.bar && player.progress.played.bar.getElementsByTagName('span')[0];\n\n                // Volume\n                player.volume = _getElement(config.selectors.buttons.volume);\n\n                // Timing\n                player.duration = _getElement(config.selectors.duration);\n                player.currentTime = _getElement(config.selectors.currentTime);\n                player.seekTime = _getElements(config.selectors.seekTime);\n\n                return true;\n            } catch (e) {\n                _log('It looks like there\\'s a problem with your controls html. Bailing.', true);\n\n                // Restore native video controls\n                player.media.setAttribute('controls', '');\n\n                return false;\n            }\n        }\n\n        // Setup aria attribute for play\n        function _setupPlayAria() {\n            // If there's no play button, bail\n            if (!player.buttons.play) {\n                return;\n            }\n\n            // Find the current text\n            var label = player.buttons.play.innerText || config.i18n.play;\n\n            // If there's a media title set, use that for the label\n            if (typeof (config.title) !== 'undefined' && config.title.length) {\n                label += ', ' + config.title;\n            }\n\n            player.buttons.play.setAttribute('aria-label', label);\n        }\n\n        // Setup media\n        function _setupMedia() {\n            // If there's no media, bail\n            if (!player.media) {\n                _log('No audio or video element found!', true);\n                return false;\n            }\n\n            if (player.supported.full) {\n                // Remove native video controls\n                player.media.removeAttribute('controls');\n\n                // Add type class\n                _toggleClass(player.container, config.classes.type.replace('{0}', player.type), true);\n\n                // If there's no autoplay attribute, assume the video is stopped and add state class\n                _toggleClass(player.container, config.classes.stopped, (player.media.getAttribute('autoplay') === null));\n\n                // Add iOS class\n                if (player.browser.ios) {\n                    _toggleClass(player.container, 'ios', true);\n                }\n\n                // Inject the player wrapper\n                if (player.type === 'video') {\n                    // Create the wrapper div\n                    var wrapper = document.createElement('div');\n                    wrapper.setAttribute('class', config.classes.videoWrapper);\n\n                    // Wrap the video in a container\n                    _wrap(player.media, wrapper);\n\n                    // Cache the container\n                    player.videoContainer = wrapper;\n                }\n            }\n\n            // YouTube\n            if (player.type == 'youtube') {\n                _setupYouTube(player.media.getAttribute('data-video-id'));\n            }\n\n            // Autoplay\n            if (player.media.getAttribute('autoplay') !== null) {\n                _play();\n            }\n        }\n\n        // Setup YouTube\n        function _setupYouTube(id) {\n            // Remove old containers\n            var containers = _getElements('[id^=\"youtube\"]');\n            for (var i = containers.length - 1; i >= 0; i--) {\n                _remove(containers[i]);\n            }\n\n            // Create the YouTube container\n            var container = document.createElement('div');\n            container.setAttribute('id', 'youtube-' + Math.floor(Math.random() * (10000)));\n            player.media.appendChild(container);\n\n            // Add embed class for responsive\n            _toggleClass(player.media, config.classes.videoWrapper, true);\n            _toggleClass(player.media, config.classes.embedWrapper, true);\n\n            if (typeof YT === 'object') {\n                _YTReady(id, container);\n            } else {\n                // Load the API\n                _injectScript('https://www.youtube.com/iframe_api');\n\n                // Add callback to queue\n                callbacks.youtube.push(function () {\n                    _YTReady(id, container);\n                });\n\n                // Setup callback for the API\n                window.onYouTubeIframeAPIReady = function () {\n                    for (var i = callbacks.youtube.length - 1; i >= 0; i--) {\n                        // Fire callback\n                        callbacks.youtube[i]();\n\n                        // Remove from queue\n                        callbacks.youtube.splice(i, 1);\n                    }\n                };\n            }\n        }\n\n        // Handle API ready\n        function _YTReady(id, container) {\n            _log('YouTube API Ready');\n\n            // Setup timers object\n            // We have to poll YouTube for updates\n            if (!('timer' in player)) {\n                player.timer = {};\n            }\n\n            // Setup instance\n            // https://developers.google.com/youtube/iframe_api_reference\n            player.embed = new YT.Player(container.id, {\n                videoId: id,\n                playerVars: {\n                    autoplay: 0,\n                    controls: (player.supported.full ? 0 : 1),\n                    rel: 0,\n                    showinfo: 0,\n                    iv_load_policy: 3,\n                    cc_load_policy: (config.captions.defaultActive ? 1 : 0),\n                    cc_lang_pref: 'en',\n                    wmode: 'transparent',\n                    modestbranding: 1,\n                    disablekb: 1\n                },\n                events: {\n                    'onReady': function (event) {\n                        // Get the instance\n                        var instance = event.target;\n\n                        // Create a faux HTML5 API using the YouTube API\n                        player.media.play = function () {\n                            instance.playVideo();\n                        };\n                        player.media.pause = function () {\n                            instance.pauseVideo();\n                        };\n                        player.media.stop = function () {\n                            instance.stopVideo();\n                        };\n                        player.media.duration = instance.getDuration();\n                        player.media.paused = true;\n                        player.media.currentTime = instance.getCurrentTime();\n                        player.media.muted = instance.isMuted();\n\n                        // Trigger timeupdate\n                        _triggerEvent(player.media, 'timeupdate');\n\n                        // Reset timer\n                        window.clearInterval(player.timer.buffering);\n\n                        // Setup buffering\n                        player.timer.buffering = window.setInterval(function () {\n                            // Get loaded % from YouTube\n                            player.media.buffered = instance.getVideoLoadedFraction();\n\n                            // Trigger progress\n                            _triggerEvent(player.media, 'progress');\n\n                            // Bail if we're at 100%\n                            if (player.media.buffered === 1) {\n                                window.clearInterval(player.timer.buffering);\n                            }\n                        }, 200);\n\n                        if (player.supported.full) {\n                            // Only setup controls once\n                            if (!player.container.querySelectorAll(config.selectors.controls).length) {\n                                _setupInterface();\n                            }\n\n                            // Display duration if available\n                            if (config.displayDuration) {\n                                _displayDuration();\n                            }\n                        }\n                    },\n                    'onStateChange': function (event) {\n                        // Get the instance\n                        var instance = event.target;\n\n                        // Reset timer\n                        window.clearInterval(player.timer.playing);\n\n                        // Handle events\n                        // -1   Unstarted\n                        // 0    Ended\n                        // 1    Playing\n                        // 2    Paused\n                        // 3    Buffering\n                        // 5    Video cued\n                        switch (event.data) {\n                        case 0:\n                            player.media.paused = true;\n                            _triggerEvent(player.media, 'ended');\n                            break;\n\n                        case 1:\n                            player.media.paused = false;\n                            _triggerEvent(player.media, 'play');\n\n                            // Poll to get playback progress\n                            player.timer.playing = window.setInterval(function () {\n                                // Set the current time\n                                player.media.currentTime = instance.getCurrentTime();\n\n                                // Trigger timeupdate\n                                _triggerEvent(player.media, 'timeupdate');\n                            }, 200);\n\n                            break;\n\n                        case 2:\n                            player.media.paused = true;\n                            _triggerEvent(player.media, 'pause');\n                        }\n                    }\n                }\n            });\n        }\n\n        // Setup captions\n        function _setupCaptions() {\n            if (player.type === 'video') {\n                // Inject the container\n                player.videoContainer.insertAdjacentHTML('afterbegin', '<div class=\"' + config.selectors.captions.replace('.', '') + '\"><span></span></div>');\n\n                // Cache selector\n                player.captionsContainer = _getElement(config.selectors.captions).querySelector('span');\n\n                // Determine if HTML5 textTracks is supported\n                player.usingTextTracks = false;\n                if (player.media.textTracks) {\n                    player.usingTextTracks = true;\n                }\n\n                // Get URL of caption file if exists\n                var captionSrc = '',\n                    kind,\n                    children = player.media.childNodes;\n\n                for (var i = 0; i < children.length; i++) {\n                    if (children[i].nodeName.toLowerCase() === 'track') {\n                        kind = children[i].kind;\n                        if (kind === 'captions' || kind === 'subtitles') {\n                            captionSrc = children[i].getAttribute('src');\n                        }\n                    }\n                }\n\n                // Record if caption file exists or not\n                player.captionExists = true;\n                if (captionSrc === '') {\n                    player.captionExists = false;\n                    _log('No caption track found.');\n                } else {\n                    _log('Caption track found; URI: ' + captionSrc);\n                }\n\n                // If no caption file exists, hide container for caption text\n                if (!player.captionExists) {\n                    _toggleClass(player.container, config.classes.captions.enabled);\n                }\n                // If caption file exists, process captions\n                else {\n                    // Turn off native caption rendering to avoid double captions\n                    // This doesn't seem to work in Safari 7+, so the <track> elements are removed from the dom below\n                    var tracks = player.media.textTracks;\n                    for (var x = 0; x < tracks.length; x++) {\n                        tracks[x].mode = 'hidden';\n                    }\n\n                    // Enable UI\n                    _showCaptions(player);\n\n                    // Disable unsupported browsers than report false positive\n                    if ((player.browser.name === 'IE' && player.browser.version >= 10) ||\n                        (player.browser.name === 'Firefox' && player.browser.version >= 31) ||\n                        (player.browser.name === 'Chrome' && player.browser.version >= 43) ||\n                        (player.browser.name === 'Safari' && player.browser.version >= 7)) {\n                        // Debugging\n                        _log('Detected unsupported browser for HTML5 captions. Using fallback.');\n\n                        // Set to false so skips to 'manual' captioning\n                        player.usingTextTracks = false;\n                    }\n\n                    // Rendering caption tracks\n                    // Native support required - http://caniuse.com/webvtt\n                    if (player.usingTextTracks) {\n                        _log('TextTracks supported.');\n\n                        for (var y = 0; y < tracks.length; y++) {\n                            var track = tracks[y];\n\n                            if (track.kind === 'captions' || track.kind === 'subtitles') {\n                                _on(track, 'cuechange', function () {\n                                    // Clear container\n                                    player.captionsContainer.innerHTML = '';\n\n                                    // Display a cue, if there is one\n                                    if (this.activeCues[0] && this.activeCues[0].hasOwnProperty('text')) {\n                                        player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim());\n                                    }\n                                });\n                            }\n                        }\n                    }\n                    // Caption tracks not natively supported\n                    else {\n                        _log('TextTracks not supported so rendering captions manually.');\n\n                        // Render captions from array at appropriate time\n                        player.currentCaption = '';\n                        player.captions = [];\n\n                        if (captionSrc !== '') {\n                            // Create XMLHttpRequest Object\n                            var xhr = new XMLHttpRequest();\n\n                            xhr.onreadystatechange = function () {\n                                if (xhr.readyState === 4) {\n                                    if (xhr.status === 200) {\n                                        var records = [],\n                                            record,\n                                            req = xhr.responseText;\n\n                                        records = req.split('\\n\\n');\n\n                                        for (var r = 0; r < records.length; r++) {\n                                            record = records[r];\n                                            player.captions[r] = [];\n                                            player.captions[r] = record.split('\\n');\n                                        }\n\n                                        // Remove first element ('VTT')\n                                        player.captions.shift();\n\n                                        _log('Successfully loaded the caption file via AJAX.');\n                                    } else {\n                                        _log('There was a problem loading the caption file via AJAX.', true);\n                                    }\n                                }\n                            };\n\n                            xhr.open('get', captionSrc, true);\n\n                            xhr.send();\n                        }\n                    }\n\n                    // If Safari 7+, removing track from DOM [see 'turn off native caption rendering' above]\n                    if (player.browser.name === 'Safari' && player.browser.version >= 7) {\n                        _log('Safari 7+ detected; removing track from DOM.');\n\n                        // Find all <track> elements\n                        tracks = player.media.getElementsByTagName('track');\n\n                        // Loop through and remove one by one\n                        for (var t = 0; t < tracks.length; t++) {\n                            player.media.removeChild(tracks[t]);\n                        }\n                    }\n                }\n            }\n        }\n\n        // Setup fullscreen\n        function _setupFullscreen() {\n            if (player.type != 'audio' && config.fullscreen.enabled) {\n                // Check for native support\n                var nativeSupport = fullscreen.supportsFullScreen;\n\n                if (nativeSupport || (config.fullscreen.fallback && !_inFrame())) {\n                    _log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled.');\n\n                    // Add styling hook\n                    _toggleClass(player.container, config.classes.fullscreen.enabled, true);\n                } else {\n                    _log('Fullscreen not supported and fallback disabled.');\n                }\n\n                // Toggle state\n                _toggleState(player.buttons.fullscreen, false);\n\n                // Set control hide class hook\n                if (config.fullscreen.hideControls) {\n                    _toggleClass(player.container, config.classes.fullscreen.hideControls, true);\n                }\n            }\n        }\n\n        // Play media\n        function _play() {\n            player.media.play();\n        }\n\n        // Pause media\n        function _pause() {\n            player.media.pause();\n        }\n\n        // Toggle playback\n        function _togglePlay(toggle) {\n            // Play\n            if (toggle === true) {\n                _play();\n            }\n            // Pause\n            else if (toggle === false) {\n                _pause();\n            }\n            // True toggle\n            else {\n                player.media[player.media.paused ? 'play' : 'pause']();\n            }\n        }\n\n        // Rewind\n        function _rewind(seekTime) {\n            // Use default if needed\n            if (typeof seekTime !== 'number') {\n                seekTime = config.seekTime;\n            }\n            _seek(player.media.currentTime - seekTime);\n        }\n\n        // Fast forward\n        function _forward(seekTime) {\n            // Use default if needed\n            if (typeof seekTime !== 'number') {\n                seekTime = config.seekTime;\n            }\n            _seek(player.media.currentTime + seekTime);\n        }\n\n        // Seek to time\n        // The input parameter can be an event or a number\n        function _seek(input) {\n            var targetTime = 0,\n                paused = player.media.paused;\n\n            // Explicit position\n            if (typeof input === 'number') {\n                targetTime = input;\n            }\n            // Event\n            else if (typeof input === 'object' && (input.type === 'input' || input.type === 'change')) {\n                // It's the seek slider\n                // Seek to the selected time\n                targetTime = ((input.target.value / input.target.max) * player.media.duration);\n            }\n\n            // Normalise targetTime\n            if (targetTime < 0) {\n                targetTime = 0;\n            } else if (targetTime > player.media.duration) {\n                targetTime = player.media.duration;\n            }\n\n            // Set the current time\n            // Try/catch incase the media isn't set and we're calling seek() from source() and IE moans\n            try {\n                player.media.currentTime = targetTime.toFixed(1);\n            } catch (e) {}\n\n            // YouTube\n            if (player.type == 'youtube') {\n                player.embed.seekTo(targetTime);\n\n                if (paused) {\n                    _pause();\n                }\n\n                // Trigger timeupdate\n                _triggerEvent(player.media, 'timeupdate');\n            }\n\n            // Logging\n            _log('Seeking to ' + player.media.currentTime + ' seconds');\n\n            // Special handling for 'manual' captions\n            _seekManualCaptions(targetTime);\n        }\n\n        // Check playing state\n        function _checkPlaying() {\n            _toggleClass(player.container, config.classes.playing, !player.media.paused);\n            _toggleClass(player.container, config.classes.stopped, player.media.paused);\n        }\n\n        // Toggle fullscreen\n        function _toggleFullscreen(event) {\n            // Check for native support\n            var nativeSupport = fullscreen.supportsFullScreen;\n\n            // If it's a fullscreen change event, it's probably a native close\n            if (event && event.type === fullscreen.fullScreenEventName) {\n                player.isFullscreen = fullscreen.isFullScreen(player.container);\n            }\n            // If there's native support, use it\n            else if (nativeSupport) {\n                // Request fullscreen\n                if (!fullscreen.isFullScreen(player.container)) {\n                    fullscreen.requestFullScreen(player.container);\n                }\n                // Bail from fullscreen\n                else {\n                    fullscreen.cancelFullScreen();\n                }\n\n                // Check if we're actually full screen (it could fail)\n                player.isFullscreen = fullscreen.isFullScreen(player.container);\n            } else {\n                // Otherwise, it's a simple toggle\n                player.isFullscreen = !player.isFullscreen;\n\n                // Bind/unbind escape key\n                if (player.isFullscreen) {\n                    _on(document, 'keyup', _handleEscapeFullscreen);\n                    document.body.style.overflow = 'hidden';\n                } else {\n                    _off(document, 'keyup', _handleEscapeFullscreen);\n                    document.body.style.overflow = '';\n                }\n            }\n\n            // Set class hook\n            _toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen);\n\n            // Set button state\n            _toggleState(player.buttons.fullscreen, player.isFullscreen);\n\n            // Toggle controls visibility based on mouse movement and location\n            var hoverTimer, isMouseOver = false;\n\n            // Show the player controls\n            function _showControls() {\n                // Set shown class\n                _toggleClass(player.container, config.classes.hover, true);\n\n                // Clear timer every movement\n                window.clearTimeout(hoverTimer);\n\n                // If the mouse is not over the controls, set a timeout to hide them\n                if (!isMouseOver) {\n                    hoverTimer = window.setTimeout(function () {\n                        _toggleClass(player.container, config.classes.hover, false);\n                    }, 2000);\n                }\n            }\n\n            // Check mouse is over the controls\n            function _setMouseOver(event) {\n                isMouseOver = (event.type === 'mouseenter');\n            }\n\n            if (config.fullscreen.hideControls) {\n                // Hide on entering full screen\n                _toggleClass(player.controls, config.classes.hover, false);\n\n                // Keep an eye on the mouse location in relation to controls\n                _toggleHandler(player.controls, 'mouseenter mouseleave', _setMouseOver, player.isFullscreen);\n\n                // Show the controls on mouse move\n                _toggleHandler(player.container, 'mousemove', _showControls, player.isFullscreen);\n            }\n        }\n\n        // Bail from faux-fullscreen\n        function _handleEscapeFullscreen(event) {\n            // If it's a keypress and not escape, bail\n            if ((event.which || event.charCode || event.keyCode) === 27 && player.isFullscreen) {\n                _toggleFullscreen();\n            }\n        }\n\n        // Set volume\n        function _setVolume(volume) {\n            // Use default if no value specified\n            if (typeof volume === 'undefined') {\n                if (config.storage.enabled && _storage().supported) {\n                    volume = window.localStorage[config.storage.key] || config.volume;\n                } else {\n                    volume = config.volume;\n                }\n            }\n\n            // Maximum is 10\n            if (volume > 10) {\n                volume = 10;\n            }\n            // Minimum is 0\n            if (volume < 0) {\n                volume = 0;\n            }\n\n            // Set the player volume\n            player.media.volume = parseFloat(volume / 10);\n\n            // YouTube\n            if (player.type == 'youtube') {\n                player.embed.setVolume(player.media.volume * 100);\n\n                // Trigger timeupdate\n                _triggerEvent(player.media, 'volumechange');\n            }\n\n            // Toggle muted state\n            if (player.media.muted && volume > 0) {\n                _toggleMute();\n            }\n        }\n\n        // Mute\n        function _toggleMute(muted) {\n            // If the method is called without parameter, toggle based on current value\n            if (typeof muted !== 'boolean') {\n                muted = !player.media.muted;\n            }\n\n            // Set button state\n            _toggleState(player.buttons.mute, muted);\n\n            // Set mute on the player\n            player.media.muted = muted;\n\n            // YouTube\n            if (player.type === 'youtube') {\n                player.embed[player.media.muted ? 'mute' : 'unMute']();\n\n                // Trigger timeupdate\n                _triggerEvent(player.media, 'volumechange');\n            }\n        }\n\n        // Update volume UI and storage\n        function _updateVolume() {\n            // Get the current volume\n            var volume = player.media.muted ? 0 : (player.media.volume * 10);\n\n            // Update the <input type=\"range\"> if present\n            if (player.supported.full && player.volume) {\n                player.volume.value = volume;\n            }\n\n            // Store the volume in storage\n            if (config.storage.enabled && _storage().supported) {\n                window.localStorage.setItem(config.storage.key, volume);\n            }\n\n            // Toggle class if muted\n            _toggleClass(player.container, config.classes.muted, (volume === 0));\n\n            // Update checkbox for mute state\n            if (player.supported.full && player.buttons.mute) {\n                _toggleState(player.buttons.mute, (volume === 0));\n            }\n        }\n\n        // Toggle captions\n        function _toggleCaptions(show) {\n            // If there's no full support, or there's no caption toggle\n            if (!player.supported.full || !player.buttons.captions) {\n                return;\n            }\n\n            // If the method is called without parameter, toggle based on current value\n            if (typeof show !== 'boolean') {\n                show = (player.container.className.indexOf(config.classes.captions.active) === -1);\n            }\n\n            // Toggle state\n            _toggleState(player.buttons.captions, show);\n\n            // Add class hook\n            _toggleClass(player.container, config.classes.captions.active, show);\n        }\n\n        // Check if media is loading\n        function _checkLoading(event) {\n            var loading = (event.type === 'waiting');\n\n            // Clear timer\n            clearTimeout(player.loadingTimer);\n\n            // Timer to prevent flicker when seeking\n            player.loadingTimer = setTimeout(function () {\n                _toggleClass(player.container, config.classes.loading, loading);\n            }, (loading ? 250 : 0));\n        }\n\n        // Update <progress> elements\n        function _updateProgress(event) {\n            var progress = player.progress.played.bar,\n                text = player.progress.played.text,\n                value = 0;\n\n            if (event) {\n                switch (event.type) {\n                    // Video playing\n                case 'timeupdate':\n                case 'seeking':\n                    value = _getPercentage(player.media.currentTime, player.media.duration);\n\n                    // Set seek range value only if it's a 'natural' time event\n                    if (event.type == 'timeupdate' && player.buttons.seek) {\n                        player.buttons.seek.value = value;\n                    }\n\n                    break;\n\n                    // Events from seek range\n                case 'change':\n                case 'input':\n                    value = event.target.value;\n                    break;\n\n\n                    // Check buffer status\n                case 'playing':\n                case 'progress':\n                    progress = player.progress.buffer.bar;\n                    text = player.progress.buffer.text;\n                    value = (function () {\n                        var buffered = player.media.buffered;\n\n                        // HTML5\n                        if (buffered && buffered.length) {\n                            return _getPercentage(buffered.end(0), player.media.duration);\n                        }\n                        // YouTube returns between 0 and 1\n                        else if (typeof buffered === 'number') {\n                            return (buffered * 100);\n                        }\n\n                        return 0;\n                    })();\n                }\n            }\n\n            // Set values\n            if (progress) {\n                progress.value = value;\n            }\n            if (text) {\n                text.innerHTML = value;\n            }\n        }\n\n        // Update the displayed time\n        function _updateTimeDisplay(time, element) {\n            // Bail if there's no duration display\n            if (!element) {\n                return;\n            }\n\n            player.secs = parseInt(time % 60);\n            player.mins = parseInt((time / 60) % 60);\n            player.hours = parseInt(((time / 60) / 60) % 60);\n\n            // Do we need to display hours?\n            var displayHours = (parseInt(((player.media.duration / 60) / 60) % 60) > 0);\n\n            // Ensure it's two digits. For example, 03 rather than 3.\n            player.secs = ('0' + player.secs).slice(-2);\n            player.mins = ('0' + player.mins).slice(-2);\n\n            // Render\n            element.innerHTML = (displayHours ? player.hours + ':' : '') + player.mins + ':' + player.secs;\n        }\n\n        // Show the duration on metadataloaded\n        function _displayDuration() {\n            var duration = player.media.duration || 0;\n\n            // If there's only one time display, display duration there\n            if (!player.duration && config.displayDuration && player.media.paused) {\n                _updateTimeDisplay(duration, player.currentTime);\n            }\n\n            // If there's a duration element, update content\n            if (player.duration) {\n                _updateTimeDisplay(duration, player.duration);\n            }\n        }\n\n        // Handle time change event\n        function _timeUpdate(event) {\n            // Duration\n            _updateTimeDisplay(player.media.currentTime, player.currentTime);\n\n            // Playing progress\n            _updateProgress(event);\n        }\n\n        // Remove <source> children and src attribute\n        function _removeSources() {\n            // Find child <source> elements\n            var sources = player.media.querySelectorAll('source');\n\n            // Remove each\n            for (var i = sources.length - 1; i >= 0; i--) {\n                _remove(sources[i]);\n            }\n\n            // Remove src attribute\n            player.media.removeAttribute('src');\n        }\n\n        // Inject a source\n        function _addSource(attributes) {\n            if (attributes.src) {\n                // Create a new <source>\n                var element = document.createElement('source');\n\n                // Set all passed attributes\n                _setAttributes(element, attributes);\n\n                // Inject the new source\n                _prependChild(player.media, element);\n            }\n        }\n\n        // Update source\n        // Sources are not checked for support so be careful\n        function _parseSource(sources) {\n            // YouTube\n            if (player.type === 'youtube' && typeof sources === 'string') {\n                // Destroy YouTube instance\n                player.embed.destroy();\n\n                // Re-setup YouTube\n                // We don't use loadVideoBy[x] here since it has issues\n                _setupYouTube(sources);\n\n                // Update times\n                _timeUpdate();\n\n                // Bail\n                return;\n            }\n\n            // Pause playback (webkit freaks out)\n            _pause();\n\n            // Restart\n            _seek();\n\n            // Remove current sources\n            _removeSources();\n\n            // If a single source is passed\n            // .source('path/to/video.mp4')\n            if (typeof sources === 'string') {\n                _addSource({\n                    src: sources\n                });\n            }\n\n            // An array of source objects\n            // Check if a source exists, use that or set the 'src' attribute?\n            // .source([{ src: 'path/to/video.mp4', type: 'video/mp4' },{ src: 'path/to/video.webm', type: 'video/webm' }])\n            else if (sources.constructor === Array) {\n                for (var index in sources) {\n                    _addSource(sources[index]);\n                }\n            }\n\n            if (player.supported.full) {\n                // Reset time display\n                _timeUpdate();\n\n                // Update the UI\n                _checkPlaying();\n            }\n\n            // Re-load sources\n            player.media.load();\n\n            // Play if autoplay attribute is present\n            if (player.media.getAttribute('autoplay') !== null) {\n                _play();\n            }\n        }\n\n        // Update poster\n        function _updatePoster(source) {\n            if (player.type === 'video') {\n                player.media.setAttribute('poster', source);\n            }\n        }\n\n        // Listen for events\n        function _listeners() {\n            // IE doesn't support input event, so we fallback to change\n            var inputEvent = (player.browser.name == 'IE' ? 'change' : 'input');\n\n            // Detect tab focus\n            function checkFocus() {\n                var focused = document.activeElement;\n                if (!focused || focused == document.body) {\n                    focused = null;\n                } else if (document.querySelector) {\n                    focused = document.querySelector(':focus');\n                }\n                for (var button in player.buttons) {\n                    var element = player.buttons[button];\n\n                    _toggleClass(element, 'tab-focus', (element === focused));\n                }\n            }\n            _on(window, 'keyup', function (event) {\n                var code = (event.keyCode ? event.keyCode : event.which);\n\n                if (code == 9) {\n                    checkFocus();\n                }\n            });\n            for (var button in player.buttons) {\n                var element = player.buttons[button];\n\n                _on(element, 'blur', function () {\n                    _toggleClass(element, 'tab-focus', false);\n                });\n            }\n\n            // Play\n            _on(player.buttons.play, 'click', function () {\n                _play();\n                setTimeout(function () {\n                    player.buttons.pause.focus();\n                }, 100);\n            });\n\n            // Pause\n            _on(player.buttons.pause, 'click', function () {\n                _pause();\n                setTimeout(function () {\n                    player.buttons.play.focus();\n                }, 100);\n            });\n\n            // Restart\n            _on(player.buttons.restart, 'click', _seek);\n\n            // Rewind\n            _on(player.buttons.rewind, 'click', _rewind);\n\n            // Fast forward\n            _on(player.buttons.forward, 'click', _forward);\n\n            // Seek\n            _on(player.buttons.seek, inputEvent, _seek);\n\n            // Set volume\n            _on(player.volume, inputEvent, function () {\n                _setVolume(this.value);\n            });\n\n            // Mute\n            _on(player.buttons.mute, 'click', _toggleMute);\n\n            // Fullscreen\n            _on(player.buttons.fullscreen, 'click', _toggleFullscreen);\n\n            // Handle user exiting fullscreen by escaping etc\n            if (fullscreen.supportsFullScreen) {\n                _on(document, fullscreen.fullScreenEventName, _toggleFullscreen);\n            }\n\n            // Time change on media\n            _on(player.media, 'timeupdate seeking', _timeUpdate);\n\n            // Update manual captions\n            _on(player.media, 'timeupdate', _seekManualCaptions);\n\n            // Display duration\n            _on(player.media, 'loadedmetadata', _displayDuration);\n\n            // Captions\n            _on(player.buttons.captions, 'click', _toggleCaptions);\n\n            // Handle the media finishing\n            _on(player.media, 'ended', function () {\n                // Clear\n                if (player.type === 'video') {\n                    player.captionsContainer.innerHTML = '';\n                }\n\n                // Reset UI\n                _checkPlaying();\n            });\n\n            // Check for buffer progress\n            _on(player.media, 'progress playing', _updateProgress);\n\n            // Handle native mute\n            _on(player.media, 'volumechange', _updateVolume);\n\n            // Handle native play/pause\n            _on(player.media, 'play pause', _checkPlaying);\n\n            // Loading\n            _on(player.media, 'waiting canplay seeked', _checkLoading);\n\n            // Click video\n            if (player.type === 'video' && config.click) {\n                _on(player.videoContainer, 'click', function () {\n                    if (player.media.paused) {\n                        _triggerEvent(player.buttons.play, 'click');\n                    } else if (player.media.ended) {\n                        _seek();\n                        _triggerEvent(player.buttons.play, 'click');\n                    } else {\n                        _triggerEvent(player.buttons.pause, 'click');\n                    }\n                });\n            }\n        }\n\n        // Destroy an instance\n        // Event listeners are removed when elements are removed\n        // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n        function _destroy() {\n            // Bail if the element is not initialized\n            if (!player.init) {\n                return null;\n            }\n\n            // Reset container classname\n            player.container.setAttribute('class', config.selectors.container.replace('.', ''));\n\n            // Remove init flag\n            player.init = false;\n\n            // Remove controls\n            _remove(_getElement(config.selectors.controls));\n\n            // YouTube\n            if (player.type === 'youtube') {\n                player.embed.destroy();\n                return;\n            }\n\n            // If video, we need to remove some more\n            if (player.type === 'video') {\n                // Remove captions\n                _remove(_getElement(config.selectors.captions));\n\n                // Remove video wrapper\n                _unwrap(player.videoContainer);\n            }\n\n            // Restore native video controls\n            player.media.setAttribute('controls', '');\n\n            // Clone the media element to remove listeners\n            // http://stackoverflow.com/questions/19469881/javascript-remove-all-event-listeners-of-specific-type\n            var clone = player.media.cloneNode(true);\n            player.media.parentNode.replaceChild(clone, player.media);\n        }\n\n        // Setup a player\n        function _init() {\n            // Bail if the element is initialized\n            if (player.init) {\n                return null;\n            }\n\n            // Setup the fullscreen api\n            fullscreen = _fullscreen();\n\n            // Sniff out the browser\n            player.browser = _browserSniff();\n\n            // Get the media element\n            player.media = player.container.querySelectorAll('audio, video, div')[0];\n\n            // Set media type\n            var tagName = player.media.tagName.toLowerCase();\n            if (tagName === 'div') {\n                player.type = player.media.getAttribute('data-type');\n            } else {\n                player.type = tagName;\n            }\n\n            // Check for full support\n            player.supported = api.supported(player.type);\n\n            // If no native support, bail\n            if (!player.supported.basic) {\n                return false;\n            }\n\n            // Debug info\n            _log(player.browser.name + ' ' + player.browser.version);\n\n            // Setup media\n            _setupMedia();\n\n            // Setup interface\n            if (player.type == 'video' || player.type == 'audio') {\n                // Bail if no support\n                if (!player.supported.full) {\n                    // Successful setup\n                    player.init = true;\n\n                    // Don't inject controls if no full support\n                    return;\n                }\n\n                // Setup UI\n                _setupInterface();\n\n                // Display duration if available\n                if (config.displayDuration) {\n                    _displayDuration();\n                }\n\n                // Set up aria-label for Play button with the title option\n                _setupPlayAria();\n            }\n\n            // Successful setup\n            player.init = true;\n        }\n\n        function _setupInterface() {\n            // Inject custom controls\n            _injectControls();\n\n            // Find the elements\n            if (!_findElements()) {\n                return false;\n            }\n\n            // Captions\n            _setupCaptions();\n\n            // Set volume\n            _setVolume();\n            _updateVolume();\n\n            // Setup fullscreen\n            _setupFullscreen();\n\n            // Listeners\n            _listeners();\n        }\n\n        // Initialize instance\n        _init();\n\n        // If init failed, return an empty object\n        if (!player.init) {\n            return {};\n        }\n\n        return {\n            media: player.media,\n            play: _play,\n            pause: _pause,\n            restart: _seek,\n            rewind: _rewind,\n            forward: _forward,\n            seek: _seek,\n            source: _parseSource,\n            poster: _updatePoster,\n            setVolume: _setVolume,\n            togglePlay: _togglePlay,\n            toggleMute: _toggleMute,\n            toggleCaptions: _toggleCaptions,\n            toggleFullscreen: _toggleFullscreen,\n            isFullscreen: function () {\n                return player.isFullscreen || false;\n            },\n            support: function (mimeType) {\n                return _supportMime(player, mimeType);\n            },\n            destroy: _destroy,\n            restore: _init\n        };\n    }\n\n    // Check for support\n    api.supported = function (type) {\n        var browser = _browserSniff(),\n            oldIE = (browser.name === 'IE' && browser.version <= 9),\n            iPhone = /iPhone|iPod/i.test(navigator.userAgent),\n            audio = !!document.createElement('audio').canPlayType,\n            video = !!document.createElement('video').canPlayType,\n            basic, full;\n\n        switch (type) {\n        case 'video':\n            basic = video;\n            full = (basic && (!oldIE && !iPhone));\n            break;\n\n        case 'audio':\n            basic = audio;\n            full = (basic && !oldIE);\n            break;\n\n        case 'youtube':\n            basic = true;\n            full = (!oldIE && !iPhone);\n            break;\n\n        default:\n            basic = (audio && video);\n            full = (basic && !oldIE);\n        }\n\n        return {\n            basic: basic,\n            full: full\n        };\n    };\n\n    // Expose setup function\n    api.setup = function (options) {\n        // Extend the default options with user specified\n        config = _extend(defaults, options);\n\n        // Bail if disabled or no basic support\n        // You may want to disable certain UAs etc\n        if (!config.enabled || !api.supported().basic) {\n            return false;\n        }\n\n        // Get the players\n        var elements = document.querySelectorAll(config.selectors.container),\n            players = [];\n\n        // Create a player instance for each element\n        for (var i = elements.length - 1; i >= 0; i--) {\n            // Get the current element\n            var element = elements[i];\n\n            // Setup a player instance and add to the element\n            if (typeof element.plyr === 'undefined') {\n                // Create new instance\n                var instance = new Plyr(element);\n\n                // Set plyr to false if setup failed\n                element.plyr = (Object.keys(instance).length ? instance : false);\n\n                // Callback\n                if (typeof config.onSetup === 'function') {\n                    config.onSetup.apply(element.plyr);\n                }\n            }\n\n            // Add to return array even if it's already setup\n            players.push(element.plyr);\n        }\n\n        return players;\n    };\n\n}(this.plyr = this.plyr || {}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/prettyfile/bootstrap-prettyfile.js",
    "content": "/*\n * jQuery and Bootsrap3 Plugin prettyFile\n *\n * version 2.0, Jan 20th, 2014\n * by episage, sujin2f\n * Git repository : https://github.com/episage/bootstrap-3-pretty-file-upload\n */\n( function( $ ) {\n\t$.fn.extend({\n\t\tprettyFile: function( options ) {\n\t\t\tvar defaults = {\n\t\t\t\ttext : \"选择文件\"\n\t\t\t};\n\n\t\t\tvar options =  $.extend(defaults, options);\n\t\t\tvar plugin = this;\n\n\t\t\tfunction make_form( $el, text ) {\n\t\t\t\t$el.wrap('<div></div>');\n\n\t\t\t\t$el.hide();\n\t\t\t\t$el.after( '\\\n\t\t\t\t<div class=\"input-append input-group\"\">\\\n\t\t\t\t\t<span class=\"input-group-btn\">\\\n\t\t\t\t\t\t<button class=\"btn btn-white\" type=\"button\">' + text + '</button>\\\n\t\t\t\t\t</span>\\\n\t\t\t\t\t<input class=\"input-large form-control\" type=\"text\">\\\n\t\t\t\t</div>\\\n\t\t\t\t' );\n\n\t\t\t\treturn $el.parent();\n\t\t\t};\n\n\t\t\tfunction bind_change( $wrap, multiple ) {\n\t\t\t\t$wrap.find( 'input[type=\"file\"]' ).change(function () {\n\t\t\t\t\t// When original file input changes, get its value, show it in the fake input\n\t\t\t\t\tvar files = $( this )[0].files,\n\t\t\t\t\tinfo = '';\n\n\t\t\t\t\tif ( files.length == 0 )\n\t\t\t\t\t\treturn false;\n\n\t\t\t\t\tif ( !multiple || files.length == 1 ) {\n\t\t\t\t\t\tvar path = $( this ).val().split('\\\\');\n\t\t\t\t\t\tinfo = path[path.length - 1];\n\t\t\t\t\t} else if ( files.length > 1 ) {\n\t\t\t\t\t\t// Display number of selected files instead of filenames\n\t\t\t\t\t\tinfo = \"已选择了\" + files.length + ' 个文件';\n\t\t\t\t\t}\n\n\t\t\t\t\t$wrap.find('.input-append input').val( info );\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tfunction bind_button( $wrap, multiple ) {\n\t\t\t\t$wrap.find( '.input-append' ).click( function( e ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\t$wrap.find( 'input[type=\"file\"]' ).click();\n\t\t\t\t});\n\t\t\t};\n\n\t\t\treturn plugin.each( function() {\n\t\t\t\t$this = $( this );\n\n\t\t\t\tif ( $this ) {\n\t\t\t\t\tvar multiple = $this.attr( 'multiple' );\n\n\t\t\t\t\t$wrap = make_form( $this, options.text );\n\t\t\t\t\tbind_change( $wrap, multiple );\n\t\t\t\t\tbind_button( $wrap );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n}( jQuery ));\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/rickshaw/vendor/d3.v3.js",
    "content": "d3=function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(){}function o(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function a(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=Do.length;r>e;++e){var u=Do[e]+t;if(u in n)return u}}function c(){}function l(){}function s(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function f(){mo.event.preventDefault()}function h(){for(var n,t=mo.event;n=t.sourceEvent;)t=n;return t}function g(n){for(var t=new l,e=0,r=arguments.length;++e<r;)t[arguments[e]]=s(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=mo.event;u.target=n,mo.event=u,t[u.type].apply(e,r)}finally{mo.event=i}}},t}function p(n){return Lo(n,Ro),n}function d(n){return\"function\"==typeof n?n:function(){return Ho(n,this)}}function v(n){return\"function\"==typeof n?n:function(){return Fo(n,this)}}function m(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=mo.ns.qualify(n),null==t?n.local?r:e:\"function\"==typeof t?n.local?a:o:n.local?i:u}function y(n){return n.trim().replace(/\\s+/g,\" \")}function M(n){return new RegExp(\"(?:^|\\\\s+)\"+mo.requote(n)+\"(?:\\\\s+|$)\",\"g\")}function x(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=n.trim().split(/\\s+/).map(b);var u=n.length;return\"function\"==typeof t?r:e}function b(n){var t=M(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute(\"class\")||\"\";r?(t.lastIndex=0,t.test(u)||e.setAttribute(\"class\",y(u+\" \"+n))):e.setAttribute(\"class\",y(u.replace(t,\" \")))}}function _(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:\"function\"==typeof t?i:u}function w(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:\"function\"==typeof t?u:r}function S(n){return\"function\"==typeof n?n:(n=mo.ns.qualify(n)).local?function(){return xo.createElementNS(n.space,n.local)}:function(){return xo.createElementNS(this.namespaceURI,n)}}function E(n){return{__data__:n}}function k(n){return function(){return Oo(this,n)}}function A(n){return arguments.length||(n=mo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function N(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function T(n){return Lo(n,Io),n}function q(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function z(){var n=this.__transition__;n&&++n.active}function C(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=l(t,Mo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp(\"^__on([^.]+)\"+mo.requote(n)+\"$\");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o=\"__on\"+n,a=n.indexOf(\".\"),l=D;a>0&&(n=n.substring(0,a));var s=Zo.get(n);return s&&(n=s,l=j),a?t?u:r:t?c:i}function D(n,t){return function(e){var r=mo.event;mo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{mo.event=r}}}function j(n,t){var e=D(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function L(){var n=\".dragsuppress-\"+ ++Xo,t=\"touchmove\"+n,e=\"selectstart\"+n,r=\"dragstart\"+n,u=\"click\"+n,i=mo.select(_o).on(t,f).on(e,f).on(r,f),o=bo.style,a=o[Vo];return o[Vo]=\"none\",function(t){function e(){i.on(u,null)}i.on(n,null),o[Vo]=a,t&&(i.on(u,function(){f(),e()},!0),setTimeout(e,0))}}function H(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>$o&&(_o.scrollX||_o.scrollY)){e=mo.select(\"body\").append(\"svg\").style({position:\"absolute\",top:0,left:0,margin:0,padding:0,border:\"none\"},\"important\");var u=e[0][0].getScreenCTM();$o=!(u.f||u.e),e.remove()}return $o?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function F(n){return n>0?1:0>n?-1:0}function P(n){return n>1?0:-1>n?Bo:Math.acos(n)}function O(n){return n>1?Jo:-1>n?-Jo:Math.asin(n)}function R(n){return((n=Math.exp(n))-1/n)/2}function Y(n){return((n=Math.exp(n))+1/n)/2}function I(n){return((n=Math.exp(2*n))-1)/(n+1)}function U(n){return(n=Math.sin(n/2))*n}function Z(){}function V(n,t,e){return new X(n,t,e)}function X(n,t,e){this.h=n,this.s=t,this.l=e}function $(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,ot(u(n+120),u(n),u(n-120))}function B(n,t,e){return new W(n,t,e)}function W(n,t,e){this.h=n,this.c=t,this.l=e}function J(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),G(e,Math.cos(n*=Qo)*t,Math.sin(n)*t)}function G(n,t,e){return new K(n,t,e)}function K(n,t,e){this.l=n,this.a=t,this.b=e}function Q(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=tt(u)*sa,r=tt(r)*fa,i=tt(i)*ha,ot(rt(3.2404542*u-1.5371385*r-.4985314*i),rt(-.969266*u+1.8760108*r+.041556*i),rt(.0556434*u-.2040259*r+1.0572252*i))}function nt(n,t,e){return n>0?B(Math.atan2(e,t)*na,Math.sqrt(t*t+e*e),n):B(0/0,0/0,n)}function tt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function et(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function rt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ut(n){return ot(n>>16,255&n>>8,255&n)}function it(n){return ut(n)+\"\"}function ot(n,t,e){return new at(n,t,e)}function at(n,t,e){this.r=n,this.g=t,this.b=e}function ct(n){return 16>n?\"0\"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function lt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\\((.*)\\)/i.exec(n))switch(u=r[2].split(\",\"),r[1]){case\"hsl\":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case\"rgb\":return t(gt(u[0]),gt(u[1]),gt(u[2]))}return(i=da.get(n))?t(i.r,i.g,i.b):(null!=n&&\"#\"===n.charAt(0)&&(4===n.length?(o=n.charAt(1),o+=o,a=n.charAt(2),a+=a,c=n.charAt(3),c+=c):7===n.length&&(o=n.substring(1,3),a=n.substring(3,5),c=n.substring(5,7)),o=parseInt(o,16),a=parseInt(a,16),c=parseInt(c,16)),t(o,a,c))}function st(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),V(r,u,c)}function ft(n,t,e){n=ht(n),t=ht(t),e=ht(e);var r=et((.4124564*n+.3575761*t+.1804375*e)/sa),u=et((.2126729*n+.7151522*t+.072175*e)/fa),i=et((.0193339*n+.119192*t+.9503041*e)/ha);return G(116*u-16,500*(r-u),200*(u-i))}function ht(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function gt(n){var t=parseFloat(n);return\"%\"===n.charAt(n.length-1)?Math.round(2.55*t):t}function pt(n){return\"function\"==typeof n?n:function(){return n}}function dt(n){return n}function vt(n){return function(t,e,r){return 2===arguments.length&&\"function\"==typeof e&&(r=e,e=null),mt(t,e,n,r)}}function mt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=mo.dispatch(\"beforesend\",\"progress\",\"load\",\"error\"),a={},c=new XMLHttpRequest,l=null;return!_o.XDomainRequest||\"withCredentials\"in c||!/^(http(s)?:)?\\/\\//.test(n)||(c=new XDomainRequest),\"onload\"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=mo.event;mo.event=n;try{o.progress.call(i,c)}finally{mo.event=t}},i.header=function(n,t){return n=(n+\"\").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+\"\",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+\"\",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},[\"get\",\"post\"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Mo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&\"function\"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||\"accept\"in a||(a.accept=t+\",*/*\"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on(\"error\",u).on(\"load\",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},mo.rebind(i,o,\"on\"),null==r?i:i.get(yt(r))}function yt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Mt(){var n=bt(),t=_t()-n;t>24?(isFinite(t)&&(clearTimeout(Ma),Ma=setTimeout(Mt,t)),ya=0):(ya=1,ba(Mt))}function xt(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now()),xa.callback=n,xa.time=e+t}function bt(){var n=Date.now();for(xa=va;xa;)n>=xa.time&&(xa.flush=xa.callback(n-xa.time)),xa=xa.next;return n}function _t(){for(var n,t=va,e=1/0;t;)t.flush?t=n?n.next=t.next:va=t.next:(t.time<e&&(e=t.time),t=(n=t).next);return ma=n,e}function wt(n,t){var e=Math.pow(10,3*Math.abs(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function St(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Et(n){return n+\"\"}function kt(){}function At(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function Nt(n,t){n&&Da.hasOwnProperty(n.type)&&Da[n.type](n,t)}function Tt(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function qt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)Tt(n[e],t,1);t.polygonEnd()}function zt(){function n(n,t){n*=Qo,t=t*Qo/2+Bo/4;var e=n-r,o=Math.cos(t),a=Math.sin(t),c=i*a,l=u*o+c*Math.cos(e),s=c*Math.sin(e);La.add(Math.atan2(s,l)),r=n,u=o,i=a}var t,e,r,u,i;Ha.point=function(o,a){Ha.point=n,r=(t=o)*Qo,u=Math.cos(a=(e=a)*Qo/2+Bo/4),i=Math.sin(a)},Ha.lineEnd=function(){n(t,e)}}function Ct(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function Dt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function jt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Lt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function Ht(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Ft(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function Pt(n){return[Math.atan2(n[1],n[0]),O(n[2])]}function Ot(n,t){return Math.abs(n[0]-t[0])<Go&&Math.abs(n[1]-t[1])<Go}function Rt(n,t){n*=Qo;var e=Math.cos(t*=Qo);Yt(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function Yt(n,t,e){++Fa,Oa+=(n-Oa)/Fa,Ra+=(t-Ra)/Fa,Ya+=(e-Ya)/Fa}function It(){function n(n,u){n*=Qo;var i=Math.cos(u*=Qo),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),l=Math.atan2(Math.sqrt((l=e*c-r*a)*l+(l=r*o-t*c)*l+(l=t*a-e*o)*l),t*o+e*a+r*c);Pa+=l,Ia+=l*(t+(t=o)),Ua+=l*(e+(e=a)),Za+=l*(r+(r=c)),Yt(t,e,r)}var t,e,r;Ba.point=function(u,i){u*=Qo;var o=Math.cos(i*=Qo);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),Ba.point=n,Yt(t,e,r)}}function Ut(){Ba.point=Rt}function Zt(){function n(n,t){n*=Qo;var e=Math.cos(t*=Qo),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),l=u*c-i*a,s=i*o-r*c,f=r*a-u*o,h=Math.sqrt(l*l+s*s+f*f),g=r*o+u*a+i*c,p=h&&-P(g)/h,d=Math.atan2(h,g);Va+=p*l,Xa+=p*s,$a+=p*f,Pa+=d,Ia+=d*(r+(r=o)),Ua+=d*(u+(u=a)),Za+=d*(i+(i=c)),Yt(r,u,i)}var t,e,r,u,i;Ba.point=function(o,a){t=o,e=a,Ba.point=n,o*=Qo;var c=Math.cos(a*=Qo);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),Yt(r,u,i)},Ba.lineEnd=function(){n(t,e),Ba.lineEnd=Ut,Ba.point=Rt}}function Vt(){return!0}function Xt(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(Ot(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c={point:e,points:n,other:null,visited:!1,entry:!0,subject:!0},l={point:e,points:[e],other:c,visited:!1,entry:!1,subject:!1};c.other=l,i.push(c),o.push(l),c={point:r,points:[r],other:null,visited:!1,entry:!1,subject:!0},l={point:r,points:[r],other:c,visited:!1,entry:!0,subject:!1},c.other=l,i.push(c),o.push(l)}}),o.sort(t),$t(i),$t(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].entry=c=!c;for(var s,f,h,g=i[0];;){for(s=g;s.visited;)if((s=s.next)===g)return;f=s.points,u.lineStart();do{if(s.visited=s.other.visited=!0,s.entry){if(s.subject)for(var a=0;a<f.length;a++)u.point((h=f[a])[0],h[1]);else r(s.point,s.next.point,1,u);s=s.next}else{if(s.subject){f=s.prev.points;for(var a=f.length;--a>=0;)u.point((h=f[a])[0],h[1])}else r(s.point,s.prev.point,-1,u);s=s.prev}s=s.other,f=s.points}while(!s.visited);u.lineEnd()}}}function $t(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.next=e=n[r],e.prev=u,u=e;u.next=e=n[0],e.prev=u}}function Bt(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);v.point(e[0],e[1])}function c(){y.point=a,v.lineStart()}function l(){y.point=o,v.lineEnd()}function s(n,t){d.push([n,t]);var e=u(n,t);x.point(e[0],e[1])}function f(){x.lineStart(),d=[]}function h(){s(d[0][0],d[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(d.pop(),p.push(d),d=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Wt))}}var g,p,d,v=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=mo.merge(g);var n=Kt(m,p);g.length?Xt(g,Gt,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Jt(),x=t(M);return y}}function Wt(n){return n.length>1}function Jt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:c,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Gt(n,t){return((n=n.point)[0]<0?n[1]-Jo-Go:Jo-n[1])-((t=t.point)[0]<0?t[1]-Jo-Go:Jo-t[1])}function Kt(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;La.reset();for(var a=0,c=t.length;c>a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+Bo/4,p=Math.sin(g),d=Math.cos(g),v=1;;){v===s&&(v=0),n=l[v];var m=n[0],y=n[1]/2+Bo/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=Math.abs(b)>Bo,w=p*M;if(La.add(Math.atan2(w*Math.sin(b),d*x+w*Math.cos(b))),i+=_?b+(b>=0?2:-2)*Bo:b,_^h>=e^m>=e){var S=jt(Ct(f),Ct(n));Ft(S);var E=jt(u,S);Ft(E);var k=(_^b>=0?-1:1)*O(E[2]);(r>k||r===k&&(S[0]||S[1]))&&(o+=_^b>=0?1:-1)}if(!v++)break;h=m,p=M,d=x,f=n}}return(-Go>i||Go>i&&0>La)^1&o}function Qt(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Bo:-Bo,c=Math.abs(i-e);Math.abs(c-Bo)<Go?(n.point(e,r=(r+o)/2>0?Jo:-Jo),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Bo&&(Math.abs(e-u)<Go&&(e-=u*Go),Math.abs(i-a)<Go&&(i-=a*Go),r=ne(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function ne(n,t,e,r){var u,i,o=Math.sin(n-e);return Math.abs(o)>Go?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function te(n,t,e,r){var u;if(null==n)u=e*Jo,r.point(-Bo,u),r.point(0,u),r.point(Bo,u),r.point(Bo,0),r.point(Bo,-u),r.point(0,-u),r.point(-Bo,-u),r.point(-Bo,0),r.point(-Bo,u);else if(Math.abs(n[0]-t[0])>Go){var i=(n[0]<t[0]?1:-1)*Bo;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function ee(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],d=t(f,h),v=o?d?0:u(f,h):d?u(f+(0>f?Bo:-Bo),h):0;if(!e&&(l=c=d)&&n.lineStart(),d!==c&&(g=r(e,p),(Ot(e,g)||Ot(p,g))&&(p[0]+=Go,p[1]+=Go,d=t(p[0],p[1]))),d!==c)s=0,d?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^d){var m;v&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!d||e&&Ot(e,p)||n.point(p[0],p[1]),e=p,c=d,i=v},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=Ct(n),u=Ct(t),o=[1,0,0],a=jt(r,u),c=Dt(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=jt(o,a),p=Ht(o,f),d=Ht(a,h);Lt(p,d);var v=g,m=Dt(p,v),y=Dt(v,v),M=m*m-y*(Dt(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=Ht(v,(-m-x)/y);if(Lt(b,p),b=Pt(b),!e)return b;var _,w=n[0],S=t[0],E=n[1],k=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=Math.abs(A-Bo)<Go,T=N||Go>A;if(!N&&E>k&&(_=E,E=k,k=_),T?N?E+k>0^b[1]<(Math.abs(b[0]-w)<Go?E:k):E<=b[1]&&b[1]<=k:A>Bo^(w<=b[0]&&b[0]<=S)){var q=Ht(v,(-m+x)/y);return Lt(q,p),[b,Pt(q)]}}}function u(t,e){var r=o?n:Bo-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=Math.abs(i)>Go,c=Te(n,6*Qo);return Bt(t,e,c,o?[0,-n]:[-Bo,n-Bo])}function re(n,t,e,r){function u(r,u){return Math.abs(r[0]-n)<Go?u>0?0:3:Math.abs(r[0]-e)<Go?u>0?2:1:Math.abs(r[1]-t)<Go?u>0?1:0:u>0?3:2}function i(n,t){return o(n.point,t.point)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}function a(u,i){var o=i[0]-u[0],a=i[1]-u[1],c=[0,1];return Math.abs(o)<Go&&Math.abs(a)<Go?n<=u[0]&&u[0]<=e&&t<=u[1]&&u[1]<=r:ue(n-u[0],o,c)&&ue(u[0]-e,-o,c)&&ue(t-u[1],a,c)&&ue(u[1]-r,-a,c)?(c[1]<1&&(i[0]=u[0]+c[1]*o,i[1]=u[1]+c[1]*a),c[0]>0&&(u[0]+=c[0]*o,u[1]+=c[0]*a),!0):!1}return function(c){function l(n){for(var t=0,e=y.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=y[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&s(l,i,n)>0&&++t:i[1]<=r&&s(l,i,n)<0&&--t,l=i;return 0!==t}function s(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(e[0]-n[0])*(t[1]-n[1])}function f(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function h(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function g(n,t){h(n,t)&&c.point(n,t)}function p(){q.point=v,y&&y.push(M=[]),k=!0,E=!1,w=S=0/0}function d(){m&&(v(x,b),_&&E&&T.rejoin(),m.push(T.buffer())),q.point=g,E&&c.lineEnd()}function v(n,t){n=Math.max(-Ja,Math.min(Ja,n)),t=Math.max(-Ja,Math.min(Ja,t));var e=h(n,t);if(y&&M.push([n,t]),k)x=n,b=t,_=e,k=!1,e&&(c.lineStart(),c.point(n,t));else if(e&&E)c.point(n,t);else{var r=[w,S],u=[n,t];a(r,u)?(E||(c.lineStart(),c.point(r[0],r[1])),c.point(u[0],u[1]),e||c.lineEnd(),A=!1):e&&(c.lineStart(),c.point(n,t),A=!1)}w=n,S=t,E=e}var m,y,M,x,b,_,w,S,E,k,A,N=c,T=Jt(),q={point:g,lineStart:p,lineEnd:d,polygonStart:function(){c=T,m=[],y=[],A=!0},polygonEnd:function(){c=N,m=mo.merge(m);var t=l([n,r]),e=A&&t,u=m.length;(e||u)&&(c.polygonStart(),e&&(c.lineStart(),f(null,null,1,c),c.lineEnd()),u&&Xt(m,i,t,f,c),c.polygonEnd()),m=y=M=null}};return q}}function ue(n,t,e){if(Math.abs(t)<Go)return 0>=n;var r=n/t;if(t>0){if(r>e[1])return!1;r>e[0]&&(e[0]=r)}else{if(r<e[0])return!1;r<e[1]&&(e[1]=r)}return!0}function ie(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function oe(n){var t=0,e=Bo/3,r=be(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Bo/180,e=n[1]*Bo/180):[180*(t/Bo),180*(e/Bo)]},u}function ae(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,O((i-(n*n+e*e)*u*u)/(2*u))]},e}function ce(){function n(n,t){Ka+=u*n-r*t,r=n,u=t}var t,e,r,u;rc.point=function(i,o){rc.point=n,t=r=i,e=u=o},rc.lineEnd=function(){n(t,e)}}function le(n,t){Qa>n&&(Qa=n),n>tc&&(tc=n),nc>t&&(nc=t),t>ec&&(ec=t)}function se(){function n(n,t){o.push(\"M\",n,\",\",t,i)}function t(n,t){o.push(\"M\",n,\",\",t),a.point=e}function e(n,t){o.push(\"L\",n,\",\",t)}function r(){a.point=n}function u(){o.push(\"Z\")}var i=fe(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=fe(n),a},result:function(){if(o.length){var n=o.join(\"\");return o=[],n}}};return a}function fe(n){return\"m0,\"+n+\"a\"+n+\",\"+n+\" 0 1,1 0,\"+-2*n+\"a\"+n+\",\"+n+\" 0 1,1 0,\"+2*n+\"z\"}function he(n,t){Oa+=n,Ra+=t,++Ya}function ge(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);Ia+=o*(t+n)/2,Ua+=o*(e+r)/2,Za+=o,he(t=n,e=r)}var t,e;ic.point=function(r,u){ic.point=n,he(t=r,e=u)}}function pe(){ic.point=he}function de(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);Ia+=o*(r+n)/2,Ua+=o*(u+t)/2,Za+=o,o=u*n-r*t,Va+=o*(r+n),Xa+=o*(u+t),$a+=3*o,he(r=n,u=t)}var t,e,r,u;ic.point=function(i,o){ic.point=n,he(t=r=i,e=u=o)},ic.lineEnd=function(){n(t,e)}}function ve(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,Wo)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:c};return a}function me(n){function t(t){function r(e,r){e=n(e,r),t.point(e[0],e[1])}function u(){M=0/0,S.point=o,t.lineStart()}function o(r,u){var o=Ct([r,u]),a=n(r,u);e(M,x,y,b,_,w,M=a[0],x=a[1],y=r,b=o[0],_=o[1],w=o[2],i,t),t.point(M,x)}function a(){S.point=r,t.lineEnd()}function c(){u(),S.point=l,S.lineEnd=s}function l(n,t){o(f=n,h=t),g=M,p=x,d=b,v=_,m=w,S.point=o}function s(){e(M,x,y,b,_,w,g,p,f,d,v,m,i,t),S.lineEnd=a,a()}var f,h,g,p,d,v,m,y,M,x,b,_,w,S={point:r,lineStart:u,lineEnd:a,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=u}};return S}function e(t,i,o,a,c,l,s,f,h,g,p,d,v,m){var y=s-t,M=f-i,x=y*y+M*M;if(x>4*r&&v--){var b=a+g,_=c+p,w=l+d,S=Math.sqrt(b*b+_*_+w*w),E=Math.asin(w/=S),k=Math.abs(Math.abs(w)-1)<Go?(o+h)/2:Math.atan2(_,b),A=n(k,E),N=A[0],T=A[1],q=N-t,z=T-i,C=M*q-y*z;(C*C/x>r||Math.abs((y*q+M*z)/x-.5)>.3||u>a*g+c*p+l*d)&&(e(t,i,o,a,c,l,N,T,k,b/=S,_/=S,w,v,m),m.point(N,T),e(N,T,k,b,_,w,s,f,h,g,p,d,v,m))}}var r=.5,u=Math.cos(30*Qo),i=16;return t.precision=function(n){return arguments.length?(i=(r=n*n)>0&&16,t):Math.sqrt(r)},t}function ye(n){this.stream=n}function Me(n){var t=me(function(t,e){return n([t*na,e*na])});return function(n){var e=new ye(n=t(n));return e.point=function(t,e){n.point(t*Qo,e*Qo)},e}}function xe(n){return be(function(){return n})()}function be(n){function t(n){return n=a(n[0]*Qo,n[1]*Qo),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*na,n[1]*na]}function r(){a=ie(o=Ee(m,y,M),i);var n=i(d,v);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=me(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,d=0,v=0,m=0,y=0,M=0,x=Wa,b=dt,_=null,w=null;return t.stream=function(n){return s&&(s.valid=!1),s=_e(x(o,f(b(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(x=null==n?(_=n,Wa):ee((_=+n)*Qo),u()):_},t.clipExtent=function(n){return arguments.length?(w=n,b=n?re(n[0][0],n[0][1],n[1][0],n[1][1]):dt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(d=n[0]%360*Qo,v=n[1]%360*Qo,r()):[d*na,v*na]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Qo,y=n[1]%360*Qo,M=n.length>2?n[2]%360*Qo:0,r()):[m*na,y*na,M*na]},mo.rebind(t,f,\"precision\"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function _e(n){var t=new ye(n);return t.point=function(t,e){n.point(t*Qo,e*Qo)},t}function we(n,t){return[n,t]}function Se(n,t){return[n>Bo?n-Wo:-Bo>n?n+Wo:n,t]}function Ee(n,t,e){return n?t||e?ie(Ae(n),Ne(t,e)):Ae(n):t||e?Ne(t,e):Se}function ke(n){return function(t,e){return t+=n,[t>Bo?t-Wo:-Bo>t?t+Wo:t,e]}}function Ae(n){var t=ke(n);return t.invert=ke(-n),t}function Ne(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),O(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),O(s*r-a*u)]},e}function Te(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=qe(e,u),i=qe(e,i),(o>0?i>u:u>i)&&(u+=o*Wo)):(u=n+o*Wo,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=Pt([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function qe(n,t){var e=Ct(t);e[0]-=n,Ft(e);var r=P(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Go)%(2*Math.PI)}function ze(n,t,e){var r=mo.range(n,t-Go,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function Ce(n,t,e){var r=mo.range(n,t-Go,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function De(n){return n.source}function je(n){return n.target}function Le(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(U(r-t)+u*o*U(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*na,Math.atan2(o,Math.sqrt(r*r+u*u))*na]}:function(){return[n*na,t*na]};return p.distance=h,p}function He(){function n(n,u){var i=Math.sin(u*=Qo),o=Math.cos(u),a=Math.abs((n*=Qo)-t),c=Math.cos(a);oc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;ac.point=function(u,i){t=u*Qo,e=Math.sin(i*=Qo),r=Math.cos(i),ac.point=n},ac.lineEnd=function(){ac.point=ac.lineEnd=c}}function Fe(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function Pe(n,t){function e(n,t){var e=Math.abs(Math.abs(t)-Jo)<Go?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Bo/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=F(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Jo]},e):Re}function Oe(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return Math.abs(u)<Go?we:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-F(u)*Math.sqrt(n*n+e*e)]},e)}function Re(n,t){return[n,Math.log(Math.tan(Bo/4+t/2))]}function Ye(n){var t,e=xe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Bo*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Ie(n,t){var e=Math.cos(t)*Math.sin(n);return[Math.log((1+e)/(1-e))/2,Math.atan2(Math.tan(t),Math.cos(n))]}function Ue(n){function t(t){function o(){l.push(\"M\",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=pt(e),p=pt(r);++f<h;)u.call(this,c=t[f],f)?s.push([+g.call(this,c,f),+p.call(this,c,f)]):s.length&&(o(),s=[]);return s.length&&o(),l.length?l.join(\"\"):null}var e=Ze,r=Ve,u=Vt,i=Xe,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o=\"function\"==typeof n?i=n:(i=gc.get(n)||Xe).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function Ze(n){return n[0]}function Ve(n){return n[1]}function Xe(n){return n.join(\"L\")}function $e(n){return Xe(n)+\"Z\"}function Be(n){for(var t=0,e=n.length,r=n[0],u=[r[0],\",\",r[1]];++t<e;)u.push(\"H\",(r[0]+(r=n[t])[0])/2,\"V\",r[1]);return e>1&&u.push(\"H\",r[0]),u.join(\"\")}function We(n){for(var t=0,e=n.length,r=n[0],u=[r[0],\",\",r[1]];++t<e;)u.push(\"V\",(r=n[t])[1],\"H\",r[0]);return u.join(\"\")}function Je(n){for(var t=0,e=n.length,r=n[0],u=[r[0],\",\",r[1]];++t<e;)u.push(\"H\",(r=n[t])[0],\"V\",r[1]);return u.join(\"\")}function Ge(n,t){return n.length<4?Xe(n):n[1]+nr(n.slice(1,n.length-1),tr(n,t))}function Ke(n,t){return n.length<3?Xe(n):n[0]+nr((n.push(n[0]),n),tr([n[n.length-2]].concat(n,[n[1]]),t))}function Qe(n,t){return n.length<3?Xe(n):n[0]+nr(n,tr(n,t))}function nr(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return Xe(n);var e=n.length!=t.length,r=\"\",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+=\"Q\"+(i[0]-2*o[0]/3)+\",\"+(i[1]-2*o[1]/3)+\",\"+i[0]+\",\"+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+=\"C\"+(u[0]+o[0])+\",\"+(u[1]+o[1])+\",\"+(i[0]-a[0])+\",\"+(i[1]-a[1])+\",\"+i[0]+\",\"+i[1];for(var l=2;l<t.length;l++,c++)i=n[c],a=t[l],r+=\"S\"+(i[0]-a[0])+\",\"+(i[1]-a[1])+\",\"+i[0]+\",\"+i[1]}if(e){var s=n[c];r+=\"Q\"+(i[0]+2*a[0]/3)+\",\"+(i[1]+2*a[1]/3)+\",\"+s[0]+\",\"+s[1]}return r}function tr(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function er(n){if(n.length<3)return Xe(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,\",\",i,\"L\",or(vc,o),\",\",or(vc,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),ar(c,o,a);return n.pop(),c.push(\"L\",r),c.join(\"\")}function rr(n){if(n.length<4)return Xe(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(or(vc,i)+\",\"+or(vc,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),ar(e,i,o);return e.join(\"\")}function ur(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[or(vc,o),\",\",or(vc,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),ar(t,o,a);return t.join(\"\")}function ir(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,l=-1;++l<=e;)r=n[l],u=l/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return er(n)}function or(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function ar(n,t,e){n.push(\"C\",or(pc,t),\",\",or(pc,e),\",\",or(dc,t),\",\",or(dc,e),\",\",or(vc,t),\",\",or(vc,e))}function cr(n,t){return(t[1]-n[1])/(t[0]-n[0])}function lr(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=cr(u,i);++t<e;)r[t]=(o+(o=cr(u=i,i=n[t+1])))/2;return r[t]=o,r\n}function sr(n){for(var t,e,r,u,i=[],o=lr(n),a=-1,c=n.length-1;++a<c;)t=cr(n[a],n[a+1]),Math.abs(t)<Go?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function fr(n){return n.length<3?Xe(n):n[0]+nr(n,sr(n))}function hr(n,t,e,r){var u,i,o,a,c,l,s;return u=r[n],i=u[0],o=u[1],u=r[t],a=u[0],c=u[1],u=r[e],l=u[0],s=u[1],(s-o)*(a-i)-(c-o)*(l-i)>0}function gr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function pr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function dr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function vr(n,t){var e={list:n.map(function(n,t){return{index:t,x:n[0],y:n[1]}}).sort(function(n,t){return n.y<t.y?-1:n.y>t.y?1:n.x<t.x?-1:n.x>t.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,\"l\"),r.rightEnd=r.createHalfEdge(null,\"l\"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(n,t){return{edge:n,side:t,vertex:null,l:null,r:null}},insert:function(n,t){t.l=n,t.r=n.r,n.r.l=t,n.r=t},leftBound:function(n){var t=r.leftEnd;do t=t.r;while(t!=r.rightEnd&&u.rightOf(t,n));return t=t.l},del:function(n){n.l.r=n.r,n.r.l=n.l,n.edge=null},right:function(n){return n.r},left:function(n){return n.l},leftRegion:function(n){return null==n.edge?e.bottomSite:n.edge.region[n.side]},rightRegion:function(n){return null==n.edge?e.bottomSite:n.edge.region[yc[n.side]]}},u={bisect:function(n,t){var e={region:{l:n,r:t},ep:{l:null,r:null}},r=t.x-n.x,u=t.y-n.y,i=r>0?r:-r,o=u>0?u:-u;return e.c=n.x*r+n.y*u+.5*(r*r+u*u),i>o?(e.a=1,e.b=u/r,e.c/=r):(e.b=1,e.a=r/u,e.c/=u),e},intersect:function(n,t){var e=n.edge,r=t.edge;if(!e||!r||e.region.r==r.region.r)return null;var u=e.a*r.b-e.b*r.a;if(Math.abs(u)<1e-10)return null;var i,o,a=(e.c*r.b-r.c*e.b)/u,c=(r.c*e.a-e.c*r.a)/u,l=e.region.r,s=r.region.r;l.y<s.y||l.y==s.y&&l.x<s.x?(i=n,o=e):(i=t,o=r);var f=a>=o.region.r.x;return f&&\"l\"===i.side||!f&&\"r\"===i.side?null:{x:a,y:c}},rightOf:function(n,t){var e=n.edge,r=e.region.r,u=t.x>r.x;if(u&&\"l\"===n.side)return 1;if(!u&&\"r\"===n.side)return 0;if(1===e.a){var i=t.y-r.y,o=t.x-r.x,a=0,c=0;if(!u&&e.b<0||u&&e.b>=0?c=a=i>=e.b*o:(c=t.x+t.y*e.b>e.c,e.b<0&&(c=!c),c||(a=1)),!a){var l=r.x-e.region.l.x;c=e.b*(o*o-i*i)<l*i*(1+2*o/l+e.b*e.b),e.b<0&&(c=!c)}}else{var s=e.c-e.a*t.x,f=t.y-s,h=t.x-r.x,g=s-r.y;c=f*f>h*h+g*g}return\"l\"===n.side?c:!c},endPoint:function(n,e,r){n.ep[e]=r,n.ep[yc[e]]&&t(n)},distance:function(n,t){var e=n.x-t.x,r=n.y-t.y;return Math.sqrt(e*e+r*r)}},i={list:[],insert:function(n,t,e){n.vertex=t,n.ystar=t.y+e;for(var r=0,u=i.list,o=u.length;o>r;r++){var a=u[r];if(!(n.ystar>a.ystar||n.ystar==a.ystar&&t.x>a.vertex.x))break}u.splice(r,0,n)},del:function(n){for(var t=0,e=i.list,r=e.length;r>t&&e[t]!=n;++t);e.splice(t,1)},empty:function(){return 0===i.list.length},nextEvent:function(n){for(var t=0,e=i.list,r=e.length;r>t;++t)if(e[t]==n)return e[t+1];return null},min:function(){var n=i.list[0];return{x:n.vertex.x,y:n.ystar}},extractMin:function(){return i.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var o,a,c,l,s,f,h,g,p,d,v,m,y,M=e.list.shift();;)if(i.empty()||(o=i.min()),M&&(i.empty()||M.y<o.y||M.y==o.y&&M.x<o.x))a=r.leftBound(M),c=r.right(a),h=r.rightRegion(a),m=u.bisect(h,M),f=r.createHalfEdge(m,\"l\"),r.insert(a,f),d=u.intersect(a,f),d&&(i.del(a),i.insert(a,d,u.distance(d,M))),a=f,f=r.createHalfEdge(m,\"r\"),r.insert(a,f),d=u.intersect(f,c),d&&i.insert(f,d,u.distance(d,M)),M=e.list.shift();else{if(i.empty())break;a=i.extractMin(),l=r.left(a),c=r.right(a),s=r.right(c),h=r.leftRegion(a),g=r.rightRegion(c),v=a.vertex,u.endPoint(a.edge,a.side,v),u.endPoint(c.edge,c.side,v),r.del(a),i.del(c),r.del(c),y=\"l\",h.y>g.y&&(p=h,h=g,g=p,y=\"r\"),m=u.bisect(h,g),f=r.createHalfEdge(m,y),r.insert(l,f),u.endPoint(m,yc[y],v),d=u.intersect(l,f),d&&(i.del(l),i.insert(l,d,u.distance(d,h))),d=u.intersect(f,s),d&&i.insert(f,d,u.distance(d,h))}for(a=r.right(r.leftEnd);a!=r.rightEnd;a=r.right(a))t(a.edge)}function mr(n){return n.x}function yr(n){return n.y}function Mr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function xr(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&xr(n,c[0],e,r,o,a),c[1]&&xr(n,c[1],o,r,u,a),c[2]&&xr(n,c[2],e,a,o,i),c[3]&&xr(n,c[3],o,a,u,i)}}function br(n,t){n=mo.rgb(n),t=mo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return\"#\"+ct(Math.round(e+i*n))+ct(Math.round(r+o*n))+ct(Math.round(u+a*n))}}function _r(n,t){var e,r={},u={};for(e in n)e in t?r[e]=Er(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function wr(n,t){return t-=n=+n,function(e){return n+t*e}}function Sr(n,t){var e,r,u,i,o,a=0,c=0,l=[],s=[];for(n+=\"\",t+=\"\",Mc.lastIndex=0,r=0;e=Mc.exec(t);++r)e.index&&l.push(t.substring(a,c=e.index)),s.push({i:l.length,x:e[0]}),l.push(null),a=Mc.lastIndex;for(a<t.length&&l.push(t.substring(a)),r=0,i=s.length;(e=Mc.exec(n))&&i>r;++r)if(o=s[r],o.x==e[0]){if(o.i)if(null==l[o.i+1])for(l[o.i-1]+=o.x,l.splice(o.i,1),u=r+1;i>u;++u)s[u].i--;else for(l[o.i-1]+=o.x+l[o.i+1],l.splice(o.i,2),u=r+1;i>u;++u)s[u].i-=2;else if(null==l[o.i+1])l[o.i]=o.x;else for(l[o.i]=o.x+l[o.i+1],l.splice(o.i+1,1),u=r+1;i>u;++u)s[u].i--;s.splice(r,1),i--,r--}else o.x=wr(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=s.pop(),null==l[o.i+1]?l[o.i]=o.x:(l[o.i]=o.x+l[o.i+1],l.splice(o.i+1,1)),i--;return 1===l.length?null==l[0]?(o=s[0].x,function(n){return o(n)+\"\"}):function(){return t}:function(n){for(r=0;i>r;++r)l[(o=s[r]).i]=o.x(n);return l.join(\"\")}}function Er(n,t){for(var e,r=mo.interpolators.length;--r>=0&&!(e=mo.interpolators[r](n,t)););return e}function kr(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Er(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Ar(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function Nr(n){return function(t){return 1-n(1-t)}}function Tr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function qr(n){return n*n}function zr(n){return n*n*n}function Cr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Dr(n){return function(t){return Math.pow(t,n)}}function jr(n){return 1-Math.cos(n*Jo)}function Lr(n){return Math.pow(2,10*(n-1))}function Hr(n){return 1-Math.sqrt(1-n*n)}function Fr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Wo*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Wo/t)}}function Pr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Or(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=mo.hcl(n),t=mo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return J(e+i*n,r+o*n,u+a*n)+\"\"}}function Yr(n,t){n=mo.hsl(n),t=mo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return $(e+i*n,r+o*n,u+a*n)+\"\"}}function Ir(n,t){n=mo.lab(n),t=mo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return Q(e+i*n,r+o*n,u+a*n)+\"\"}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Zr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Xr(t),u=Vr(t,e),i=Xr($r(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*na,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*na:0}function Vr(n,t){return n[0]*t[0]+n[1]*t[1]}function Xr(n){var t=Math.sqrt(Vr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function $r(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Br(n,t){var e,r=[],u=[],i=mo.transform(n),o=mo.transform(t),a=i.translate,c=o.translate,l=i.rotate,s=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push(\"translate(\",null,\",\",null,\")\"),u.push({i:1,x:wr(a[0],c[0])},{i:3,x:wr(a[1],c[1])})):c[0]||c[1]?r.push(\"translate(\"+c+\")\"):r.push(\"\"),l!=s?(l-s>180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+\"rotate(\",null,\")\")-2,x:wr(l,s)})):s&&r.push(r.pop()+\"rotate(\"+s+\")\"),f!=h?u.push({i:r.push(r.pop()+\"skewX(\",null,\")\")-2,x:wr(f,h)}):h&&r.push(r.pop()+\"skewX(\"+h+\")\"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+\"scale(\",null,\",\",null,\")\"),u.push({i:e-4,x:wr(g[0],p[0])},{i:e-2,x:wr(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+\"scale(\"+p+\")\"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join(\"\")}}function Wr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Jr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Gr(n){for(var t=n.source,e=n.target,r=Qr(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Kr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Qr(n,t){if(n===t)return n;for(var e=Kr(n),r=Kr(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function nu(n){n.fixed|=2}function tu(n){n.fixed&=-7}function eu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function ru(n){n.fixed&=-5}function uu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(uu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var l=t*e[n.point.index];n.charge+=n.pointCharge=l,r+=l*n.point.x,u+=l*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function iu(n,t){return mo.rebind(n,t,\"sort\",\"children\",\"value\"),n.nodes=n,n.links=lu,n}function ou(n){return n.children}function au(n){return n.value}function cu(n,t){return t.value-n.value}function lu(n){return mo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function su(n){return n.x}function fu(n){return n.y}function hu(n,t,e){n.y0=t,n.y=e}function gu(n){return mo.range(n.length)}function pu(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function du(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function vu(n){return n.reduce(mu,0)}function mu(n,t){return n+t[1]}function yu(n,t){return Mu(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function Mu(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function xu(n){return[mo.min(n),mo.max(n)]}function bu(n,t){return n.parent==t.parent?1:2}function _u(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function wu(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function Su(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=Su(e[i],t),n)>0&&(n=r);return n}function Eu(n,t){return n.x-t.x}function ku(n,t){return t.x-n.x}function Au(n,t){return n.depth-t.depth}function Nu(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function Tu(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function qu(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function zu(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function Cu(n,t){return n.value-t.value}function Du(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function ju(n,t){n._pack_next=t,t._pack_prev=n}function Lu(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Hu(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(Fu),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],Ru(r,u,i),t(i),Du(r,i),r._pack_prev=i,Du(i,u),u=r._pack_next,o=3;l>o;o++){Ru(r,u,i=e[o]);var p=0,d=1,v=1;for(a=u._pack_next;a!==u;a=a._pack_next,d++)if(Lu(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!Lu(c,i);c=c._pack_prev,v++);p?(v>d||d==v&&u.r<r.r?ju(r,u=a):ju(r=c,u),o--):(Du(r,i),u=i,t(i))}var m=(s+f)/2,y=(h+g)/2,M=0;for(o=0;l>o;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(Pu)}}function Fu(n){n._pack_next=n._pack_prev=n}function Pu(n){delete n._pack_next,delete n._pack_prev}function Ou(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)Ou(u[i],t,e,r)}function Ru(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),l=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+l*i,e.y=n.y+c*i-l*u}else e.x=n.x+r,e.y=n.y}function Yu(n){return 1+mo.max(n,function(n){return n.y})}function Iu(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Uu(n){var t=n.children;return t&&t.length?Uu(t[0]):n}function Zu(n){var t,e=n.children;return e&&(t=e.length)?Zu(e[t-1]):n}function Vu(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Xu(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function $u(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Bu(n){return n.rangeExtent?n.rangeExtent():$u(n.range())}function Wu(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ju(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Gu(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Tc}function Ku(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=mo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Qu(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Ku:Wu,c=r?Jr:Wr;return o=u(n,t,c,e),a=u(t,n,c,Er),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Ur)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return ri(n,t)},i.tickFormat=function(t,e){return ui(n,t,e)},i.nice=function(t){return ti(n,t),u()},i.copy=function(){return Qu(n,t,e,r)},u()}function ni(n,t){return mo.rebind(n,t,\"range\",\"rangeRound\",\"interpolate\",\"clamp\")}function ti(n,t){return Ju(n,Gu(ei(n,t)[2]))}function ei(n,t){null==t&&(t=10);var e=$u(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function ri(n,t){return mo.range.apply(mo,ei(n,t))}function ui(n,t,e){var r=-Math.floor(Math.log(ei(n,t)[2])/Math.LN10+.01);return mo.format(e?e.replace(Aa,function(n,t,e,u,i,o,a,c,l,s){return[t,e,u,i,o,a,c,l||\".\"+(r-2*(\"%\"===s)),s].join(\"\")}):\",.\"+r+\"f\")}function ii(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ju(r.map(u),e?Math:zc);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=$u(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++<s;)for(var h=f-1;h>0;h--)o.push(i(l)*h);for(l=0;o[l]<a;l++);for(s=o.length;o[s-1]>c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return qc;arguments.length<2?t=qc:\"function\"!=typeof t&&(t=mo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):\"\"}},o.copy=function(){return ii(n.copy(),t,e,r)},ni(o,n)}function oi(n,t,e){function r(t){return n(u(t))}var u=ai(t),i=ai(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return ri(e,n)},r.tickFormat=function(n,t){return ui(e,n,t)},r.nice=function(n){return r.domain(ti(e,n))},r.exponent=function(o){return arguments.length?(u=ai(t=o),i=ai(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return oi(n.copy(),t,e)},ni(r,n)}function ai(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ci(n,t){function e(e){return o[((i.get(e)||\"range\"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return mo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:\"range\",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],l=u[1],s=(l-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+l)/2:c+s*i/2,s),a=0,t={t:\"rangePoints\",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=(f-s)/(n.length-i+2*c);return o=r(s+h*c,h),l&&o.reverse(),a=h*(1-i),t={t:\"rangeBands\",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=Math.floor((f-s)/(n.length-i+2*c)),g=f-s-(n.length-i)*h;return o=r(s+Math.round(g/2),h),l&&o.reverse(),a=Math.round(h*(1-i)),t={t:\"rangeRoundBands\",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return $u(t.a[0])},e.copy=function(){return ci(n,t)},e.domain(n)}function li(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=mo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[mo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(mo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return li(n,t)},e()}function si(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return si(n,t,e)},u()}function fi(n,t){function e(e){return e>=e?t[mo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return fi(n,t)},e}function hi(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return ri(n,t)},t.tickFormat=function(t,e){return ui(n,t,e)},t.copy=function(){return hi(n)},t}function gi(n){return n.innerRadius}function pi(n){return n.outerRadius}function di(n){return n.startAngle}function vi(n){return n.endAngle}function mi(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+Hc,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function yi(n){function t(t){function c(){d.push(\"M\",a(n(m),f),s,l(n(v.reverse()),f),\"Z\")}for(var h,g,p,d=[],v=[],m=[],y=-1,M=t.length,x=pt(e),b=pt(u),_=e===r?function(){return g}:pt(r),w=u===i?function(){return p}:pt(i);++y<M;)o.call(this,h=t[y],y)?(v.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),m.push([+_.call(this,h,y),+w.call(this,h,y)])):v.length&&(c(),v=[],m=[]);return v.length&&c(),d.length?d.join(\"\"):null}var e=Ze,r=Ze,u=0,i=Ve,o=Vt,a=Xe,c=a.key,l=a,s=\"L\",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c=\"function\"==typeof n?a=n:(a=gc.get(n)||Xe).key,l=a.reverse||a,s=a.closed?\"M\":\"L\",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Mi(n){return n.radius}function xi(n){return[n.x,n.y]}function bi(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+Hc;return[e*Math.cos(r),e*Math.sin(r)]}}function _i(){return 64}function wi(){return\"circle\"}function Si(n){var t=Math.sqrt(n/Bo);return\"M0,\"+t+\"A\"+t+\",\"+t+\" 0 1,1 0,\"+-t+\"A\"+t+\",\"+t+\" 0 1,1 0,\"+t+\"Z\"}function Ei(n,t){return Lo(n,Uc),n.id=t,n}function ki(n,t,e,r){var u=n.id;return N(n,\"function\"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Ai(n){return null==n&&(n=\"\"),function(){this.textContent=n}}function Ni(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,mo.timer(function(r){function u(r){return i.active>e?l():(i.active=e,o.event&&o.event.start.call(n,s,t),o.tween.forEach(function(e,r){(r=r.call(n,s,t))&&p.push(r)}),c(r||1)?1:(xt(c,h,a),void 0))}function c(r){if(i.active!==e)return l();for(var u=r/g,a=f(u),c=p.length;c>0;)p[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,s,t),l()):void 0}function l(){return--i.count?delete i[e]:delete n.__transition__,1}var s=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=[];return r>=h?u(r-h):(xt(u,h,a),void 0)},0,a)}}function Ti(n,t){n.attr(\"transform\",function(n){return\"translate(\"+t(n)+\",0)\"})}function qi(n,t){n.attr(\"transform\",function(n){return\"translate(0,\"+t(n)+\")\"})}function zi(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ci(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new Jc(e-1)),1),e}function i(n,e){return t(n=new Jc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{Jc=zi;var r=new zi;return r._=n,o(r,t,e)}finally{Jc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Di(n);return c.floor=c,c.round=Di(r),c.ceil=Di(u),c.offset=Di(i),c.range=a,n}function Di(n){return function(t,e){try{Jc=zi;var r=new zi;return r._=t,n(r,e)._}finally{Jc=Date}}}function ji(n){function t(t){for(var r,u,i,o=[],a=-1,c=0;++a<e;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=dl[r=n.charAt(++a)])&&(r=n.charAt(++a)),(i=vl[r])&&(r=i(t,null==u?\"e\"===r?\" \":\"0\":u)),o.push(r),c=a+1);return o.push(n.substring(c,a)),o.join(\"\")}var e=n.length;return t.parse=function(t){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},r=Li(e,n,t,0);if(r!=t.length)return null;\"p\"in e&&(e.H=e.H%12+12*e.p);var u=null!=e.Z&&Jc!==zi,i=new(u?zi:Jc);return\"j\"in e?i.setFullYear(e.y,0,e.j):\"w\"in e&&(\"W\"in e||\"U\"in e)?(i.setFullYear(e.y,0,1),i.setFullYear(e.y,0,\"W\"in e?(e.w+6)%7+7*e.W-(i.getDay()+5)%7:e.w+7*e.U-(i.getDay()+6)%7)):i.setFullYear(e.y,e.m,e.d),i.setHours(e.H+Math.floor(e.Z/100),e.M+e.Z%100,e.S,e.L),u?i._:i},t.toString=function(){return n},t}function Li(n,t,e,r){for(var u,i,o,a=0,c=t.length,l=e.length;c>a;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=ml[o in dl?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function Hi(n){return new RegExp(\"^(?:\"+n.map(mo.requote).join(\"|\")+\")\",\"i\")}function Fi(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Pi(n,t,e){var r=0>n?\"-\":\"\",u=(r?-n:n)+\"\",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Oi(n,t,e){cl.lastIndex=0;var r=cl.exec(t.substring(e));return r?(n.w=ll.get(r[0].toLowerCase()),e+r[0].length):-1}function Ri(n,t,e){ol.lastIndex=0;var r=ol.exec(t.substring(e));return r?(n.w=al.get(r[0].toLowerCase()),e+r[0].length):-1}function Yi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ii(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Ui(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function Zi(n,t,e){hl.lastIndex=0;var r=hl.exec(t.substring(e));return r?(n.m=gl.get(r[0].toLowerCase()),e+r[0].length):-1}function Vi(n,t,e){sl.lastIndex=0;var r=sl.exec(t.substring(e));return r?(n.m=fl.get(r[0].toLowerCase()),e+r[0].length):-1}function Xi(n,t,e){return Li(n,vl.c.toString(),t,e)}function $i(n,t,e){return Li(n,vl.x.toString(),t,e)}function Bi(n,t,e){return Li(n,vl.X.toString(),t,e)}function Wi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Ji(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.y=Ki(+r[0]),e+r[0].length):-1}function Gi(n,t,e){return/^[+-]\\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Ki(n){return n+(n>68?1900:2e3)}function Qi(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function no(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function to(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function eo(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ro(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function uo(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function io(n,t,e){yl.lastIndex=0;var r=yl.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function oo(n,t,e){var r=Ml.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}function ao(n){var t=n.getTimezoneOffset(),e=t>0?\"-\":\"+\",r=~~(Math.abs(t)/60),u=Math.abs(t)%60;return e+Pi(r,\"0\",2)+Pi(u,\"0\",2)}function co(n,t,e){pl.lastIndex=0;var r=pl.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function lo(n){function t(n){try{Jc=zi;var t=new Jc;return t._=n,e(t)}finally{Jc=Date}}var e=ji(n);return t.parse=function(n){try{Jc=zi;var t=e.parse(n);return t&&t._}finally{Jc=Date}},t.toString=e.toString,t}function so(n){return n.toISOString()}function fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=mo.bisect(bl,u);return i==bl.length?[t.year,ei(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/bl[i-1]<bl[i]/u?i-1:i]:[El,ei(n,e)[2]]}return r.invert=function(t){return ho(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(ho)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,ho(+e+1),t).length}var i=r.domain(),o=$u(i),a=null==n?u(o,10):\"number\"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Ju(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=ho(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=ho(+t+1);return t}}:n))},r.ticks=function(n,t){var e=$u(r.domain()),i=null==n?u(e,10):\"number\"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],ho(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return fo(n.copy(),t,e)},ni(r,n)}function ho(n){return new Date(n)}function go(n){return function(t){for(var e=n.length-1,r=n[e];!r[1](t);)r=n[--e];return r[0](t)}}function po(n){return JSON.parse(n.responseText)}function vo(n){var t=xo.createRange();return t.selectNode(xo.body),t.createContextualFragment(n.responseText)}var mo={version:\"3.3.6\"};Date.now||(Date.now=function(){return+new Date});var yo=[].slice,Mo=function(n){return yo.call(n)},xo=document,bo=xo.documentElement,_o=window;try{Mo(bo.childNodes)[0].nodeType}catch(wo){Mo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{xo.createElement(\"div\").style.setProperty(\"opacity\",0,\"\")}catch(So){var Eo=_o.Element.prototype,ko=Eo.setAttribute,Ao=Eo.setAttributeNS,No=_o.CSSStyleDeclaration.prototype,To=No.setProperty;Eo.setAttribute=function(n,t){ko.call(this,n,t+\"\")},Eo.setAttributeNS=function(n,t,e){Ao.call(this,n,t,e+\"\")},No.setProperty=function(n,t,e){To.call(this,n,t+\"\",e)}}mo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},mo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},mo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},mo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},mo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},mo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},mo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},mo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},mo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?mo.quantile(t.sort(mo.ascending),.5):void 0},mo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var qo=mo.bisector(function(n){return n});mo.bisectLeft=qo.left,mo.bisect=mo.bisectRight=qo.right,mo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},mo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},mo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},mo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=mo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},mo.transpose=function(n){return mo.zip.apply(mo,n)},mo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},mo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},mo.entries=function(n){var t=[];\n    for(var e in n)t.push({key:e,value:n[e]});return t},mo.merge=function(n){return Array.prototype.concat.apply([],n)},mo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error(\"infinite range\");var u,i=[],o=e(Math.abs(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},mo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:function(n){return zo+n in this},get:function(n){return this[zo+n]},set:function(n,t){return this[zo+n]=t},remove:function(n){return n=zo+n,n in this&&delete this[n]},keys:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===Co&&n.call(this,t.substring(1),this[t])}});var zo=\"\\x00\",Co=zo.charCodeAt(0);mo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var l,s,f,h,g=-1,p=a.length,d=o[c++],v=new u;++g<p;)(h=v.get(l=d(s=a[g])))?h.push(s):v.set(l,[s]);return t?(s=t(),f=function(e,r){s.set(e,n(t,r,c))}):(s={},f=function(e,r){s[e]=n(t,r,c)}),v.forEach(f),s}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(mo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},mo.set=function(n){var t=new i;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(i,{has:function(n){return zo+n in this},add:function(n){return this[zo+n]=!0,n},remove:function(n){return n=zo+n,n in this&&delete this[n]},values:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===Co&&n.call(this,t.substring(1))}}),mo.behavior={},mo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=o(n,t,t[e]);return n};var Do=[\"webkit\",\"ms\",\"moz\",\"Moz\",\"o\",\"O\"];mo.dispatch=function(){for(var n=new l,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=s(n);return n},l.prototype.on=function(n,t){var e=n.indexOf(\".\"),r=\"\";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},mo.event=null,mo.requote=function(n){return n.replace(jo,\"\\\\$&\")};var jo=/[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g,Lo={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ho=function(n,t){return t.querySelector(n)},Fo=function(n,t){return t.querySelectorAll(n)},Po=bo[a(bo,\"matchesSelector\")],Oo=function(n,t){return Po.call(n,t)};\"function\"==typeof Sizzle&&(Ho=function(n,t){return Sizzle(n,t)[0]||null},Fo=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},Oo=Sizzle.matchesSelector),mo.selection=function(){return Uo};var Ro=mo.selection.prototype=[];Ro.select=function(n){var t,e,r,u,i=[];n=d(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,l=r.length;++c<l;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&\"__data__\"in u&&(e.__data__=u.__data__)):t.push(null)}return p(i)},Ro.selectAll=function(n){var t,e,r=[];n=v(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Mo(n.call(e,e.__data__,a,u))),t.parentNode=e);return p(r)};var Yo={svg:\"http://www.w3.org/2000/svg\",xhtml:\"http://www.w3.org/1999/xhtml\",xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"};mo.ns={prefix:Yo,qualify:function(n){var t=n.indexOf(\":\"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),Yo.hasOwnProperty(e)?{space:Yo[e],local:n}:n}},Ro.attr=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node();return n=mo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(m(t,n[t]));return this}return this.each(m(n,t))},Ro.classed=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node(),r=(n=n.trim().split(/^|\\s+/g)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute(\"class\");++u<r;)if(!M(n[u]).test(t))return!1;return!0}for(t in n)this.each(x(t,n[t]));return this}return this.each(x(n,t))},Ro.style=function(n,t,e){var r=arguments.length;if(3>r){if(\"string\"!=typeof n){2>r&&(t=\"\");for(e in n)this.each(_(e,n[e],t));return this}if(2>r)return _o.getComputedStyle(this.node(),null).getPropertyValue(n);e=\"\"}return this.each(_(n,t,e))},Ro.property=function(n,t){if(arguments.length<2){if(\"string\"==typeof n)return this.node()[n];for(t in n)this.each(w(t,n[t]));return this}return this.each(w(n,t))},Ro.text=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?\"\":t}:null==n?function(){this.textContent=\"\"}:function(){this.textContent=n}):this.node().textContent},Ro.html=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?\"\":t}:null==n?function(){this.innerHTML=\"\"}:function(){this.innerHTML=n}):this.node().innerHTML},Ro.append=function(n){return n=S(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Ro.insert=function(n,t){return n=S(n),t=d(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments))})},Ro.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},Ro.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),d=new Array(a);if(t){var v,m=new u,y=new u,M=[];for(r=-1;++r<a;)v=t.call(i=n[r],i.__data__,r),m.has(v)?d[r]=i:m.set(v,i),M.push(v);for(r=-1;++r<f;)v=t.call(e,o=e[r],r),(i=m.get(v))?(g[r]=i,i.__data__=o):y.has(v)||(p[r]=E(o)),y.set(v,o),m.remove(v);for(r=-1;++r<a;)m.has(M[r])&&(d[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=E(o);for(;f>r;++r)p[r]=E(e[r]);for(;a>r;++r)d[r]=n[r]}p.update=g,p.parentNode=g.parentNode=d.parentNode=n.parentNode,c.push(p),l.push(g),s.push(d)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=T([]),l=p([]),s=p([]);if(\"function\"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return l.enter=function(){return c},l.exit=function(){return s},l},Ro.datum=function(n){return arguments.length?this.property(\"__data__\",n):this.property(\"__data__\")},Ro.filter=function(n){var t,e,r,u=[];\"function\"!=typeof n&&(n=k(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a)&&t.push(r)}return p(u)},Ro.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Ro.sort=function(n){n=A.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Ro.each=function(n){return N(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Ro.call=function(n){var t=Mo(arguments);return n.apply(t[0]=this,t),this},Ro.empty=function(){return!this.node()},Ro.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Ro.size=function(){var n=0;return this.each(function(){++n}),n};var Io=[];mo.selection.enter=T,mo.selection.enter.prototype=Io,Io.append=Ro.append,Io.empty=Ro.empty,Io.node=Ro.node,Io.call=Ro.call,Io.size=Ro.size,Io.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var l=-1,s=u.length;++l<s;)(i=u[l])?(t.push(r[l]=e=n.call(u.parentNode,i.__data__,l,a)),e.__data__=i.__data__):t.push(null)}return p(o)},Io.insert=function(n,t){return arguments.length<2&&(t=q(this)),Ro.insert.call(this,n,t)},Ro.transition=function(){for(var n,t,e=Oc||++Zc,r=[],u=Rc||{time:Date.now(),ease:Cr,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,l=a.length;++c<l;)(t=a[c])&&Ni(t,c,e,u),n.push(t)}return Ei(r,e)},Ro.interrupt=function(){return this.each(z)},mo.select=function(n){var t=[\"string\"==typeof n?Ho(n,xo):n];return t.parentNode=bo,p([t])},mo.selectAll=function(n){var t=Mo(\"string\"==typeof n?Fo(n,xo):n);return t.parentNode=bo,p([t])};var Uo=mo.select(bo);Ro.on=function(n,t,e){var r=arguments.length;if(3>r){if(\"string\"!=typeof n){2>r&&(t=!1);for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return(r=this.node()[\"__on\"+n])&&r._;e=!1}return this.each(C(n,t,e))};var Zo=mo.map({mouseenter:\"mouseover\",mouseleave:\"mouseout\"});Zo.forEach(function(n){\"on\"+n in xo&&Zo.remove(n)});var Vo=a(bo.style,\"userSelect\"),Xo=0;mo.mouse=function(n){return H(n,h())};var $o=/WebKit/.test(_o.navigator.userAgent)?-1:0;mo.touches=function(n,t){return arguments.length<2&&(t=h().touches),t?Mo(t).map(function(t){var e=H(n,t);return e.identifier=t.identifier,e}):[]},mo.behavior.drag=function(){function n(){this.on(\"mousedown.drag\",o).on(\"touchstart.drag\",a)}function t(){return mo.event.changedTouches[0].identifier}function e(n,t){return mo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(s,g),e=n[0]-d[0],r=n[1]-d[1];v|=e|r,d=n,f({type:\"drag\",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+\".\"+p,null).on(r+\".\"+p,null),y(v&&mo.event.target===h),f({type:\"dragend\"})}var c,l=this,s=l.parentNode,f=u.of(l,arguments),h=mo.event.target,g=n(),p=null==g?\"drag\":\"drag-\"+g,d=t(s,g),v=0,m=mo.select(_o).on(e+\".\"+p,o).on(r+\".\"+p,a),y=L();i?(c=i.apply(l,arguments),c=[c.x-d[0],c.y-d[1]]):c=[0,0],f({type:\"dragstart\"})}}var u=g(n,\"drag\",\"dragstart\",\"dragend\"),i=null,o=r(c,mo.mouse,\"mousemove\",\"mouseup\"),a=r(t,e,\"touchmove\",\"touchend\");return n.origin=function(t){return arguments.length?(i=t,n):i},mo.rebind(n,u,\"on\")};var Bo=Math.PI,Wo=2*Bo,Jo=Bo/2,Go=1e-6,Ko=Go*Go,Qo=Bo/180,na=180/Bo,ta=Math.SQRT2,ea=2,ra=4;mo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Y(d),o=i/(ea*h)*(e*I(ta*t+d)-R(d));return[r+o*l,u+o*s,i*e/Y(ta*t+d)]}return[r+n*l,u+n*s,i*Math.exp(ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+ra*f)/(2*i*ea*h),p=(c*c-i*i-ra*f)/(2*c*ea*h),d=Math.log(Math.sqrt(g*g+1)-g),v=Math.log(Math.sqrt(p*p+1)-p),m=v-d,y=(m||Math.log(c/i))/ta;return e.duration=1e3*y,e},mo.behavior.zoom=function(){function n(n){n.on(A,l).on(oa+\".zoom\",h).on(N,p).on(\"dblclick.zoom\",d).on(q,s)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(k[0],Math.min(k[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){b&&b.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-S.y)/S.k}).map(_.invert))}function o(n){n({type:\"zoomstart\"})}function a(n){i(),n({type:\"zoom\",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:\"zoomend\"})}function l(){function n(){s=1,u(mo.mouse(r),h),a(i)}function e(){f.on(N,_o===r?p:null).on(T,null),g(s&&mo.event.target===l),c(i)}var r=this,i=C.of(r,arguments),l=mo.event.target,s=0,f=mo.select(_o).on(N,n).on(T,e),h=t(mo.mouse(r)),g=L();z.call(r),o(i)}function s(){function n(){var n=mo.touches(p);return g=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=mo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-M){var l=o[0],s=v[l.identifier];r(2*S.k),u(l,s),f(),a(d)}M=c}else if(o.length>1){var l=o[0],h=o[1],g=l[0]-h[0],p=l[1]-h[1];m=g*g+p*p}}function i(){for(var n,t,e,i,o=mo.touches(p),c=0,l=o.length;l>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*g)}M=null,u(n,t),a(d)}function h(){if(mo.event.touches.length){for(var t=mo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}_.on(x,null).on(b,null),w.on(A,l).on(q,s),E(),c(d)}var g,p=this,d=C.of(p,arguments),v={},m=0,y=mo.event.changedTouches[0].identifier,x=\"touchmove.zoom-\"+y,b=\"touchend.zoom-\"+y,_=mo.select(_o).on(x,i).on(b,h),w=mo.select(p).on(A,null).on(q,e),E=L();z.call(p),e(),o(d)}function h(){var n=C.of(this,arguments);y?clearTimeout(y):(z.call(this),o(n)),y=setTimeout(function(){y=null,c(n)},50),f();var e=m||mo.mouse(this);v||(v=t(e)),r(Math.pow(2,.002*ua())*S.k),u(e,v),a(n)}function p(){v=null}function d(){var n=C.of(this,arguments),e=mo.mouse(this),i=t(e),l=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,mo.event.shiftKey?Math.ceil(l)-1:Math.floor(l)+1)),u(e,i),a(n),c(n)}var v,m,y,M,x,b,_,w,S={x:0,y:0,k:1},E=[960,500],k=ia,A=\"mousedown.zoom\",N=\"mousemove.zoom\",T=\"mouseup.zoom\",q=\"touchstart.zoom\",C=g(n,\"zoomstart\",\"zoom\",\"zoomend\");return n.event=function(n){n.each(function(){var n=C.of(this,arguments),t=S;Oc?mo.select(this).transition().each(\"start.zoom\",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween(\"zoom:zoom\",function(){var e=E[0],r=E[1],u=e/2,i=r/2,o=mo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each(\"end.zoom\",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(k=null==t?ia:[+t[0],+t[1]],n):k},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.x=function(t){return arguments.length?(b=t,x=t.copy(),S={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),S={x:0,y:0,k:1},n):w},mo.rebind(n,C,\"on\")};var ua,ia=[0,1/0],oa=\"onwheel\"in xo?(ua=function(){return-mo.event.deltaY*(mo.event.deltaMode?120:1)},\"wheel\"):\"onmousewheel\"in xo?(ua=function(){return mo.event.wheelDelta},\"mousewheel\"):(ua=function(){return-mo.event.detail},\"MozMousePixelScroll\");Z.prototype.toString=function(){return this.rgb()+\"\"},mo.hsl=function(n,t,e){return 1===arguments.length?n instanceof X?V(n.h,n.s,n.l):lt(\"\"+n,st,V):V(+n,+t,+e)};var aa=X.prototype=new Z;aa.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),V(this.h,this.s,this.l/n)},aa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),V(this.h,this.s,n*this.l)},aa.rgb=function(){return $(this.h,this.s,this.l)},mo.hcl=function(n,t,e){return 1===arguments.length?n instanceof W?B(n.h,n.c,n.l):n instanceof K?nt(n.l,n.a,n.b):nt((n=ft((n=mo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):B(+n,+t,+e)};var ca=W.prototype=new Z;ca.brighter=function(n){return B(this.h,this.c,Math.min(100,this.l+la*(arguments.length?n:1)))},ca.darker=function(n){return B(this.h,this.c,Math.max(0,this.l-la*(arguments.length?n:1)))},ca.rgb=function(){return J(this.h,this.c,this.l).rgb()},mo.lab=function(n,t,e){return 1===arguments.length?n instanceof K?G(n.l,n.a,n.b):n instanceof W?J(n.l,n.c,n.h):ft((n=mo.rgb(n)).r,n.g,n.b):G(+n,+t,+e)};var la=18,sa=.95047,fa=1,ha=1.08883,ga=K.prototype=new Z;ga.brighter=function(n){return G(Math.min(100,this.l+la*(arguments.length?n:1)),this.a,this.b)},ga.darker=function(n){return G(Math.max(0,this.l-la*(arguments.length?n:1)),this.a,this.b)},ga.rgb=function(){return Q(this.l,this.a,this.b)},mo.rgb=function(n,t,e){return 1===arguments.length?n instanceof at?ot(n.r,n.g,n.b):lt(\"\"+n,ot,$):ot(~~n,~~t,~~e)};var pa=at.prototype=new Z;pa.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),ot(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):ot(u,u,u)},pa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),ot(~~(n*this.r),~~(n*this.g),~~(n*this.b))},pa.hsl=function(){return st(this.r,this.g,this.b)},pa.toString=function(){return\"#\"+ct(this.r)+ct(this.g)+ct(this.b)};var da=mo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});da.forEach(function(n,t){da.set(n,ut(t))}),mo.functor=pt,mo.xhr=vt(dt),mo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=mo.xhr(n,t,i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o.row(e)}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function o(t){return t.map(a).join(n)}function a(n){return c.test(n)?'\"'+n.replace(/\\\"/g,'\"\"')+'\"':n}var c=new RegExp('[\"'+n+\"\\n]\"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function(\"d\",\"return {\"+n.map(function(n,t){return JSON.stringify(n)+\": d[\"+t+\"]\"}).join(\",\")+\"}\");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=c)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++<c;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}s=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++s):10===r&&(u=!0),n.substring(t+1,e).replace(/\"\"/g,'\"')}for(;c>s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==l)continue;return n.substring(t,s-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],c=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new i,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(a).join(n)].concat(t.map(function(t){return u.map(function(n){return a(t[n])}).join(n)})).join(\"\\n\")},e.formatRows=function(n){return n.map(o).join(\"\\n\")},e},mo.csv=mo.dsv(\",\",\"text/csv\"),mo.tsv=mo.dsv(\"\t\",\"text/tab-separated-values\");var va,ma,ya,Ma,xa,ba=_o[a(_o,\"requestAnimationFrame\")]||function(n){setTimeout(n,17)};mo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={callback:n,time:u,next:null};ma?ma.next=i:va=i,ma=i,ya||(Ma=clearTimeout(Ma),ya=1,ba(Mt))},mo.timer.flush=function(){bt(),_t()};var _a=\".\",wa=\",\",Sa=[3,3],Ea=\"$\",ka=[\"y\",\"z\",\"a\",\"f\",\"p\",\"n\",\"\\xb5\",\"m\",\"\",\"k\",\"M\",\"G\",\"T\",\"P\",\"E\",\"Z\",\"Y\"].map(wt);mo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=mo.round(n,St(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),ka[8+e/3]},mo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)},mo.format=function(n){var t=Aa.exec(n),e=t[1]||\" \",r=t[2]||\">\",u=t[3]||\"\",i=t[4]||\"\",o=t[5],a=+t[6],c=t[7],l=t[8],s=t[9],f=1,h=\"\",g=!1;switch(l&&(l=+l.substring(1)),(o||\"0\"===e&&\"=\"===r)&&(o=e=\"0\",r=\"=\",c&&(a-=Math.floor((a-1)/4))),s){case\"n\":c=!0,s=\"g\";break;case\"%\":f=100,h=\"%\",s=\"f\";break;case\"p\":f=100,h=\"%\",s=\"r\";break;case\"b\":case\"o\":case\"x\":case\"X\":\"#\"===i&&(i=\"0\"+s.toLowerCase());case\"c\":case\"d\":g=!0,l=0;break;case\"s\":f=-1,s=\"r\"}\"#\"===i?i=\"\":\"$\"===i&&(i=Ea),\"r\"!=s||l||(s=\"g\"),null!=l&&(\"g\"==s?l=Math.max(1,Math.min(21,l)):(\"e\"==s||\"f\"==s)&&(l=Math.max(0,Math.min(20,l)))),s=Na.get(s)||Et;var p=o&&c;return function(n){if(g&&n%1)return\"\";var t=0>n||0===n&&0>1/n?(n=-n,\"-\"):u;if(0>f){var d=mo.formatPrefix(n,l);n=d.scale(n),h=d.symbol}else n*=f;n=s(n,l);var v=n.lastIndexOf(\".\"),m=0>v?n:n.substring(0,v),y=0>v?\"\":_a+n.substring(v+1);!o&&c&&(m=Ta(m));var M=i.length+m.length+y.length+(p?0:t.length),x=a>M?new Array(M=a-M+1).join(e):\"\";return p&&(m=Ta(x+m)),t+=i,n=m+y,(\"<\"===r?t+n+x:\">\"===r?x+t+n:\"^\"===r?x.substring(0,M>>=1)+t+n+x.substring(M):t+(p?n:x+n))+h}};var Aa=/(?:([^{])?([<>=^]))?([+\\- ])?([$#])?(0)?(\\d+)?(,)?(\\.-?\\d+)?([a-z%])?/i,Na=mo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=mo.round(n,St(n,t))).toFixed(Math.max(0,Math.min(20,St(n*(1+1e-15),t))))}}),Ta=dt;if(Sa){var qa=Sa.length;Ta=function(n){for(var t=n.length,e=[],r=0,u=Sa[0];t>0&&u>0;)e.push(n.substring(t-=u,t+u)),u=Sa[r=(r+1)%qa];return e.reverse().join(wa)}}mo.geo={},kt.prototype={s:0,t:0,add:function(n){At(n,this.t,za),At(za.s,this.s,this),this.s?this.t+=za.t:this.s=za.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var za=new kt;mo.geo.stream=function(n,t){n&&Ca.hasOwnProperty(n.type)?Ca[n.type](n,t):Nt(n,t)};var Ca={Feature:function(n,t){Nt(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)Nt(e[r].geometry,t)}},Da={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){Tt(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)Tt(e[r],t,0)},Polygon:function(n,t){qt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)qt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)Nt(e[r],t)}};mo.geo.area=function(n){return ja=0,mo.geo.stream(n,Ha),ja};var ja,La=new kt,Ha={sphere:function(){ja+=4*Bo},point:c,lineStart:c,lineEnd:c,polygonStart:function(){La.reset(),Ha.lineStart=zt},polygonEnd:function(){var n=2*La;ja+=0>n?4*Bo+n:n,Ha.lineStart=Ha.lineEnd=Ha.point=c}};mo.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=Ct([t*Qo,e*Qo]);if(m){var u=jt(m,r),i=[u[1],-u[0],0],o=jt(i,u);Ft(o),o=Pt(o);var c=t-p,l=c>0?1:-1,d=o[0]*na*l,v=Math.abs(c)>180;if(v^(d>l*p&&l*t>d)){var y=o[1]*na;y>g&&(g=y)}else if(d=(d+360)%360-180,v^(d>l*p&&l*t>d)){var y=-o[1]*na;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);v?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=Math.abs(r)>180?r+(r>0?360:-360):r}else d=n,v=e;Ha.point(n,e),t(n,e)}function i(){Ha.lineStart()}function o(){u(d,v),Ha.lineEnd(),Math.abs(y)>Go&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var s,f,h,g,p,d,v,m,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=u,b.lineStart=i,b.lineEnd=o,y=0,Ha.polygonStart()},polygonEnd:function(){Ha.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>La?(s=-(h=180),f=-(g=90)):y>Go?g=90:-Go>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],mo.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),mo.geo.centroid=function(n){Fa=Pa=Oa=Ra=Ya=Ia=Ua=Za=Va=Xa=$a=0,mo.geo.stream(n,Ba);var t=Va,e=Xa,r=$a,u=t*t+e*e+r*r;return Ko>u&&(t=Ia,e=Ua,r=Za,Go>Pa&&(t=Oa,e=Ra,r=Ya),u=t*t+e*e+r*r,Ko>u)?[0/0,0/0]:[Math.atan2(e,t)*na,O(r/Math.sqrt(u))*na]};var Fa,Pa,Oa,Ra,Ya,Ia,Ua,Za,Va,Xa,$a,Ba={sphere:c,point:Rt,lineStart:It,lineEnd:Ut,polygonStart:function(){Ba.lineStart=Zt},polygonEnd:function(){Ba.lineStart=It}},Wa=Bt(Vt,Qt,te,[-Bo,-Bo/2]),Ja=1e9;mo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=re(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(mo.geo.conicEqualArea=function(){return oe(ae)}).raw=ae,mo.geo.albers=function(){return mo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},mo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=mo.geo.albers(),o=mo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=mo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Go,f+.12*l+Go],[s-.214*l-Go,f+.234*l-Go]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Go,f+.166*l+Go],[s-.115*l-Go,f+.234*l-Go]]).stream(c).point,n},n.scale(1070)};var Ga,Ka,Qa,nc,tc,ec,rc={point:c,lineStart:c,lineEnd:c,polygonStart:function(){Ka=0,rc.lineStart=ce},polygonEnd:function(){rc.lineStart=rc.lineEnd=rc.point=c,Ga+=Math.abs(Ka/2)}},uc={point:le,lineStart:c,lineEnd:c,polygonStart:c,polygonEnd:c},ic={point:he,lineStart:ge,lineEnd:pe,polygonStart:function(){ic.lineStart=de},polygonEnd:function(){ic.point=he,ic.lineStart=ge,ic.lineEnd=pe}};mo.geo.transform=function(n){return{stream:function(t){var e=new ye(t);for(var r in n)e[r]=n[r];return e}}},ye.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},mo.geo.path=function(){function n(n){return n&&(\"function\"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),mo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ga=0,mo.geo.stream(n,u(rc)),Ga},n.centroid=function(n){return Oa=Ra=Ya=Ia=Ua=Za=Va=Xa=$a=0,mo.geo.stream(n,u(ic)),$a?[Va/$a,Xa/$a]:Za?[Ia/Za,Ua/Za]:Ya?[Oa/Ya,Ra/Ya]:[0/0,0/0]},n.bounds=function(n){return tc=ec=-(Qa=nc=1/0),mo.geo.stream(n,u(uc)),[[Qa,nc],[tc,ec]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Me(n):dt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new se:new ve(n),\"function\"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a=\"function\"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(mo.geo.albersUsa()).context(null)},mo.geo.projection=xe,mo.geo.projectionMutator=be,(mo.geo.equirectangular=function(){return xe(we)}).raw=we.invert=we,mo.geo.rotation=function(n){function t(t){return t=n(t[0]*Qo,t[1]*Qo),t[0]*=na,t[1]*=na,t}return n=Ee(n[0]%360*Qo,n[1]*Qo,n.length>2?n[2]*Qo:0),t.invert=function(t){return t=n.invert(t[0]*Qo,t[1]*Qo),t[0]*=na,t[1]*=na,t},t},Se.invert=we,mo.geo.circle=function(){function n(){var n=\"function\"==typeof r?r.apply(this,arguments):r,t=Ee(-n[0]*Qo,-n[1]*Qo,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=na,n[1]*=na}}),{type:\"Polygon\",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=Te((t=+r)*Qo,u*Qo),n):t},n.precision=function(r){return arguments.length?(e=Te(t*Qo,(u=+r)*Qo),n):u},n.angle(90)},mo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Qo,u=n[1]*Qo,i=t[1]*Qo,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},mo.geo.graticule=function(){function n(){return{type:\"MultiLineString\",coordinates:t()}}function t(){return mo.range(Math.ceil(i/v)*v,u,v).map(h).concat(mo.range(Math.ceil(l/m)*m,c,m).map(g)).concat(mo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Math.abs(n%v)>Go\n}).map(s)).concat(mo.range(Math.ceil(a/d)*d,o,d).filter(function(n){return Math.abs(n%m)>Go}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,d=p,v=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:\"LineString\",coordinates:n}})},n.outline=function(){return{type:\"Polygon\",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(v=+t[0],m=+t[1],n):[v,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],d=+t[1],n):[p,d]},n.precision=function(t){return arguments.length?(y=+t,s=ze(a,o,90),f=Ce(r,e,y),h=ze(l,c,90),g=Ce(i,u,y),n):y},n.majorExtent([[-180,-90+Go],[180,90-Go]]).minorExtent([[-180,-80-Go],[180,80+Go]])},mo.geo.greatArc=function(){function n(){return{type:\"LineString\",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=De,u=je;return n.distance=function(){return mo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t=\"function\"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e=\"function\"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},mo.geo.interpolate=function(n,t){return Le(n[0]*Qo,n[1]*Qo,t[0]*Qo,t[1]*Qo)},mo.geo.length=function(n){return oc=0,mo.geo.stream(n,ac),oc};var oc,ac={sphere:c,point:c,lineStart:He,lineEnd:c,polygonStart:c,polygonEnd:c},cc=Fe(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(mo.geo.azimuthalEqualArea=function(){return xe(cc)}).raw=cc;var lc=Fe(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},dt);(mo.geo.azimuthalEquidistant=function(){return xe(lc)}).raw=lc,(mo.geo.conicConformal=function(){return oe(Pe)}).raw=Pe,(mo.geo.conicEquidistant=function(){return oe(Oe)}).raw=Oe;var sc=Fe(function(n){return 1/n},Math.atan);(mo.geo.gnomonic=function(){return xe(sc)}).raw=sc,Re.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Jo]},(mo.geo.mercator=function(){return Ye(Re)}).raw=Re;var fc=Fe(function(){return 1},Math.asin);(mo.geo.orthographic=function(){return xe(fc)}).raw=fc;var hc=Fe(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(mo.geo.stereographic=function(){return xe(hc)}).raw=hc,Ie.invert=function(n,t){return[Math.atan2(R(n),Math.cos(t)),O(Math.sin(t)/Y(n))]},(mo.geo.transverseMercator=function(){return Ye(Ie)}).raw=Ie,mo.geom={},mo.svg={},mo.svg.line=function(){return Ue(dt)};var gc=mo.map({linear:Xe,\"linear-closed\":$e,step:Be,\"step-before\":We,\"step-after\":Je,basis:er,\"basis-open\":rr,\"basis-closed\":ur,bundle:ir,cardinal:Qe,\"cardinal-open\":Ge,\"cardinal-closed\":Ke,monotone:fr});gc.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var pc=[0,2/3,1/3,0],dc=[0,1/3,2/3,0],vc=[0,1/6,2/3,1/6];mo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u,i,o,a,c,l,s,f,h,g,p,d=pt(e),v=pt(r),m=n.length,y=m-1,M=[],x=[],b=0;if(d===Ze&&r===Ve)t=n;else for(i=0,t=[];m>i;++i)t.push([+d.call(this,u=n[i],i),+v.call(this,u,i)]);for(i=1;m>i;++i)(t[i][1]<t[b][1]||t[i][1]==t[b][1]&&t[i][0]<t[b][0])&&(b=i);for(i=0;m>i;++i)i!==b&&(c=t[i][1]-t[b][1],a=t[i][0]-t[b][0],M.push({angle:Math.atan2(c,a),index:i}));for(M.sort(function(n,t){return n.angle-t.angle}),g=M[0].angle,h=M[0].index,f=0,i=1;y>i;++i){if(o=M[i].index,g==M[i].angle){if(a=t[h][0]-t[b][0],c=t[h][1]-t[b][1],l=t[o][0]-t[b][0],s=t[o][1]-t[b][1],a*a+c*c>=l*l+s*s){M[i].index=-1;continue}M[f].index=-1}g=M[i].angle,f=i,h=o}for(x.push(b),i=0,o=0;2>i;++o)M[o].index>-1&&(x.push(M[o].index),i++);for(p=x.length;y>o;++o)if(!(M[o].index<0)){for(;!hr(x[p-2],x[p-1],M[o].index,t);)--p;x[p++]=M[o].index}var _=[];for(i=p-1;i>=0;--i)_.push(n[x[i]]);return _}var e=Ze,r=Ve;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},mo.geom.polygon=function(n){return Lo(n,mc),n};var mc=mo.geom.polygon.prototype=[];mc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},mc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},mc.clip=function(n){for(var t,e,r,u,i,o,a=dr(n),c=-1,l=this.length-dr(this),s=this[l-1];++c<l;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],gr(o,s,u)?(gr(i,s,u)||n.push(pr(i,o,s,u)),n.push(o)):gr(i,s,u)&&n.push(pr(i,o,s,u)),i=o;a&&n.push(n[0]),s=u}return n},mo.geom.delaunay=function(n){var t=n.map(function(){return[]}),e=[];return vr(n,function(e){t[e.region.l.index].push(n[e.region.r.index])}),t.forEach(function(t,r){var u=n[r],i=u[0],o=u[1];t.forEach(function(n){n.angle=Math.atan2(n[0]-i,n[1]-o)}),t.sort(function(n,t){return n.angle-t.angle});for(var a=0,c=t.length-1;c>a;a++)e.push([u,t[a],t[a+1]])}),e},mo.geom.voronoi=function(n){function t(n){var t,i,o,a=n.map(function(){return[]}),c=pt(e),l=pt(r),s=n.length,f=1e6;if(c===Ze&&l===Ve)t=n;else for(t=new Array(s),o=0;s>o;++o)t[o]=[+c.call(this,i=n[o],o),+l.call(this,i,o)];if(vr(t,function(n){var t,e,r,u,i,o;1===n.a&&n.b>=0?(t=n.ep.r,e=n.ep.l):(t=n.ep.l,e=n.ep.r),1===n.a?(i=t?t.y:-f,r=n.c-n.b*i,o=e?e.y:f,u=n.c-n.b*o):(r=t?t.x:-f,i=n.c-n.a*r,u=e?e.x:f,o=n.c-n.a*u);var c=[r,i],l=[u,o];a[n.region.l.index].push(c,l),a[n.region.r.index].push(c,l)}),a=a.map(function(n,e){var r=t[e][0],u=t[e][1],i=n.map(function(n){return Math.atan2(n[0]-r,n[1]-u)}),o=mo.range(n.length).sort(function(n,t){return i[n]-i[t]});return o.filter(function(n,t){return!t||i[n]-i[o[t-1]]>Go}).map(function(t){return n[t]})}),a.forEach(function(n,e){var r=n.length;if(!r)return n.push([-f,-f],[-f,f],[f,f],[f,-f]);if(!(r>2)){var u=t[e],i=n[0],o=n[1],a=u[0],c=u[1],l=i[0],s=i[1],h=o[0],g=o[1],p=Math.abs(h-l),d=g-s;if(Math.abs(d)<Go){var v=s>c?-f:f;n.push([-f,v],[f,v])}else if(Go>p){var m=l>a?-f:f;n.push([m,-f],[m,f])}else{var v=(l-a)*(g-s)>(h-l)*(s-c)?f:-f,y=Math.abs(d)-p;Math.abs(y)<Go?n.push([0>d?v:-v,v]):(y>0&&(v*=-1),n.push([-f,v],[f,v]))}}}),u)for(o=0;s>o;++o)u.clip(a[o]);for(o=0;s>o;++o)a[o].point=n[o];return a}var e=Ze,r=Ve,u=null;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.clipExtent=function(n){if(!arguments.length)return u&&[u[0],u[2]];if(null==n)u=null;else{var e=+n[0][0],r=+n[0][1],i=+n[1][0],o=+n[1][1];u=mo.geom.polygon([[e,r],[e,o],[i,o],[i,r]])}return t},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):u&&u[2]},t.links=function(n){var t,u,i,o=n.map(function(){return[]}),a=[],c=pt(e),l=pt(r),s=n.length;if(c===Ze&&l===Ve)t=n;else for(t=new Array(s),i=0;s>i;++i)t[i]=[+c.call(this,u=n[i],i),+l.call(this,u,i)];return vr(t,function(t){var e=t.region.l.index,r=t.region.r.index;o[e][r]||(o[e][r]=o[r][e]=!0,a.push({source:n[e],target:n[r]}))}),a},t.triangles=function(n){if(e===Ze&&r===Ve)return mo.geom.delaunay(n);for(var t,u=new Array(c),i=pt(e),o=pt(r),a=-1,c=n.length;++a<c;)(u[a]=[+i.call(this,t=n[a],a),+o.call(this,t,a)]).data=t;return mo.geom.delaunay(u).map(function(n){return n.map(function(n){return n.data})})},t)};var yc={l:\"r\",r:\"l\"};mo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,s=n.y;if(null!=c)if(Math.abs(c-e)+Math.abs(s-r)<.01)l(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,l(n,f,c,s,u,i,o,a),l(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,u,i,o,a)}function l(n,t,e,r,u,o,a,c){var l=.5*(u+a),s=.5*(o+c),f=e>=l,h=r>=s,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=Mr()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,d,v,m,y,M=pt(a),x=pt(c);if(null!=t)d=t,v=e,m=r,y=u;else if(m=y=-(d=v=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.x<d&&(d=s.x),s.y<v&&(v=s.y),s.x>m&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);d>b&&(d=b),v>_&&(v=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-d,S=y-v;w>S?y=v+w:m=d+S;var E=Mr();if(E.add=function(n){i(E,n,+M(n,++g),+x(n,g),d,v,m,y)},E.visit=function(n){xr(n,E,d,v,m,y)},g=-1,null==t){for(;++g<p;)i(E,n[g],f[g],h[g],d,v,m,y);--g}else n.forEach(E.add);return f=h=n=s=null,E}var o,a=Ze,c=Ve;return(o=arguments.length)?(a=mr,c=yr,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},mo.interpolateRgb=br,mo.interpolateObject=_r,mo.interpolateNumber=wr,mo.interpolateString=Sr;var Mc=/[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g;mo.interpolate=Er,mo.interpolators=[function(n,t){var e=typeof t;return(\"string\"===e?da.has(t)||/^(#|rgb\\(|hsl\\()/.test(t)?br:Sr:t instanceof Z?br:\"object\"===e?Array.isArray(t)?kr:_r:wr)(n,t)}],mo.interpolateArray=kr;var xc=function(){return dt},bc=mo.map({linear:xc,poly:Dr,quad:function(){return qr},cubic:function(){return zr},sin:function(){return jr},exp:function(){return Lr},circle:function(){return Hr},elastic:Fr,back:Pr,bounce:function(){return Or}}),_c=mo.map({\"in\":dt,out:Nr,\"in-out\":Tr,\"out-in\":function(n){return Tr(Nr(n))}});mo.ease=function(n){var t=n.indexOf(\"-\"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):\"in\";return e=bc.get(e)||xc,r=_c.get(r)||dt,Ar(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},mo.interpolateHcl=Rr,mo.interpolateHsl=Yr,mo.interpolateLab=Ir,mo.interpolateRound=Ur,mo.transform=function(n){var t=xo.createElementNS(mo.ns.prefix.svg,\"g\");return(mo.transform=function(n){if(null!=n){t.setAttribute(\"transform\",n);var e=t.transform.baseVal.consolidate()}return new Zr(e?e.matrix:wc)})(n)},Zr.prototype.toString=function(){return\"translate(\"+this.translate+\")rotate(\"+this.rotate+\")skewX(\"+this.skew+\")scale(\"+this.scale+\")\"};var wc={a:1,b:0,c:0,d:1,e:0,f:0};mo.interpolateTransform=Br,mo.layout={},mo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Gr(n[e]));return t}},mo.layout.chord=function(){function n(){var n,l,f,h,g,p={},d=[],v=mo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(l=0,g=-1;++g<i;)l+=u[h][g];d.push(l),m.push(mo.range(i)),n+=l}for(o&&v.sort(function(n,t){return o(d[n],d[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(Wo-s*i)/n,l=0,h=-1;++h<i;){for(f=l,g=-1;++g<i;){var y=v[h],M=m[y][g],x=u[y][M],b=l,_=l+=x*n;p[y+\"-\"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:f,endAngle:l,value:(l-f)/n},l+=s}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+\"-\"+g],S=p[g+\"-\"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,l={},s=0;return l.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,l):u},l.padding=function(n){return arguments.length?(s=n,e=r=null,l):s},l.sortGroups=function(n){return arguments.length?(o=n,e=r=null,l):o},l.sortSubgroups=function(n){return arguments.length?(a=n,e=null,l):a},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},mo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=1/Math.sqrt(i*i+o*o);if(d>(u-e)*a){var c=t.charge*a*a;return n.px-=i*c,n.py-=o*c,!0}if(t.point&&isFinite(a)){var c=t.pointCharge*a*a;n.px-=i*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=mo.event.x,n.py=mo.event.y,a.resume()}var e,r,u,i,o,a={},c=mo.dispatch(\"start\",\"tick\",\"end\"),l=[1,1],s=.9,f=Sc,h=Ec,g=-30,p=.1,d=.8,v=[],m=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:\"end\",alpha:r=0}),!0;var t,e,a,f,h,d,y,M,x,b=v.length,_=m.length;for(e=0;_>e;++e)a=m[e],f=a.source,h=a.target,M=h.x-f.x,x=h.y-f.y,(d=M*M+x*x)&&(d=r*i[e]*((d=Math.sqrt(d))-u[e])/d,M*=d,x*=d,h.x-=M*(y=f.weight/(h.weight+f.weight)),h.y-=x*y,f.x+=M*(y=1-y),f.y+=x*y);if((y=r*p)&&(M=l[0]/2,x=l[1]/2,e=-1,y))for(;++e<b;)a=v[e],a.x+=(M-a.x)*y,a.y+=(x-a.y)*y;if(g)for(uu(t=mo.geom.quadtree(v),r,o),e=-1;++e<b;)(a=v[e]).fixed||t.visit(n(a));for(e=-1;++e<b;)a=v[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*s,a.y-=(a.py-(a.py=a.y))*s);c.tick({type:\"tick\",alpha:r})},a.nodes=function(n){return arguments.length?(v=n,a):v},a.links=function(n){return arguments.length?(m=n,a):m},a.size=function(n){return arguments.length?(l=n,a):l},a.linkDistance=function(n){return arguments.length?(f=\"function\"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h=\"function\"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(s=+n,a):s},a.charge=function(n){return arguments.length?(g=\"function\"==typeof n?n:+n,a):g},a.gravity=function(n){return arguments.length?(p=+n,a):p},a.theta=function(n){return arguments.length?(d=+n,a):d},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:\"start\",alpha:r=n}),mo.timer(a.tick)),a):r},a.start=function(){function n(n,r){for(var u,i=t(e),o=-1,a=i.length;++o<a;)if(!isNaN(u=i[o][n]))return u;return Math.random()*r}function t(){if(!c){for(c=[],r=0;p>r;++r)c[r]=[];for(r=0;d>r;++r){var n=m[r];c[n.source.index].push(n.target),c[n.target.index].push(n.source)}}return c[e]}var e,r,c,s,p=v.length,d=m.length,y=l[0],M=l[1];for(e=0;p>e;++e)(s=v[e]).index=e,s.weight=0;for(e=0;d>e;++e)s=m[e],\"number\"==typeof s.source&&(s.source=v[s.source]),\"number\"==typeof s.target&&(s.target=v[s.target]),++s.source.weight,++s.target.weight;for(e=0;p>e;++e)s=v[e],isNaN(s.x)&&(s.x=n(\"x\",y)),isNaN(s.y)&&(s.y=n(\"y\",M)),isNaN(s.px)&&(s.px=s.x),isNaN(s.py)&&(s.py=s.y);if(u=[],\"function\"==typeof f)for(e=0;d>e;++e)u[e]=+f.call(this,m[e],e);else for(e=0;d>e;++e)u[e]=f;if(i=[],\"function\"==typeof h)for(e=0;d>e;++e)i[e]=+h.call(this,m[e],e);else for(e=0;d>e;++e)i[e]=h;if(o=[],\"function\"==typeof g)for(e=0;p>e;++e)o[e]=+g.call(this,v[e],e);else for(e=0;p>e;++e)o[e]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=mo.behavior.drag().origin(dt).on(\"dragstart.force\",nu).on(\"drag.force\",t).on(\"dragend.force\",tu)),arguments.length?(this.on(\"mouseover.force\",eu).on(\"mouseout.force\",ru).call(e),void 0):e},mo.rebind(a,c,\"on\")};var Sc=20,Ec=1;mo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(l=c.length)){for(var l,s,f=-1,h=t.children=[],g=0,p=o+1;++f<l;)s=n(c[f],p,a),s.parent=t,h.push(s),g+=s.value;r&&h.sort(r),i&&(t.value=g)}else i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,l=r+1;++c<a;)o+=t(u[c],l);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=cu,u=ou,i=au;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},mo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++l<o;)n(a=i[l],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=mo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},iu(e,r)},mo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+(\"function\"==typeof r?r.apply(this,arguments):r),c=((\"function\"==typeof u?u.apply(this,arguments):u)-a)/mo.sum(o),l=mo.range(i.length);null!=e&&l.sort(e===kc?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var s=[];return l.forEach(function(n){var t;s[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),s}var t=Number,e=kc,r=0,u=Wo;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var kc={};mo.layout.stack=function(){function n(a,c){var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=mo.permute(l,f),s=mo.permute(s,f);var h,g,p,d=r.call(n,s,c),v=l.length,m=l[0].length;for(g=0;m>g;++g)for(u.call(n,l[0][g],p=d[g],s[0][g][1]),h=1;v>h;++h)u.call(n,l[h][g],p+=s[h-1][g][1],s[h][g][1]);return a}var t=dt,e=gu,r=pu,u=hu,i=su,o=fu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e=\"function\"==typeof t?t:Ac.get(t)||gu,n):e},n.offset=function(t){return arguments.length?(r=\"function\"==typeof t?t:Nc.get(t)||pu,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var Ac=mo.map({\"inside-out\":function(n){var t,e,r=n.length,u=n.map(du),i=n.map(vu),o=mo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return mo.range(n.length).reverse()},\"default\":gu}),Nc=mo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:pu});mo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=l[i],a>=s[0]&&a<=s[1]&&(o=c[mo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=xu,u=yu;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=pt(t),n):r},n.bins=function(t){return arguments.length?(u=\"number\"==typeof t?function(n){return Mu(n,t)}:pt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},mo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,l,s=r[0],f=s,h=-1;++h<i;)l=r[h],o(l,a),f=c(l,a,f),a=l;Tu(n);var g=.5*(s._tree.prelim+l._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],l=i._tree.mod,s=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=wu(a),i=_u(i),a&&i;)c=_u(c),o=wu(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-l+e(a,i),u>0&&(qu(zu(a,n,r),n,u),l+=u,s+=u),f+=a._tree.mod,l+=i._tree.mod,h+=c._tree.mod,s+=o._tree.mod;a&&!wu(o)&&(o._tree.thread=a,o._tree.mod+=f-s),i&&!_u(c)&&(c._tree.thread=i,c._tree.mod+=l-h,r=n)}return r}var l=t.call(this,n,i),s=l[0];Nu(s,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(s),a(s,-s._tree.prelim);var f=Su(s,ku),h=Su(s,Eu),g=Su(s,Au),p=f.x-e(f,h)/2,d=h.x+e(h,f)/2,v=g.depth||1;return Nu(s,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(d-p)*r[0],n.y=n.depth/v*r[1],delete n._tree}),l}var t=mo.layout.hierarchy().sort(null).value(null),e=bu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},iu(n,t)},mo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:\"function\"==typeof t?t:function(){return t};if(a.x=a.y=0,Nu(a,function(n){n.r=+s(n.value)}),Nu(a,Hu),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Nu(a,function(n){n.r+=f}),Nu(a,Hu),Nu(a,function(n){n.r-=f})}return Ou(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=mo.layout.hierarchy().sort(Cu),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||\"function\"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},iu(n,e)},mo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Nu(c,function(n){var t=n.children;t&&t.length?(n.x=Iu(t),n.y=Yu(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Uu(c),f=Zu(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Nu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=mo.layout.hierarchy().sort(null).value(null),e=bu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},iu(n,t)},mo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,d=\"slice\"===g?l.dx:\"dice\"===g?l.dy:\"slice-dice\"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,\"squarify\"!==g||(a=r(s,d))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,d,l,!1),d=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,d,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++i<o;)u=n[i],u.x=a,u.y=l,u.dy=s,a+=u.dx=Math.min(e.x+e.dx-a,s?c(u.area/s):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=s,e.dy-=s}else{for((r||s>e.dx)&&(s=e.dx);++i<o;)u=n[i],u.x=a,u.y=l,u.dx=s,l+=u.dy=Math.min(e.y+e.dy-l,s?c(u.area/s):0);u.z=!1,u.dy+=e.y+e.dy-l,e.x+=s,e.dx-=s}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=l[0],i.dy=l[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=mo.layout.hierarchy(),c=Math.round,l=[1,1],s=null,f=Vu,h=!1,g=\"squarify\",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(l=n,i):l},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Vu(t):Xu(t,\"number\"==typeof e?[e,e,e,e]:e)}function e(t){return Xu(t,n)}if(!arguments.length)return s;var r;return f=null==(s=n)?Vu:\"function\"==(r=typeof n)?t:\"number\"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+\"\",i):g},iu(i,a)},mo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=mo.random.normal.apply(mo,arguments);return function(){return Math.exp(n())}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t/n}}},mo.scale={};var Tc={floor:dt,ceil:dt};mo.scale.linear=function(){return Qu([0,1],[0,1],Er,!1)},mo.scale.log=function(){return ii(mo.scale.linear().domain([0,1]),10,!0,[1,10])};var qc=mo.format(\".0e\"),zc={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};mo.scale.pow=function(){return oi(mo.scale.linear(),1,[0,1])},mo.scale.sqrt=function(){return mo.scale.pow().exponent(.5)},mo.scale.ordinal=function(){return ci([],{t:\"range\",a:[[]]})},mo.scale.category10=function(){return mo.scale.ordinal().range(Cc)},mo.scale.category20=function(){return mo.scale.ordinal().range(Dc)},mo.scale.category20b=function(){return mo.scale.ordinal().range(jc)},mo.scale.category20c=function(){return mo.scale.ordinal().range(Lc)};var Cc=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(it),Dc=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(it),jc=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(it),Lc=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(it);mo.scale.quantile=function(){return li([],[])},mo.scale.quantize=function(){return si(0,1,[0,1])},mo.scale.threshold=function(){return fi([.5],[0,1])},mo.scale.identity=function(){return hi([0,1])},mo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+Hc,a=u.apply(this,arguments)+Hc,c=(o>a&&(c=o,o=a,a=c),a-o),l=Bo>c?\"0\":\"1\",s=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=Fc?n?\"M0,\"+i+\"A\"+i+\",\"+i+\" 0 1,1 0,\"+-i+\"A\"+i+\",\"+i+\" 0 1,1 0,\"+i+\"M0,\"+n+\"A\"+n+\",\"+n+\" 0 1,0 0,\"+-n+\"A\"+n+\",\"+n+\" 0 1,0 0,\"+n+\"Z\":\"M0,\"+i+\"A\"+i+\",\"+i+\" 0 1,1 0,\"+-i+\"A\"+i+\",\"+i+\" 0 1,1 0,\"+i+\"Z\":n?\"M\"+i*s+\",\"+i*f+\"A\"+i+\",\"+i+\" 0 \"+l+\",1 \"+i*h+\",\"+i*g+\"L\"+n*h+\",\"+n*g+\"A\"+n+\",\"+n+\" 0 \"+l+\",0 \"+n*s+\",\"+n*f+\"Z\":\"M\"+i*s+\",\"+i*f+\"A\"+i+\",\"+i+\" 0 \"+l+\",1 \"+i*h+\",\"+i*g+\"L0,0\"+\"Z\"}var t=gi,e=pi,r=di,u=vi;return n.innerRadius=function(e){return arguments.length?(t=pt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=pt(t),n):e},n.startAngle=function(t){return arguments.length?(r=pt(t),n):r},n.endAngle=function(t){return arguments.length?(u=pt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+Hc;return[Math.cos(i)*n,Math.sin(i)*n]},n};var Hc=-Jo,Fc=Wo-Go;mo.svg.line.radial=function(){var n=Ue(mi);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},We.reverse=Je,Je.reverse=We,mo.svg.area=function(){return yi(dt)},mo.svg.area.radial=function(){var n=yi(mi);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},mo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return\"M\"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+\"Z\"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+Hc,s=l.call(n,u,r)+Hc;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return\"A\"+n+\",\"+n+\" 0 \"+ +(e>Bo)+\",1 \"+t}function u(n,t,e,r){return\"Q 0,0 \"+r}var i=De,o=je,a=Mi,c=di,l=vi;return n.radius=function(t){return arguments.length?(a=pt(t),n):a},n.source=function(t){return arguments.length?(i=pt(t),n):i},n.target=function(t){return arguments.length?(o=pt(t),n):o},n.startAngle=function(t){return arguments.length?(c=pt(t),n):c},n.endAngle=function(t){return arguments.length?(l=pt(t),n):l},n},mo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),\"M\"+c[0]+\"C\"+c[1]+\" \"+c[2]+\" \"+c[3]}var t=De,e=je,r=xi;return n.source=function(e){return arguments.length?(t=pt(e),n):t},n.target=function(t){return arguments.length?(e=pt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},mo.svg.diagonal.radial=function(){var n=mo.svg.diagonal(),t=xi,e=n.projection;return n.projection=function(n){return arguments.length?e(bi(t=n)):t},n},mo.svg.symbol=function(){function n(n,r){return(Pc.get(t.call(this,n,r))||Si)(e.call(this,n,r))}var t=wi,e=_i;return n.type=function(e){return arguments.length?(t=pt(e),n):t},n.size=function(t){return arguments.length?(e=pt(t),n):e},n};var Pc=mo.map({circle:Si,cross:function(n){var t=Math.sqrt(n/5)/2;return\"M\"+-3*t+\",\"+-t+\"H\"+-t+\"V\"+-3*t+\"H\"+t+\"V\"+-t+\"H\"+3*t+\"V\"+t+\"H\"+t+\"V\"+3*t+\"H\"+-t+\"V\"+t+\"H\"+-3*t+\"Z\"},diamond:function(n){var t=Math.sqrt(n/(2*Ic)),e=t*Ic;return\"M0,\"+-t+\"L\"+e+\",0\"+\" 0,\"+t+\" \"+-e+\",0\"+\"Z\"},square:function(n){var t=Math.sqrt(n)/2;return\"M\"+-t+\",\"+-t+\"L\"+t+\",\"+-t+\" \"+t+\",\"+t+\" \"+-t+\",\"+t+\"Z\"},\"triangle-down\":function(n){var t=Math.sqrt(n/Yc),e=t*Yc/2;return\"M0,\"+e+\"L\"+t+\",\"+-e+\" \"+-t+\",\"+-e+\"Z\"},\"triangle-up\":function(n){var t=Math.sqrt(n/Yc),e=t*Yc/2;return\"M0,\"+-e+\"L\"+t+\",\"+e+\" \"+-t+\",\"+e+\"Z\"}});mo.svg.symbolTypes=Pc.keys();var Oc,Rc,Yc=Math.sqrt(3),Ic=Math.tan(30*Qo),Uc=[],Zc=0;Uc.call=Ro.call,Uc.empty=Ro.empty,Uc.node=Ro.node,Uc.size=Ro.size,mo.transition=function(n){return arguments.length?Oc?n.transition():n:Uo.transition()},mo.transition.prototype=Uc,Uc.select=function(n){var t,e,r,u=this.id,i=[];n=d(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],l=-1,s=c.length;++l<s;)(r=c[l])&&(e=n.call(r,r.__data__,l,o))?(\"__data__\"in r&&(e.__data__=r.__data__),Ni(e,l,u,r.__transition__[u]),t.push(e)):t.push(null)}return Ei(i,u)},Uc.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=v(n);for(var c=-1,l=this.length;++c<l;)for(var s=this[c],f=-1,h=s.length;++f<h;)if(r=s[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&Ni(u,g,o,i),t.push(u)}return Ei(a,o)},Uc.filter=function(n){var t,e,r,u=[];\"function\"!=typeof n&&(n=k(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a)&&t.push(r)}return Ei(u,this.id)},Uc.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):N(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Uc.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+=\"\",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+=\"\",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))\n})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o=\"transform\"==n?Br:Er,a=mo.ns.qualify(n);return ki(this,\"attr.\"+n,t,a.local?i:u)},Uc.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=mo.ns.qualify(n);return this.tween(\"attr.\"+n,u.local?r:e)},Uc.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+=\"\",function(){var r,u=_o.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=Er(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if(\"string\"!=typeof n){2>i&&(t=\"\");for(e in n)this.style(e,n[e],t);return this}e=\"\"}return ki(this,\"style.\"+n,t,u)},Uc.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,_o.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=\"\"),this.tween(\"style.\"+n,r)},Uc.text=function(n){return ki(this,\"text\",n,Ai)},Uc.remove=function(){return this.each(\"end.transition\",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Uc.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:(\"function\"!=typeof n&&(n=mo.ease.apply(mo,arguments)),N(this,function(e){e.__transition__[t].ease=n}))},Uc.delay=function(n){var t=this.id;return N(this,\"function\"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Uc.duration=function(n){var t=this.id;return N(this,\"function\"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Uc.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Rc,u=Oc;Oc=e,N(this,function(t,r,u){Rc=t.__transition__[e],n.call(t,t.__data__,r,u)}),Rc=r,Oc=u}else N(this,function(r){var u=r.__transition__[e];(u.event||(u.event=mo.dispatch(\"start\",\"end\"))).on(n,t)});return this},Uc.transition=function(){for(var n,t,e,r,u=this.id,i=++Zc,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],l=0,s=t.length;s>l;l++)(e=t[l])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Ni(e,l,i,r)),n.push(e)}return Ei(o,i)},mo.svg.axis=function(){function n(n){n.each(function(){var n,l=mo.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):dt:t,p=l.selectAll(\".tick\").data(h,f),d=p.enter().insert(\"g\",\".domain\").attr(\"class\",\"tick\").style(\"opacity\",Go),v=mo.transition(p.exit()).style(\"opacity\",Go).remove(),m=mo.transition(p).style(\"opacity\",1),y=Bu(f),M=l.selectAll(\".domain\").data([0]),x=(M.enter().append(\"path\").attr(\"class\",\"domain\"),mo.transition(M));d.append(\"line\"),d.append(\"text\");var b=d.select(\"line\"),_=m.select(\"line\"),w=p.select(\"text\").text(g),S=d.select(\"text\"),E=m.select(\"text\");switch(r){case\"bottom\":n=Ti,b.attr(\"y2\",u),S.attr(\"y\",Math.max(u,0)+o),_.attr(\"x2\",0).attr(\"y2\",u),E.attr(\"x\",0).attr(\"y\",Math.max(u,0)+o),w.attr(\"dy\",\".71em\").style(\"text-anchor\",\"middle\"),x.attr(\"d\",\"M\"+y[0]+\",\"+i+\"V0H\"+y[1]+\"V\"+i);break;case\"top\":n=Ti,b.attr(\"y2\",-u),S.attr(\"y\",-(Math.max(u,0)+o)),_.attr(\"x2\",0).attr(\"y2\",-u),E.attr(\"x\",0).attr(\"y\",-(Math.max(u,0)+o)),w.attr(\"dy\",\"0em\").style(\"text-anchor\",\"middle\"),x.attr(\"d\",\"M\"+y[0]+\",\"+-i+\"V0H\"+y[1]+\"V\"+-i);break;case\"left\":n=qi,b.attr(\"x2\",-u),S.attr(\"x\",-(Math.max(u,0)+o)),_.attr(\"x2\",-u).attr(\"y2\",0),E.attr(\"x\",-(Math.max(u,0)+o)).attr(\"y\",0),w.attr(\"dy\",\".32em\").style(\"text-anchor\",\"end\"),x.attr(\"d\",\"M\"+-i+\",\"+y[0]+\"H0V\"+y[1]+\"H\"+-i);break;case\"right\":n=qi,b.attr(\"x2\",u),S.attr(\"x\",Math.max(u,0)+o),_.attr(\"x2\",u).attr(\"y2\",0),E.attr(\"x\",Math.max(u,0)+o).attr(\"y\",0),w.attr(\"dy\",\".32em\").style(\"text-anchor\",\"start\"),x.attr(\"d\",\"M\"+i+\",\"+y[0]+\"H0V\"+y[1]+\"H\"+i)}if(f.rangeBand){var k=f.rangeBand()/2,A=function(n){return f(n)+k};d.call(n,A),m.call(n,A)}else d.call(n,s),m.call(n,f),v.call(n,f)})}var t,e=mo.scale.linear(),r=Vc,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xc?t+\"\":Vc,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vc=\"bottom\",Xc={top:1,right:1,bottom:1,left:1};mo.svg.brush=function(){function n(i){i.each(function(){var i=mo.select(this).style(\"pointer-events\",\"all\").style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\").on(\"mousedown.brush\",u).on(\"touchstart.brush\",u),o=i.selectAll(\".background\").data([0]);o.enter().append(\"rect\").attr(\"class\",\"background\").style(\"visibility\",\"hidden\").style(\"cursor\",\"crosshair\"),i.selectAll(\".extent\").data([0]).enter().append(\"rect\").attr(\"class\",\"extent\").style(\"cursor\",\"move\");var a=i.selectAll(\".resize\").data(v,dt);a.exit().remove(),a.enter().append(\"g\").attr(\"class\",function(n){return\"resize \"+n}).style(\"cursor\",function(n){return $c[n]}).append(\"rect\").attr(\"x\",function(n){return/[ew]$/.test(n)?-3:null}).attr(\"y\",function(n){return/^[ns]/.test(n)?-3:null}).attr(\"width\",6).attr(\"height\",6).style(\"visibility\",\"hidden\"),a.style(\"display\",n.empty()?\"none\":null);var s,f=mo.transition(i),h=mo.transition(o);c&&(s=Bu(c),h.attr(\"x\",s[0]).attr(\"width\",s[1]-s[0]),e(f)),l&&(s=Bu(l),h.attr(\"y\",s[0]).attr(\"height\",s[1]-s[0]),r(f)),t(f)})}function t(n){n.selectAll(\".resize\").attr(\"transform\",function(n){return\"translate(\"+s[+/e$/.test(n)]+\",\"+h[+/^s/.test(n)]+\")\"})}function e(n){n.select(\".extent\").attr(\"x\",s[0]),n.selectAll(\".extent,.n>rect,.s>rect\").attr(\"width\",s[1]-s[0])}function r(n){n.select(\".extent\").attr(\"y\",h[0]),n.selectAll(\".extent,.e>rect,.w>rect\").attr(\"height\",h[1]-h[0])}function u(){function u(){32==mo.event.keyCode&&(N||(M=null,q[0]-=s[1],q[1]-=h[1],N=2),f())}function g(){32==mo.event.keyCode&&2==N&&(q[0]+=s[1],q[1]+=h[1],N=0,f())}function v(){var n=mo.mouse(b),u=!1;x&&(n[0]+=x[0],n[1]+=x[1]),N||(mo.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),q[0]=s[+(n[0]<M[0])],q[1]=h[+(n[1]<M[1])]):M=null),k&&m(n,c,0)&&(e(S),u=!0),A&&m(n,l,1)&&(r(S),u=!0),u&&(t(S),w({type:\"brush\",mode:N?\"move\":\"resize\"}))}function m(n,t,e){var r,u,a=Bu(t),c=a[0],l=a[1],f=q[e],g=e?h:s,v=g[1]-g[0];return N&&(c-=f,l-=v+f),r=(e?d:p)?Math.max(c,Math.min(l,n[e])):n[e],N?u=(r+=f)+v:(M&&(f=Math.max(c,Math.min(l,2*M[e]-r))),r>f?(u=r,r=f):u=f),g[0]!=r||g[1]!=u?(e?o=null:i=null,g[0]=r,g[1]=u,!0):void 0}function y(){v(),S.style(\"pointer-events\",\"all\").selectAll(\".resize\").style(\"display\",n.empty()?\"none\":null),mo.select(\"body\").style(\"cursor\",null),z.on(\"mousemove.brush\",null).on(\"mouseup.brush\",null).on(\"touchmove.brush\",null).on(\"touchend.brush\",null).on(\"keydown.brush\",null).on(\"keyup.brush\",null),T(),w({type:\"brushend\"})}var M,x,b=this,_=mo.select(mo.event.target),w=a.of(b,arguments),S=mo.select(b),E=_.datum(),k=!/^(n|s)$/.test(E)&&c,A=!/^(e|w)$/.test(E)&&l,N=_.classed(\"extent\"),T=L(),q=mo.mouse(b),z=mo.select(_o).on(\"keydown.brush\",u).on(\"keyup.brush\",g);if(mo.event.changedTouches?z.on(\"touchmove.brush\",v).on(\"touchend.brush\",y):z.on(\"mousemove.brush\",v).on(\"mouseup.brush\",y),S.interrupt().selectAll(\"*\").interrupt(),N)q[0]=s[0]-q[0],q[1]=h[0]-q[1];else if(E){var C=+/w$/.test(E),D=+/^n/.test(E);x=[s[1-C]-q[0],h[1-D]-q[1]],q[0]=s[C],q[1]=h[D]}else mo.event.altKey&&(M=q.slice());S.style(\"pointer-events\",\"none\").selectAll(\".resize\").style(\"display\",null),mo.select(\"body\").style(\"cursor\",_.style(\"cursor\")),w({type:\"brushstart\"}),v()}var i,o,a=g(n,\"brushstart\",\"brush\",\"brushend\"),c=null,l=null,s=[0,0],h=[0,0],p=!0,d=!0,v=Bc[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:s,y:h,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Oc?mo.select(this).transition().each(\"start.brush\",function(){i=e.i,o=e.j,s=e.x,h=e.y,n({type:\"brushstart\"})}).tween(\"brush:brush\",function(){var e=kr(s,t.x),r=kr(h,t.y);return i=o=null,function(u){s=t.x=e(u),h=t.y=r(u),n({type:\"brush\",mode:\"resize\"})}}).each(\"end.brush\",function(){i=t.i,o=t.j,n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"})}):(n({type:\"brushstart\"}),n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"}))})},n.x=function(t){return arguments.length?(c=t,v=Bc[!c<<1|!l],n):c},n.y=function(t){return arguments.length?(l=t,v=Bc[!c<<1|!l],n):l},n.clamp=function(t){return arguments.length?(c&&l?(p=!!t[0],d=!!t[1]):c?p=!!t:l&&(d=!!t),n):c&&l?[p,d]:c?p:l?d:null},n.extent=function(t){var e,r,u,a,f;return arguments.length?(c&&(e=t[0],r=t[1],l&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(f=e,e=r,r=f),(e!=s[0]||r!=s[1])&&(s=[e,r])),l&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],l.invert&&(u=l(u),a=l(a)),u>a&&(f=u,u=a,a=f),(u!=h[0]||a!=h[1])&&(h=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(f=e,e=r,r=f))),l&&(o?(u=o[0],a=o[1]):(u=h[0],a=h[1],l.invert&&(u=l.invert(u),a=l.invert(a)),u>a&&(f=u,u=a,a=f))),c&&l?[[e,u],[r,a]]:c?[e,r]:l&&[u,a])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],i=o=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!l&&h[0]==h[1]},mo.rebind(n,a,\"on\")};var $c={n:\"ns-resize\",e:\"ew-resize\",s:\"ns-resize\",w:\"ew-resize\",nw:\"nwse-resize\",ne:\"nesw-resize\",se:\"nwse-resize\",sw:\"nesw-resize\"},Bc=[[\"n\",\"e\",\"s\",\"w\",\"nw\",\"ne\",\"se\",\"sw\"],[\"e\",\"w\"],[\"n\",\"s\"],[]],Wc=mo.time={},Jc=Date,Gc=[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"];zi.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){Kc.setUTCDate.apply(this._,arguments)},setDay:function(){Kc.setUTCDay.apply(this._,arguments)},setFullYear:function(){Kc.setUTCFullYear.apply(this._,arguments)},setHours:function(){Kc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){Kc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){Kc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){Kc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){Kc.setUTCSeconds.apply(this._,arguments)},setTime:function(){Kc.setTime.apply(this._,arguments)}};var Kc=Date.prototype,Qc=\"%a %b %e %X %Y\",nl=\"%m/%d/%Y\",tl=\"%H:%M:%S\",el=[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"],rl=[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],ul=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"],il=[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];Wc.year=Ci(function(n){return n=Wc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Wc.years=Wc.year.range,Wc.years.utc=Wc.year.utc.range,Wc.day=Ci(function(n){var t=new Jc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Wc.days=Wc.day.range,Wc.days.utc=Wc.day.utc.range,Wc.dayOfYear=function(n){var t=Wc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},Gc.forEach(function(n,t){n=n.toLowerCase(),t=7-t;var e=Wc[n]=Ci(function(n){return(n=Wc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Wc.year(n).getDay();return Math.floor((Wc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Wc[n+\"s\"]=e.range,Wc[n+\"s\"].utc=e.utc.range,Wc[n+\"OfYear\"]=function(n){var e=Wc.year(n).getDay();return Math.floor((Wc.dayOfYear(n)+(e+t)%7)/7)}}),Wc.week=Wc.sunday,Wc.weeks=Wc.sunday.range,Wc.weeks.utc=Wc.sunday.utc.range,Wc.weekOfYear=Wc.sundayOfYear,Wc.format=ji;var ol=Hi(el),al=Fi(el),cl=Hi(rl),ll=Fi(rl),sl=Hi(ul),fl=Fi(ul),hl=Hi(il),gl=Fi(il),pl=/^%/,dl={\"-\":\"\",_:\" \",0:\"0\"},vl={a:function(n){return rl[n.getDay()]},A:function(n){return el[n.getDay()]},b:function(n){return il[n.getMonth()]},B:function(n){return ul[n.getMonth()]},c:ji(Qc),d:function(n,t){return Pi(n.getDate(),t,2)},e:function(n,t){return Pi(n.getDate(),t,2)},H:function(n,t){return Pi(n.getHours(),t,2)},I:function(n,t){return Pi(n.getHours()%12||12,t,2)},j:function(n,t){return Pi(1+Wc.dayOfYear(n),t,3)},L:function(n,t){return Pi(n.getMilliseconds(),t,3)},m:function(n,t){return Pi(n.getMonth()+1,t,2)},M:function(n,t){return Pi(n.getMinutes(),t,2)},p:function(n){return n.getHours()>=12?\"PM\":\"AM\"},S:function(n,t){return Pi(n.getSeconds(),t,2)},U:function(n,t){return Pi(Wc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Pi(Wc.mondayOfYear(n),t,2)},x:ji(nl),X:ji(tl),y:function(n,t){return Pi(n.getFullYear()%100,t,2)},Y:function(n,t){return Pi(n.getFullYear()%1e4,t,4)},Z:ao,\"%\":function(){return\"%\"}},ml={a:Oi,A:Ri,b:Zi,B:Vi,c:Xi,d:no,e:no,H:eo,I:eo,j:to,L:io,m:Qi,M:ro,p:oo,S:uo,U:Ii,w:Yi,W:Ui,x:$i,X:Bi,y:Ji,Y:Wi,Z:Gi,\"%\":co},yl=/^\\s*\\d+/,Ml=mo.map({am:0,pm:1});ji.utc=lo;var xl=lo(\"%Y-%m-%dT%H:%M:%S.%LZ\");ji.iso=Date.prototype.toISOString&&+new Date(\"2000-01-01T00:00:00.000Z\")?so:xl,so.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},so.toString=xl.toString,Wc.second=Ci(function(n){return new Jc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Wc.seconds=Wc.second.range,Wc.seconds.utc=Wc.second.utc.range,Wc.minute=Ci(function(n){return new Jc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Wc.minutes=Wc.minute.range,Wc.minutes.utc=Wc.minute.utc.range,Wc.hour=Ci(function(n){var t=n.getTimezoneOffset()/60;return new Jc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Wc.hours=Wc.hour.range,Wc.hours.utc=Wc.hour.utc.range,Wc.month=Ci(function(n){return n=Wc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Wc.months=Wc.month.range,Wc.months.utc=Wc.month.utc.range;var bl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],_l=[[Wc.second,1],[Wc.second,5],[Wc.second,15],[Wc.second,30],[Wc.minute,1],[Wc.minute,5],[Wc.minute,15],[Wc.minute,30],[Wc.hour,1],[Wc.hour,3],[Wc.hour,6],[Wc.hour,12],[Wc.day,1],[Wc.day,2],[Wc.week,1],[Wc.month,1],[Wc.month,3],[Wc.year,1]],wl=[[ji(\"%Y\"),Vt],[ji(\"%B\"),function(n){return n.getMonth()}],[ji(\"%b %d\"),function(n){return 1!=n.getDate()}],[ji(\"%a %d\"),function(n){return n.getDay()&&1!=n.getDate()}],[ji(\"%I %p\"),function(n){return n.getHours()}],[ji(\"%I:%M\"),function(n){return n.getMinutes()}],[ji(\":%S\"),function(n){return n.getSeconds()}],[ji(\".%L\"),function(n){return n.getMilliseconds()}]],Sl=go(wl);_l.year=Wc.year,Wc.scale=function(){return fo(mo.scale.linear(),_l,Sl)};var El={range:function(n,t,e){return mo.range(+n,+t,e).map(ho)}},kl=_l.map(function(n){return[n[0].utc,n[1]]}),Al=[[lo(\"%Y\"),Vt],[lo(\"%B\"),function(n){return n.getUTCMonth()}],[lo(\"%b %d\"),function(n){return 1!=n.getUTCDate()}],[lo(\"%a %d\"),function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],[lo(\"%I %p\"),function(n){return n.getUTCHours()}],[lo(\"%I:%M\"),function(n){return n.getUTCMinutes()}],[lo(\":%S\"),function(n){return n.getUTCSeconds()}],[lo(\".%L\"),function(n){return n.getUTCMilliseconds()}]],Nl=go(Al);return kl.year=Wc.year.utc,Wc.scale.utc=function(){return fo(mo.scale.linear(),kl,Nl)},mo.text=vt(function(n){return n.responseText}),mo.json=function(n,t){return mt(n,\"application/json\",po,t)},mo.html=function(n,t){return mt(n,\"text/html\",vo,t)},mo.xml=vt(function(n){return n.responseXML}),mo}();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/css/select2.css",
    "content": ".select2-container {\n    box-sizing: border-box;\n    display: inline-block;\n    margin: 0;\n    position: relative;\n    vertical-align: middle;\n}\n\n.select2-container .select2-selection--single {\n    box-sizing: border-box;\n    cursor: pointer;\n    display: block;\n    height: 28px;\n    user-select: none;\n    -webkit-user-select: none;\n}\n\n.select2-container .select2-selection--single .select2-selection__rendered {\n    display: block;\n    padding-left: 8px;\n    padding-right: 20px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n.select2-container .select2-selection--single .select2-selection__clear {\n    position: relative;\n}\n\n.select2-container[dir=\"rtl\"] .select2-selection--single .select2-selection__rendered {\n    padding-right: 8px;\n    padding-left: 20px;\n}\n\n.select2-container .select2-selection--multiple {\n    box-sizing: border-box;\n    cursor: pointer;\n    display: block;\n    min-height: 32px;\n    user-select: none;\n    -webkit-user-select: none;\n}\n\n.select2-container .select2-selection--multiple .select2-selection__rendered {\n    display: inline-block;\n    overflow: hidden;\n    padding-left: 8px;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n.select2-container .select2-search--inline {\n    float: left;\n}\n\n.select2-container .select2-search--inline .select2-search__field {\n    box-sizing: border-box;\n    border: none;\n    font-size: 100%;\n    margin-top: 5px;\n    padding: 0;\n}\n\n.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {\n    -webkit-appearance: none;\n}\n\n.select2-dropdown {\n    background-color: white;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    box-sizing: border-box;\n    display: block;\n    position: absolute;\n    left: -100000px;\n    width: 100%;\n    z-index: 1051;\n}\n\n.select2-results {\n    display: block;\n}\n\n.select2-results__options {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n}\n\n.select2-results__option {\n    padding: 6px;\n    user-select: none;\n    -webkit-user-select: none;\n}\n\n.select2-results__option[aria-selected] {\n    cursor: pointer;\n}\n\n.select2-container--open .select2-dropdown {\n    left: 0;\n}\n\n.select2-container--open .select2-dropdown--above {\n    border-bottom: none;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n}\n\n.select2-container--open .select2-dropdown--below {\n    border-top: none;\n    border-top-left-radius: 0;\n    border-top-right-radius: 0;\n}\n\n.select2-search--dropdown {\n    display: block;\n    padding: 4px;\n}\n\n.select2-search--dropdown .select2-search__field {\n    padding: 4px;\n    width: 100%;\n    box-sizing: border-box;\n}\n\n.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {\n    -webkit-appearance: none;\n}\n\n.select2-search--dropdown.select2-search--hide {\n    display: none;\n}\n\n.select2-close-mask {\n    border: 0;\n    margin: 0;\n    padding: 0;\n    display: block;\n    position: fixed;\n    left: 0;\n    top: 0;\n    min-height: 100%;\n    min-width: 100%;\n    height: auto;\n    width: auto;\n    opacity: 0;\n    z-index: 99;\n    background-color: #fff;\n    filter: alpha(opacity=0);\n}\n\n.select2-hidden-accessible {\n    border: 0 !important;\n    clip: rect(0 0 0 0) !important;\n    -webkit-clip-path: inset(50%) !important;\n    clip-path: inset(50%) !important;\n    height: 1px !important;\n    overflow: hidden !important;\n    padding: 0 !important;\n    position: absolute !important;\n    width: 1px !important;\n    white-space: nowrap !important;\n}\n\n.select2-container--default .select2-selection--single {\n    background-color: #fff;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n}\n\n.select2-container--default .select2-selection--single .select2-selection__rendered {\n    color: #444;\n    line-height: 28px;\n}\n\n.select2-container--default .select2-selection--single .select2-selection__clear {\n    cursor: pointer;\n    float: right;\n    font-weight: bold;\n}\n\n.select2-container--default .select2-selection--single .select2-selection__placeholder {\n    color: #999;\n}\n\n.select2-container--default .select2-selection--single .select2-selection__arrow {\n    height: 26px;\n    position: absolute;\n    top: 1px;\n    right: 1px;\n    width: 20px;\n}\n\n.select2-container--default .select2-selection--single .select2-selection__arrow b {\n    border-color: #888 transparent transparent transparent;\n    border-style: solid;\n    border-width: 5px 4px 0 4px;\n    height: 0;\n    left: 50%;\n    margin-left: -4px;\n    margin-top: -2px;\n    position: absolute;\n    top: 50%;\n    width: 0;\n}\n\n.select2-container--default[dir=\"rtl\"] .select2-selection--single .select2-selection__clear {\n    float: left;\n}\n\n.select2-container--default[dir=\"rtl\"] .select2-selection--single .select2-selection__arrow {\n    left: 1px;\n    right: auto;\n}\n\n.select2-container--default.select2-container--disabled .select2-selection--single {\n    background-color: #eee;\n    cursor: default;\n}\n\n.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {\n    display: none;\n}\n\n.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {\n    border-color: transparent transparent #888 transparent;\n    border-width: 0 4px 5px 4px;\n}\n\n.select2-container--default .select2-selection--multiple {\n    background-color: white;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    cursor: text;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__rendered {\n    box-sizing: border-box;\n    list-style: none;\n    margin: 0;\n    padding: 0 5px;\n    width: 100%;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__rendered li {\n    list-style: none;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__placeholder {\n    color: #999;\n    margin-top: 5px;\n    float: left;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__clear {\n    cursor: pointer;\n    float: right;\n    font-weight: bold;\n    margin-top: 5px;\n    margin-right: 10px;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__choice {\n    background-color: #e4e4e4;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    cursor: default;\n    float: left;\n    margin-right: 5px;\n    margin-top: 5px;\n    padding: 0 5px;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {\n    color: #999;\n    cursor: pointer;\n    display: inline-block;\n    font-weight: bold;\n    margin-right: 2px;\n}\n\n.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {\n    color: #333;\n}\n\n.select2-container--default[dir=\"rtl\"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir=\"rtl\"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir=\"rtl\"] .select2-selection--multiple .select2-search--inline {\n    float: right;\n}\n\n.select2-container--default[dir=\"rtl\"] .select2-selection--multiple .select2-selection__choice {\n    margin-left: 5px;\n    margin-right: auto;\n}\n\n.select2-container--default[dir=\"rtl\"] .select2-selection--multiple .select2-selection__choice__remove {\n    margin-left: 2px;\n    margin-right: auto;\n}\n\n.select2-container--default.select2-container--focus .select2-selection--multiple {\n    border: solid black 1px;\n    outline: 0;\n}\n\n.select2-container--default.select2-container--disabled .select2-selection--multiple {\n    background-color: #eee;\n    cursor: default;\n}\n\n.select2-container--default.select2-container--disabled .select2-selection__choice__remove {\n    display: none;\n}\n\n.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {\n    border-top-left-radius: 0;\n    border-top-right-radius: 0;\n}\n\n.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n}\n\n.select2-container--default .select2-search--dropdown .select2-search__field {\n    border: 1px solid #aaa;\n}\n\n.select2-container--default .select2-search--inline .select2-search__field {\n    background: transparent;\n    border: none;\n    outline: 0;\n    box-shadow: none;\n    -webkit-appearance: textfield;\n}\n\n.select2-container--default .select2-results > .select2-results__options {\n    max-height: 200px;\n    overflow-y: auto;\n}\n\n.select2-container--default .select2-results__option[role=group] {\n    padding: 0;\n}\n\n.select2-container--default .select2-results__option[aria-disabled=true] {\n    color: #999;\n}\n\n.select2-container--default .select2-results__option[aria-selected=true] {\n    background-color: #ddd;\n}\n\n.select2-container--default .select2-results__option .select2-results__option {\n    padding-left: 1em;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__group {\n    padding-left: 0;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__option {\n    margin-left: -1em;\n    padding-left: 2em;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {\n    margin-left: -2em;\n    padding-left: 3em;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {\n    margin-left: -3em;\n    padding-left: 4em;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {\n    margin-left: -4em;\n    padding-left: 5em;\n}\n\n.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {\n    margin-left: -5em;\n    padding-left: 6em;\n}\n\n.select2-container--default .select2-results__option--highlighted[aria-selected] {\n    background-color: #5897fb;\n    color: white;\n}\n\n.select2-container--default .select2-results__group {\n    cursor: default;\n    display: block;\n    padding: 6px;\n}\n\n.select2-container--classic .select2-selection--single {\n    background-color: #f7f7f7;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    outline: 0;\n    background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);\n    background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);\n    background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);\n}\n\n.select2-container--classic .select2-selection--single:focus {\n    border: 1px solid #5897fb;\n}\n\n.select2-container--classic .select2-selection--single .select2-selection__rendered {\n    color: #444;\n    line-height: 28px;\n}\n\n.select2-container--classic .select2-selection--single .select2-selection__clear {\n    cursor: pointer;\n    float: right;\n    font-weight: bold;\n    margin-right: 10px;\n}\n\n.select2-container--classic .select2-selection--single .select2-selection__placeholder {\n    color: #999;\n}\n\n.select2-container--classic .select2-selection--single .select2-selection__arrow {\n    background-color: #ddd;\n    border: none;\n    border-left: 1px solid #aaa;\n    border-top-right-radius: 4px;\n    border-bottom-right-radius: 4px;\n    height: 26px;\n    position: absolute;\n    top: 1px;\n    right: 1px;\n    width: 20px;\n    background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);\n    background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);\n    background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0);\n}\n\n.select2-container--classic .select2-selection--single .select2-selection__arrow b {\n    border-color: #888 transparent transparent transparent;\n    border-style: solid;\n    border-width: 5px 4px 0 4px;\n    height: 0;\n    left: 50%;\n    margin-left: -4px;\n    margin-top: -2px;\n    position: absolute;\n    top: 50%;\n    width: 0;\n}\n\n.select2-container--classic[dir=\"rtl\"] .select2-selection--single .select2-selection__clear {\n    float: left;\n}\n\n.select2-container--classic[dir=\"rtl\"] .select2-selection--single .select2-selection__arrow {\n    border: none;\n    border-right: 1px solid #aaa;\n    border-radius: 0;\n    border-top-left-radius: 4px;\n    border-bottom-left-radius: 4px;\n    left: 1px;\n    right: auto;\n}\n\n.select2-container--classic.select2-container--open .select2-selection--single {\n    border: 1px solid #5897fb;\n}\n\n.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {\n    background: transparent;\n    border: none;\n}\n\n.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {\n    border-color: transparent transparent #888 transparent;\n    border-width: 0 4px 5px 4px;\n}\n\n.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {\n    border-top: none;\n    border-top-left-radius: 0;\n    border-top-right-radius: 0;\n    background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);\n    background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);\n    background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);\n}\n\n.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {\n    border-bottom: none;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n    background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);\n    background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);\n    background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0);\n}\n\n.select2-container--classic .select2-selection--multiple {\n    background-color: white;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    cursor: text;\n    outline: 0;\n}\n\n.select2-container--classic .select2-selection--multiple:focus {\n    border: 1px solid #5897fb;\n}\n\n.select2-container--classic .select2-selection--multiple .select2-selection__rendered {\n    list-style: none;\n    margin: 0;\n    padding: 0 5px;\n}\n\n.select2-container--classic .select2-selection--multiple .select2-selection__clear {\n    display: none;\n}\n\n.select2-container--classic .select2-selection--multiple .select2-selection__choice {\n    background-color: #e4e4e4;\n    border: 1px solid #aaa;\n    border-radius: 4px;\n    cursor: default;\n    float: left;\n    margin-right: 5px;\n    margin-top: 5px;\n    padding: 0 5px;\n}\n\n.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {\n    color: #888;\n    cursor: pointer;\n    display: inline-block;\n    font-weight: bold;\n    margin-right: 2px;\n}\n\n.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {\n    color: #555;\n}\n\n.select2-container--classic[dir=\"rtl\"] .select2-selection--multiple .select2-selection__choice {\n    float: right;\n    margin-left: 5px;\n    margin-right: auto;\n}\n\n.select2-container--classic[dir=\"rtl\"] .select2-selection--multiple .select2-selection__choice__remove {\n    margin-left: 2px;\n    margin-right: auto;\n}\n\n.select2-container--classic.select2-container--open .select2-selection--multiple {\n    border: 1px solid #5897fb;\n}\n\n.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {\n    border-top: none;\n    border-top-left-radius: 0;\n    border-top-right-radius: 0;\n}\n\n.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {\n    border-bottom: none;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n}\n\n.select2-container--classic .select2-search--dropdown .select2-search__field {\n    border: 1px solid #aaa;\n    outline: 0;\n}\n\n.select2-container--classic .select2-search--inline .select2-search__field {\n    outline: 0;\n    box-shadow: none;\n}\n\n.select2-container--classic .select2-dropdown {\n    background-color: white;\n    border: 1px solid transparent;\n}\n\n.select2-container--classic .select2-dropdown--above {\n    border-bottom: none;\n}\n\n.select2-container--classic .select2-dropdown--below {\n    border-top: none;\n}\n\n.select2-container--classic .select2-results > .select2-results__options {\n    max-height: 200px;\n    overflow-y: auto;\n}\n\n.select2-container--classic .select2-results__option[role=group] {\n    padding: 0;\n}\n\n.select2-container--classic .select2-results__option[aria-disabled=true] {\n    color: grey;\n}\n\n.select2-container--classic .select2-results__option--highlighted[aria-selected] {\n    background-color: #3875d7;\n    color: white;\n}\n\n.select2-container--classic .select2-results__group {\n    cursor: default;\n    display: block;\n    padding: 6px;\n}\n\n.select2-container--classic.select2-container--open .select2-dropdown {\n    border-color: #5897fb;\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/af.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/af\",[],function(){return{errorLoading:function(){return\"Die resultate kon nie gelaai word nie.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Verwyders asseblief \"+t+\" character\";return t!=1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Voer asseblief \"+t+\" of meer karakters\";return n},loadingMore:function(){return\"Meer resultate word gelaai…\"},maximumSelected:function(e){var t=\"Kies asseblief net \"+e.maximum+\" item\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"Geen resultate gevind\"},searching:function(){return\"Besig…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ar.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ar\",[],function(){return{errorLoading:function(){return\"لا يمكن تحميل النتائج\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"الرجاء حذف \"+t+\" عناصر\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"الرجاء إضافة \"+t+\" عناصر\"},loadingMore:function(){return\"جاري تحميل نتائج إضافية...\"},maximumSelected:function(e){return\"تستطيع إختيار \"+e.maximum+\" بنود فقط\"},noResults:function(){return\"لم يتم العثور على أي نتائج\"},searching:function(){return\"جاري البحث…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/az.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/az\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return t+\" simvol silin\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t+\" simvol daxil edin\"},loadingMore:function(){return\"Daha çox nəticə yüklənir…\"},maximumSelected:function(e){return\"Sadəcə \"+e.maximum+\" element seçə bilərsiniz\"},noResults:function(){return\"Nəticə tapılmadı\"},searching:function(){return\"Axtarılır…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/bg.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/bg\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Моля въведете с \"+t+\" по-малко символ\";return t>1&&(n+=\"a\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Моля въведете още \"+t+\" символ\";return t>1&&(n+=\"a\"),n},loadingMore:function(){return\"Зареждат се още…\"},maximumSelected:function(e){var t=\"Можете да направите до \"+e.maximum+\" \";return e.maximum>1?t+=\"избора\":t+=\"избор\",t},noResults:function(){return\"Няма намерени съвпадения\"},searching:function(){return\"Търсене…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/bs.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/bs\",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return\"Preuzimanje nije uspijelo.\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Obrišite \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Ukucajte bar još \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},loadingMore:function(){return\"Preuzimanje još rezultata…\"},maximumSelected:function(t){var n=\"Možete izabrati samo \"+t.maximum+\" stavk\";return n+=e(t.maximum,\"u\",\"e\",\"i\"),n},noResults:function(){return\"Ništa nije pronađeno\"},searching:function(){return\"Pretraga…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ca.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ca\",[],function(){return{errorLoading:function(){return\"La càrrega ha fallat\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Si us plau, elimina \"+t+\" car\";return t==1?n+=\"àcter\":n+=\"àcters\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Si us plau, introdueix \"+t+\" car\";return t==1?n+=\"àcter\":n+=\"àcters\",n},loadingMore:function(){return\"Carregant més resultats…\"},maximumSelected:function(e){var t=\"Només es pot seleccionar \"+e.maximum+\" element\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No s'han trobat resultats\"},searching:function(){return\"Cercant…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/cs.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/cs\",[],function(){function e(e,t){switch(e){case 2:return t?\"dva\":\"dvě\";case 3:return\"tři\";case 4:return\"čtyři\"}return\"\"}return{errorLoading:function(){return\"Výsledky nemohly být načteny.\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?\"Prosím, zadejte o jeden znak méně.\":n<=4?\"Prosím, zadejte o \"+e(n,!0)+\" znaky méně.\":\"Prosím, zadejte o \"+n+\" znaků méně.\"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?\"Prosím, zadejte ještě jeden znak.\":n<=4?\"Prosím, zadejte ještě další \"+e(n,!0)+\" znaky.\":\"Prosím, zadejte ještě dalších \"+n+\" znaků.\"},loadingMore:function(){return\"Načítají se další výsledky…\"},maximumSelected:function(t){var n=t.maximum;return n==1?\"Můžete zvolit jen jednu položku.\":n<=4?\"Můžete zvolit maximálně \"+e(n,!1)+\" položky.\":\"Můžete zvolit maximálně \"+n+\" položek.\"},noResults:function(){return\"Nenalezeny žádné položky.\"},searching:function(){return\"Vyhledávání…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/da.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/da\",[],function(){return{errorLoading:function(){return\"Resultaterne kunne ikke indlæses.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Angiv venligst \"+t+\" tegn mindre\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Angiv venligst \"+t+\" tegn mere\"},loadingMore:function(){return\"Indlæser flere resultater…\"},maximumSelected:function(e){var t=\"Du kan kun vælge \"+e.maximum+\" emne\";return e.maximum!=1&&(t+=\"r\"),t},noResults:function(){return\"Ingen resultater fundet\"},searching:function(){return\"Søger…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/de.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/de\",[],function(){return{errorLoading:function(){return\"Die Ergebnisse konnten nicht geladen werden.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Bitte \"+t+\" Zeichen weniger eingeben\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Bitte \"+t+\" Zeichen mehr eingeben\"},loadingMore:function(){return\"Lade mehr Ergebnisse…\"},maximumSelected:function(e){var t=\"Sie können nur \"+e.maximum+\" Eintr\";return e.maximum===1?t+=\"ag\":t+=\"äge\",t+=\" auswählen\",t},noResults:function(){return\"Keine Übereinstimmungen gefunden\"},searching:function(){return\"Suche…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/dsb.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/dsb\",[],function(){var e=[\"znamuško\",\"znamušce\",\"znamuška\",\"znamuškow\"],t=[\"zapisk\",\"zapiska\",\"zapiski\",\"zapiskow\"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return\"Wuslědki njejsu se dali zacytaś.\"},inputTooLong:function(t){var r=t.input.length-t.maximum;return\"Pšosym lašuj \"+r+\" \"+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return\"Pšosym zapódaj nanejmjenjej \"+r+\" \"+n(r,e)},loadingMore:function(){return\"Dalšne wuslědki se zacytaju…\"},maximumSelected:function(e){return\"Móžoš jano \"+e.maximum+\" \"+n(e.maximum,t)+\"wubraś.\"},noResults:function(){return\"Žedne wuslědki namakane\"},searching:function(){return\"Pyta se…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/el.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/el\",[],function(){return{errorLoading:function(){return\"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Παρακαλώ διαγράψτε \"+t+\" χαρακτήρ\";return t==1&&(n+=\"α\"),t!=1&&(n+=\"ες\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Παρακαλώ συμπληρώστε \"+t+\" ή περισσότερους χαρακτήρες\";return n},loadingMore:function(){return\"Φόρτωση περισσότερων αποτελεσμάτων…\"},maximumSelected:function(e){var t=\"Μπορείτε να επιλέξετε μόνο \"+e.maximum+\" επιλογ\";return e.maximum==1&&(t+=\"ή\"),e.maximum!=1&&(t+=\"ές\"),t},noResults:function(){return\"Δεν βρέθηκαν αποτελέσματα\"},searching:function(){return\"Αναζήτηση…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/en.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/en\",[],function(){return{errorLoading:function(){return\"The results could not be loaded.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Please delete \"+t+\" character\";return t!=1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Please enter \"+t+\" or more characters\";return n},loadingMore:function(){return\"Loading more results…\"},maximumSelected:function(e){var t=\"You can only select \"+e.maximum+\" item\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No results found\"},searching:function(){return\"Searching…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/es.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/es\",[],function(){return{errorLoading:function(){return\"No se pudieron cargar los resultados\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Por favor, elimine \"+t+\" car\";return t==1?n+=\"ácter\":n+=\"acteres\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Por favor, introduzca \"+t+\" car\";return t==1?n+=\"ácter\":n+=\"acteres\",n},loadingMore:function(){return\"Cargando más resultados…\"},maximumSelected:function(e){var t=\"Sólo puede seleccionar \"+e.maximum+\" elemento\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No se encontraron resultados\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/et.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/et\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Sisesta \"+t+\" täht\";return t!=1&&(n+=\"e\"),n+=\" vähem\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Sisesta \"+t+\" täht\";return t!=1&&(n+=\"e\"),n+=\" rohkem\",n},loadingMore:function(){return\"Laen tulemusi…\"},maximumSelected:function(e){var t=\"Saad vaid \"+e.maximum+\" tulemus\";return e.maximum==1?t+=\"e\":t+=\"t\",t+=\" valida\",t},noResults:function(){return\"Tulemused puuduvad\"},searching:function(){return\"Otsin…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/eu.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/eu\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Idatzi \";return t==1?n+=\"karaktere bat\":n+=t+\" karaktere\",n+=\" gutxiago\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Idatzi \";return t==1?n+=\"karaktere bat\":n+=t+\" karaktere\",n+=\" gehiago\",n},loadingMore:function(){return\"Emaitza gehiago kargatzen…\"},maximumSelected:function(e){return e.maximum===1?\"Elementu bakarra hauta dezakezu\":e.maximum+\" elementu hauta ditzakezu soilik\"},noResults:function(){return\"Ez da bat datorrenik aurkitu\"},searching:function(){return\"Bilatzen…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/fa.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fa\",[],function(){return{errorLoading:function(){return\"امکان بارگذاری نتایج وجود ندارد.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"لطفاً \"+t+\" کاراکتر را حذف نمایید\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"لطفاً تعداد \"+t+\" کاراکتر یا بیشتر وارد نمایید\";return n},loadingMore:function(){return\"در حال بارگذاری نتایج بیشتر...\"},maximumSelected:function(e){var t=\"شما تنها می‌توانید \"+e.maximum+\" آیتم را انتخاب نمایید\";return t},noResults:function(){return\"هیچ نتیجه‌ای یافت نشد\"},searching:function(){return\"در حال جستجو...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/fi.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fi\",[],function(){return{errorLoading:function(){return\"Tuloksia ei saatu ladattua.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Ole hyvä ja anna \"+t+\" merkkiä vähemmän\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Ole hyvä ja anna \"+t+\" merkkiä lisää\"},loadingMore:function(){return\"Ladataan lisää tuloksia…\"},maximumSelected:function(e){return\"Voit valita ainoastaan \"+e.maximum+\" kpl\"},noResults:function(){return\"Ei tuloksia\"},searching:function(){return\"Haetaan…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/fr.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fr\",[],function(){return{errorLoading:function(){return\"Les résultats ne peuvent pas être chargés.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Supprimez \"+t+\" caractère\"+(t>1?\"s\":\"\")},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Saisissez au moins \"+t+\" caractère\"+(t>1?\"s\":\"\")},loadingMore:function(){return\"Chargement de résultats supplémentaires…\"},maximumSelected:function(e){return\"Vous pouvez seulement sélectionner \"+e.maximum+\" élément\"+(e.maximum>1?\"s\":\"\")},noResults:function(){return\"Aucun résultat trouvé\"},searching:function(){return\"Recherche en cours…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/gl.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/gl\",[],function(){return{errorLoading:function(){return\"Non foi posíbel cargar os resultados.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return t===1?\"Elimine un carácter\":\"Elimine \"+t+\" caracteres\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t===1?\"Engada un carácter\":\"Engada \"+t+\" caracteres\"},loadingMore:function(){return\"Cargando máis resultados…\"},maximumSelected:function(e){return e.maximum===1?\"Só pode seleccionar un elemento\":\"Só pode seleccionar \"+e.maximum+\" elementos\"},noResults:function(){return\"Non se atoparon resultados\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/he.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/he\",[],function(){return{errorLoading:function(){return\"שגיאה בטעינת התוצאות\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"נא למחוק \";return t===1?n+=\"תו אחד\":n+=t+\" תווים\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"נא להכניס \";return t===1?n+=\"תו אחד\":n+=t+\" תווים\",n+=\" או יותר\",n},loadingMore:function(){return\"טוען תוצאות נוספות…\"},maximumSelected:function(e){var t=\"באפשרותך לבחור עד \";return e.maximum===1?t+=\"פריט אחד\":t+=e.maximum+\" פריטים\",t},noResults:function(){return\"לא נמצאו תוצאות\"},searching:function(){return\"מחפש…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/hi.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hi\",[],function(){return{errorLoading:function(){return\"परिणामों को लोड नहीं किया जा सका।\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" अक्षर को हटा दें\";return t>1&&(n=t+\" अक्षरों को हटा दें \"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"कृपया \"+t+\" या अधिक अक्षर दर्ज करें\";return n},loadingMore:function(){return\"अधिक परिणाम लोड हो रहे है...\"},maximumSelected:function(e){var t=\"आप केवल \"+e.maximum+\" आइटम का चयन कर सकते हैं\";return t},noResults:function(){return\"कोई परिणाम नहीं मिला\"},searching:function(){return\"खोज रहा है...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/hr.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hr\",[],function(){function e(e){var t=\" \"+e+\" znak\";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+=\"a\"):t+=\"ova\",t}return{errorLoading:function(){return\"Preuzimanje nije uspjelo.\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return\"Unesite \"+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return\"Unesite još \"+e(n)},loadingMore:function(){return\"Učitavanje rezultata…\"},maximumSelected:function(e){return\"Maksimalan broj odabranih stavki je \"+e.maximum},noResults:function(){return\"Nema rezultata\"},searching:function(){return\"Pretraga…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/hsb.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hsb\",[],function(){var e=[\"znamješko\",\"znamješce\",\"znamješka\",\"znamješkow\"],t=[\"zapisk\",\"zapiskaj\",\"zapiski\",\"zapiskow\"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return\"Wuslědki njedachu so začitać.\"},inputTooLong:function(t){var r=t.input.length-t.maximum;return\"Prošu zhašej \"+r+\" \"+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return\"Prošu zapodaj znajmjeńša \"+r+\" \"+n(r,e)},loadingMore:function(){return\"Dalše wuslědki so začitaja…\"},maximumSelected:function(e){return\"Móžeš jenož \"+e.maximum+\" \"+n(e.maximum,t)+\"wubrać\"},noResults:function(){return\"Žane wuslědki namakane\"},searching:function(){return\"Pyta so…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/hu.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hu\",[],function(){return{errorLoading:function(){return\"Az eredmények betöltése nem sikerült.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Túl hosszú. \"+t+\" karakterrel több, mint kellene.\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Túl rövid. Még \"+t+\" karakter hiányzik.\"},loadingMore:function(){return\"Töltés…\"},maximumSelected:function(e){return\"Csak \"+e.maximum+\" elemet lehet kiválasztani.\"},noResults:function(){return\"Nincs találat.\"},searching:function(){return\"Keresés…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/hy.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hy\",[],function(){return{errorLoading:function(){return\"Արդյունքները հնարավոր չէ բեռնել։\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Խնդրում ենք հեռացնել \"+t+\" նշան\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Խնդրում ենք մուտքագրել \"+t+\" կամ ավել նշաններ\";return n},loadingMore:function(){return\"Բեռնվում են նոր արդյունքներ․․․\"},maximumSelected:function(e){var t=\"Դուք կարող եք ընտրել առավելագույնը \"+e.maximum+\" կետ\";return t},noResults:function(){return\"Արդյունքներ չեն գտնվել\"},searching:function(){return\"Որոնում․․․\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/id.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/id\",[],function(){return{errorLoading:function(){return\"Data tidak boleh diambil.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Hapuskan \"+t+\" huruf\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Masukkan \"+t+\" huruf lagi\"},loadingMore:function(){return\"Mengambil data…\"},maximumSelected:function(e){return\"Anda hanya dapat memilih \"+e.maximum+\" pilihan\"},noResults:function(){return\"Tidak ada data yang sesuai\"},searching:function(){return\"Mencari…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/is.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/is\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vinsamlegast styttið texta um \"+t+\" staf\";return t<=1?n:n+\"i\"},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vinsamlegast skrifið \"+t+\" staf\";return t>1&&(n+=\"i\"),n+=\" í viðbót\",n},loadingMore:function(){return\"Sæki fleiri niðurstöður…\"},maximumSelected:function(e){return\"Þú getur aðeins valið \"+e.maximum+\" atriði\"},noResults:function(){return\"Ekkert fannst\"},searching:function(){return\"Leita…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/it.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/it\",[],function(){return{errorLoading:function(){return\"I risultati non possono essere caricati.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Per favore cancella \"+t+\" caratter\";return t!==1?n+=\"i\":n+=\"e\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Per favore inserisci \"+t+\" o più caratteri\";return n},loadingMore:function(){return\"Caricando più risultati…\"},maximumSelected:function(e){var t=\"Puoi selezionare solo \"+e.maximum+\" element\";return e.maximum!==1?t+=\"i\":t+=\"o\",t},noResults:function(){return\"Nessun risultato trovato\"},searching:function(){return\"Sto cercando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ja.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ja\",[],function(){return{errorLoading:function(){return\"結果が読み込まれませんでした\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" 文字を削除してください\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"少なくとも \"+t+\" 文字を入力してください\";return n},loadingMore:function(){return\"読み込み中…\"},maximumSelected:function(e){var t=e.maximum+\" 件しか選択できません\";return t},noResults:function(){return\"対象が見つかりません\"},searching:function(){return\"検索しています…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/km.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/km\",[],function(){return{errorLoading:function(){return\"មិនអាចទាញយកទិន្នន័យ\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"សូមលុបចេញ  \"+t+\" អក្សរ\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"សូមបញ្ចូល\"+t+\" អក្សរ រឺ ច្រើនជាងនេះ\";return n},loadingMore:function(){return\"កំពុងទាញយកទិន្នន័យបន្ថែម...\"},maximumSelected:function(e){var t=\"អ្នកអាចជ្រើសរើសបានតែ \"+e.maximum+\" ជម្រើសប៉ុណ្ណោះ\";return t},noResults:function(){return\"មិនមានលទ្ធផល\"},searching:function(){return\"កំពុងស្វែងរក...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ko.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ko\",[],function(){return{errorLoading:function(){return\"결과를 불러올 수 없습니다.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"너무 깁니다. \"+t+\" 글자 지워주세요.\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"너무 짧습니다. \"+t+\" 글자 더 입력해주세요.\";return n},loadingMore:function(){return\"불러오는 중…\"},maximumSelected:function(e){var t=\"최대 \"+e.maximum+\"개까지만 선택 가능합니다.\";return t},noResults:function(){return\"결과가 없습니다.\"},searching:function(){return\"검색 중…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/lt.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/lt\",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Pašalinkite \"+n+\" simbol\";return r+=e(n,\"į\",\"ius\",\"ių\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Įrašykite dar \"+n+\" simbol\";return r+=e(n,\"į\",\"ius\",\"ių\"),r},loadingMore:function(){return\"Kraunama daugiau rezultatų…\"},maximumSelected:function(t){var n=\"Jūs galite pasirinkti tik \"+t.maximum+\" element\";return n+=e(t.maximum,\"ą\",\"us\",\"ų\"),n},noResults:function(){return\"Atitikmenų nerasta\"},searching:function(){return\"Ieškoma…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/lv.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/lv\",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Lūdzu ievadiet par  \"+n;return r+=\" simbol\"+e(n,\"iem\",\"u\",\"iem\"),r+\" mazāk\"},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Lūdzu ievadiet vēl \"+n;return r+=\" simbol\"+e(n,\"us\",\"u\",\"us\"),r},loadingMore:function(){return\"Datu ielāde…\"},maximumSelected:function(t){var n=\"Jūs varat izvēlēties ne vairāk kā \"+t.maximum;return n+=\" element\"+e(t.maximum,\"us\",\"u\",\"us\"),n},noResults:function(){return\"Sakritību nav\"},searching:function(){return\"Meklēšana…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/mk.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/mk\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Ве молиме внесете \"+e.maximum+\" помалку карактер\";return e.maximum!==1&&(n+=\"и\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Ве молиме внесете уште \"+e.maximum+\" карактер\";return e.maximum!==1&&(n+=\"и\"),n},loadingMore:function(){return\"Вчитување резултати…\"},maximumSelected:function(e){var t=\"Можете да изберете само \"+e.maximum+\" ставк\";return e.maximum===1?t+=\"а\":t+=\"и\",t},noResults:function(){return\"Нема пронајдено совпаѓања\"},searching:function(){return\"Пребарување…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ms.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ms\",[],function(){return{errorLoading:function(){return\"Keputusan tidak berjaya dimuatkan.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Sila hapuskan \"+t+\" aksara\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Sila masukkan \"+t+\" atau lebih aksara\"},loadingMore:function(){return\"Sedang memuatkan keputusan…\"},maximumSelected:function(e){return\"Anda hanya boleh memilih \"+e.maximum+\" pilihan\"},noResults:function(){return\"Tiada padanan yang ditemui\"},searching:function(){return\"Mencari…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/nb.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/nb\",[],function(){return{errorLoading:function(){return\"Kunne ikke hente resultater.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Vennligst fjern \"+t+\" tegn\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Vennligst skriv inn \"+t+\" tegn til\"},loadingMore:function(){return\"Laster flere resultater…\"},maximumSelected:function(e){return\"Du kan velge maks \"+e.maximum+\" elementer\"},noResults:function(){return\"Ingen treff\"},searching:function(){return\"Søker…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/nl.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/nl\",[],function(){return{errorLoading:function(){return\"De resultaten konden niet worden geladen.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Gelieve \"+t+\" karakters te verwijderen\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Gelieve \"+t+\" of meer karakters in te voeren\";return n},loadingMore:function(){return\"Meer resultaten laden…\"},maximumSelected:function(e){var t=e.maximum==1?\"kan\":\"kunnen\",n=\"Er \"+t+\" maar \"+e.maximum+\" item\";return e.maximum!=1&&(n+=\"s\"),n+=\" worden geselecteerd\",n},noResults:function(){return\"Geen resultaten gevonden…\"},searching:function(){return\"Zoeken…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/pl.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pl\",[],function(){var e=[\"znak\",\"znaki\",\"znaków\"],t=[\"element\",\"elementy\",\"elementów\"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return\"Nie można załadować wyników.\"},inputTooLong:function(t){var r=t.input.length-t.maximum;return\"Usuń \"+r+\" \"+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return\"Podaj przynajmniej \"+r+\" \"+n(r,e)},loadingMore:function(){return\"Trwa ładowanie…\"},maximumSelected:function(e){return\"Możesz zaznaczyć tylko \"+e.maximum+\" \"+n(e.maximum,t)},noResults:function(){return\"Brak wyników\"},searching:function(){return\"Trwa wyszukiwanie…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ps.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ps\",[],function(){return{errorLoading:function(){return\"پايلي نه سي ترلاسه کېدای\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"د مهربانۍ لمخي \"+t+\" توری ړنګ کړئ\";return t!=1&&(n=n.replace(\"توری\",\"توري\")),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"لږ تر لږه \"+t+\" يا ډېر توري وليکئ\";return n},loadingMore:function(){return\"نوري پايلي ترلاسه کيږي...\"},maximumSelected:function(e){var t=\"تاسو يوازي \"+e.maximum+\" قلم په نښه کولای سی\";return e.maximum!=1&&(t=t.replace(\"قلم\",\"قلمونه\")),t},noResults:function(){return\"پايلي و نه موندل سوې\"},searching:function(){return\"لټول کيږي...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/pt-BR.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pt-BR\",[],function(){return{errorLoading:function(){return\"Os resultados não puderam ser carregados.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Apague \"+t+\" caracter\";return t!=1&&(n+=\"es\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Digite \"+t+\" ou mais caracteres\";return n},loadingMore:function(){return\"Carregando mais resultados…\"},maximumSelected:function(e){var t=\"Você só pode selecionar \"+e.maximum+\" ite\";return e.maximum==1?t+=\"m\":t+=\"ns\",t},noResults:function(){return\"Nenhum resultado encontrado\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/pt.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pt\",[],function(){return{errorLoading:function(){return\"Os resultados não puderam ser carregados.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Por favor apague \"+t+\" \";return n+=t!=1?\"caracteres\":\"caractere\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Introduza \"+t+\" ou mais caracteres\";return n},loadingMore:function(){return\"A carregar mais resultados…\"},maximumSelected:function(e){var t=\"Apenas pode seleccionar \"+e.maximum+\" \";return t+=e.maximum!=1?\"itens\":\"item\",t},noResults:function(){return\"Sem resultados\"},searching:function(){return\"A procurar…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ro.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ro\",[],function(){return{errorLoading:function(){return\"Rezultatele nu au putut fi incărcate.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vă rugăm să ștergeți\"+t+\" caracter\";return t!==1&&(n+=\"e\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vă rugăm să introduceți \"+t+\" sau mai multe caractere\";return n},loadingMore:function(){return\"Se încarcă mai multe rezultate…\"},maximumSelected:function(e){var t=\"Aveți voie să selectați cel mult \"+e.maximum;return t+=\" element\",e.maximum!==1&&(t+=\"e\"),t},noResults:function(){return\"Nu au fost găsite rezultate\"},searching:function(){return\"Căutare…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/ru.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ru\",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return\"Невозможно загрузить результаты\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Пожалуйста, введите на \"+n+\" символ\";return r+=e(n,\"\",\"a\",\"ов\"),r+=\" меньше\",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Пожалуйста, введите еще хотя бы \"+n+\" символ\";return r+=e(n,\"\",\"a\",\"ов\"),r},loadingMore:function(){return\"Загрузка данных…\"},maximumSelected:function(t){var n=\"Вы можете выбрать не более \"+t.maximum+\" элемент\";return n+=e(t.maximum,\"\",\"a\",\"ов\"),n},noResults:function(){return\"Совпадений не найдено\"},searching:function(){return\"Поиск…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/sk.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sk\",[],function(){var e={2:function(e){return e?\"dva\":\"dve\"},3:function(){return\"tri\"},4:function(){return\"štyri\"}};return{errorLoading:function(){return\"Výsledky sa nepodarilo načítať.\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?\"Prosím, zadajte o jeden znak menej\":n>=2&&n<=4?\"Prosím, zadajte o \"+e[n](!0)+\" znaky menej\":\"Prosím, zadajte o \"+n+\" znakov menej\"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?\"Prosím, zadajte ešte jeden znak\":n<=4?\"Prosím, zadajte ešte ďalšie \"+e[n](!0)+\" znaky\":\"Prosím, zadajte ešte ďalších \"+n+\" znakov\"},loadingMore:function(){return\"Načítanie ďalších výsledkov…\"},maximumSelected:function(t){return t.maximum==1?\"Môžete zvoliť len jednu položku\":t.maximum>=2&&t.maximum<=4?\"Môžete zvoliť najviac \"+e[t.maximum](!1)+\" položky\":\"Môžete zvoliť najviac \"+t.maximum+\" položiek\"},noResults:function(){return\"Nenašli sa žiadne položky\"},searching:function(){return\"Vyhľadávanie…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/sl.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sl\",[],function(){return{errorLoading:function(){return\"Zadetkov iskanja ni bilo mogoče naložiti.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Prosim zbrišite \"+t+\" znak\";return t==2?n+=\"a\":t!=1&&(n+=\"e\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Prosim vpišite še \"+t+\" znak\";return t==2?n+=\"a\":t!=1&&(n+=\"e\"),n},loadingMore:function(){return\"Nalagam več zadetkov…\"},maximumSelected:function(e){var t=\"Označite lahko največ \"+e.maximum+\" predmet\";return e.maximum==2?t+=\"a\":e.maximum!=1&&(t+=\"e\"),t},noResults:function(){return\"Ni zadetkov.\"},searching:function(){return\"Iščem…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/sr-Cyrl.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sr-Cyrl\",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return\"Преузимање није успело.\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Обришите \"+n+\" симбол\";return r+=e(n,\"\",\"а\",\"а\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Укуцајте бар још \"+n+\" симбол\";return r+=e(n,\"\",\"а\",\"а\"),r},loadingMore:function(){return\"Преузимање још резултата…\"},maximumSelected:function(t){var n=\"Можете изабрати само \"+t.maximum+\" ставк\";return n+=e(t.maximum,\"у\",\"е\",\"и\"),n},noResults:function(){return\"Ништа није пронађено\"},searching:function(){return\"Претрага…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/sr.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sr\",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return\"Preuzimanje nije uspelo.\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Obrišite \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Ukucajte bar još \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},loadingMore:function(){return\"Preuzimanje još rezultata…\"},maximumSelected:function(t){var n=\"Možete izabrati samo \"+t.maximum+\" stavk\";return n+=e(t.maximum,\"u\",\"e\",\"i\"),n},noResults:function(){return\"Ništa nije pronađeno\"},searching:function(){return\"Pretraga…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/sv.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sv\",[],function(){return{errorLoading:function(){return\"Resultat kunde inte laddas.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vänligen sudda ut \"+t+\" tecken\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vänligen skriv in \"+t+\" eller fler tecken\";return n},loadingMore:function(){return\"Laddar fler resultat…\"},maximumSelected:function(e){var t=\"Du kan max välja \"+e.maximum+\" element\";return t},noResults:function(){return\"Inga träffar\"},searching:function(){return\"Söker…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/th.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/th\",[],function(){return{errorLoading:function(){return\"ไม่สามารถค้นข้อมูลได้\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"โปรดลบออก \"+t+\" ตัวอักษร\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"โปรดพิมพ์เพิ่มอีก \"+t+\" ตัวอักษร\";return n},loadingMore:function(){return\"กำลังค้นข้อมูลเพิ่ม…\"},maximumSelected:function(e){var t=\"คุณสามารถเลือกได้ไม่เกิน \"+e.maximum+\" รายการ\";return t},noResults:function(){return\"ไม่พบข้อมูล\"},searching:function(){return\"กำลังค้นข้อมูล…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/tk.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/tk\",[],function(){return{errorLoading:function(){return\"Netije ýüklenmedi.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" harp bozuň.\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Ýene-de iň az \"+t+\" harp ýazyň.\";return n},loadingMore:function(){return\"Köpräk netije görkezilýär…\"},maximumSelected:function(e){var t=\"Diňe \"+e.maximum+\" sanysyny saýlaň.\";return t},noResults:function(){return\"Netije tapylmady.\"},searching:function(){return\"Gözlenýär…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/tr.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/tr\",[],function(){return{errorLoading:function(){return\"Sonuç yüklenemedi\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" karakter daha girmelisiniz\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"En az \"+t+\" karakter daha girmelisiniz\";return n},loadingMore:function(){return\"Daha fazla…\"},maximumSelected:function(e){var t=\"Sadece \"+e.maximum+\" seçim yapabilirsiniz\";return t},noResults:function(){return\"Sonuç bulunamadı\"},searching:function(){return\"Aranıyor…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/uk.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/uk\",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return\"Неможливо завантажити результати\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return\"Будь ласка, видаліть \"+n+\" \"+e(t.maximum,\"літеру\",\"літери\",\"літер\")},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Будь ласка, введіть \"+t+\" або більше літер\"},loadingMore:function(){return\"Завантаження інших результатів…\"},maximumSelected:function(t){return\"Ви можете вибрати лише \"+t.maximum+\" \"+e(t.maximum,\"пункт\",\"пункти\",\"пунктів\")},noResults:function(){return\"Нічого не знайдено\"},searching:function(){return\"Пошук…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/vi.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/vi\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vui lòng nhập ít hơn \"+t+\" ký tự\";return t!=1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vui lòng nhập nhiều hơn \"+t+\" ký tự\";return n},loadingMore:function(){return\"Đang lấy thêm kết quả…\"},maximumSelected:function(e){var t=\"Chỉ có thể chọn được \"+e.maximum+\" lựa chọn\";return t},noResults:function(){return\"Không tìm thấy kết quả\"},searching:function(){return\"Đang tìm…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/zh-CN.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/zh-CN\",[],function(){return{errorLoading:function(){return\"无法载入结果。\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"请删除\"+t+\"个字符\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"请再输入至少\"+t+\"个字符\";return n},loadingMore:function(){return\"载入更多结果…\"},maximumSelected:function(e){var t=\"最多只能选择\"+e.maximum+\"个项目\";return t},noResults:function(){return\"未找到结果\"},searching:function(){return\"搜索中…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/i18n/zh-TW.js",
    "content": "/*! Select2 4.0.6-rc.1 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/zh-TW\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"請刪掉\"+t+\"個字元\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"請再輸入\"+t+\"個字元\";return n},loadingMore:function(){return\"載入中…\"},maximumSelected:function(e){var t=\"你只能選擇最多\"+e.maximum+\"項\";return t},noResults:function(){return\"沒有找到相符的項目\"},searching:function(){return\"搜尋中…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/select2.full.js",
    "content": "/*!\n * Select2 4.0.6-rc.1\n * https://select2.github.io\n *\n * Released under the MIT license\n * https://github.com/select2/select2/blob/master/LICENSE.md\n */\n;(function (factory) {\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 = function (root, jQuery) {\n            if (jQuery === undefined) {\n                // require('jQuery') returns a factory that requires window to\n                // build a jQuery instance, we normalize how we use modules\n                // that require this pattern but the window provided is a noop\n                // if it's defined (how jquery works)\n                if (typeof window !== 'undefined') {\n                    jQuery = require('jquery');\n                }\n                else {\n                    jQuery = require('jquery')(root);\n                }\n            }\n            factory(jQuery);\n            return jQuery;\n        };\n    } else {\n        // Browser globals\n        factory(jQuery);\n    }\n}(function (jQuery) {\n    // This is needed so we can catch the AMD loader configuration and use it\n    // The inner file should be wrapped (by `banner.start.js`) in a function that\n    // returns the AMD loader references.\n    var S2 = (function () {\n        // Restore the Select2 AMD loader so it can be used\n        // Needed mostly in the language files, where the loader is not inserted\n        if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {\n            var S2 = jQuery.fn.select2.amd;\n        }\n        var S2;\n        (function () {\n            if (!S2 || !S2.requirejs) {\n                if (!S2) {\n                    S2 = {};\n                } else {\n                    require = S2;\n                }\n                /**\n                 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n                 * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n                 */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n                /*global setTimeout: false */\n\n                var requirejs, require, define;\n                (function (undef) {\n                    var main, req, makeMap, handlers,\n                        defined = {},\n                        waiting = {},\n                        config = {},\n                        defining = {},\n                        hasOwn = Object.prototype.hasOwnProperty,\n                        aps = [].slice,\n                        jsSuffixRegExp = /\\.js$/;\n\n                    function hasProp(obj, prop) {\n                        return hasOwn.call(obj, prop);\n                    }\n\n                    /**\n                     * Given a relative module name, like ./something, normalize it to\n                     * a real name that can be mapped to a path.\n                     * @param {String} name the relative name\n                     * @param {String} baseName a real name that the name arg is relative\n                     * to.\n                     * @returns {String} normalized name\n                     */\n                    function normalize(name, baseName) {\n                        var nameParts, nameSegment, mapValue, foundMap, lastIndex,\n                            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n                            baseParts = baseName && baseName.split(\"/\"),\n                            map = config.map,\n                            starMap = (map && map['*']) || {};\n\n                        //Adjust any relative paths.\n                        if (name) {\n                            name = name.split('/');\n                            lastIndex = name.length - 1;\n\n                            // If wanting node ID compatibility, strip .js from end\n                            // of IDs. Have to do this here, and not in nameToUrl\n                            // because node allows either .js or non .js to map\n                            // to same file.\n                            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n                                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n                            }\n\n                            // Starts with a '.' so need the baseName\n                            if (name[0].charAt(0) === '.' && baseParts) {\n                                //Convert baseName to array, and lop off the last part,\n                                //so that . matches that 'directory' and not name of the baseName's\n                                //module. For instance, baseName of 'one/two/three', maps to\n                                //'one/two/three.js', but we want the directory, 'one/two' for\n                                //this normalization.\n                                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n                                name = normalizedBaseParts.concat(name);\n                            }\n\n                            //start trimDots\n                            for (i = 0; i < name.length; i++) {\n                                part = name[i];\n                                if (part === '.') {\n                                    name.splice(i, 1);\n                                    i -= 1;\n                                } else if (part === '..') {\n                                    // If at the start, or previous value is still ..,\n                                    // keep them so that when converted to a path it may\n                                    // still work when converted to a path, even though\n                                    // as an ID it is less than ideal. In larger point\n                                    // releases, may be better to just kick out an error.\n                                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n                                        continue;\n                                    } else if (i > 0) {\n                                        name.splice(i - 1, 2);\n                                        i -= 2;\n                                    }\n                                }\n                            }\n                            //end trimDots\n\n                            name = name.join('/');\n                        }\n\n                        //Apply map config if available.\n                        if ((baseParts || starMap) && map) {\n                            nameParts = name.split('/');\n\n                            for (i = nameParts.length; i > 0; i -= 1) {\n                                nameSegment = nameParts.slice(0, i).join(\"/\");\n\n                                if (baseParts) {\n                                    //Find the longest baseName segment match in the config.\n                                    //So, do joins on the biggest to smallest lengths of baseParts.\n                                    for (j = baseParts.length; j > 0; j -= 1) {\n                                        mapValue = map[baseParts.slice(0, j).join('/')];\n\n                                        //baseName segment has  config, find if it has one for\n                                        //this name.\n                                        if (mapValue) {\n                                            mapValue = mapValue[nameSegment];\n                                            if (mapValue) {\n                                                //Match, update name to the new value.\n                                                foundMap = mapValue;\n                                                foundI = i;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n\n                                if (foundMap) {\n                                    break;\n                                }\n\n                                //Check for a star map match, but just hold on to it,\n                                //if there is a shorter segment match later in a matching\n                                //config, then favor over this star map.\n                                if (!foundStarMap && starMap && starMap[nameSegment]) {\n                                    foundStarMap = starMap[nameSegment];\n                                    starI = i;\n                                }\n                            }\n\n                            if (!foundMap && foundStarMap) {\n                                foundMap = foundStarMap;\n                                foundI = starI;\n                            }\n\n                            if (foundMap) {\n                                nameParts.splice(0, foundI, foundMap);\n                                name = nameParts.join('/');\n                            }\n                        }\n\n                        return name;\n                    }\n\n                    function makeRequire(relName, forceSync) {\n                        return function () {\n                            //A version of a require function that passes a moduleName\n                            //value for items that may need to\n                            //look up paths relative to the moduleName\n                            var args = aps.call(arguments, 0);\n\n                            //If first arg is not require('string'), and there is only\n                            //one arg, it is the array form without a callback. Insert\n                            //a null so that the following concat is correct.\n                            if (typeof args[0] !== 'string' && args.length === 1) {\n                                args.push(null);\n                            }\n                            return req.apply(undef, args.concat([relName, forceSync]));\n                        };\n                    }\n\n                    function makeNormalize(relName) {\n                        return function (name) {\n                            return normalize(name, relName);\n                        };\n                    }\n\n                    function makeLoad(depName) {\n                        return function (value) {\n                            defined[depName] = value;\n                        };\n                    }\n\n                    function callDep(name) {\n                        if (hasProp(waiting, name)) {\n                            var args = waiting[name];\n                            delete waiting[name];\n                            defining[name] = true;\n                            main.apply(undef, args);\n                        }\n\n                        if (!hasProp(defined, name) && !hasProp(defining, name)) {\n                            throw new Error('No ' + name);\n                        }\n                        return defined[name];\n                    }\n\n                    //Turns a plugin!resource to [plugin, resource]\n                    //with the plugin being undefined if the name\n                    //did not have a plugin prefix.\n                    function splitPrefix(name) {\n                        var prefix,\n                            index = name ? name.indexOf('!') : -1;\n                        if (index > -1) {\n                            prefix = name.substring(0, index);\n                            name = name.substring(index + 1, name.length);\n                        }\n                        return [prefix, name];\n                    }\n\n                    //Creates a parts array for a relName where first part is plugin ID,\n                    //second part is resource ID. Assumes relName has already been normalized.\n                    function makeRelParts(relName) {\n                        return relName ? splitPrefix(relName) : [];\n                    }\n\n                    /**\n                     * Makes a name map, normalizing the name, and using a plugin\n                     * for normalization if necessary. Grabs a ref to plugin\n                     * too, as an optimization.\n                     */\n                    makeMap = function (name, relParts) {\n                        var plugin,\n                            parts = splitPrefix(name),\n                            prefix = parts[0],\n                            relResourceName = relParts[1];\n\n                        name = parts[1];\n\n                        if (prefix) {\n                            prefix = normalize(prefix, relResourceName);\n                            plugin = callDep(prefix);\n                        }\n\n                        //Normalize according\n                        if (prefix) {\n                            if (plugin && plugin.normalize) {\n                                name = plugin.normalize(name, makeNormalize(relResourceName));\n                            } else {\n                                name = normalize(name, relResourceName);\n                            }\n                        } else {\n                            name = normalize(name, relResourceName);\n                            parts = splitPrefix(name);\n                            prefix = parts[0];\n                            name = parts[1];\n                            if (prefix) {\n                                plugin = callDep(prefix);\n                            }\n                        }\n\n                        //Using ridiculous property names for space reasons\n                        return {\n                            f: prefix ? prefix + '!' + name : name, //fullName\n                            n: name,\n                            pr: prefix,\n                            p: plugin\n                        };\n                    };\n\n                    function makeConfig(name) {\n                        return function () {\n                            return (config && config.config && config.config[name]) || {};\n                        };\n                    }\n\n                    handlers = {\n                        require: function (name) {\n                            return makeRequire(name);\n                        },\n                        exports: function (name) {\n                            var e = defined[name];\n                            if (typeof e !== 'undefined') {\n                                return e;\n                            } else {\n                                return (defined[name] = {});\n                            }\n                        },\n                        module: function (name) {\n                            return {\n                                id: name,\n                                uri: '',\n                                exports: defined[name],\n                                config: makeConfig(name)\n                            };\n                        }\n                    };\n\n                    main = function (name, deps, callback, relName) {\n                        var cjsModule, depName, ret, map, i, relParts,\n                            args = [],\n                            callbackType = typeof callback,\n                            usingExports;\n\n                        //Use name if no relName\n                        relName = relName || name;\n                        relParts = makeRelParts(relName);\n\n                        //Call the callback to define the module, if necessary.\n                        if (callbackType === 'undefined' || callbackType === 'function') {\n                            //Pull out the defined dependencies and pass the ordered\n                            //values to the callback.\n                            //Default to [require, exports, module] if no deps\n                            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n                            for (i = 0; i < deps.length; i += 1) {\n                                map = makeMap(deps[i], relParts);\n                                depName = map.f;\n\n                                //Fast path CommonJS standard dependencies.\n                                if (depName === \"require\") {\n                                    args[i] = handlers.require(name);\n                                } else if (depName === \"exports\") {\n                                    //CommonJS module spec 1.1\n                                    args[i] = handlers.exports(name);\n                                    usingExports = true;\n                                } else if (depName === \"module\") {\n                                    //CommonJS module spec 1.1\n                                    cjsModule = args[i] = handlers.module(name);\n                                } else if (hasProp(defined, depName) ||\n                                    hasProp(waiting, depName) ||\n                                    hasProp(defining, depName)) {\n                                    args[i] = callDep(depName);\n                                } else if (map.p) {\n                                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n                                    args[i] = defined[depName];\n                                } else {\n                                    throw new Error(name + ' missing ' + depName);\n                                }\n                            }\n\n                            ret = callback ? callback.apply(defined[name], args) : undefined;\n\n                            if (name) {\n                                //If setting exports via \"module\" is in play,\n                                //favor that over return value and exports. After that,\n                                //favor a non-undefined return value over exports use.\n                                if (cjsModule && cjsModule.exports !== undef &&\n                                    cjsModule.exports !== defined[name]) {\n                                    defined[name] = cjsModule.exports;\n                                } else if (ret !== undef || !usingExports) {\n                                    //Use the return value from the function.\n                                    defined[name] = ret;\n                                }\n                            }\n                        } else if (name) {\n                            //May just be an object definition for the module. Only\n                            //worry about defining if have a module name.\n                            defined[name] = callback;\n                        }\n                    };\n\n                    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n                        if (typeof deps === \"string\") {\n                            if (handlers[deps]) {\n                                //callback in this case is really relName\n                                return handlers[deps](callback);\n                            }\n                            //Just return the module wanted. In this scenario, the\n                            //deps arg is the module name, and second arg (if passed)\n                            //is just the relName.\n                            //Normalize module name, if it contains . or ..\n                            return callDep(makeMap(deps, makeRelParts(callback)).f);\n                        } else if (!deps.splice) {\n                            //deps is a config object, not an array.\n                            config = deps;\n                            if (config.deps) {\n                                req(config.deps, config.callback);\n                            }\n                            if (!callback) {\n                                return;\n                            }\n\n                            if (callback.splice) {\n                                //callback is an array, which means it is a dependency list.\n                                //Adjust args if there are dependencies\n                                deps = callback;\n                                callback = relName;\n                                relName = null;\n                            } else {\n                                deps = undef;\n                            }\n                        }\n\n                        //Support require(['a'])\n                        callback = callback || function () {\n                        };\n\n                        //If relName is a function, it is an errback handler,\n                        //so remove it.\n                        if (typeof relName === 'function') {\n                            relName = forceSync;\n                            forceSync = alt;\n                        }\n\n                        //Simulate async callback;\n                        if (forceSync) {\n                            main(undef, deps, callback, relName);\n                        } else {\n                            //Using a non-zero value because of concern for what old browsers\n                            //do, and latest browsers \"upgrade\" to 4 if lower value is used:\n                            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n                            //If want a value immediately, use require('id') instead -- something\n                            //that works in almond on the global level, but not guaranteed and\n                            //unlikely to work in other AMD implementations.\n                            setTimeout(function () {\n                                main(undef, deps, callback, relName);\n                            }, 4);\n                        }\n\n                        return req;\n                    };\n\n                    /**\n                     * Just drops the config on the floor, but returns req in case\n                     * the config return value is used.\n                     */\n                    req.config = function (cfg) {\n                        return req(cfg);\n                    };\n\n                    /**\n                     * Expose module registry for debugging and tooling\n                     */\n                    requirejs._defined = defined;\n\n                    define = function (name, deps, callback) {\n                        if (typeof name !== 'string') {\n                            throw new Error('See almond README: incorrect module build, no module name');\n                        }\n\n                        //This module may not have dependencies\n                        if (!deps.splice) {\n                            //deps is not an array, so probably means\n                            //an object literal or factory function for\n                            //the value. Adjust args.\n                            callback = deps;\n                            deps = [];\n                        }\n\n                        if (!hasProp(defined, name) && !hasProp(waiting, name)) {\n                            waiting[name] = [name, deps, callback];\n                        }\n                    };\n\n                    define.amd = {\n                        jQuery: true\n                    };\n                }());\n\n                S2.requirejs = requirejs;\n                S2.require = require;\n                S2.define = define;\n            }\n        }());\n        S2.define(\"almond\", function () {\n        });\n\n        /* global jQuery:false, $:false */\n        S2.define('jquery', [], function () {\n            var _$ = jQuery || $;\n\n            if (_$ == null && console && console.error) {\n                console.error(\n                    'Select2: An instance of jQuery or a jQuery-compatible library was not ' +\n                    'found. Make sure that you are including jQuery before Select2 on your ' +\n                    'web page.'\n                );\n            }\n\n            return _$;\n        });\n\n        S2.define('select2/utils', [\n            'jquery'\n        ], function ($) {\n            var Utils = {};\n\n            Utils.Extend = function (ChildClass, SuperClass) {\n                var __hasProp = {}.hasOwnProperty;\n\n                function BaseConstructor() {\n                    this.constructor = ChildClass;\n                }\n\n                for (var key in SuperClass) {\n                    if (__hasProp.call(SuperClass, key)) {\n                        ChildClass[key] = SuperClass[key];\n                    }\n                }\n\n                BaseConstructor.prototype = SuperClass.prototype;\n                ChildClass.prototype = new BaseConstructor();\n                ChildClass.__super__ = SuperClass.prototype;\n\n                return ChildClass;\n            };\n\n            function getMethods(theClass) {\n                var proto = theClass.prototype;\n\n                var methods = [];\n\n                for (var methodName in proto) {\n                    var m = proto[methodName];\n\n                    if (typeof m !== 'function') {\n                        continue;\n                    }\n\n                    if (methodName === 'constructor') {\n                        continue;\n                    }\n\n                    methods.push(methodName);\n                }\n\n                return methods;\n            }\n\n            Utils.Decorate = function (SuperClass, DecoratorClass) {\n                var decoratedMethods = getMethods(DecoratorClass);\n                var superMethods = getMethods(SuperClass);\n\n                function DecoratedClass() {\n                    var unshift = Array.prototype.unshift;\n\n                    var argCount = DecoratorClass.prototype.constructor.length;\n\n                    var calledConstructor = SuperClass.prototype.constructor;\n\n                    if (argCount > 0) {\n                        unshift.call(arguments, SuperClass.prototype.constructor);\n\n                        calledConstructor = DecoratorClass.prototype.constructor;\n                    }\n\n                    calledConstructor.apply(this, arguments);\n                }\n\n                DecoratorClass.displayName = SuperClass.displayName;\n\n                function ctr() {\n                    this.constructor = DecoratedClass;\n                }\n\n                DecoratedClass.prototype = new ctr();\n\n                for (var m = 0; m < superMethods.length; m++) {\n                    var superMethod = superMethods[m];\n\n                    DecoratedClass.prototype[superMethod] =\n                        SuperClass.prototype[superMethod];\n                }\n\n                var calledMethod = function (methodName) {\n                    // Stub out the original method if it's not decorating an actual method\n                    var originalMethod = function () {\n                    };\n\n                    if (methodName in DecoratedClass.prototype) {\n                        originalMethod = DecoratedClass.prototype[methodName];\n                    }\n\n                    var decoratedMethod = DecoratorClass.prototype[methodName];\n\n                    return function () {\n                        var unshift = Array.prototype.unshift;\n\n                        unshift.call(arguments, originalMethod);\n\n                        return decoratedMethod.apply(this, arguments);\n                    };\n                };\n\n                for (var d = 0; d < decoratedMethods.length; d++) {\n                    var decoratedMethod = decoratedMethods[d];\n\n                    DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);\n                }\n\n                return DecoratedClass;\n            };\n\n            var Observable = function () {\n                this.listeners = {};\n            };\n\n            Observable.prototype.on = function (event, callback) {\n                this.listeners = this.listeners || {};\n\n                if (event in this.listeners) {\n                    this.listeners[event].push(callback);\n                } else {\n                    this.listeners[event] = [callback];\n                }\n            };\n\n            Observable.prototype.trigger = function (event) {\n                var slice = Array.prototype.slice;\n                var params = slice.call(arguments, 1);\n\n                this.listeners = this.listeners || {};\n\n                // Params should always come in as an array\n                if (params == null) {\n                    params = [];\n                }\n\n                // If there are no arguments to the event, use a temporary object\n                if (params.length === 0) {\n                    params.push({});\n                }\n\n                // Set the `_type` of the first object to the event\n                params[0]._type = event;\n\n                if (event in this.listeners) {\n                    this.invoke(this.listeners[event], slice.call(arguments, 1));\n                }\n\n                if ('*' in this.listeners) {\n                    this.invoke(this.listeners['*'], arguments);\n                }\n            };\n\n            Observable.prototype.invoke = function (listeners, params) {\n                for (var i = 0, len = listeners.length; i < len; i++) {\n                    listeners[i].apply(this, params);\n                }\n            };\n\n            Utils.Observable = Observable;\n\n            Utils.generateChars = function (length) {\n                var chars = '';\n\n                for (var i = 0; i < length; i++) {\n                    var randomChar = Math.floor(Math.random() * 36);\n                    chars += randomChar.toString(36);\n                }\n\n                return chars;\n            };\n\n            Utils.bind = function (func, context) {\n                return function () {\n                    func.apply(context, arguments);\n                };\n            };\n\n            Utils._convertData = function (data) {\n                for (var originalKey in data) {\n                    var keys = originalKey.split('-');\n\n                    var dataLevel = data;\n\n                    if (keys.length === 1) {\n                        continue;\n                    }\n\n                    for (var k = 0; k < keys.length; k++) {\n                        var key = keys[k];\n\n                        // Lowercase the first letter\n                        // By default, dash-separated becomes camelCase\n                        key = key.substring(0, 1).toLowerCase() + key.substring(1);\n\n                        if (!(key in dataLevel)) {\n                            dataLevel[key] = {};\n                        }\n\n                        if (k == keys.length - 1) {\n                            dataLevel[key] = data[originalKey];\n                        }\n\n                        dataLevel = dataLevel[key];\n                    }\n\n                    delete data[originalKey];\n                }\n\n                return data;\n            };\n\n            Utils.hasScroll = function (index, el) {\n                // Adapted from the function created by @ShadowScripter\n                // and adapted by @BillBarry on the Stack Exchange Code Review website.\n                // The original code can be found at\n                // http://codereview.stackexchange.com/q/13338\n                // and was designed to be used with the Sizzle selector engine.\n\n                var $el = $(el);\n                var overflowX = el.style.overflowX;\n                var overflowY = el.style.overflowY;\n\n                //Check both x and y declarations\n                if (overflowX === overflowY &&\n                    (overflowY === 'hidden' || overflowY === 'visible')) {\n                    return false;\n                }\n\n                if (overflowX === 'scroll' || overflowY === 'scroll') {\n                    return true;\n                }\n\n                return ($el.innerHeight() < el.scrollHeight ||\n                    $el.innerWidth() < el.scrollWidth);\n            };\n\n            Utils.escapeMarkup = function (markup) {\n                var replaceMap = {\n                    '\\\\': '&#92;',\n                    '&': '&amp;',\n                    '<': '&lt;',\n                    '>': '&gt;',\n                    '\"': '&quot;',\n                    '\\'': '&#39;',\n                    '/': '&#47;'\n                };\n\n                // Do not try to escape the markup if it's not a string\n                if (typeof markup !== 'string') {\n                    return markup;\n                }\n\n                return String(markup).replace(/[&<>\"'\\/\\\\]/g, function (match) {\n                    return replaceMap[match];\n                });\n            };\n\n            // Append an array of jQuery nodes to a given element.\n            Utils.appendMany = function ($element, $nodes) {\n                // jQuery 1.7.x does not support $.fn.append() with an array\n                // Fall back to a jQuery object collection using $.fn.add()\n                if ($.fn.jquery.substr(0, 3) === '1.7') {\n                    var $jqNodes = $();\n\n                    $.map($nodes, function (node) {\n                        $jqNodes = $jqNodes.add(node);\n                    });\n\n                    $nodes = $jqNodes;\n                }\n\n                $element.append($nodes);\n            };\n\n            // Cache objects in Utils.__cache instead of $.data (see #4346)\n            Utils.__cache = {};\n\n            var id = 0;\n            Utils.GetUniqueElementId = function (element) {\n                // Get a unique element Id. If element has no id,\n                // creates a new unique number, stores it in the id\n                // attribute and returns the new id.\n                // If an id already exists, it simply returns it.\n\n                var select2Id = element.getAttribute('data-select2-id');\n                if (select2Id == null) {\n                    // If element has id, use it.\n                    if (element.id) {\n                        select2Id = element.id;\n                        element.setAttribute('data-select2-id', select2Id);\n                    } else {\n                        element.setAttribute('data-select2-id', ++id);\n                        select2Id = id.toString();\n                    }\n                }\n                return select2Id;\n            };\n\n            Utils.StoreData = function (element, name, value) {\n                // Stores an item in the cache for a specified element.\n                // name is the cache key.\n                var id = Utils.GetUniqueElementId(element);\n                if (!Utils.__cache[id]) {\n                    Utils.__cache[id] = {};\n                }\n\n                Utils.__cache[id][name] = value;\n            };\n\n            Utils.GetData = function (element, name) {\n                // Retrieves a value from the cache by its key (name)\n                // name is optional. If no name specified, return\n                // all cache items for the specified element.\n                // and for a specified element.\n                var id = Utils.GetUniqueElementId(element);\n                if (name) {\n                    if (Utils.__cache[id]) {\n                        return Utils.__cache[id][name] != null ?\n                            Utils.__cache[id][name] :\n                            $(element).data(name); // Fallback to HTML5 data attribs.\n                    }\n                    return $(element).data(name); // Fallback to HTML5 data attribs.\n                } else {\n                    return Utils.__cache[id];\n                }\n            };\n\n            Utils.RemoveData = function (element) {\n                // Removes all cached items for a specified element.\n                var id = Utils.GetUniqueElementId(element);\n                if (Utils.__cache[id] != null) {\n                    delete Utils.__cache[id];\n                }\n            };\n\n            return Utils;\n        });\n\n        S2.define('select2/results', [\n            'jquery',\n            './utils'\n        ], function ($, Utils) {\n            function Results($element, options, dataAdapter) {\n                this.$element = $element;\n                this.data = dataAdapter;\n                this.options = options;\n\n                Results.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(Results, Utils.Observable);\n\n            Results.prototype.render = function () {\n                var $results = $(\n                    '<ul class=\"select2-results__options\" role=\"tree\"></ul>'\n                );\n\n                if (this.options.get('multiple')) {\n                    $results.attr('aria-multiselectable', 'true');\n                }\n\n                this.$results = $results;\n\n                return $results;\n            };\n\n            Results.prototype.clear = function () {\n                this.$results.empty();\n            };\n\n            Results.prototype.displayMessage = function (params) {\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                this.clear();\n                this.hideLoading();\n\n                var $message = $(\n                    '<li role=\"treeitem\" aria-live=\"assertive\"' +\n                    ' class=\"select2-results__option\"></li>'\n                );\n\n                var message = this.options.get('translations').get(params.message);\n\n                $message.append(\n                    escapeMarkup(\n                        message(params.args)\n                    )\n                );\n\n                $message[0].className += ' select2-results__message';\n\n                this.$results.append($message);\n            };\n\n            Results.prototype.hideMessages = function () {\n                this.$results.find('.select2-results__message').remove();\n            };\n\n            Results.prototype.append = function (data) {\n                this.hideLoading();\n\n                var $options = [];\n\n                if (data.results == null || data.results.length === 0) {\n                    if (this.$results.children().length === 0) {\n                        this.trigger('results:message', {\n                            message: 'noResults'\n                        });\n                    }\n\n                    return;\n                }\n\n                data.results = this.sort(data.results);\n\n                for (var d = 0; d < data.results.length; d++) {\n                    var item = data.results[d];\n\n                    var $option = this.option(item);\n\n                    $options.push($option);\n                }\n\n                this.$results.append($options);\n            };\n\n            Results.prototype.position = function ($results, $dropdown) {\n                var $resultsContainer = $dropdown.find('.select2-results');\n                $resultsContainer.append($results);\n            };\n\n            Results.prototype.sort = function (data) {\n                var sorter = this.options.get('sorter');\n\n                return sorter(data);\n            };\n\n            Results.prototype.highlightFirstItem = function () {\n                var $options = this.$results\n                    .find('.select2-results__option[aria-selected]');\n\n                var $selected = $options.filter('[aria-selected=true]');\n\n                // Check if there are any selected options\n                if ($selected.length > 0) {\n                    // If there are selected options, highlight the first\n                    $selected.first().trigger('mouseenter');\n                } else {\n                    // If there are no selected options, highlight the first option\n                    // in the dropdown\n                    $options.first().trigger('mouseenter');\n                }\n\n                this.ensureHighlightVisible();\n            };\n\n            Results.prototype.setClasses = function () {\n                var self = this;\n\n                this.data.current(function (selected) {\n                    var selectedIds = $.map(selected, function (s) {\n                        return s.id.toString();\n                    });\n\n                    var $options = self.$results\n                        .find('.select2-results__option[aria-selected]');\n\n                    $options.each(function () {\n                        var $option = $(this);\n\n                        var item = Utils.GetData(this, 'data');\n\n                        // id needs to be converted to a string when comparing\n                        var id = '' + item.id;\n\n                        if ((item.element != null && item.element.selected) ||\n                            (item.element == null && $.inArray(id, selectedIds) > -1)) {\n                            $option.attr('aria-selected', 'true');\n                        } else {\n                            $option.attr('aria-selected', 'false');\n                        }\n                    });\n\n                });\n            };\n\n            Results.prototype.showLoading = function (params) {\n                this.hideLoading();\n\n                var loadingMore = this.options.get('translations').get('searching');\n\n                var loading = {\n                    disabled: true,\n                    loading: true,\n                    text: loadingMore(params)\n                };\n                var $loading = this.option(loading);\n                $loading.className += ' loading-results';\n\n                this.$results.prepend($loading);\n            };\n\n            Results.prototype.hideLoading = function () {\n                this.$results.find('.loading-results').remove();\n            };\n\n            Results.prototype.option = function (data) {\n                var option = document.createElement('li');\n                option.className = 'select2-results__option';\n\n                var attrs = {\n                    'role': 'treeitem',\n                    'aria-selected': 'false'\n                };\n\n                if (data.disabled) {\n                    delete attrs['aria-selected'];\n                    attrs['aria-disabled'] = 'true';\n                }\n\n                if (data.id == null) {\n                    delete attrs['aria-selected'];\n                }\n\n                if (data._resultId != null) {\n                    option.id = data._resultId;\n                }\n\n                if (data.title) {\n                    option.title = data.title;\n                }\n\n                if (data.children) {\n                    attrs.role = 'group';\n                    attrs['aria-label'] = data.text;\n                    delete attrs['aria-selected'];\n                }\n\n                for (var attr in attrs) {\n                    var val = attrs[attr];\n\n                    option.setAttribute(attr, val);\n                }\n\n                if (data.children) {\n                    var $option = $(option);\n\n                    var label = document.createElement('strong');\n                    label.className = 'select2-results__group';\n\n                    var $label = $(label);\n                    this.template(data, label);\n\n                    var $children = [];\n\n                    for (var c = 0; c < data.children.length; c++) {\n                        var child = data.children[c];\n\n                        var $child = this.option(child);\n\n                        $children.push($child);\n                    }\n\n                    var $childrenContainer = $('<ul></ul>', {\n                        'class': 'select2-results__options select2-results__options--nested'\n                    });\n\n                    $childrenContainer.append($children);\n\n                    $option.append(label);\n                    $option.append($childrenContainer);\n                } else {\n                    this.template(data, option);\n                }\n\n                Utils.StoreData(option, 'data', data);\n\n                return option;\n            };\n\n            Results.prototype.bind = function (container, $container) {\n                var self = this;\n\n                var id = container.id + '-results';\n\n                this.$results.attr('id', id);\n\n                container.on('results:all', function (params) {\n                    self.clear();\n                    self.append(params.data);\n\n                    if (container.isOpen()) {\n                        self.setClasses();\n                        self.highlightFirstItem();\n                    }\n                });\n\n                container.on('results:append', function (params) {\n                    self.append(params.data);\n\n                    if (container.isOpen()) {\n                        self.setClasses();\n                    }\n                });\n\n                container.on('query', function (params) {\n                    self.hideMessages();\n                    self.showLoading(params);\n                });\n\n                container.on('select', function () {\n                    if (!container.isOpen()) {\n                        return;\n                    }\n\n                    self.setClasses();\n                    self.highlightFirstItem();\n                });\n\n                container.on('unselect', function () {\n                    if (!container.isOpen()) {\n                        return;\n                    }\n\n                    self.setClasses();\n                    self.highlightFirstItem();\n                });\n\n                container.on('open', function () {\n                    // When the dropdown is open, aria-expended=\"true\"\n                    self.$results.attr('aria-expanded', 'true');\n                    self.$results.attr('aria-hidden', 'false');\n\n                    self.setClasses();\n                    self.ensureHighlightVisible();\n                });\n\n                container.on('close', function () {\n                    // When the dropdown is closed, aria-expended=\"false\"\n                    self.$results.attr('aria-expanded', 'false');\n                    self.$results.attr('aria-hidden', 'true');\n                    self.$results.removeAttr('aria-activedescendant');\n                });\n\n                container.on('results:toggle', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    if ($highlighted.length === 0) {\n                        return;\n                    }\n\n                    $highlighted.trigger('mouseup');\n                });\n\n                container.on('results:select', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    if ($highlighted.length === 0) {\n                        return;\n                    }\n\n                    var data = Utils.GetData($highlighted[0], 'data');\n\n                    if ($highlighted.attr('aria-selected') == 'true') {\n                        self.trigger('close', {});\n                    } else {\n                        self.trigger('select', {\n                            data: data\n                        });\n                    }\n                });\n\n                container.on('results:previous', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    var $options = self.$results.find('[aria-selected]');\n\n                    var currentIndex = $options.index($highlighted);\n\n                    // If we are already at te top, don't move further\n                    // If no options, currentIndex will be -1\n                    if (currentIndex <= 0) {\n                        return;\n                    }\n\n                    var nextIndex = currentIndex - 1;\n\n                    // If none are highlighted, highlight the first\n                    if ($highlighted.length === 0) {\n                        nextIndex = 0;\n                    }\n\n                    var $next = $options.eq(nextIndex);\n\n                    $next.trigger('mouseenter');\n\n                    var currentOffset = self.$results.offset().top;\n                    var nextTop = $next.offset().top;\n                    var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);\n\n                    if (nextIndex === 0) {\n                        self.$results.scrollTop(0);\n                    } else if (nextTop - currentOffset < 0) {\n                        self.$results.scrollTop(nextOffset);\n                    }\n                });\n\n                container.on('results:next', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    var $options = self.$results.find('[aria-selected]');\n\n                    var currentIndex = $options.index($highlighted);\n\n                    var nextIndex = currentIndex + 1;\n\n                    // If we are at the last option, stay there\n                    if (nextIndex >= $options.length) {\n                        return;\n                    }\n\n                    var $next = $options.eq(nextIndex);\n\n                    $next.trigger('mouseenter');\n\n                    var currentOffset = self.$results.offset().top +\n                        self.$results.outerHeight(false);\n                    var nextBottom = $next.offset().top + $next.outerHeight(false);\n                    var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;\n\n                    if (nextIndex === 0) {\n                        self.$results.scrollTop(0);\n                    } else if (nextBottom > currentOffset) {\n                        self.$results.scrollTop(nextOffset);\n                    }\n                });\n\n                container.on('results:focus', function (params) {\n                    params.element.addClass('select2-results__option--highlighted');\n                });\n\n                container.on('results:message', function (params) {\n                    self.displayMessage(params);\n                });\n\n                if ($.fn.mousewheel) {\n                    this.$results.on('mousewheel', function (e) {\n                        var top = self.$results.scrollTop();\n\n                        var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;\n\n                        var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;\n                        var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();\n\n                        if (isAtTop) {\n                            self.$results.scrollTop(0);\n\n                            e.preventDefault();\n                            e.stopPropagation();\n                        } else if (isAtBottom) {\n                            self.$results.scrollTop(\n                                self.$results.get(0).scrollHeight - self.$results.height()\n                            );\n\n                            e.preventDefault();\n                            e.stopPropagation();\n                        }\n                    });\n                }\n\n                this.$results.on('mouseup', '.select2-results__option[aria-selected]',\n                    function (evt) {\n                        var $this = $(this);\n\n                        var data = Utils.GetData(this, 'data');\n\n                        if ($this.attr('aria-selected') === 'true') {\n                            if (self.options.get('multiple')) {\n                                self.trigger('unselect', {\n                                    originalEvent: evt,\n                                    data: data\n                                });\n                            } else {\n                                self.trigger('close', {});\n                            }\n\n                            return;\n                        }\n\n                        self.trigger('select', {\n                            originalEvent: evt,\n                            data: data\n                        });\n                    });\n\n                this.$results.on('mouseenter', '.select2-results__option[aria-selected]',\n                    function (evt) {\n                        var data = Utils.GetData(this, 'data');\n\n                        self.getHighlightedResults()\n                            .removeClass('select2-results__option--highlighted');\n\n                        self.trigger('results:focus', {\n                            data: data,\n                            element: $(this)\n                        });\n                    });\n            };\n\n            Results.prototype.getHighlightedResults = function () {\n                var $highlighted = this.$results\n                    .find('.select2-results__option--highlighted');\n\n                return $highlighted;\n            };\n\n            Results.prototype.destroy = function () {\n                this.$results.remove();\n            };\n\n            Results.prototype.ensureHighlightVisible = function () {\n                var $highlighted = this.getHighlightedResults();\n\n                if ($highlighted.length === 0) {\n                    return;\n                }\n\n                var $options = this.$results.find('[aria-selected]');\n\n                var currentIndex = $options.index($highlighted);\n\n                var currentOffset = this.$results.offset().top;\n                var nextTop = $highlighted.offset().top;\n                var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);\n\n                var offsetDelta = nextTop - currentOffset;\n                nextOffset -= $highlighted.outerHeight(false) * 2;\n\n                if (currentIndex <= 2) {\n                    this.$results.scrollTop(0);\n                } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {\n                    this.$results.scrollTop(nextOffset);\n                }\n            };\n\n            Results.prototype.template = function (result, container) {\n                var template = this.options.get('templateResult');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                var content = template(result, container);\n\n                if (content == null) {\n                    container.style.display = 'none';\n                } else if (typeof content === 'string') {\n                    container.innerHTML = escapeMarkup(content);\n                } else {\n                    $(container).append(content);\n                }\n            };\n\n            return Results;\n        });\n\n        S2.define('select2/keys', [], function () {\n            var KEYS = {\n                BACKSPACE: 8,\n                TAB: 9,\n                ENTER: 13,\n                SHIFT: 16,\n                CTRL: 17,\n                ALT: 18,\n                ESC: 27,\n                SPACE: 32,\n                PAGE_UP: 33,\n                PAGE_DOWN: 34,\n                END: 35,\n                HOME: 36,\n                LEFT: 37,\n                UP: 38,\n                RIGHT: 39,\n                DOWN: 40,\n                DELETE: 46\n            };\n\n            return KEYS;\n        });\n\n        S2.define('select2/selection/base', [\n            'jquery',\n            '../utils',\n            '../keys'\n        ], function ($, Utils, KEYS) {\n            function BaseSelection($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                BaseSelection.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(BaseSelection, Utils.Observable);\n\n            BaseSelection.prototype.render = function () {\n                var $selection = $(\n                    '<span class=\"select2-selection\" role=\"combobox\" ' +\n                    ' aria-haspopup=\"true\" aria-expanded=\"false\">' +\n                    '</span>'\n                );\n\n                this._tabindex = 0;\n\n                if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {\n                    this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');\n                } else if (this.$element.attr('tabindex') != null) {\n                    this._tabindex = this.$element.attr('tabindex');\n                }\n\n                $selection.attr('title', this.$element.attr('title'));\n                $selection.attr('tabindex', this._tabindex);\n\n                this.$selection = $selection;\n\n                return $selection;\n            };\n\n            BaseSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                var id = container.id + '-container';\n                var resultsId = container.id + '-results';\n\n                this.container = container;\n\n                this.$selection.on('focus', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this.$selection.on('blur', function (evt) {\n                    self._handleBlur(evt);\n                });\n\n                this.$selection.on('keydown', function (evt) {\n                    self.trigger('keypress', evt);\n\n                    if (evt.which === KEYS.SPACE) {\n                        evt.preventDefault();\n                    }\n                });\n\n                container.on('results:focus', function (params) {\n                    self.$selection.attr('aria-activedescendant', params.data._resultId);\n                });\n\n                container.on('selection:update', function (params) {\n                    self.update(params.data);\n                });\n\n                container.on('open', function () {\n                    // When the dropdown is open, aria-expanded=\"true\"\n                    self.$selection.attr('aria-expanded', 'true');\n                    self.$selection.attr('aria-owns', resultsId);\n\n                    self._attachCloseHandler(container);\n                });\n\n                container.on('close', function () {\n                    // When the dropdown is closed, aria-expanded=\"false\"\n                    self.$selection.attr('aria-expanded', 'false');\n                    self.$selection.removeAttr('aria-activedescendant');\n                    self.$selection.removeAttr('aria-owns');\n\n                    self.$selection.focus();\n                    window.setTimeout(function () {\n                        self.$selection.focus();\n                    }, 0);\n\n                    self._detachCloseHandler(container);\n                });\n\n                container.on('enable', function () {\n                    self.$selection.attr('tabindex', self._tabindex);\n                });\n\n                container.on('disable', function () {\n                    self.$selection.attr('tabindex', '-1');\n                });\n            };\n\n            BaseSelection.prototype._handleBlur = function (evt) {\n                var self = this;\n\n                // This needs to be delayed as the active element is the body when the tab\n                // key is pressed, possibly along with others.\n                window.setTimeout(function () {\n                    // Don't trigger `blur` if the focus is still in the selection\n                    if (\n                        (document.activeElement == self.$selection[0]) ||\n                        ($.contains(self.$selection[0], document.activeElement))\n                    ) {\n                        return;\n                    }\n\n                    self.trigger('blur', evt);\n                }, 1);\n            };\n\n            BaseSelection.prototype._attachCloseHandler = function (container) {\n                var self = this;\n\n                $(document.body).on('mousedown.select2.' + container.id, function (e) {\n                    var $target = $(e.target);\n\n                    var $select = $target.closest('.select2');\n\n                    var $all = $('.select2.select2-container--open');\n\n                    $all.each(function () {\n                        var $this = $(this);\n\n                        if (this == $select[0]) {\n                            return;\n                        }\n\n                        var $element = Utils.GetData(this, 'element');\n\n                        $element.select2('close');\n                    });\n                });\n            };\n\n            BaseSelection.prototype._detachCloseHandler = function (container) {\n                $(document.body).off('mousedown.select2.' + container.id);\n            };\n\n            BaseSelection.prototype.position = function ($selection, $container) {\n                var $selectionContainer = $container.find('.selection');\n                $selectionContainer.append($selection);\n            };\n\n            BaseSelection.prototype.destroy = function () {\n                this._detachCloseHandler(this.container);\n            };\n\n            BaseSelection.prototype.update = function (data) {\n                throw new Error('The `update` method must be defined in child classes.');\n            };\n\n            return BaseSelection;\n        });\n\n        S2.define('select2/selection/single', [\n            'jquery',\n            './base',\n            '../utils',\n            '../keys'\n        ], function ($, BaseSelection, Utils, KEYS) {\n            function SingleSelection() {\n                SingleSelection.__super__.constructor.apply(this, arguments);\n            }\n\n            Utils.Extend(SingleSelection, BaseSelection);\n\n            SingleSelection.prototype.render = function () {\n                var $selection = SingleSelection.__super__.render.call(this);\n\n                $selection.addClass('select2-selection--single');\n\n                $selection.html(\n                    '<span class=\"select2-selection__rendered\"></span>' +\n                    '<span class=\"select2-selection__arrow\" role=\"presentation\">' +\n                    '<b role=\"presentation\"></b>' +\n                    '</span>'\n                );\n\n                return $selection;\n            };\n\n            SingleSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                SingleSelection.__super__.bind.apply(this, arguments);\n\n                var id = container.id + '-container';\n\n                this.$selection.find('.select2-selection__rendered')\n                    .attr('id', id)\n                    .attr('role', 'textbox')\n                    .attr('aria-readonly', 'true');\n                this.$selection.attr('aria-labelledby', id);\n\n                this.$selection.on('mousedown', function (evt) {\n                    // Only respond to left clicks\n                    if (evt.which !== 1) {\n                        return;\n                    }\n\n                    self.trigger('toggle', {\n                        originalEvent: evt\n                    });\n                });\n\n                this.$selection.on('focus', function (evt) {\n                    // User focuses on the container\n                });\n\n                this.$selection.on('blur', function (evt) {\n                    // User exits the container\n                });\n\n                container.on('focus', function (evt) {\n                    if (!container.isOpen()) {\n                        self.$selection.focus();\n                    }\n                });\n            };\n\n            SingleSelection.prototype.clear = function () {\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                $rendered.empty();\n                $rendered.removeAttr('title'); // clear tooltip on empty\n            };\n\n            SingleSelection.prototype.display = function (data, container) {\n                var template = this.options.get('templateSelection');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                return escapeMarkup(template(data, container));\n            };\n\n            SingleSelection.prototype.selectionContainer = function () {\n                return $('<span></span>');\n            };\n\n            SingleSelection.prototype.update = function (data) {\n                if (data.length === 0) {\n                    this.clear();\n                    return;\n                }\n\n                var selection = data[0];\n\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                var formatted = this.display(selection, $rendered);\n\n                $rendered.empty().append(formatted);\n                $rendered.attr('title', selection.title || selection.text);\n            };\n\n            return SingleSelection;\n        });\n\n        S2.define('select2/selection/multiple', [\n            'jquery',\n            './base',\n            '../utils'\n        ], function ($, BaseSelection, Utils) {\n            function MultipleSelection($element, options) {\n                MultipleSelection.__super__.constructor.apply(this, arguments);\n            }\n\n            Utils.Extend(MultipleSelection, BaseSelection);\n\n            MultipleSelection.prototype.render = function () {\n                var $selection = MultipleSelection.__super__.render.call(this);\n\n                $selection.addClass('select2-selection--multiple');\n\n                $selection.html(\n                    '<ul class=\"select2-selection__rendered\"></ul>'\n                );\n\n                return $selection;\n            };\n\n            MultipleSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                MultipleSelection.__super__.bind.apply(this, arguments);\n\n                this.$selection.on('click', function (evt) {\n                    self.trigger('toggle', {\n                        originalEvent: evt\n                    });\n                });\n\n                this.$selection.on(\n                    'click',\n                    '.select2-selection__choice__remove',\n                    function (evt) {\n                        // Ignore the event if it is disabled\n                        if (self.options.get('disabled')) {\n                            return;\n                        }\n\n                        var $remove = $(this);\n                        var $selection = $remove.parent();\n\n                        var data = Utils.GetData($selection[0], 'data');\n\n                        self.trigger('unselect', {\n                            originalEvent: evt,\n                            data: data\n                        });\n                    }\n                );\n            };\n\n            MultipleSelection.prototype.clear = function () {\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                $rendered.empty();\n                $rendered.removeAttr('title');\n            };\n\n            MultipleSelection.prototype.display = function (data, container) {\n                var template = this.options.get('templateSelection');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                return escapeMarkup(template(data, container));\n            };\n\n            MultipleSelection.prototype.selectionContainer = function () {\n                var $container = $(\n                    '<li class=\"select2-selection__choice\">' +\n                    '<span class=\"select2-selection__choice__remove\" role=\"presentation\">' +\n                    '&times;' +\n                    '</span>' +\n                    '</li>'\n                );\n\n                return $container;\n            };\n\n            MultipleSelection.prototype.update = function (data) {\n                this.clear();\n\n                if (data.length === 0) {\n                    return;\n                }\n\n                var $selections = [];\n\n                for (var d = 0; d < data.length; d++) {\n                    var selection = data[d];\n\n                    var $selection = this.selectionContainer();\n                    var formatted = this.display(selection, $selection);\n\n                    $selection.append(formatted);\n                    $selection.attr('title', selection.title || selection.text);\n\n                    Utils.StoreData($selection[0], 'data', selection);\n\n                    $selections.push($selection);\n                }\n\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n\n                Utils.appendMany($rendered, $selections);\n            };\n\n            return MultipleSelection;\n        });\n\n        S2.define('select2/selection/placeholder', [\n            '../utils'\n        ], function (Utils) {\n            function Placeholder(decorated, $element, options) {\n                this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n                decorated.call(this, $element, options);\n            }\n\n            Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {\n                if (typeof placeholder === 'string') {\n                    placeholder = {\n                        id: '',\n                        text: placeholder\n                    };\n                }\n\n                return placeholder;\n            };\n\n            Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {\n                var $placeholder = this.selectionContainer();\n\n                $placeholder.html(this.display(placeholder));\n                $placeholder.addClass('select2-selection__placeholder')\n                    .removeClass('select2-selection__choice');\n\n                return $placeholder;\n            };\n\n            Placeholder.prototype.update = function (decorated, data) {\n                var singlePlaceholder = (\n                    data.length == 1 && data[0].id != this.placeholder.id\n                );\n                var multipleSelections = data.length > 1;\n\n                if (multipleSelections || singlePlaceholder) {\n                    return decorated.call(this, data);\n                }\n\n                this.clear();\n\n                var $placeholder = this.createPlaceholder(this.placeholder);\n\n                this.$selection.find('.select2-selection__rendered').append($placeholder);\n            };\n\n            return Placeholder;\n        });\n\n        S2.define('select2/selection/allowClear', [\n            'jquery',\n            '../keys',\n            '../utils'\n        ], function ($, KEYS, Utils) {\n            function AllowClear() {\n            }\n\n            AllowClear.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                if (this.placeholder == null) {\n                    if (this.options.get('debug') && window.console && console.error) {\n                        console.error(\n                            'Select2: The `allowClear` option should be used in combination ' +\n                            'with the `placeholder` option.'\n                        );\n                    }\n                }\n\n                this.$selection.on('mousedown', '.select2-selection__clear',\n                    function (evt) {\n                        self._handleClear(evt);\n                    });\n\n                container.on('keypress', function (evt) {\n                    self._handleKeyboardClear(evt, container);\n                });\n            };\n\n            AllowClear.prototype._handleClear = function (_, evt) {\n                // Ignore the event if it is disabled\n                if (this.options.get('disabled')) {\n                    return;\n                }\n\n                var $clear = this.$selection.find('.select2-selection__clear');\n\n                // Ignore the event if nothing has been selected\n                if ($clear.length === 0) {\n                    return;\n                }\n\n                evt.stopPropagation();\n\n                var data = Utils.GetData($clear[0], 'data');\n\n                var previousVal = this.$element.val();\n                this.$element.val(this.placeholder.id);\n\n                var unselectData = {\n                    data: data\n                };\n                this.trigger('clear', unselectData);\n                if (unselectData.prevented) {\n                    this.$element.val(previousVal);\n                    return;\n                }\n\n                for (var d = 0; d < data.length; d++) {\n                    unselectData = {\n                        data: data[d]\n                    };\n\n                    // Trigger the `unselect` event, so people can prevent it from being\n                    // cleared.\n                    this.trigger('unselect', unselectData);\n\n                    // If the event was prevented, don't clear it out.\n                    if (unselectData.prevented) {\n                        this.$element.val(previousVal);\n                        return;\n                    }\n                }\n\n                this.$element.trigger('change');\n\n                this.trigger('toggle', {});\n            };\n\n            AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {\n                if (container.isOpen()) {\n                    return;\n                }\n\n                if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {\n                    this._handleClear(evt);\n                }\n            };\n\n            AllowClear.prototype.update = function (decorated, data) {\n                decorated.call(this, data);\n\n                if (this.$selection.find('.select2-selection__placeholder').length > 0 ||\n                    data.length === 0) {\n                    return;\n                }\n\n                var $remove = $(\n                    '<span class=\"select2-selection__clear\">' +\n                    '&times;' +\n                    '</span>'\n                );\n                Utils.StoreData($remove[0], 'data', data);\n\n                this.$selection.find('.select2-selection__rendered').prepend($remove);\n            };\n\n            return AllowClear;\n        });\n\n        S2.define('select2/selection/search', [\n            'jquery',\n            '../utils',\n            '../keys'\n        ], function ($, Utils, KEYS) {\n            function Search(decorated, $element, options) {\n                decorated.call(this, $element, options);\n            }\n\n            Search.prototype.render = function (decorated) {\n                var $search = $(\n                    '<li class=\"select2-search select2-search--inline\">' +\n                    '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n                    ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"none\"' +\n                    ' spellcheck=\"false\" role=\"textbox\" aria-autocomplete=\"list\" />' +\n                    '</li>'\n                );\n\n                this.$searchContainer = $search;\n                this.$search = $search.find('input');\n\n                var $rendered = decorated.call(this);\n\n                this._transferTabIndex();\n\n                return $rendered;\n            };\n\n            Search.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('open', function () {\n                    self.$search.trigger('focus');\n                });\n\n                container.on('close', function () {\n                    self.$search.val('');\n                    self.$search.removeAttr('aria-activedescendant');\n                    self.$search.trigger('focus');\n                });\n\n                container.on('enable', function () {\n                    self.$search.prop('disabled', false);\n\n                    self._transferTabIndex();\n                });\n\n                container.on('disable', function () {\n                    self.$search.prop('disabled', true);\n                });\n\n                container.on('focus', function (evt) {\n                    self.$search.trigger('focus');\n                });\n\n                container.on('results:focus', function (params) {\n                    self.$search.attr('aria-activedescendant', params.id);\n                });\n\n                this.$selection.on('focusin', '.select2-search--inline', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this.$selection.on('focusout', '.select2-search--inline', function (evt) {\n                    self._handleBlur(evt);\n                });\n\n                this.$selection.on('keydown', '.select2-search--inline', function (evt) {\n                    evt.stopPropagation();\n\n                    self.trigger('keypress', evt);\n\n                    self._keyUpPrevented = evt.isDefaultPrevented();\n\n                    var key = evt.which;\n\n                    if (key === KEYS.BACKSPACE && self.$search.val() === '') {\n                        var $previousChoice = self.$searchContainer\n                            .prev('.select2-selection__choice');\n\n                        if ($previousChoice.length > 0) {\n                            var item = Utils.GetData($previousChoice[0], 'data');\n\n                            self.searchRemoveChoice(item);\n\n                            evt.preventDefault();\n                        }\n                    }\n                });\n\n                // Try to detect the IE version should the `documentMode` property that\n                // is stored on the document. This is only implemented in IE and is\n                // slightly cleaner than doing a user agent check.\n                // This property is not available in Edge, but Edge also doesn't have\n                // this bug.\n                var msie = document.documentMode;\n                var disableInputEvents = msie && msie <= 11;\n\n                // Workaround for browsers which do not support the `input` event\n                // This will prevent double-triggering of events for browsers which support\n                // both the `keyup` and `input` events.\n                this.$selection.on(\n                    'input.searchcheck',\n                    '.select2-search--inline',\n                    function (evt) {\n                        // IE will trigger the `input` event when a placeholder is used on a\n                        // search box. To get around this issue, we are forced to ignore all\n                        // `input` events in IE and keep using `keyup`.\n                        if (disableInputEvents) {\n                            self.$selection.off('input.search input.searchcheck');\n                            return;\n                        }\n\n                        // Unbind the duplicated `keyup` event\n                        self.$selection.off('keyup.search');\n                    }\n                );\n\n                this.$selection.on(\n                    'keyup.search input.search',\n                    '.select2-search--inline',\n                    function (evt) {\n                        // IE will trigger the `input` event when a placeholder is used on a\n                        // search box. To get around this issue, we are forced to ignore all\n                        // `input` events in IE and keep using `keyup`.\n                        if (disableInputEvents && evt.type === 'input') {\n                            self.$selection.off('input.search input.searchcheck');\n                            return;\n                        }\n\n                        var key = evt.which;\n\n                        // We can freely ignore events from modifier keys\n                        if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {\n                            return;\n                        }\n\n                        // Tabbing will be handled during the `keydown` phase\n                        if (key == KEYS.TAB) {\n                            return;\n                        }\n\n                        self.handleSearch(evt);\n                    }\n                );\n            };\n\n            /**\n             * This method will transfer the tabindex attribute from the rendered\n             * selection to the search box. This allows for the search box to be used as\n             * the primary focus instead of the selection container.\n             *\n             * @private\n             */\n            Search.prototype._transferTabIndex = function (decorated) {\n                this.$search.attr('tabindex', this.$selection.attr('tabindex'));\n                this.$selection.attr('tabindex', '-1');\n            };\n\n            Search.prototype.createPlaceholder = function (decorated, placeholder) {\n                this.$search.attr('placeholder', placeholder.text);\n            };\n\n            Search.prototype.update = function (decorated, data) {\n                var searchHadFocus = this.$search[0] == document.activeElement;\n\n                this.$search.attr('placeholder', '');\n\n                decorated.call(this, data);\n\n                this.$selection.find('.select2-selection__rendered')\n                    .append(this.$searchContainer);\n\n                this.resizeSearch();\n                if (searchHadFocus) {\n                    var isTagInput = this.$element.find('[data-select2-tag]').length;\n                    if (isTagInput) {\n                        // fix IE11 bug where tag input lost focus\n                        this.$element.focus();\n                    } else {\n                        this.$search.focus();\n                    }\n                }\n            };\n\n            Search.prototype.handleSearch = function () {\n                this.resizeSearch();\n\n                if (!this._keyUpPrevented) {\n                    var input = this.$search.val();\n\n                    this.trigger('query', {\n                        term: input\n                    });\n                }\n\n                this._keyUpPrevented = false;\n            };\n\n            Search.prototype.searchRemoveChoice = function (decorated, item) {\n                this.trigger('unselect', {\n                    data: item\n                });\n\n                this.$search.val(item.text);\n                this.handleSearch();\n            };\n\n            Search.prototype.resizeSearch = function () {\n                this.$search.css('width', '25px');\n\n                var width = '';\n\n                if (this.$search.attr('placeholder') !== '') {\n                    width = this.$selection.find('.select2-selection__rendered').innerWidth();\n                } else {\n                    var minimumWidth = this.$search.val().length + 1;\n\n                    width = (minimumWidth * 0.75) + 'em';\n                }\n\n                this.$search.css('width', width);\n            };\n\n            return Search;\n        });\n\n        S2.define('select2/selection/eventRelay', [\n            'jquery'\n        ], function ($) {\n            function EventRelay() {\n            }\n\n            EventRelay.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n                var relayEvents = [\n                    'open', 'opening',\n                    'close', 'closing',\n                    'select', 'selecting',\n                    'unselect', 'unselecting',\n                    'clear', 'clearing'\n                ];\n\n                var preventableEvents = [\n                    'opening', 'closing', 'selecting', 'unselecting', 'clearing'\n                ];\n\n                decorated.call(this, container, $container);\n\n                container.on('*', function (name, params) {\n                    // Ignore events that should not be relayed\n                    if ($.inArray(name, relayEvents) === -1) {\n                        return;\n                    }\n\n                    // The parameters should always be an object\n                    params = params || {};\n\n                    // Generate the jQuery event for the Select2 event\n                    var evt = $.Event('select2:' + name, {\n                        params: params\n                    });\n\n                    self.$element.trigger(evt);\n\n                    // Only handle preventable events if it was one\n                    if ($.inArray(name, preventableEvents) === -1) {\n                        return;\n                    }\n\n                    params.prevented = evt.isDefaultPrevented();\n                });\n            };\n\n            return EventRelay;\n        });\n\n        S2.define('select2/translation', [\n            'jquery',\n            'require'\n        ], function ($, require) {\n            function Translation(dict) {\n                this.dict = dict || {};\n            }\n\n            Translation.prototype.all = function () {\n                return this.dict;\n            };\n\n            Translation.prototype.get = function (key) {\n                return this.dict[key];\n            };\n\n            Translation.prototype.extend = function (translation) {\n                this.dict = $.extend({}, translation.all(), this.dict);\n            };\n\n            // Static functions\n\n            Translation._cache = {};\n\n            Translation.loadPath = function (path) {\n                if (!(path in Translation._cache)) {\n                    var translations = require(path);\n\n                    Translation._cache[path] = translations;\n                }\n\n                return new Translation(Translation._cache[path]);\n            };\n\n            return Translation;\n        });\n\n        S2.define('select2/diacritics', [], function () {\n            var diacritics = {\n                '\\u24B6': 'A',\n                '\\uFF21': 'A',\n                '\\u00C0': 'A',\n                '\\u00C1': 'A',\n                '\\u00C2': 'A',\n                '\\u1EA6': 'A',\n                '\\u1EA4': 'A',\n                '\\u1EAA': 'A',\n                '\\u1EA8': 'A',\n                '\\u00C3': 'A',\n                '\\u0100': 'A',\n                '\\u0102': 'A',\n                '\\u1EB0': 'A',\n                '\\u1EAE': 'A',\n                '\\u1EB4': 'A',\n                '\\u1EB2': 'A',\n                '\\u0226': 'A',\n                '\\u01E0': 'A',\n                '\\u00C4': 'A',\n                '\\u01DE': 'A',\n                '\\u1EA2': 'A',\n                '\\u00C5': 'A',\n                '\\u01FA': 'A',\n                '\\u01CD': 'A',\n                '\\u0200': 'A',\n                '\\u0202': 'A',\n                '\\u1EA0': 'A',\n                '\\u1EAC': 'A',\n                '\\u1EB6': 'A',\n                '\\u1E00': 'A',\n                '\\u0104': 'A',\n                '\\u023A': 'A',\n                '\\u2C6F': 'A',\n                '\\uA732': 'AA',\n                '\\u00C6': 'AE',\n                '\\u01FC': 'AE',\n                '\\u01E2': 'AE',\n                '\\uA734': 'AO',\n                '\\uA736': 'AU',\n                '\\uA738': 'AV',\n                '\\uA73A': 'AV',\n                '\\uA73C': 'AY',\n                '\\u24B7': 'B',\n                '\\uFF22': 'B',\n                '\\u1E02': 'B',\n                '\\u1E04': 'B',\n                '\\u1E06': 'B',\n                '\\u0243': 'B',\n                '\\u0182': 'B',\n                '\\u0181': 'B',\n                '\\u24B8': 'C',\n                '\\uFF23': 'C',\n                '\\u0106': 'C',\n                '\\u0108': 'C',\n                '\\u010A': 'C',\n                '\\u010C': 'C',\n                '\\u00C7': 'C',\n                '\\u1E08': 'C',\n                '\\u0187': 'C',\n                '\\u023B': 'C',\n                '\\uA73E': 'C',\n                '\\u24B9': 'D',\n                '\\uFF24': 'D',\n                '\\u1E0A': 'D',\n                '\\u010E': 'D',\n                '\\u1E0C': 'D',\n                '\\u1E10': 'D',\n                '\\u1E12': 'D',\n                '\\u1E0E': 'D',\n                '\\u0110': 'D',\n                '\\u018B': 'D',\n                '\\u018A': 'D',\n                '\\u0189': 'D',\n                '\\uA779': 'D',\n                '\\u01F1': 'DZ',\n                '\\u01C4': 'DZ',\n                '\\u01F2': 'Dz',\n                '\\u01C5': 'Dz',\n                '\\u24BA': 'E',\n                '\\uFF25': 'E',\n                '\\u00C8': 'E',\n                '\\u00C9': 'E',\n                '\\u00CA': 'E',\n                '\\u1EC0': 'E',\n                '\\u1EBE': 'E',\n                '\\u1EC4': 'E',\n                '\\u1EC2': 'E',\n                '\\u1EBC': 'E',\n                '\\u0112': 'E',\n                '\\u1E14': 'E',\n                '\\u1E16': 'E',\n                '\\u0114': 'E',\n                '\\u0116': 'E',\n                '\\u00CB': 'E',\n                '\\u1EBA': 'E',\n                '\\u011A': 'E',\n                '\\u0204': 'E',\n                '\\u0206': 'E',\n                '\\u1EB8': 'E',\n                '\\u1EC6': 'E',\n                '\\u0228': 'E',\n                '\\u1E1C': 'E',\n                '\\u0118': 'E',\n                '\\u1E18': 'E',\n                '\\u1E1A': 'E',\n                '\\u0190': 'E',\n                '\\u018E': 'E',\n                '\\u24BB': 'F',\n                '\\uFF26': 'F',\n                '\\u1E1E': 'F',\n                '\\u0191': 'F',\n                '\\uA77B': 'F',\n                '\\u24BC': 'G',\n                '\\uFF27': 'G',\n                '\\u01F4': 'G',\n                '\\u011C': 'G',\n                '\\u1E20': 'G',\n                '\\u011E': 'G',\n                '\\u0120': 'G',\n                '\\u01E6': 'G',\n                '\\u0122': 'G',\n                '\\u01E4': 'G',\n                '\\u0193': 'G',\n                '\\uA7A0': 'G',\n                '\\uA77D': 'G',\n                '\\uA77E': 'G',\n                '\\u24BD': 'H',\n                '\\uFF28': 'H',\n                '\\u0124': 'H',\n                '\\u1E22': 'H',\n                '\\u1E26': 'H',\n                '\\u021E': 'H',\n                '\\u1E24': 'H',\n                '\\u1E28': 'H',\n                '\\u1E2A': 'H',\n                '\\u0126': 'H',\n                '\\u2C67': 'H',\n                '\\u2C75': 'H',\n                '\\uA78D': 'H',\n                '\\u24BE': 'I',\n                '\\uFF29': 'I',\n                '\\u00CC': 'I',\n                '\\u00CD': 'I',\n                '\\u00CE': 'I',\n                '\\u0128': 'I',\n                '\\u012A': 'I',\n                '\\u012C': 'I',\n                '\\u0130': 'I',\n                '\\u00CF': 'I',\n                '\\u1E2E': 'I',\n                '\\u1EC8': 'I',\n                '\\u01CF': 'I',\n                '\\u0208': 'I',\n                '\\u020A': 'I',\n                '\\u1ECA': 'I',\n                '\\u012E': 'I',\n                '\\u1E2C': 'I',\n                '\\u0197': 'I',\n                '\\u24BF': 'J',\n                '\\uFF2A': 'J',\n                '\\u0134': 'J',\n                '\\u0248': 'J',\n                '\\u24C0': 'K',\n                '\\uFF2B': 'K',\n                '\\u1E30': 'K',\n                '\\u01E8': 'K',\n                '\\u1E32': 'K',\n                '\\u0136': 'K',\n                '\\u1E34': 'K',\n                '\\u0198': 'K',\n                '\\u2C69': 'K',\n                '\\uA740': 'K',\n                '\\uA742': 'K',\n                '\\uA744': 'K',\n                '\\uA7A2': 'K',\n                '\\u24C1': 'L',\n                '\\uFF2C': 'L',\n                '\\u013F': 'L',\n                '\\u0139': 'L',\n                '\\u013D': 'L',\n                '\\u1E36': 'L',\n                '\\u1E38': 'L',\n                '\\u013B': 'L',\n                '\\u1E3C': 'L',\n                '\\u1E3A': 'L',\n                '\\u0141': 'L',\n                '\\u023D': 'L',\n                '\\u2C62': 'L',\n                '\\u2C60': 'L',\n                '\\uA748': 'L',\n                '\\uA746': 'L',\n                '\\uA780': 'L',\n                '\\u01C7': 'LJ',\n                '\\u01C8': 'Lj',\n                '\\u24C2': 'M',\n                '\\uFF2D': 'M',\n                '\\u1E3E': 'M',\n                '\\u1E40': 'M',\n                '\\u1E42': 'M',\n                '\\u2C6E': 'M',\n                '\\u019C': 'M',\n                '\\u24C3': 'N',\n                '\\uFF2E': 'N',\n                '\\u01F8': 'N',\n                '\\u0143': 'N',\n                '\\u00D1': 'N',\n                '\\u1E44': 'N',\n                '\\u0147': 'N',\n                '\\u1E46': 'N',\n                '\\u0145': 'N',\n                '\\u1E4A': 'N',\n                '\\u1E48': 'N',\n                '\\u0220': 'N',\n                '\\u019D': 'N',\n                '\\uA790': 'N',\n                '\\uA7A4': 'N',\n                '\\u01CA': 'NJ',\n                '\\u01CB': 'Nj',\n                '\\u24C4': 'O',\n                '\\uFF2F': 'O',\n                '\\u00D2': 'O',\n                '\\u00D3': 'O',\n                '\\u00D4': 'O',\n                '\\u1ED2': 'O',\n                '\\u1ED0': 'O',\n                '\\u1ED6': 'O',\n                '\\u1ED4': 'O',\n                '\\u00D5': 'O',\n                '\\u1E4C': 'O',\n                '\\u022C': 'O',\n                '\\u1E4E': 'O',\n                '\\u014C': 'O',\n                '\\u1E50': 'O',\n                '\\u1E52': 'O',\n                '\\u014E': 'O',\n                '\\u022E': 'O',\n                '\\u0230': 'O',\n                '\\u00D6': 'O',\n                '\\u022A': 'O',\n                '\\u1ECE': 'O',\n                '\\u0150': 'O',\n                '\\u01D1': 'O',\n                '\\u020C': 'O',\n                '\\u020E': 'O',\n                '\\u01A0': 'O',\n                '\\u1EDC': 'O',\n                '\\u1EDA': 'O',\n                '\\u1EE0': 'O',\n                '\\u1EDE': 'O',\n                '\\u1EE2': 'O',\n                '\\u1ECC': 'O',\n                '\\u1ED8': 'O',\n                '\\u01EA': 'O',\n                '\\u01EC': 'O',\n                '\\u00D8': 'O',\n                '\\u01FE': 'O',\n                '\\u0186': 'O',\n                '\\u019F': 'O',\n                '\\uA74A': 'O',\n                '\\uA74C': 'O',\n                '\\u01A2': 'OI',\n                '\\uA74E': 'OO',\n                '\\u0222': 'OU',\n                '\\u24C5': 'P',\n                '\\uFF30': 'P',\n                '\\u1E54': 'P',\n                '\\u1E56': 'P',\n                '\\u01A4': 'P',\n                '\\u2C63': 'P',\n                '\\uA750': 'P',\n                '\\uA752': 'P',\n                '\\uA754': 'P',\n                '\\u24C6': 'Q',\n                '\\uFF31': 'Q',\n                '\\uA756': 'Q',\n                '\\uA758': 'Q',\n                '\\u024A': 'Q',\n                '\\u24C7': 'R',\n                '\\uFF32': 'R',\n                '\\u0154': 'R',\n                '\\u1E58': 'R',\n                '\\u0158': 'R',\n                '\\u0210': 'R',\n                '\\u0212': 'R',\n                '\\u1E5A': 'R',\n                '\\u1E5C': 'R',\n                '\\u0156': 'R',\n                '\\u1E5E': 'R',\n                '\\u024C': 'R',\n                '\\u2C64': 'R',\n                '\\uA75A': 'R',\n                '\\uA7A6': 'R',\n                '\\uA782': 'R',\n                '\\u24C8': 'S',\n                '\\uFF33': 'S',\n                '\\u1E9E': 'S',\n                '\\u015A': 'S',\n                '\\u1E64': 'S',\n                '\\u015C': 'S',\n                '\\u1E60': 'S',\n                '\\u0160': 'S',\n                '\\u1E66': 'S',\n                '\\u1E62': 'S',\n                '\\u1E68': 'S',\n                '\\u0218': 'S',\n                '\\u015E': 'S',\n                '\\u2C7E': 'S',\n                '\\uA7A8': 'S',\n                '\\uA784': 'S',\n                '\\u24C9': 'T',\n                '\\uFF34': 'T',\n                '\\u1E6A': 'T',\n                '\\u0164': 'T',\n                '\\u1E6C': 'T',\n                '\\u021A': 'T',\n                '\\u0162': 'T',\n                '\\u1E70': 'T',\n                '\\u1E6E': 'T',\n                '\\u0166': 'T',\n                '\\u01AC': 'T',\n                '\\u01AE': 'T',\n                '\\u023E': 'T',\n                '\\uA786': 'T',\n                '\\uA728': 'TZ',\n                '\\u24CA': 'U',\n                '\\uFF35': 'U',\n                '\\u00D9': 'U',\n                '\\u00DA': 'U',\n                '\\u00DB': 'U',\n                '\\u0168': 'U',\n                '\\u1E78': 'U',\n                '\\u016A': 'U',\n                '\\u1E7A': 'U',\n                '\\u016C': 'U',\n                '\\u00DC': 'U',\n                '\\u01DB': 'U',\n                '\\u01D7': 'U',\n                '\\u01D5': 'U',\n                '\\u01D9': 'U',\n                '\\u1EE6': 'U',\n                '\\u016E': 'U',\n                '\\u0170': 'U',\n                '\\u01D3': 'U',\n                '\\u0214': 'U',\n                '\\u0216': 'U',\n                '\\u01AF': 'U',\n                '\\u1EEA': 'U',\n                '\\u1EE8': 'U',\n                '\\u1EEE': 'U',\n                '\\u1EEC': 'U',\n                '\\u1EF0': 'U',\n                '\\u1EE4': 'U',\n                '\\u1E72': 'U',\n                '\\u0172': 'U',\n                '\\u1E76': 'U',\n                '\\u1E74': 'U',\n                '\\u0244': 'U',\n                '\\u24CB': 'V',\n                '\\uFF36': 'V',\n                '\\u1E7C': 'V',\n                '\\u1E7E': 'V',\n                '\\u01B2': 'V',\n                '\\uA75E': 'V',\n                '\\u0245': 'V',\n                '\\uA760': 'VY',\n                '\\u24CC': 'W',\n                '\\uFF37': 'W',\n                '\\u1E80': 'W',\n                '\\u1E82': 'W',\n                '\\u0174': 'W',\n                '\\u1E86': 'W',\n                '\\u1E84': 'W',\n                '\\u1E88': 'W',\n                '\\u2C72': 'W',\n                '\\u24CD': 'X',\n                '\\uFF38': 'X',\n                '\\u1E8A': 'X',\n                '\\u1E8C': 'X',\n                '\\u24CE': 'Y',\n                '\\uFF39': 'Y',\n                '\\u1EF2': 'Y',\n                '\\u00DD': 'Y',\n                '\\u0176': 'Y',\n                '\\u1EF8': 'Y',\n                '\\u0232': 'Y',\n                '\\u1E8E': 'Y',\n                '\\u0178': 'Y',\n                '\\u1EF6': 'Y',\n                '\\u1EF4': 'Y',\n                '\\u01B3': 'Y',\n                '\\u024E': 'Y',\n                '\\u1EFE': 'Y',\n                '\\u24CF': 'Z',\n                '\\uFF3A': 'Z',\n                '\\u0179': 'Z',\n                '\\u1E90': 'Z',\n                '\\u017B': 'Z',\n                '\\u017D': 'Z',\n                '\\u1E92': 'Z',\n                '\\u1E94': 'Z',\n                '\\u01B5': 'Z',\n                '\\u0224': 'Z',\n                '\\u2C7F': 'Z',\n                '\\u2C6B': 'Z',\n                '\\uA762': 'Z',\n                '\\u24D0': 'a',\n                '\\uFF41': 'a',\n                '\\u1E9A': 'a',\n                '\\u00E0': 'a',\n                '\\u00E1': 'a',\n                '\\u00E2': 'a',\n                '\\u1EA7': 'a',\n                '\\u1EA5': 'a',\n                '\\u1EAB': 'a',\n                '\\u1EA9': 'a',\n                '\\u00E3': 'a',\n                '\\u0101': 'a',\n                '\\u0103': 'a',\n                '\\u1EB1': 'a',\n                '\\u1EAF': 'a',\n                '\\u1EB5': 'a',\n                '\\u1EB3': 'a',\n                '\\u0227': 'a',\n                '\\u01E1': 'a',\n                '\\u00E4': 'a',\n                '\\u01DF': 'a',\n                '\\u1EA3': 'a',\n                '\\u00E5': 'a',\n                '\\u01FB': 'a',\n                '\\u01CE': 'a',\n                '\\u0201': 'a',\n                '\\u0203': 'a',\n                '\\u1EA1': 'a',\n                '\\u1EAD': 'a',\n                '\\u1EB7': 'a',\n                '\\u1E01': 'a',\n                '\\u0105': 'a',\n                '\\u2C65': 'a',\n                '\\u0250': 'a',\n                '\\uA733': 'aa',\n                '\\u00E6': 'ae',\n                '\\u01FD': 'ae',\n                '\\u01E3': 'ae',\n                '\\uA735': 'ao',\n                '\\uA737': 'au',\n                '\\uA739': 'av',\n                '\\uA73B': 'av',\n                '\\uA73D': 'ay',\n                '\\u24D1': 'b',\n                '\\uFF42': 'b',\n                '\\u1E03': 'b',\n                '\\u1E05': 'b',\n                '\\u1E07': 'b',\n                '\\u0180': 'b',\n                '\\u0183': 'b',\n                '\\u0253': 'b',\n                '\\u24D2': 'c',\n                '\\uFF43': 'c',\n                '\\u0107': 'c',\n                '\\u0109': 'c',\n                '\\u010B': 'c',\n                '\\u010D': 'c',\n                '\\u00E7': 'c',\n                '\\u1E09': 'c',\n                '\\u0188': 'c',\n                '\\u023C': 'c',\n                '\\uA73F': 'c',\n                '\\u2184': 'c',\n                '\\u24D3': 'd',\n                '\\uFF44': 'd',\n                '\\u1E0B': 'd',\n                '\\u010F': 'd',\n                '\\u1E0D': 'd',\n                '\\u1E11': 'd',\n                '\\u1E13': 'd',\n                '\\u1E0F': 'd',\n                '\\u0111': 'd',\n                '\\u018C': 'd',\n                '\\u0256': 'd',\n                '\\u0257': 'd',\n                '\\uA77A': 'd',\n                '\\u01F3': 'dz',\n                '\\u01C6': 'dz',\n                '\\u24D4': 'e',\n                '\\uFF45': 'e',\n                '\\u00E8': 'e',\n                '\\u00E9': 'e',\n                '\\u00EA': 'e',\n                '\\u1EC1': 'e',\n                '\\u1EBF': 'e',\n                '\\u1EC5': 'e',\n                '\\u1EC3': 'e',\n                '\\u1EBD': 'e',\n                '\\u0113': 'e',\n                '\\u1E15': 'e',\n                '\\u1E17': 'e',\n                '\\u0115': 'e',\n                '\\u0117': 'e',\n                '\\u00EB': 'e',\n                '\\u1EBB': 'e',\n                '\\u011B': 'e',\n                '\\u0205': 'e',\n                '\\u0207': 'e',\n                '\\u1EB9': 'e',\n                '\\u1EC7': 'e',\n                '\\u0229': 'e',\n                '\\u1E1D': 'e',\n                '\\u0119': 'e',\n                '\\u1E19': 'e',\n                '\\u1E1B': 'e',\n                '\\u0247': 'e',\n                '\\u025B': 'e',\n                '\\u01DD': 'e',\n                '\\u24D5': 'f',\n                '\\uFF46': 'f',\n                '\\u1E1F': 'f',\n                '\\u0192': 'f',\n                '\\uA77C': 'f',\n                '\\u24D6': 'g',\n                '\\uFF47': 'g',\n                '\\u01F5': 'g',\n                '\\u011D': 'g',\n                '\\u1E21': 'g',\n                '\\u011F': 'g',\n                '\\u0121': 'g',\n                '\\u01E7': 'g',\n                '\\u0123': 'g',\n                '\\u01E5': 'g',\n                '\\u0260': 'g',\n                '\\uA7A1': 'g',\n                '\\u1D79': 'g',\n                '\\uA77F': 'g',\n                '\\u24D7': 'h',\n                '\\uFF48': 'h',\n                '\\u0125': 'h',\n                '\\u1E23': 'h',\n                '\\u1E27': 'h',\n                '\\u021F': 'h',\n                '\\u1E25': 'h',\n                '\\u1E29': 'h',\n                '\\u1E2B': 'h',\n                '\\u1E96': 'h',\n                '\\u0127': 'h',\n                '\\u2C68': 'h',\n                '\\u2C76': 'h',\n                '\\u0265': 'h',\n                '\\u0195': 'hv',\n                '\\u24D8': 'i',\n                '\\uFF49': 'i',\n                '\\u00EC': 'i',\n                '\\u00ED': 'i',\n                '\\u00EE': 'i',\n                '\\u0129': 'i',\n                '\\u012B': 'i',\n                '\\u012D': 'i',\n                '\\u00EF': 'i',\n                '\\u1E2F': 'i',\n                '\\u1EC9': 'i',\n                '\\u01D0': 'i',\n                '\\u0209': 'i',\n                '\\u020B': 'i',\n                '\\u1ECB': 'i',\n                '\\u012F': 'i',\n                '\\u1E2D': 'i',\n                '\\u0268': 'i',\n                '\\u0131': 'i',\n                '\\u24D9': 'j',\n                '\\uFF4A': 'j',\n                '\\u0135': 'j',\n                '\\u01F0': 'j',\n                '\\u0249': 'j',\n                '\\u24DA': 'k',\n                '\\uFF4B': 'k',\n                '\\u1E31': 'k',\n                '\\u01E9': 'k',\n                '\\u1E33': 'k',\n                '\\u0137': 'k',\n                '\\u1E35': 'k',\n                '\\u0199': 'k',\n                '\\u2C6A': 'k',\n                '\\uA741': 'k',\n                '\\uA743': 'k',\n                '\\uA745': 'k',\n                '\\uA7A3': 'k',\n                '\\u24DB': 'l',\n                '\\uFF4C': 'l',\n                '\\u0140': 'l',\n                '\\u013A': 'l',\n                '\\u013E': 'l',\n                '\\u1E37': 'l',\n                '\\u1E39': 'l',\n                '\\u013C': 'l',\n                '\\u1E3D': 'l',\n                '\\u1E3B': 'l',\n                '\\u017F': 'l',\n                '\\u0142': 'l',\n                '\\u019A': 'l',\n                '\\u026B': 'l',\n                '\\u2C61': 'l',\n                '\\uA749': 'l',\n                '\\uA781': 'l',\n                '\\uA747': 'l',\n                '\\u01C9': 'lj',\n                '\\u24DC': 'm',\n                '\\uFF4D': 'm',\n                '\\u1E3F': 'm',\n                '\\u1E41': 'm',\n                '\\u1E43': 'm',\n                '\\u0271': 'm',\n                '\\u026F': 'm',\n                '\\u24DD': 'n',\n                '\\uFF4E': 'n',\n                '\\u01F9': 'n',\n                '\\u0144': 'n',\n                '\\u00F1': 'n',\n                '\\u1E45': 'n',\n                '\\u0148': 'n',\n                '\\u1E47': 'n',\n                '\\u0146': 'n',\n                '\\u1E4B': 'n',\n                '\\u1E49': 'n',\n                '\\u019E': 'n',\n                '\\u0272': 'n',\n                '\\u0149': 'n',\n                '\\uA791': 'n',\n                '\\uA7A5': 'n',\n                '\\u01CC': 'nj',\n                '\\u24DE': 'o',\n                '\\uFF4F': 'o',\n                '\\u00F2': 'o',\n                '\\u00F3': 'o',\n                '\\u00F4': 'o',\n                '\\u1ED3': 'o',\n                '\\u1ED1': 'o',\n                '\\u1ED7': 'o',\n                '\\u1ED5': 'o',\n                '\\u00F5': 'o',\n                '\\u1E4D': 'o',\n                '\\u022D': 'o',\n                '\\u1E4F': 'o',\n                '\\u014D': 'o',\n                '\\u1E51': 'o',\n                '\\u1E53': 'o',\n                '\\u014F': 'o',\n                '\\u022F': 'o',\n                '\\u0231': 'o',\n                '\\u00F6': 'o',\n                '\\u022B': 'o',\n                '\\u1ECF': 'o',\n                '\\u0151': 'o',\n                '\\u01D2': 'o',\n                '\\u020D': 'o',\n                '\\u020F': 'o',\n                '\\u01A1': 'o',\n                '\\u1EDD': 'o',\n                '\\u1EDB': 'o',\n                '\\u1EE1': 'o',\n                '\\u1EDF': 'o',\n                '\\u1EE3': 'o',\n                '\\u1ECD': 'o',\n                '\\u1ED9': 'o',\n                '\\u01EB': 'o',\n                '\\u01ED': 'o',\n                '\\u00F8': 'o',\n                '\\u01FF': 'o',\n                '\\u0254': 'o',\n                '\\uA74B': 'o',\n                '\\uA74D': 'o',\n                '\\u0275': 'o',\n                '\\u01A3': 'oi',\n                '\\u0223': 'ou',\n                '\\uA74F': 'oo',\n                '\\u24DF': 'p',\n                '\\uFF50': 'p',\n                '\\u1E55': 'p',\n                '\\u1E57': 'p',\n                '\\u01A5': 'p',\n                '\\u1D7D': 'p',\n                '\\uA751': 'p',\n                '\\uA753': 'p',\n                '\\uA755': 'p',\n                '\\u24E0': 'q',\n                '\\uFF51': 'q',\n                '\\u024B': 'q',\n                '\\uA757': 'q',\n                '\\uA759': 'q',\n                '\\u24E1': 'r',\n                '\\uFF52': 'r',\n                '\\u0155': 'r',\n                '\\u1E59': 'r',\n                '\\u0159': 'r',\n                '\\u0211': 'r',\n                '\\u0213': 'r',\n                '\\u1E5B': 'r',\n                '\\u1E5D': 'r',\n                '\\u0157': 'r',\n                '\\u1E5F': 'r',\n                '\\u024D': 'r',\n                '\\u027D': 'r',\n                '\\uA75B': 'r',\n                '\\uA7A7': 'r',\n                '\\uA783': 'r',\n                '\\u24E2': 's',\n                '\\uFF53': 's',\n                '\\u00DF': 's',\n                '\\u015B': 's',\n                '\\u1E65': 's',\n                '\\u015D': 's',\n                '\\u1E61': 's',\n                '\\u0161': 's',\n                '\\u1E67': 's',\n                '\\u1E63': 's',\n                '\\u1E69': 's',\n                '\\u0219': 's',\n                '\\u015F': 's',\n                '\\u023F': 's',\n                '\\uA7A9': 's',\n                '\\uA785': 's',\n                '\\u1E9B': 's',\n                '\\u24E3': 't',\n                '\\uFF54': 't',\n                '\\u1E6B': 't',\n                '\\u1E97': 't',\n                '\\u0165': 't',\n                '\\u1E6D': 't',\n                '\\u021B': 't',\n                '\\u0163': 't',\n                '\\u1E71': 't',\n                '\\u1E6F': 't',\n                '\\u0167': 't',\n                '\\u01AD': 't',\n                '\\u0288': 't',\n                '\\u2C66': 't',\n                '\\uA787': 't',\n                '\\uA729': 'tz',\n                '\\u24E4': 'u',\n                '\\uFF55': 'u',\n                '\\u00F9': 'u',\n                '\\u00FA': 'u',\n                '\\u00FB': 'u',\n                '\\u0169': 'u',\n                '\\u1E79': 'u',\n                '\\u016B': 'u',\n                '\\u1E7B': 'u',\n                '\\u016D': 'u',\n                '\\u00FC': 'u',\n                '\\u01DC': 'u',\n                '\\u01D8': 'u',\n                '\\u01D6': 'u',\n                '\\u01DA': 'u',\n                '\\u1EE7': 'u',\n                '\\u016F': 'u',\n                '\\u0171': 'u',\n                '\\u01D4': 'u',\n                '\\u0215': 'u',\n                '\\u0217': 'u',\n                '\\u01B0': 'u',\n                '\\u1EEB': 'u',\n                '\\u1EE9': 'u',\n                '\\u1EEF': 'u',\n                '\\u1EED': 'u',\n                '\\u1EF1': 'u',\n                '\\u1EE5': 'u',\n                '\\u1E73': 'u',\n                '\\u0173': 'u',\n                '\\u1E77': 'u',\n                '\\u1E75': 'u',\n                '\\u0289': 'u',\n                '\\u24E5': 'v',\n                '\\uFF56': 'v',\n                '\\u1E7D': 'v',\n                '\\u1E7F': 'v',\n                '\\u028B': 'v',\n                '\\uA75F': 'v',\n                '\\u028C': 'v',\n                '\\uA761': 'vy',\n                '\\u24E6': 'w',\n                '\\uFF57': 'w',\n                '\\u1E81': 'w',\n                '\\u1E83': 'w',\n                '\\u0175': 'w',\n                '\\u1E87': 'w',\n                '\\u1E85': 'w',\n                '\\u1E98': 'w',\n                '\\u1E89': 'w',\n                '\\u2C73': 'w',\n                '\\u24E7': 'x',\n                '\\uFF58': 'x',\n                '\\u1E8B': 'x',\n                '\\u1E8D': 'x',\n                '\\u24E8': 'y',\n                '\\uFF59': 'y',\n                '\\u1EF3': 'y',\n                '\\u00FD': 'y',\n                '\\u0177': 'y',\n                '\\u1EF9': 'y',\n                '\\u0233': 'y',\n                '\\u1E8F': 'y',\n                '\\u00FF': 'y',\n                '\\u1EF7': 'y',\n                '\\u1E99': 'y',\n                '\\u1EF5': 'y',\n                '\\u01B4': 'y',\n                '\\u024F': 'y',\n                '\\u1EFF': 'y',\n                '\\u24E9': 'z',\n                '\\uFF5A': 'z',\n                '\\u017A': 'z',\n                '\\u1E91': 'z',\n                '\\u017C': 'z',\n                '\\u017E': 'z',\n                '\\u1E93': 'z',\n                '\\u1E95': 'z',\n                '\\u01B6': 'z',\n                '\\u0225': 'z',\n                '\\u0240': 'z',\n                '\\u2C6C': 'z',\n                '\\uA763': 'z',\n                '\\u0386': '\\u0391',\n                '\\u0388': '\\u0395',\n                '\\u0389': '\\u0397',\n                '\\u038A': '\\u0399',\n                '\\u03AA': '\\u0399',\n                '\\u038C': '\\u039F',\n                '\\u038E': '\\u03A5',\n                '\\u03AB': '\\u03A5',\n                '\\u038F': '\\u03A9',\n                '\\u03AC': '\\u03B1',\n                '\\u03AD': '\\u03B5',\n                '\\u03AE': '\\u03B7',\n                '\\u03AF': '\\u03B9',\n                '\\u03CA': '\\u03B9',\n                '\\u0390': '\\u03B9',\n                '\\u03CC': '\\u03BF',\n                '\\u03CD': '\\u03C5',\n                '\\u03CB': '\\u03C5',\n                '\\u03B0': '\\u03C5',\n                '\\u03C9': '\\u03C9',\n                '\\u03C2': '\\u03C3'\n            };\n\n            return diacritics;\n        });\n\n        S2.define('select2/data/base', [\n            '../utils'\n        ], function (Utils) {\n            function BaseAdapter($element, options) {\n                BaseAdapter.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(BaseAdapter, Utils.Observable);\n\n            BaseAdapter.prototype.current = function (callback) {\n                throw new Error('The `current` method must be defined in child classes.');\n            };\n\n            BaseAdapter.prototype.query = function (params, callback) {\n                throw new Error('The `query` method must be defined in child classes.');\n            };\n\n            BaseAdapter.prototype.bind = function (container, $container) {\n                // Can be implemented in subclasses\n            };\n\n            BaseAdapter.prototype.destroy = function () {\n                // Can be implemented in subclasses\n            };\n\n            BaseAdapter.prototype.generateResultId = function (container, data) {\n                var id = container.id + '-result-';\n\n                id += Utils.generateChars(4);\n\n                if (data.id != null) {\n                    id += '-' + data.id.toString();\n                } else {\n                    id += '-' + Utils.generateChars(4);\n                }\n                return id;\n            };\n\n            return BaseAdapter;\n        });\n\n        S2.define('select2/data/select', [\n            './base',\n            '../utils',\n            'jquery'\n        ], function (BaseAdapter, Utils, $) {\n            function SelectAdapter($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                SelectAdapter.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(SelectAdapter, BaseAdapter);\n\n            SelectAdapter.prototype.current = function (callback) {\n                var data = [];\n                var self = this;\n\n                this.$element.find(':selected').each(function () {\n                    var $option = $(this);\n\n                    var option = self.item($option);\n\n                    data.push(option);\n                });\n\n                callback(data);\n            };\n\n            SelectAdapter.prototype.select = function (data) {\n                var self = this;\n\n                data.selected = true;\n\n                // If data.element is a DOM node, use it instead\n                if ($(data.element).is('option')) {\n                    data.element.selected = true;\n\n                    this.$element.trigger('change');\n\n                    return;\n                }\n\n                if (this.$element.prop('multiple')) {\n                    this.current(function (currentData) {\n                        var val = [];\n\n                        data = [data];\n                        data.push.apply(data, currentData);\n\n                        for (var d = 0; d < data.length; d++) {\n                            var id = data[d].id;\n\n                            if ($.inArray(id, val) === -1) {\n                                val.push(id);\n                            }\n                        }\n\n                        self.$element.val(val);\n                        self.$element.trigger('change');\n                    });\n                } else {\n                    var val = data.id;\n\n                    this.$element.val(val);\n                    this.$element.trigger('change');\n                }\n            };\n\n            SelectAdapter.prototype.unselect = function (data) {\n                var self = this;\n\n                if (!this.$element.prop('multiple')) {\n                    return;\n                }\n\n                data.selected = false;\n\n                if ($(data.element).is('option')) {\n                    data.element.selected = false;\n\n                    this.$element.trigger('change');\n\n                    return;\n                }\n\n                this.current(function (currentData) {\n                    var val = [];\n\n                    for (var d = 0; d < currentData.length; d++) {\n                        var id = currentData[d].id;\n\n                        if (id !== data.id && $.inArray(id, val) === -1) {\n                            val.push(id);\n                        }\n                    }\n\n                    self.$element.val(val);\n\n                    self.$element.trigger('change');\n                });\n            };\n\n            SelectAdapter.prototype.bind = function (container, $container) {\n                var self = this;\n\n                this.container = container;\n\n                container.on('select', function (params) {\n                    self.select(params.data);\n                });\n\n                container.on('unselect', function (params) {\n                    self.unselect(params.data);\n                });\n            };\n\n            SelectAdapter.prototype.destroy = function () {\n                // Remove anything added to child elements\n                this.$element.find('*').each(function () {\n                    // Remove any custom data set by Select2\n                    Utils.RemoveData(this);\n                });\n            };\n\n            SelectAdapter.prototype.query = function (params, callback) {\n                var data = [];\n                var self = this;\n\n                var $options = this.$element.children();\n\n                $options.each(function () {\n                    var $option = $(this);\n\n                    if (!$option.is('option') && !$option.is('optgroup')) {\n                        return;\n                    }\n\n                    var option = self.item($option);\n\n                    var matches = self.matches(params, option);\n\n                    if (matches !== null) {\n                        data.push(matches);\n                    }\n                });\n\n                callback({\n                    results: data\n                });\n            };\n\n            SelectAdapter.prototype.addOptions = function ($options) {\n                Utils.appendMany(this.$element, $options);\n            };\n\n            SelectAdapter.prototype.option = function (data) {\n                var option;\n\n                if (data.children) {\n                    option = document.createElement('optgroup');\n                    option.label = data.text;\n                } else {\n                    option = document.createElement('option');\n\n                    if (option.textContent !== undefined) {\n                        option.textContent = data.text;\n                    } else {\n                        option.innerText = data.text;\n                    }\n                }\n\n                if (data.id !== undefined) {\n                    option.value = data.id;\n                }\n\n                if (data.disabled) {\n                    option.disabled = true;\n                }\n\n                if (data.selected) {\n                    option.selected = true;\n                }\n\n                if (data.title) {\n                    option.title = data.title;\n                }\n\n                var $option = $(option);\n\n                var normalizedData = this._normalizeItem(data);\n                normalizedData.element = option;\n\n                // Override the option's data with the combined data\n                Utils.StoreData(option, 'data', normalizedData);\n\n                return $option;\n            };\n\n            SelectAdapter.prototype.item = function ($option) {\n                var data = {};\n\n                data = Utils.GetData($option[0], 'data');\n\n                if (data != null) {\n                    return data;\n                }\n\n                if ($option.is('option')) {\n                    data = {\n                        id: $option.val(),\n                        text: $option.text(),\n                        disabled: $option.prop('disabled'),\n                        selected: $option.prop('selected'),\n                        title: $option.prop('title')\n                    };\n                } else if ($option.is('optgroup')) {\n                    data = {\n                        text: $option.prop('label'),\n                        children: [],\n                        title: $option.prop('title')\n                    };\n\n                    var $children = $option.children('option');\n                    var children = [];\n\n                    for (var c = 0; c < $children.length; c++) {\n                        var $child = $($children[c]);\n\n                        var child = this.item($child);\n\n                        children.push(child);\n                    }\n\n                    data.children = children;\n                }\n\n                data = this._normalizeItem(data);\n                data.element = $option[0];\n\n                Utils.StoreData($option[0], 'data', data);\n\n                return data;\n            };\n\n            SelectAdapter.prototype._normalizeItem = function (item) {\n                if (item !== Object(item)) {\n                    item = {\n                        id: item,\n                        text: item\n                    };\n                }\n\n                item = $.extend({}, {\n                    text: ''\n                }, item);\n\n                var defaults = {\n                    selected: false,\n                    disabled: false\n                };\n\n                if (item.id != null) {\n                    item.id = item.id.toString();\n                }\n\n                if (item.text != null) {\n                    item.text = item.text.toString();\n                }\n\n                if (item._resultId == null && item.id && this.container != null) {\n                    item._resultId = this.generateResultId(this.container, item);\n                }\n\n                return $.extend({}, defaults, item);\n            };\n\n            SelectAdapter.prototype.matches = function (params, data) {\n                var matcher = this.options.get('matcher');\n\n                return matcher(params, data);\n            };\n\n            return SelectAdapter;\n        });\n\n        S2.define('select2/data/array', [\n            './select',\n            '../utils',\n            'jquery'\n        ], function (SelectAdapter, Utils, $) {\n            function ArrayAdapter($element, options) {\n                var data = options.get('data') || [];\n\n                ArrayAdapter.__super__.constructor.call(this, $element, options);\n\n                this.addOptions(this.convertToOptions(data));\n            }\n\n            Utils.Extend(ArrayAdapter, SelectAdapter);\n\n            ArrayAdapter.prototype.select = function (data) {\n                var $option = this.$element.find('option').filter(function (i, elm) {\n                    return elm.value == data.id.toString();\n                });\n\n                if ($option.length === 0) {\n                    $option = this.option(data);\n\n                    this.addOptions($option);\n                }\n\n                ArrayAdapter.__super__.select.call(this, data);\n            };\n\n            ArrayAdapter.prototype.convertToOptions = function (data) {\n                var self = this;\n\n                var $existing = this.$element.find('option');\n                var existingIds = $existing.map(function () {\n                    return self.item($(this)).id;\n                }).get();\n\n                var $options = [];\n\n                // Filter out all items except for the one passed in the argument\n                function onlyItem(item) {\n                    return function () {\n                        return $(this).val() == item.id;\n                    };\n                }\n\n                for (var d = 0; d < data.length; d++) {\n                    var item = this._normalizeItem(data[d]);\n\n                    // Skip items which were pre-loaded, only merge the data\n                    if ($.inArray(item.id, existingIds) >= 0) {\n                        var $existingOption = $existing.filter(onlyItem(item));\n\n                        var existingData = this.item($existingOption);\n                        var newData = $.extend(true, {}, item, existingData);\n\n                        var $newOption = this.option(newData);\n\n                        $existingOption.replaceWith($newOption);\n\n                        continue;\n                    }\n\n                    var $option = this.option(item);\n\n                    if (item.children) {\n                        var $children = this.convertToOptions(item.children);\n\n                        Utils.appendMany($option, $children);\n                    }\n\n                    $options.push($option);\n                }\n\n                return $options;\n            };\n\n            return ArrayAdapter;\n        });\n\n        S2.define('select2/data/ajax', [\n            './array',\n            '../utils',\n            'jquery'\n        ], function (ArrayAdapter, Utils, $) {\n            function AjaxAdapter($element, options) {\n                this.ajaxOptions = this._applyDefaults(options.get('ajax'));\n\n                if (this.ajaxOptions.processResults != null) {\n                    this.processResults = this.ajaxOptions.processResults;\n                }\n\n                AjaxAdapter.__super__.constructor.call(this, $element, options);\n            }\n\n            Utils.Extend(AjaxAdapter, ArrayAdapter);\n\n            AjaxAdapter.prototype._applyDefaults = function (options) {\n                var defaults = {\n                    data: function (params) {\n                        return $.extend({}, params, {\n                            q: params.term\n                        });\n                    },\n                    transport: function (params, success, failure) {\n                        var $request = $.ajax(params);\n\n                        $request.then(success);\n                        $request.fail(failure);\n\n                        return $request;\n                    }\n                };\n\n                return $.extend({}, defaults, options, true);\n            };\n\n            AjaxAdapter.prototype.processResults = function (results) {\n                return results;\n            };\n\n            AjaxAdapter.prototype.query = function (params, callback) {\n                var matches = [];\n                var self = this;\n\n                if (this._request != null) {\n                    // JSONP requests cannot always be aborted\n                    if ($.isFunction(this._request.abort)) {\n                        this._request.abort();\n                    }\n\n                    this._request = null;\n                }\n\n                var options = $.extend({\n                    type: 'GET'\n                }, this.ajaxOptions);\n\n                if (typeof options.url === 'function') {\n                    options.url = options.url.call(this.$element, params);\n                }\n\n                if (typeof options.data === 'function') {\n                    options.data = options.data.call(this.$element, params);\n                }\n\n                function request() {\n                    var $request = options.transport(options, function (data) {\n                        var results = self.processResults(data, params);\n\n                        if (self.options.get('debug') && window.console && console.error) {\n                            // Check to make sure that the response included a `results` key.\n                            if (!results || !results.results || !$.isArray(results.results)) {\n                                console.error(\n                                    'Select2: The AJAX results did not return an array in the ' +\n                                    '`results` key of the response.'\n                                );\n                            }\n                        }\n\n                        callback(results);\n                    }, function () {\n                        // Attempt to detect if a request was aborted\n                        // Only works if the transport exposes a status property\n                        if ('status' in $request &&\n                            ($request.status === 0 || $request.status === '0')) {\n                            return;\n                        }\n\n                        self.trigger('results:message', {\n                            message: 'errorLoading'\n                        });\n                    });\n\n                    self._request = $request;\n                }\n\n                if (this.ajaxOptions.delay && params.term != null) {\n                    if (this._queryTimeout) {\n                        window.clearTimeout(this._queryTimeout);\n                    }\n\n                    this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);\n                } else {\n                    request();\n                }\n            };\n\n            return AjaxAdapter;\n        });\n\n        S2.define('select2/data/tags', [\n            'jquery'\n        ], function ($) {\n            function Tags(decorated, $element, options) {\n                var tags = options.get('tags');\n\n                var createTag = options.get('createTag');\n\n                if (createTag !== undefined) {\n                    this.createTag = createTag;\n                }\n\n                var insertTag = options.get('insertTag');\n\n                if (insertTag !== undefined) {\n                    this.insertTag = insertTag;\n                }\n\n                decorated.call(this, $element, options);\n\n                if ($.isArray(tags)) {\n                    for (var t = 0; t < tags.length; t++) {\n                        var tag = tags[t];\n                        var item = this._normalizeItem(tag);\n\n                        var $option = this.option(item);\n\n                        this.$element.append($option);\n                    }\n                }\n            }\n\n            Tags.prototype.query = function (decorated, params, callback) {\n                var self = this;\n\n                this._removeOldTags();\n\n                if (params.term == null || params.page != null) {\n                    decorated.call(this, params, callback);\n                    return;\n                }\n\n                function wrapper(obj, child) {\n                    var data = obj.results;\n\n                    for (var i = 0; i < data.length; i++) {\n                        var option = data[i];\n\n                        var checkChildren = (\n                            option.children != null &&\n                            !wrapper({\n                                results: option.children\n                            }, true)\n                        );\n\n                        var optionText = (option.text || '').toUpperCase();\n                        var paramsTerm = (params.term || '').toUpperCase();\n\n                        var checkText = optionText === paramsTerm;\n\n                        if (checkText || checkChildren) {\n                            if (child) {\n                                return false;\n                            }\n\n                            obj.data = data;\n                            callback(obj);\n\n                            return;\n                        }\n                    }\n\n                    if (child) {\n                        return true;\n                    }\n\n                    var tag = self.createTag(params);\n\n                    if (tag != null) {\n                        var $option = self.option(tag);\n                        $option.attr('data-select2-tag', true);\n\n                        self.addOptions([$option]);\n\n                        self.insertTag(data, tag);\n                    }\n\n                    obj.results = data;\n\n                    callback(obj);\n                }\n\n                decorated.call(this, params, wrapper);\n            };\n\n            Tags.prototype.createTag = function (decorated, params) {\n                var term = $.trim(params.term);\n\n                if (term === '') {\n                    return null;\n                }\n\n                return {\n                    id: term,\n                    text: term\n                };\n            };\n\n            Tags.prototype.insertTag = function (_, data, tag) {\n                data.unshift(tag);\n            };\n\n            Tags.prototype._removeOldTags = function (_) {\n                var tag = this._lastTag;\n\n                var $options = this.$element.find('option[data-select2-tag]');\n\n                $options.each(function () {\n                    if (this.selected) {\n                        return;\n                    }\n\n                    $(this).remove();\n                });\n            };\n\n            return Tags;\n        });\n\n        S2.define('select2/data/tokenizer', [\n            'jquery'\n        ], function ($) {\n            function Tokenizer(decorated, $element, options) {\n                var tokenizer = options.get('tokenizer');\n\n                if (tokenizer !== undefined) {\n                    this.tokenizer = tokenizer;\n                }\n\n                decorated.call(this, $element, options);\n            }\n\n            Tokenizer.prototype.bind = function (decorated, container, $container) {\n                decorated.call(this, container, $container);\n\n                this.$search = container.dropdown.$search || container.selection.$search ||\n                    $container.find('.select2-search__field');\n            };\n\n            Tokenizer.prototype.query = function (decorated, params, callback) {\n                var self = this;\n\n                function createAndSelect(data) {\n                    // Normalize the data object so we can use it for checks\n                    var item = self._normalizeItem(data);\n\n                    // Check if the data object already exists as a tag\n                    // Select it if it doesn't\n                    var $existingOptions = self.$element.find('option').filter(function () {\n                        return $(this).val() === item.id;\n                    });\n\n                    // If an existing option wasn't found for it, create the option\n                    if (!$existingOptions.length) {\n                        var $option = self.option(item);\n                        $option.attr('data-select2-tag', true);\n\n                        self._removeOldTags();\n                        self.addOptions([$option]);\n                    }\n\n                    // Select the item, now that we know there is an option for it\n                    select(item);\n                }\n\n                function select(data) {\n                    self.trigger('select', {\n                        data: data\n                    });\n                }\n\n                params.term = params.term || '';\n\n                var tokenData = this.tokenizer(params, this.options, createAndSelect);\n\n                if (tokenData.term !== params.term) {\n                    // Replace the search term if we have the search box\n                    if (this.$search.length) {\n                        this.$search.val(tokenData.term);\n                        this.$search.focus();\n                    }\n\n                    params.term = tokenData.term;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            Tokenizer.prototype.tokenizer = function (_, params, options, callback) {\n                var separators = options.get('tokenSeparators') || [];\n                var term = params.term;\n                var i = 0;\n\n                var createTag = this.createTag || function (params) {\n                    return {\n                        id: params.term,\n                        text: params.term\n                    };\n                };\n\n                while (i < term.length) {\n                    var termChar = term[i];\n\n                    if ($.inArray(termChar, separators) === -1) {\n                        i++;\n\n                        continue;\n                    }\n\n                    var part = term.substr(0, i);\n                    var partParams = $.extend({}, params, {\n                        term: part\n                    });\n\n                    var data = createTag(partParams);\n\n                    if (data == null) {\n                        i++;\n                        continue;\n                    }\n\n                    callback(data);\n\n                    // Reset the term to not include the tokenized portion\n                    term = term.substr(i + 1) || '';\n                    i = 0;\n                }\n\n                return {\n                    term: term\n                };\n            };\n\n            return Tokenizer;\n        });\n\n        S2.define('select2/data/minimumInputLength', [], function () {\n            function MinimumInputLength(decorated, $e, options) {\n                this.minimumInputLength = options.get('minimumInputLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MinimumInputLength.prototype.query = function (decorated, params, callback) {\n                params.term = params.term || '';\n\n                if (params.term.length < this.minimumInputLength) {\n                    this.trigger('results:message', {\n                        message: 'inputTooShort',\n                        args: {\n                            minimum: this.minimumInputLength,\n                            input: params.term,\n                            params: params\n                        }\n                    });\n\n                    return;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            return MinimumInputLength;\n        });\n\n        S2.define('select2/data/maximumInputLength', [], function () {\n            function MaximumInputLength(decorated, $e, options) {\n                this.maximumInputLength = options.get('maximumInputLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MaximumInputLength.prototype.query = function (decorated, params, callback) {\n                params.term = params.term || '';\n\n                if (this.maximumInputLength > 0 &&\n                    params.term.length > this.maximumInputLength) {\n                    this.trigger('results:message', {\n                        message: 'inputTooLong',\n                        args: {\n                            maximum: this.maximumInputLength,\n                            input: params.term,\n                            params: params\n                        }\n                    });\n\n                    return;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            return MaximumInputLength;\n        });\n\n        S2.define('select2/data/maximumSelectionLength', [], function () {\n            function MaximumSelectionLength(decorated, $e, options) {\n                this.maximumSelectionLength = options.get('maximumSelectionLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MaximumSelectionLength.prototype.query =\n                function (decorated, params, callback) {\n                    var self = this;\n\n                    this.current(function (currentData) {\n                        var count = currentData != null ? currentData.length : 0;\n                        if (self.maximumSelectionLength > 0 &&\n                            count >= self.maximumSelectionLength) {\n                            self.trigger('results:message', {\n                                message: 'maximumSelected',\n                                args: {\n                                    maximum: self.maximumSelectionLength\n                                }\n                            });\n                            return;\n                        }\n                        decorated.call(self, params, callback);\n                    });\n                };\n\n            return MaximumSelectionLength;\n        });\n\n        S2.define('select2/dropdown', [\n            'jquery',\n            './utils'\n        ], function ($, Utils) {\n            function Dropdown($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                Dropdown.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(Dropdown, Utils.Observable);\n\n            Dropdown.prototype.render = function () {\n                var $dropdown = $(\n                    '<span class=\"select2-dropdown\">' +\n                    '<span class=\"select2-results\"></span>' +\n                    '</span>'\n                );\n\n                $dropdown.attr('dir', this.options.get('dir'));\n\n                this.$dropdown = $dropdown;\n\n                return $dropdown;\n            };\n\n            Dropdown.prototype.bind = function () {\n                // Should be implemented in subclasses\n            };\n\n            Dropdown.prototype.position = function ($dropdown, $container) {\n                // Should be implmented in subclasses\n            };\n\n            Dropdown.prototype.destroy = function () {\n                // Remove the dropdown from the DOM\n                this.$dropdown.remove();\n            };\n\n            return Dropdown;\n        });\n\n        S2.define('select2/dropdown/search', [\n            'jquery',\n            '../utils'\n        ], function ($, Utils) {\n            function Search() {\n            }\n\n            Search.prototype.render = function (decorated) {\n                var $rendered = decorated.call(this);\n\n                var $search = $(\n                    '<span class=\"select2-search select2-search--dropdown\">' +\n                    '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n                    ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"none\"' +\n                    ' spellcheck=\"false\" role=\"textbox\" />' +\n                    '</span>'\n                );\n\n                this.$searchContainer = $search;\n                this.$search = $search.find('input');\n\n                $rendered.prepend($search);\n\n                return $rendered;\n            };\n\n            Search.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                this.$search.on('keydown', function (evt) {\n                    self.trigger('keypress', evt);\n\n                    self._keyUpPrevented = evt.isDefaultPrevented();\n                });\n\n                // Workaround for browsers which do not support the `input` event\n                // This will prevent double-triggering of events for browsers which support\n                // both the `keyup` and `input` events.\n                this.$search.on('input', function (evt) {\n                    // Unbind the duplicated `keyup` event\n                    $(this).off('keyup');\n                });\n\n                this.$search.on('keyup input', function (evt) {\n                    self.handleSearch(evt);\n                });\n\n                container.on('open', function () {\n                    self.$search.attr('tabindex', 0);\n\n                    self.$search.focus();\n\n                    window.setTimeout(function () {\n                        self.$search.focus();\n                    }, 0);\n                });\n\n                container.on('close', function () {\n                    self.$search.attr('tabindex', -1);\n\n                    self.$search.val('');\n                    self.$search.blur();\n                });\n\n                container.on('focus', function () {\n                    if (!container.isOpen()) {\n                        self.$search.focus();\n                    }\n                });\n\n                container.on('results:all', function (params) {\n                    if (params.query.term == null || params.query.term === '') {\n                        var showSearch = self.showSearch(params);\n\n                        if (showSearch) {\n                            self.$searchContainer.removeClass('select2-search--hide');\n                        } else {\n                            self.$searchContainer.addClass('select2-search--hide');\n                        }\n                    }\n                });\n            };\n\n            Search.prototype.handleSearch = function (evt) {\n                if (!this._keyUpPrevented) {\n                    var input = this.$search.val();\n\n                    this.trigger('query', {\n                        term: input\n                    });\n                }\n\n                this._keyUpPrevented = false;\n            };\n\n            Search.prototype.showSearch = function (_, params) {\n                return true;\n            };\n\n            return Search;\n        });\n\n        S2.define('select2/dropdown/hidePlaceholder', [], function () {\n            function HidePlaceholder(decorated, $element, options, dataAdapter) {\n                this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n                decorated.call(this, $element, options, dataAdapter);\n            }\n\n            HidePlaceholder.prototype.append = function (decorated, data) {\n                data.results = this.removePlaceholder(data.results);\n\n                decorated.call(this, data);\n            };\n\n            HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {\n                if (typeof placeholder === 'string') {\n                    placeholder = {\n                        id: '',\n                        text: placeholder\n                    };\n                }\n\n                return placeholder;\n            };\n\n            HidePlaceholder.prototype.removePlaceholder = function (_, data) {\n                var modifiedData = data.slice(0);\n\n                for (var d = data.length - 1; d >= 0; d--) {\n                    var item = data[d];\n\n                    if (this.placeholder.id === item.id) {\n                        modifiedData.splice(d, 1);\n                    }\n                }\n\n                return modifiedData;\n            };\n\n            return HidePlaceholder;\n        });\n\n        S2.define('select2/dropdown/infiniteScroll', [\n            'jquery'\n        ], function ($) {\n            function InfiniteScroll(decorated, $element, options, dataAdapter) {\n                this.lastParams = {};\n\n                decorated.call(this, $element, options, dataAdapter);\n\n                this.$loadingMore = this.createLoadingMore();\n                this.loading = false;\n            }\n\n            InfiniteScroll.prototype.append = function (decorated, data) {\n                this.$loadingMore.remove();\n                this.loading = false;\n\n                decorated.call(this, data);\n\n                if (this.showLoadingMore(data)) {\n                    this.$results.append(this.$loadingMore);\n                }\n            };\n\n            InfiniteScroll.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('query', function (params) {\n                    self.lastParams = params;\n                    self.loading = true;\n                });\n\n                container.on('query:append', function (params) {\n                    self.lastParams = params;\n                    self.loading = true;\n                });\n\n                this.$results.on('scroll', function () {\n                    var isLoadMoreVisible = $.contains(\n                        document.documentElement,\n                        self.$loadingMore[0]\n                    );\n\n                    if (self.loading || !isLoadMoreVisible) {\n                        return;\n                    }\n\n                    var currentOffset = self.$results.offset().top +\n                        self.$results.outerHeight(false);\n                    var loadingMoreOffset = self.$loadingMore.offset().top +\n                        self.$loadingMore.outerHeight(false);\n\n                    if (currentOffset + 50 >= loadingMoreOffset) {\n                        self.loadMore();\n                    }\n                });\n            };\n\n            InfiniteScroll.prototype.loadMore = function () {\n                this.loading = true;\n\n                var params = $.extend({}, {page: 1}, this.lastParams);\n\n                params.page++;\n\n                this.trigger('query:append', params);\n            };\n\n            InfiniteScroll.prototype.showLoadingMore = function (_, data) {\n                return data.pagination && data.pagination.more;\n            };\n\n            InfiniteScroll.prototype.createLoadingMore = function () {\n                var $option = $(\n                    '<li ' +\n                    'class=\"select2-results__option select2-results__option--load-more\"' +\n                    'role=\"treeitem\" aria-disabled=\"true\"></li>'\n                );\n\n                var message = this.options.get('translations').get('loadingMore');\n\n                $option.html(message(this.lastParams));\n\n                return $option;\n            };\n\n            return InfiniteScroll;\n        });\n\n        S2.define('select2/dropdown/attachBody', [\n            'jquery',\n            '../utils'\n        ], function ($, Utils) {\n            function AttachBody(decorated, $element, options) {\n                this.$dropdownParent = options.get('dropdownParent') || $(document.body);\n\n                decorated.call(this, $element, options);\n            }\n\n            AttachBody.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                var setupResultsEvents = false;\n\n                decorated.call(this, container, $container);\n\n                container.on('open', function () {\n                    self._showDropdown();\n                    self._attachPositioningHandler(container);\n\n                    if (!setupResultsEvents) {\n                        setupResultsEvents = true;\n\n                        container.on('results:all', function () {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n\n                        container.on('results:append', function () {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n                    }\n                });\n\n                container.on('close', function () {\n                    self._hideDropdown();\n                    self._detachPositioningHandler(container);\n                });\n\n                this.$dropdownContainer.on('mousedown', function (evt) {\n                    evt.stopPropagation();\n                });\n            };\n\n            AttachBody.prototype.destroy = function (decorated) {\n                decorated.call(this);\n\n                this.$dropdownContainer.remove();\n            };\n\n            AttachBody.prototype.position = function (decorated, $dropdown, $container) {\n                // Clone all of the container classes\n                $dropdown.attr('class', $container.attr('class'));\n\n                $dropdown.removeClass('select2');\n                $dropdown.addClass('select2-container--open');\n\n                $dropdown.css({\n                    position: 'absolute',\n                    top: -999999\n                });\n\n                this.$container = $container;\n            };\n\n            AttachBody.prototype.render = function (decorated) {\n                var $container = $('<span></span>');\n\n                var $dropdown = decorated.call(this);\n                $container.append($dropdown);\n\n                this.$dropdownContainer = $container;\n\n                return $container;\n            };\n\n            AttachBody.prototype._hideDropdown = function (decorated) {\n                this.$dropdownContainer.detach();\n            };\n\n            AttachBody.prototype._attachPositioningHandler =\n                function (decorated, container) {\n                    var self = this;\n\n                    var scrollEvent = 'scroll.select2.' + container.id;\n                    var resizeEvent = 'resize.select2.' + container.id;\n                    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n                    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n                    $watchers.each(function () {\n                        Utils.StoreData(this, 'select2-scroll-position', {\n                            x: $(this).scrollLeft(),\n                            y: $(this).scrollTop()\n                        });\n                    });\n\n                    $watchers.on(scrollEvent, function (ev) {\n                        var position = Utils.GetData(this, 'select2-scroll-position');\n                        $(this).scrollTop(position.y);\n                    });\n\n                    $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,\n                        function (e) {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n                };\n\n            AttachBody.prototype._detachPositioningHandler =\n                function (decorated, container) {\n                    var scrollEvent = 'scroll.select2.' + container.id;\n                    var resizeEvent = 'resize.select2.' + container.id;\n                    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n                    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n                    $watchers.off(scrollEvent);\n\n                    $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);\n                };\n\n            AttachBody.prototype._positionDropdown = function () {\n                var $window = $(window);\n\n                var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');\n                var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');\n\n                var newDirection = null;\n\n                var offset = this.$container.offset();\n\n                offset.bottom = offset.top + this.$container.outerHeight(false);\n\n                var container = {\n                    height: this.$container.outerHeight(false)\n                };\n\n                container.top = offset.top;\n                container.bottom = offset.top + container.height;\n\n                var dropdown = {\n                    height: this.$dropdown.outerHeight(false)\n                };\n\n                var viewport = {\n                    top: $window.scrollTop(),\n                    bottom: $window.scrollTop() + $window.height()\n                };\n\n                var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);\n                var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);\n\n                var css = {\n                    left: offset.left,\n                    top: container.bottom\n                };\n\n                // Determine what the parent element is to use for calciulating the offset\n                var $offsetParent = this.$dropdownParent;\n\n                // For statically positoned elements, we need to get the element\n                // that is determining the offset\n                if ($offsetParent.css('position') === 'static') {\n                    $offsetParent = $offsetParent.offsetParent();\n                }\n\n                var parentOffset = $offsetParent.offset();\n\n                css.top -= parentOffset.top;\n                css.left -= parentOffset.left;\n\n                if (!isCurrentlyAbove && !isCurrentlyBelow) {\n                    newDirection = 'below';\n                }\n\n                if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {\n                    newDirection = 'above';\n                } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {\n                    newDirection = 'below';\n                }\n\n                if (newDirection == 'above' ||\n                    (isCurrentlyAbove && newDirection !== 'below')) {\n                    css.top = container.top - parentOffset.top - dropdown.height;\n                }\n\n                if (newDirection != null) {\n                    this.$dropdown\n                        .removeClass('select2-dropdown--below select2-dropdown--above')\n                        .addClass('select2-dropdown--' + newDirection);\n                    this.$container\n                        .removeClass('select2-container--below select2-container--above')\n                        .addClass('select2-container--' + newDirection);\n                }\n\n                this.$dropdownContainer.css(css);\n            };\n\n            AttachBody.prototype._resizeDropdown = function () {\n                var css = {\n                    width: this.$container.outerWidth(false) + 'px'\n                };\n\n                if (this.options.get('dropdownAutoWidth')) {\n                    css.minWidth = css.width;\n                    css.position = 'relative';\n                    css.width = 'auto';\n                }\n\n                this.$dropdown.css(css);\n            };\n\n            AttachBody.prototype._showDropdown = function (decorated) {\n                this.$dropdownContainer.appendTo(this.$dropdownParent);\n\n                this._positionDropdown();\n                this._resizeDropdown();\n            };\n\n            return AttachBody;\n        });\n\n        S2.define('select2/dropdown/minimumResultsForSearch', [], function () {\n            function countResults(data) {\n                var count = 0;\n\n                for (var d = 0; d < data.length; d++) {\n                    var item = data[d];\n\n                    if (item.children) {\n                        count += countResults(item.children);\n                    } else {\n                        count++;\n                    }\n                }\n\n                return count;\n            }\n\n            function MinimumResultsForSearch(decorated, $element, options, dataAdapter) {\n                this.minimumResultsForSearch = options.get('minimumResultsForSearch');\n\n                if (this.minimumResultsForSearch < 0) {\n                    this.minimumResultsForSearch = Infinity;\n                }\n\n                decorated.call(this, $element, options, dataAdapter);\n            }\n\n            MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {\n                if (countResults(params.data.results) < this.minimumResultsForSearch) {\n                    return false;\n                }\n\n                return decorated.call(this, params);\n            };\n\n            return MinimumResultsForSearch;\n        });\n\n        S2.define('select2/dropdown/selectOnClose', [\n            '../utils'\n        ], function (Utils) {\n            function SelectOnClose() {\n            }\n\n            SelectOnClose.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('close', function (params) {\n                    self._handleSelectOnClose(params);\n                });\n            };\n\n            SelectOnClose.prototype._handleSelectOnClose = function (_, params) {\n                if (params && params.originalSelect2Event != null) {\n                    var event = params.originalSelect2Event;\n\n                    // Don't select an item if the close event was triggered from a select or\n                    // unselect event\n                    if (event._type === 'select' || event._type === 'unselect') {\n                        return;\n                    }\n                }\n\n                var $highlightedResults = this.getHighlightedResults();\n\n                // Only select highlighted results\n                if ($highlightedResults.length < 1) {\n                    return;\n                }\n\n                var data = Utils.GetData($highlightedResults[0], 'data');\n\n                // Don't re-select already selected resulte\n                if (\n                    (data.element != null && data.element.selected) ||\n                    (data.element == null && data.selected)\n                ) {\n                    return;\n                }\n\n                this.trigger('select', {\n                    data: data\n                });\n            };\n\n            return SelectOnClose;\n        });\n\n        S2.define('select2/dropdown/closeOnSelect', [], function () {\n            function CloseOnSelect() {\n            }\n\n            CloseOnSelect.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('select', function (evt) {\n                    self._selectTriggered(evt);\n                });\n\n                container.on('unselect', function (evt) {\n                    self._selectTriggered(evt);\n                });\n            };\n\n            CloseOnSelect.prototype._selectTriggered = function (_, evt) {\n                var originalEvent = evt.originalEvent;\n\n                // Don't close if the control key is being held\n                if (originalEvent && originalEvent.ctrlKey) {\n                    return;\n                }\n\n                this.trigger('close', {\n                    originalEvent: originalEvent,\n                    originalSelect2Event: evt\n                });\n            };\n\n            return CloseOnSelect;\n        });\n\n        S2.define('select2/i18n/en', [], function () {\n            // English\n            return {\n                errorLoading: function () {\n                    return 'The results could not be loaded.';\n                },\n                inputTooLong: function (args) {\n                    var overChars = args.input.length - args.maximum;\n\n                    var message = 'Please delete ' + overChars + ' character';\n\n                    if (overChars != 1) {\n                        message += 's';\n                    }\n\n                    return message;\n                },\n                inputTooShort: function (args) {\n                    var remainingChars = args.minimum - args.input.length;\n\n                    var message = 'Please enter ' + remainingChars + ' or more characters';\n\n                    return message;\n                },\n                loadingMore: function () {\n                    return 'Loading more results…';\n                },\n                maximumSelected: function (args) {\n                    var message = 'You can only select ' + args.maximum + ' item';\n\n                    if (args.maximum != 1) {\n                        message += 's';\n                    }\n\n                    return message;\n                },\n                noResults: function () {\n                    return 'No results found';\n                },\n                searching: function () {\n                    return 'Searching…';\n                }\n            };\n        });\n\n        S2.define('select2/defaults', [\n            'jquery',\n            'require',\n\n            './results',\n\n            './selection/single',\n            './selection/multiple',\n            './selection/placeholder',\n            './selection/allowClear',\n            './selection/search',\n            './selection/eventRelay',\n\n            './utils',\n            './translation',\n            './diacritics',\n\n            './data/select',\n            './data/array',\n            './data/ajax',\n            './data/tags',\n            './data/tokenizer',\n            './data/minimumInputLength',\n            './data/maximumInputLength',\n            './data/maximumSelectionLength',\n\n            './dropdown',\n            './dropdown/search',\n            './dropdown/hidePlaceholder',\n            './dropdown/infiniteScroll',\n            './dropdown/attachBody',\n            './dropdown/minimumResultsForSearch',\n            './dropdown/selectOnClose',\n            './dropdown/closeOnSelect',\n\n            './i18n/en'\n        ], function ($, require,\n                     ResultsList,\n                     SingleSelection, MultipleSelection, Placeholder, AllowClear,\n                     SelectionSearch, EventRelay,\n                     Utils, Translation, DIACRITICS,\n                     SelectData, ArrayData, AjaxData, Tags, Tokenizer,\n                     MinimumInputLength, MaximumInputLength, MaximumSelectionLength,\n                     Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,\n                     AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,\n                     EnglishTranslation) {\n            function Defaults() {\n                this.reset();\n            }\n\n            Defaults.prototype.apply = function (options) {\n                options = $.extend(true, {}, this.defaults, options);\n\n                if (options.dataAdapter == null) {\n                    if (options.ajax != null) {\n                        options.dataAdapter = AjaxData;\n                    } else if (options.data != null) {\n                        options.dataAdapter = ArrayData;\n                    } else {\n                        options.dataAdapter = SelectData;\n                    }\n\n                    if (options.minimumInputLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MinimumInputLength\n                        );\n                    }\n\n                    if (options.maximumInputLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MaximumInputLength\n                        );\n                    }\n\n                    if (options.maximumSelectionLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MaximumSelectionLength\n                        );\n                    }\n\n                    if (options.tags) {\n                        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);\n                    }\n\n                    if (options.tokenSeparators != null || options.tokenizer != null) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            Tokenizer\n                        );\n                    }\n\n                    if (options.query != null) {\n                        var Query = require(options.amdBase + 'compat/query');\n\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            Query\n                        );\n                    }\n\n                    if (options.initSelection != null) {\n                        var InitSelection = require(options.amdBase + 'compat/initSelection');\n\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            InitSelection\n                        );\n                    }\n                }\n\n                if (options.resultsAdapter == null) {\n                    options.resultsAdapter = ResultsList;\n\n                    if (options.ajax != null) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            InfiniteScroll\n                        );\n                    }\n\n                    if (options.placeholder != null) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            HidePlaceholder\n                        );\n                    }\n\n                    if (options.selectOnClose) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            SelectOnClose\n                        );\n                    }\n                }\n\n                if (options.dropdownAdapter == null) {\n                    if (options.multiple) {\n                        options.dropdownAdapter = Dropdown;\n                    } else {\n                        var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);\n\n                        options.dropdownAdapter = SearchableDropdown;\n                    }\n\n                    if (options.minimumResultsForSearch !== 0) {\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            MinimumResultsForSearch\n                        );\n                    }\n\n                    if (options.closeOnSelect) {\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            CloseOnSelect\n                        );\n                    }\n\n                    if (\n                        options.dropdownCssClass != null ||\n                        options.dropdownCss != null ||\n                        options.adaptDropdownCssClass != null\n                    ) {\n                        var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');\n\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            DropdownCSS\n                        );\n                    }\n\n                    options.dropdownAdapter = Utils.Decorate(\n                        options.dropdownAdapter,\n                        AttachBody\n                    );\n                }\n\n                if (options.selectionAdapter == null) {\n                    if (options.multiple) {\n                        options.selectionAdapter = MultipleSelection;\n                    } else {\n                        options.selectionAdapter = SingleSelection;\n                    }\n\n                    // Add the placeholder mixin if a placeholder was specified\n                    if (options.placeholder != null) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            Placeholder\n                        );\n                    }\n\n                    if (options.allowClear) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            AllowClear\n                        );\n                    }\n\n                    if (options.multiple) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            SelectionSearch\n                        );\n                    }\n\n                    if (\n                        options.containerCssClass != null ||\n                        options.containerCss != null ||\n                        options.adaptContainerCssClass != null\n                    ) {\n                        var ContainerCSS = require(options.amdBase + 'compat/containerCss');\n\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            ContainerCSS\n                        );\n                    }\n\n                    options.selectionAdapter = Utils.Decorate(\n                        options.selectionAdapter,\n                        EventRelay\n                    );\n                }\n\n                if (typeof options.language === 'string') {\n                    // Check if the language is specified with a region\n                    if (options.language.indexOf('-') > 0) {\n                        // Extract the region information if it is included\n                        var languageParts = options.language.split('-');\n                        var baseLanguage = languageParts[0];\n\n                        options.language = [options.language, baseLanguage];\n                    } else {\n                        options.language = [options.language];\n                    }\n                }\n\n                if ($.isArray(options.language)) {\n                    var languages = new Translation();\n                    options.language.push('en');\n\n                    var languageNames = options.language;\n\n                    for (var l = 0; l < languageNames.length; l++) {\n                        var name = languageNames[l];\n                        var language = {};\n\n                        try {\n                            // Try to load it with the original name\n                            language = Translation.loadPath(name);\n                        } catch (e) {\n                            try {\n                                // If we couldn't load it, check if it wasn't the full path\n                                name = this.defaults.amdLanguageBase + name;\n                                language = Translation.loadPath(name);\n                            } catch (ex) {\n                                // The translation could not be loaded at all. Sometimes this is\n                                // because of a configuration problem, other times this can be\n                                // because of how Select2 helps load all possible translation files.\n                                if (options.debug && window.console && console.warn) {\n                                    console.warn(\n                                        'Select2: The language file for \"' + name + '\" could not be ' +\n                                        'automatically loaded. A fallback will be used instead.'\n                                    );\n                                }\n\n                                continue;\n                            }\n                        }\n\n                        languages.extend(language);\n                    }\n\n                    options.translations = languages;\n                } else {\n                    var baseTranslation = Translation.loadPath(\n                        this.defaults.amdLanguageBase + 'en'\n                    );\n                    var customTranslation = new Translation(options.language);\n\n                    customTranslation.extend(baseTranslation);\n\n                    options.translations = customTranslation;\n                }\n\n                return options;\n            };\n\n            Defaults.prototype.reset = function () {\n                function stripDiacritics(text) {\n                    // Used 'uni range + named function' from http://jsperf.com/diacritics/18\n                    function match(a) {\n                        return DIACRITICS[a] || a;\n                    }\n\n                    return text.replace(/[^\\u0000-\\u007E]/g, match);\n                }\n\n                function matcher(params, data) {\n                    // Always return the object if there is nothing to compare\n                    if ($.trim(params.term) === '') {\n                        return data;\n                    }\n\n                    // Do a recursive check for options with children\n                    if (data.children && data.children.length > 0) {\n                        // Clone the data object if there are children\n                        // This is required as we modify the object to remove any non-matches\n                        var match = $.extend(true, {}, data);\n\n                        // Check each child of the option\n                        for (var c = data.children.length - 1; c >= 0; c--) {\n                            var child = data.children[c];\n\n                            var matches = matcher(params, child);\n\n                            // If there wasn't a match, remove the object in the array\n                            if (matches == null) {\n                                match.children.splice(c, 1);\n                            }\n                        }\n\n                        // If any children matched, return the new object\n                        if (match.children.length > 0) {\n                            return match;\n                        }\n\n                        // If there were no matching children, check just the plain object\n                        return matcher(params, match);\n                    }\n\n                    var original = stripDiacritics(data.text).toUpperCase();\n                    var term = stripDiacritics(params.term).toUpperCase();\n\n                    // Check if the text contains the term\n                    if (original.indexOf(term) > -1) {\n                        return data;\n                    }\n\n                    // If it doesn't contain the term, don't return anything\n                    return null;\n                }\n\n                this.defaults = {\n                    amdBase: './',\n                    amdLanguageBase: './i18n/',\n                    closeOnSelect: true,\n                    debug: false,\n                    dropdownAutoWidth: false,\n                    escapeMarkup: Utils.escapeMarkup,\n                    language: EnglishTranslation,\n                    matcher: matcher,\n                    minimumInputLength: 0,\n                    maximumInputLength: 0,\n                    maximumSelectionLength: 0,\n                    minimumResultsForSearch: 0,\n                    selectOnClose: false,\n                    sorter: function (data) {\n                        return data;\n                    },\n                    templateResult: function (result) {\n                        return result.text;\n                    },\n                    templateSelection: function (selection) {\n                        return selection.text;\n                    },\n                    theme: 'default',\n                    width: 'resolve'\n                };\n            };\n\n            Defaults.prototype.set = function (key, value) {\n                var camelKey = $.camelCase(key);\n\n                var data = {};\n                data[camelKey] = value;\n\n                var convertedData = Utils._convertData(data);\n\n                $.extend(true, this.defaults, convertedData);\n            };\n\n            var defaults = new Defaults();\n\n            return defaults;\n        });\n\n        S2.define('select2/options', [\n            'require',\n            'jquery',\n            './defaults',\n            './utils'\n        ], function (require, $, Defaults, Utils) {\n            function Options(options, $element) {\n                this.options = options;\n\n                if ($element != null) {\n                    this.fromElement($element);\n                }\n\n                this.options = Defaults.apply(this.options);\n\n                if ($element && $element.is('input')) {\n                    var InputCompat = require(this.get('amdBase') + 'compat/inputData');\n\n                    this.options.dataAdapter = Utils.Decorate(\n                        this.options.dataAdapter,\n                        InputCompat\n                    );\n                }\n            }\n\n            Options.prototype.fromElement = function ($e) {\n                var excludedData = ['select2'];\n\n                if (this.options.multiple == null) {\n                    this.options.multiple = $e.prop('multiple');\n                }\n\n                if (this.options.disabled == null) {\n                    this.options.disabled = $e.prop('disabled');\n                }\n\n                if (this.options.language == null) {\n                    if ($e.prop('lang')) {\n                        this.options.language = $e.prop('lang').toLowerCase();\n                    } else if ($e.closest('[lang]').prop('lang')) {\n                        this.options.language = $e.closest('[lang]').prop('lang');\n                    }\n                }\n\n                if (this.options.dir == null) {\n                    if ($e.prop('dir')) {\n                        this.options.dir = $e.prop('dir');\n                    } else if ($e.closest('[dir]').prop('dir')) {\n                        this.options.dir = $e.closest('[dir]').prop('dir');\n                    } else {\n                        this.options.dir = 'ltr';\n                    }\n                }\n\n                $e.prop('disabled', this.options.disabled);\n                $e.prop('multiple', this.options.multiple);\n\n                if (Utils.GetData($e[0], 'select2Tags')) {\n                    if (this.options.debug && window.console && console.warn) {\n                        console.warn(\n                            'Select2: The `data-select2-tags` attribute has been changed to ' +\n                            'use the `data-data` and `data-tags=\"true\"` attributes and will be ' +\n                            'removed in future versions of Select2.'\n                        );\n                    }\n\n                    Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));\n                    Utils.StoreData($e[0], 'tags', true);\n                }\n\n                if (Utils.GetData($e[0], 'ajaxUrl')) {\n                    if (this.options.debug && window.console && console.warn) {\n                        console.warn(\n                            'Select2: The `data-ajax-url` attribute has been changed to ' +\n                            '`data-ajax--url` and support for the old attribute will be removed' +\n                            ' in future versions of Select2.'\n                        );\n                    }\n\n                    $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));\n                    Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));\n\n                }\n\n                var dataset = {};\n\n                // Prefer the element's `dataset` attribute if it exists\n                // jQuery 1.x does not correctly handle data attributes with multiple dashes\n                if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {\n                    dataset = $.extend(true, {}, $e[0].dataset, Utils.GetData($e[0]));\n                } else {\n                    dataset = Utils.GetData($e[0]);\n                }\n\n                var data = $.extend(true, {}, dataset);\n\n                data = Utils._convertData(data);\n\n                for (var key in data) {\n                    if ($.inArray(key, excludedData) > -1) {\n                        continue;\n                    }\n\n                    if ($.isPlainObject(this.options[key])) {\n                        $.extend(this.options[key], data[key]);\n                    } else {\n                        this.options[key] = data[key];\n                    }\n                }\n\n                return this;\n            };\n\n            Options.prototype.get = function (key) {\n                return this.options[key];\n            };\n\n            Options.prototype.set = function (key, val) {\n                this.options[key] = val;\n            };\n\n            return Options;\n        });\n\n        S2.define('select2/core', [\n            'jquery',\n            './options',\n            './utils',\n            './keys'\n        ], function ($, Options, Utils, KEYS) {\n            var Select2 = function ($element, options) {\n                if (Utils.GetData($element[0], 'select2') != null) {\n                    Utils.GetData($element[0], 'select2').destroy();\n                }\n\n                this.$element = $element;\n\n                this.id = this._generateId($element);\n\n                options = options || {};\n\n                this.options = new Options(options, $element);\n\n                Select2.__super__.constructor.call(this);\n\n                // Set up the tabindex\n\n                var tabindex = $element.attr('tabindex') || 0;\n                Utils.StoreData($element[0], 'old-tabindex', tabindex);\n                $element.attr('tabindex', '-1');\n\n                // Set up containers and adapters\n\n                var DataAdapter = this.options.get('dataAdapter');\n                this.dataAdapter = new DataAdapter($element, this.options);\n\n                var $container = this.render();\n\n                this._placeContainer($container);\n\n                var SelectionAdapter = this.options.get('selectionAdapter');\n                this.selection = new SelectionAdapter($element, this.options);\n                this.$selection = this.selection.render();\n\n                this.selection.position(this.$selection, $container);\n\n                var DropdownAdapter = this.options.get('dropdownAdapter');\n                this.dropdown = new DropdownAdapter($element, this.options);\n                this.$dropdown = this.dropdown.render();\n\n                this.dropdown.position(this.$dropdown, $container);\n\n                var ResultsAdapter = this.options.get('resultsAdapter');\n                this.results = new ResultsAdapter($element, this.options, this.dataAdapter);\n                this.$results = this.results.render();\n\n                this.results.position(this.$results, this.$dropdown);\n\n                // Bind events\n\n                var self = this;\n\n                // Bind the container to all of the adapters\n                this._bindAdapters();\n\n                // Register any DOM event handlers\n                this._registerDomEvents();\n\n                // Register any internal event handlers\n                this._registerDataEvents();\n                this._registerSelectionEvents();\n                this._registerDropdownEvents();\n                this._registerResultsEvents();\n                this._registerEvents();\n\n                // Set the initial state\n                this.dataAdapter.current(function (initialData) {\n                    self.trigger('selection:update', {\n                        data: initialData\n                    });\n                });\n\n                // Hide the original select\n                $element.addClass('select2-hidden-accessible');\n                $element.attr('aria-hidden', 'true');\n\n                // Synchronize any monitored attributes\n                this._syncAttributes();\n\n                Utils.StoreData($element[0], 'select2', this);\n\n                // Ensure backwards compatibility with $element.data('select2').\n                $element.data('select2', this);\n            };\n\n            Utils.Extend(Select2, Utils.Observable);\n\n            Select2.prototype._generateId = function ($element) {\n                var id = '';\n\n                if ($element.attr('id') != null) {\n                    id = $element.attr('id');\n                } else if ($element.attr('name') != null) {\n                    id = $element.attr('name') + '-' + Utils.generateChars(2);\n                } else {\n                    id = Utils.generateChars(4);\n                }\n\n                id = id.replace(/(:|\\.|\\[|\\]|,)/g, '');\n                id = 'select2-' + id;\n\n                return id;\n            };\n\n            Select2.prototype._placeContainer = function ($container) {\n                $container.insertAfter(this.$element);\n\n                var width = this._resolveWidth(this.$element, this.options.get('width'));\n\n                if (width != null) {\n                    $container.css('width', width);\n                }\n            };\n\n            Select2.prototype._resolveWidth = function ($element, method) {\n                var WIDTH = /^width:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;\n\n                if (method == 'resolve') {\n                    var styleWidth = this._resolveWidth($element, 'style');\n\n                    if (styleWidth != null) {\n                        return styleWidth;\n                    }\n\n                    return this._resolveWidth($element, 'element');\n                }\n\n                if (method == 'element') {\n                    var elementWidth = $element.outerWidth(false);\n\n                    if (elementWidth <= 0) {\n                        return 'auto';\n                    }\n\n                    return elementWidth + 'px';\n                }\n\n                if (method == 'style') {\n                    var style = $element.attr('style');\n\n                    if (typeof(style) !== 'string') {\n                        return null;\n                    }\n\n                    var attrs = style.split(';');\n\n                    for (var i = 0, l = attrs.length; i < l; i = i + 1) {\n                        var attr = attrs[i].replace(/\\s/g, '');\n                        var matches = attr.match(WIDTH);\n\n                        if (matches !== null && matches.length >= 1) {\n                            return matches[1];\n                        }\n                    }\n\n                    return null;\n                }\n\n                return method;\n            };\n\n            Select2.prototype._bindAdapters = function () {\n                this.dataAdapter.bind(this, this.$container);\n                this.selection.bind(this, this.$container);\n\n                this.dropdown.bind(this, this.$container);\n                this.results.bind(this, this.$container);\n            };\n\n            Select2.prototype._registerDomEvents = function () {\n                var self = this;\n\n                this.$element.on('change.select2', function () {\n                    self.dataAdapter.current(function (data) {\n                        self.trigger('selection:update', {\n                            data: data\n                        });\n                    });\n                });\n\n                this.$element.on('focus.select2', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this._syncA = Utils.bind(this._syncAttributes, this);\n                this._syncS = Utils.bind(this._syncSubtree, this);\n\n                if (this.$element[0].attachEvent) {\n                    this.$element[0].attachEvent('onpropertychange', this._syncA);\n                }\n\n                var observer = window.MutationObserver ||\n                    window.WebKitMutationObserver ||\n                    window.MozMutationObserver\n                ;\n\n                if (observer != null) {\n                    this._observer = new observer(function (mutations) {\n                        $.each(mutations, self._syncA);\n                        $.each(mutations, self._syncS);\n                    });\n                    this._observer.observe(this.$element[0], {\n                        attributes: true,\n                        childList: true,\n                        subtree: false\n                    });\n                } else if (this.$element[0].addEventListener) {\n                    this.$element[0].addEventListener(\n                        'DOMAttrModified',\n                        self._syncA,\n                        false\n                    );\n                    this.$element[0].addEventListener(\n                        'DOMNodeInserted',\n                        self._syncS,\n                        false\n                    );\n                    this.$element[0].addEventListener(\n                        'DOMNodeRemoved',\n                        self._syncS,\n                        false\n                    );\n                }\n            };\n\n            Select2.prototype._registerDataEvents = function () {\n                var self = this;\n\n                this.dataAdapter.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerSelectionEvents = function () {\n                var self = this;\n                var nonRelayEvents = ['toggle', 'focus'];\n\n                this.selection.on('toggle', function () {\n                    self.toggleDropdown();\n                });\n\n                this.selection.on('focus', function (params) {\n                    self.focus(params);\n                });\n\n                this.selection.on('*', function (name, params) {\n                    if ($.inArray(name, nonRelayEvents) !== -1) {\n                        return;\n                    }\n\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerDropdownEvents = function () {\n                var self = this;\n\n                this.dropdown.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerResultsEvents = function () {\n                var self = this;\n\n                this.results.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerEvents = function () {\n                var self = this;\n\n                this.on('open', function () {\n                    self.$container.addClass('select2-container--open');\n                });\n\n                this.on('close', function () {\n                    self.$container.removeClass('select2-container--open');\n                });\n\n                this.on('enable', function () {\n                    self.$container.removeClass('select2-container--disabled');\n                });\n\n                this.on('disable', function () {\n                    self.$container.addClass('select2-container--disabled');\n                });\n\n                this.on('blur', function () {\n                    self.$container.removeClass('select2-container--focus');\n                });\n\n                this.on('query', function (params) {\n                    if (!self.isOpen()) {\n                        self.trigger('open', {});\n                    }\n\n                    this.dataAdapter.query(params, function (data) {\n                        self.trigger('results:all', {\n                            data: data,\n                            query: params\n                        });\n                    });\n                });\n\n                this.on('query:append', function (params) {\n                    this.dataAdapter.query(params, function (data) {\n                        self.trigger('results:append', {\n                            data: data,\n                            query: params\n                        });\n                    });\n                });\n\n                this.on('keypress', function (evt) {\n                    var key = evt.which;\n\n                    if (self.isOpen()) {\n                        if (key === KEYS.ESC || key === KEYS.TAB ||\n                            (key === KEYS.UP && evt.altKey)) {\n                            self.close();\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.ENTER) {\n                            self.trigger('results:select', {});\n\n                            evt.preventDefault();\n                        } else if ((key === KEYS.SPACE && evt.ctrlKey)) {\n                            self.trigger('results:toggle', {});\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.UP) {\n                            self.trigger('results:previous', {});\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.DOWN) {\n                            self.trigger('results:next', {});\n\n                            evt.preventDefault();\n                        }\n                    } else {\n                        if (key === KEYS.ENTER || key === KEYS.SPACE ||\n                            (key === KEYS.DOWN && evt.altKey)) {\n                            self.open();\n\n                            evt.preventDefault();\n                        }\n                    }\n                });\n            };\n\n            Select2.prototype._syncAttributes = function () {\n                this.options.set('disabled', this.$element.prop('disabled'));\n\n                if (this.options.get('disabled')) {\n                    if (this.isOpen()) {\n                        this.close();\n                    }\n\n                    this.trigger('disable', {});\n                } else {\n                    this.trigger('enable', {});\n                }\n            };\n\n            Select2.prototype._syncSubtree = function (evt, mutations) {\n                var changed = false;\n                var self = this;\n\n                // Ignore any mutation events raised for elements that aren't options or\n                // optgroups. This handles the case when the select element is destroyed\n                if (\n                    evt && evt.target && (\n                        evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'\n                    )\n                ) {\n                    return;\n                }\n\n                if (!mutations) {\n                    // If mutation events aren't supported, then we can only assume that the\n                    // change affected the selections\n                    changed = true;\n                } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {\n                    for (var n = 0; n < mutations.addedNodes.length; n++) {\n                        var node = mutations.addedNodes[n];\n\n                        if (node.selected) {\n                            changed = true;\n                        }\n                    }\n                } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {\n                    changed = true;\n                }\n\n                // Only re-pull the data if we think there is a change\n                if (changed) {\n                    this.dataAdapter.current(function (currentData) {\n                        self.trigger('selection:update', {\n                            data: currentData\n                        });\n                    });\n                }\n            };\n\n            /**\n             * Override the trigger method to automatically trigger pre-events when\n             * there are events that can be prevented.\n             */\n            Select2.prototype.trigger = function (name, args) {\n                var actualTrigger = Select2.__super__.trigger;\n                var preTriggerMap = {\n                    'open': 'opening',\n                    'close': 'closing',\n                    'select': 'selecting',\n                    'unselect': 'unselecting',\n                    'clear': 'clearing'\n                };\n\n                if (args === undefined) {\n                    args = {};\n                }\n\n                if (name in preTriggerMap) {\n                    var preTriggerName = preTriggerMap[name];\n                    var preTriggerArgs = {\n                        prevented: false,\n                        name: name,\n                        args: args\n                    };\n\n                    actualTrigger.call(this, preTriggerName, preTriggerArgs);\n\n                    if (preTriggerArgs.prevented) {\n                        args.prevented = true;\n\n                        return;\n                    }\n                }\n\n                actualTrigger.call(this, name, args);\n            };\n\n            Select2.prototype.toggleDropdown = function () {\n                if (this.options.get('disabled')) {\n                    return;\n                }\n\n                if (this.isOpen()) {\n                    this.close();\n                } else {\n                    this.open();\n                }\n            };\n\n            Select2.prototype.open = function () {\n                if (this.isOpen()) {\n                    return;\n                }\n\n                this.trigger('query', {});\n            };\n\n            Select2.prototype.close = function () {\n                if (!this.isOpen()) {\n                    return;\n                }\n\n                this.trigger('close', {});\n            };\n\n            Select2.prototype.isOpen = function () {\n                return this.$container.hasClass('select2-container--open');\n            };\n\n            Select2.prototype.hasFocus = function () {\n                return this.$container.hasClass('select2-container--focus');\n            };\n\n            Select2.prototype.focus = function (data) {\n                // No need to re-trigger focus events if we are already focused\n                if (this.hasFocus()) {\n                    return;\n                }\n\n                this.$container.addClass('select2-container--focus');\n                this.trigger('focus', {});\n            };\n\n            Select2.prototype.enable = function (args) {\n                if (this.options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `select2(\"enable\")` method has been deprecated and will' +\n                        ' be removed in later Select2 versions. Use $element.prop(\"disabled\")' +\n                        ' instead.'\n                    );\n                }\n\n                if (args == null || args.length === 0) {\n                    args = [true];\n                }\n\n                var disabled = !args[0];\n\n                this.$element.prop('disabled', disabled);\n            };\n\n            Select2.prototype.data = function () {\n                if (this.options.get('debug') &&\n                    arguments.length > 0 && window.console && console.warn) {\n                    console.warn(\n                        'Select2: Data can no longer be set using `select2(\"data\")`. You ' +\n                        'should consider setting the value instead using `$element.val()`.'\n                    );\n                }\n\n                var data = [];\n\n                this.dataAdapter.current(function (currentData) {\n                    data = currentData;\n                });\n\n                return data;\n            };\n\n            Select2.prototype.val = function (args) {\n                if (this.options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `select2(\"val\")` method has been deprecated and will be' +\n                        ' removed in later Select2 versions. Use $element.val() instead.'\n                    );\n                }\n\n                if (args == null || args.length === 0) {\n                    return this.$element.val();\n                }\n\n                var newVal = args[0];\n\n                if ($.isArray(newVal)) {\n                    newVal = $.map(newVal, function (obj) {\n                        return obj.toString();\n                    });\n                }\n\n                this.$element.val(newVal).trigger('change');\n            };\n\n            Select2.prototype.destroy = function () {\n                this.$container.remove();\n\n                if (this.$element[0].detachEvent) {\n                    this.$element[0].detachEvent('onpropertychange', this._syncA);\n                }\n\n                if (this._observer != null) {\n                    this._observer.disconnect();\n                    this._observer = null;\n                } else if (this.$element[0].removeEventListener) {\n                    this.$element[0]\n                        .removeEventListener('DOMAttrModified', this._syncA, false);\n                    this.$element[0]\n                        .removeEventListener('DOMNodeInserted', this._syncS, false);\n                    this.$element[0]\n                        .removeEventListener('DOMNodeRemoved', this._syncS, false);\n                }\n\n                this._syncA = null;\n                this._syncS = null;\n\n                this.$element.off('.select2');\n                this.$element.attr('tabindex',\n                    Utils.GetData(this.$element[0], 'old-tabindex'));\n\n                this.$element.removeClass('select2-hidden-accessible');\n                this.$element.attr('aria-hidden', 'false');\n                Utils.RemoveData(this.$element[0]);\n                this.$element.removeData('select2');\n\n                this.dataAdapter.destroy();\n                this.selection.destroy();\n                this.dropdown.destroy();\n                this.results.destroy();\n\n                this.dataAdapter = null;\n                this.selection = null;\n                this.dropdown = null;\n                this.results = null;\n            };\n\n            Select2.prototype.render = function () {\n                var $container = $(\n                    '<span class=\"select2 select2-container\">' +\n                    '<span class=\"selection\"></span>' +\n                    '<span class=\"dropdown-wrapper\" aria-hidden=\"true\"></span>' +\n                    '</span>'\n                );\n\n                $container.attr('dir', this.options.get('dir'));\n\n                this.$container = $container;\n\n                this.$container.addClass('select2-container--' + this.options.get('theme'));\n\n                Utils.StoreData($container[0], 'element', this.$element);\n\n                return $container;\n            };\n\n            return Select2;\n        });\n\n        S2.define('select2/compat/utils', [\n            'jquery'\n        ], function ($) {\n            function syncCssClasses($dest, $src, adapter) {\n                var classes, replacements = [], adapted;\n\n                classes = $.trim($dest.attr('class'));\n\n                if (classes) {\n                    classes = '' + classes; // for IE which returns object\n\n                    $(classes.split(/\\s+/)).each(function () {\n                        // Save all Select2 classes\n                        if (this.indexOf('select2-') === 0) {\n                            replacements.push(this);\n                        }\n                    });\n                }\n\n                classes = $.trim($src.attr('class'));\n\n                if (classes) {\n                    classes = '' + classes; // for IE which returns object\n\n                    $(classes.split(/\\s+/)).each(function () {\n                        // Only adapt non-Select2 classes\n                        if (this.indexOf('select2-') !== 0) {\n                            adapted = adapter(this);\n\n                            if (adapted != null) {\n                                replacements.push(adapted);\n                            }\n                        }\n                    });\n                }\n\n                $dest.attr('class', replacements.join(' '));\n            }\n\n            return {\n                syncCssClasses: syncCssClasses\n            };\n        });\n\n        S2.define('select2/compat/containerCss', [\n            'jquery',\n            './utils'\n        ], function ($, CompatUtils) {\n            // No-op CSS adapter that discards all classes by default\n            function _containerAdapter(clazz) {\n                return null;\n            }\n\n            function ContainerCSS() {\n            }\n\n            ContainerCSS.prototype.render = function (decorated) {\n                var $container = decorated.call(this);\n\n                var containerCssClass = this.options.get('containerCssClass') || '';\n\n                if ($.isFunction(containerCssClass)) {\n                    containerCssClass = containerCssClass(this.$element);\n                }\n\n                var containerCssAdapter = this.options.get('adaptContainerCssClass');\n                containerCssAdapter = containerCssAdapter || _containerAdapter;\n\n                if (containerCssClass.indexOf(':all:') !== -1) {\n                    containerCssClass = containerCssClass.replace(':all:', '');\n\n                    var _cssAdapter = containerCssAdapter;\n\n                    containerCssAdapter = function (clazz) {\n                        var adapted = _cssAdapter(clazz);\n\n                        if (adapted != null) {\n                            // Append the old one along with the adapted one\n                            return adapted + ' ' + clazz;\n                        }\n\n                        return clazz;\n                    };\n                }\n\n                var containerCss = this.options.get('containerCss') || {};\n\n                if ($.isFunction(containerCss)) {\n                    containerCss = containerCss(this.$element);\n                }\n\n                CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter);\n\n                $container.css(containerCss);\n                $container.addClass(containerCssClass);\n\n                return $container;\n            };\n\n            return ContainerCSS;\n        });\n\n        S2.define('select2/compat/dropdownCss', [\n            'jquery',\n            './utils'\n        ], function ($, CompatUtils) {\n            // No-op CSS adapter that discards all classes by default\n            function _dropdownAdapter(clazz) {\n                return null;\n            }\n\n            function DropdownCSS() {\n            }\n\n            DropdownCSS.prototype.render = function (decorated) {\n                var $dropdown = decorated.call(this);\n\n                var dropdownCssClass = this.options.get('dropdownCssClass') || '';\n\n                if ($.isFunction(dropdownCssClass)) {\n                    dropdownCssClass = dropdownCssClass(this.$element);\n                }\n\n                var dropdownCssAdapter = this.options.get('adaptDropdownCssClass');\n                dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;\n\n                if (dropdownCssClass.indexOf(':all:') !== -1) {\n                    dropdownCssClass = dropdownCssClass.replace(':all:', '');\n\n                    var _cssAdapter = dropdownCssAdapter;\n\n                    dropdownCssAdapter = function (clazz) {\n                        var adapted = _cssAdapter(clazz);\n\n                        if (adapted != null) {\n                            // Append the old one along with the adapted one\n                            return adapted + ' ' + clazz;\n                        }\n\n                        return clazz;\n                    };\n                }\n\n                var dropdownCss = this.options.get('dropdownCss') || {};\n\n                if ($.isFunction(dropdownCss)) {\n                    dropdownCss = dropdownCss(this.$element);\n                }\n\n                CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter);\n\n                $dropdown.css(dropdownCss);\n                $dropdown.addClass(dropdownCssClass);\n\n                return $dropdown;\n            };\n\n            return DropdownCSS;\n        });\n\n        S2.define('select2/compat/initSelection', [\n            'jquery'\n        ], function ($) {\n            function InitSelection(decorated, $element, options) {\n                if (options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `initSelection` option has been deprecated in favor' +\n                        ' of a custom data adapter that overrides the `current` method. ' +\n                        'This method is now called multiple times instead of a single ' +\n                        'time when the instance is initialized. Support will be removed ' +\n                        'for the `initSelection` option in future versions of Select2'\n                    );\n                }\n\n                this.initSelection = options.get('initSelection');\n                this._isInitialized = false;\n\n                decorated.call(this, $element, options);\n            }\n\n            InitSelection.prototype.current = function (decorated, callback) {\n                var self = this;\n\n                if (this._isInitialized) {\n                    decorated.call(this, callback);\n\n                    return;\n                }\n\n                this.initSelection.call(null, this.$element, function (data) {\n                    self._isInitialized = true;\n\n                    if (!$.isArray(data)) {\n                        data = [data];\n                    }\n\n                    callback(data);\n                });\n            };\n\n            return InitSelection;\n        });\n\n        S2.define('select2/compat/inputData', [\n            'jquery',\n            '../utils'\n        ], function ($, Utils) {\n            function InputData(decorated, $element, options) {\n                this._currentData = [];\n                this._valueSeparator = options.get('valueSeparator') || ',';\n\n                if ($element.prop('type') === 'hidden') {\n                    if (options.get('debug') && console && console.warn) {\n                        console.warn(\n                            'Select2: Using a hidden input with Select2 is no longer ' +\n                            'supported and may stop working in the future. It is recommended ' +\n                            'to use a `<select>` element instead.'\n                        );\n                    }\n                }\n\n                decorated.call(this, $element, options);\n            }\n\n            InputData.prototype.current = function (_, callback) {\n                function getSelected(data, selectedIds) {\n                    var selected = [];\n\n                    if (data.selected || $.inArray(data.id, selectedIds) !== -1) {\n                        data.selected = true;\n                        selected.push(data);\n                    } else {\n                        data.selected = false;\n                    }\n\n                    if (data.children) {\n                        selected.push.apply(selected, getSelected(data.children, selectedIds));\n                    }\n\n                    return selected;\n                }\n\n                var selected = [];\n\n                for (var d = 0; d < this._currentData.length; d++) {\n                    var data = this._currentData[d];\n\n                    selected.push.apply(\n                        selected,\n                        getSelected(\n                            data,\n                            this.$element.val().split(\n                                this._valueSeparator\n                            )\n                        )\n                    );\n                }\n\n                callback(selected);\n            };\n\n            InputData.prototype.select = function (_, data) {\n                if (!this.options.get('multiple')) {\n                    this.current(function (allData) {\n                        $.map(allData, function (data) {\n                            data.selected = false;\n                        });\n                    });\n\n                    this.$element.val(data.id);\n                    this.$element.trigger('change');\n                } else {\n                    var value = this.$element.val();\n                    value += this._valueSeparator + data.id;\n\n                    this.$element.val(value);\n                    this.$element.trigger('change');\n                }\n            };\n\n            InputData.prototype.unselect = function (_, data) {\n                var self = this;\n\n                data.selected = false;\n\n                this.current(function (allData) {\n                    var values = [];\n\n                    for (var d = 0; d < allData.length; d++) {\n                        var item = allData[d];\n\n                        if (data.id == item.id) {\n                            continue;\n                        }\n\n                        values.push(item.id);\n                    }\n\n                    self.$element.val(values.join(self._valueSeparator));\n                    self.$element.trigger('change');\n                });\n            };\n\n            InputData.prototype.query = function (_, params, callback) {\n                var results = [];\n\n                for (var d = 0; d < this._currentData.length; d++) {\n                    var data = this._currentData[d];\n\n                    var matches = this.matches(params, data);\n\n                    if (matches !== null) {\n                        results.push(matches);\n                    }\n                }\n\n                callback({\n                    results: results\n                });\n            };\n\n            InputData.prototype.addOptions = function (_, $options) {\n                var options = $.map($options, function ($option) {\n                    return Utils.GetData($option[0], 'data');\n                });\n\n                this._currentData.push.apply(this._currentData, options);\n            };\n\n            return InputData;\n        });\n\n        S2.define('select2/compat/matcher', [\n            'jquery'\n        ], function ($) {\n            function oldMatcher(matcher) {\n                function wrappedMatcher(params, data) {\n                    var match = $.extend(true, {}, data);\n\n                    if (params.term == null || $.trim(params.term) === '') {\n                        return match;\n                    }\n\n                    if (data.children) {\n                        for (var c = data.children.length - 1; c >= 0; c--) {\n                            var child = data.children[c];\n\n                            // Check if the child object matches\n                            // The old matcher returned a boolean true or false\n                            var doesMatch = matcher(params.term, child.text, child);\n\n                            // If the child didn't match, pop it off\n                            if (!doesMatch) {\n                                match.children.splice(c, 1);\n                            }\n                        }\n\n                        if (match.children.length > 0) {\n                            return match;\n                        }\n                    }\n\n                    if (matcher(params.term, data.text, data)) {\n                        return match;\n                    }\n\n                    return null;\n                }\n\n                return wrappedMatcher;\n            }\n\n            return oldMatcher;\n        });\n\n        S2.define('select2/compat/query', [], function () {\n            function Query(decorated, $element, options) {\n                if (options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `query` option has been deprecated in favor of a ' +\n                        'custom data adapter that overrides the `query` method. Support ' +\n                        'will be removed for the `query` option in future versions of ' +\n                        'Select2.'\n                    );\n                }\n\n                decorated.call(this, $element, options);\n            }\n\n            Query.prototype.query = function (_, params, callback) {\n                params.callback = callback;\n\n                var query = this.options.get('query');\n\n                query.call(null, params);\n            };\n\n            return Query;\n        });\n\n        S2.define('select2/dropdown/attachContainer', [], function () {\n            function AttachContainer(decorated, $element, options) {\n                decorated.call(this, $element, options);\n            }\n\n            AttachContainer.prototype.position =\n                function (decorated, $dropdown, $container) {\n                    var $dropdownContainer = $container.find('.dropdown-wrapper');\n                    $dropdownContainer.append($dropdown);\n\n                    $dropdown.addClass('select2-dropdown--below');\n                    $container.addClass('select2-container--below');\n                };\n\n            return AttachContainer;\n        });\n\n        S2.define('select2/dropdown/stopPropagation', [], function () {\n            function StopPropagation() {\n            }\n\n            StopPropagation.prototype.bind = function (decorated, container, $container) {\n                decorated.call(this, container, $container);\n\n                var stoppedEvents = [\n                    'blur',\n                    'change',\n                    'click',\n                    'dblclick',\n                    'focus',\n                    'focusin',\n                    'focusout',\n                    'input',\n                    'keydown',\n                    'keyup',\n                    'keypress',\n                    'mousedown',\n                    'mouseenter',\n                    'mouseleave',\n                    'mousemove',\n                    'mouseover',\n                    'mouseup',\n                    'search',\n                    'touchend',\n                    'touchstart'\n                ];\n\n                this.$dropdown.on(stoppedEvents.join(' '), function (evt) {\n                    evt.stopPropagation();\n                });\n            };\n\n            return StopPropagation;\n        });\n\n        S2.define('select2/selection/stopPropagation', [], function () {\n            function StopPropagation() {\n            }\n\n            StopPropagation.prototype.bind = function (decorated, container, $container) {\n                decorated.call(this, container, $container);\n\n                var stoppedEvents = [\n                    'blur',\n                    'change',\n                    'click',\n                    'dblclick',\n                    'focus',\n                    'focusin',\n                    'focusout',\n                    'input',\n                    'keydown',\n                    'keyup',\n                    'keypress',\n                    'mousedown',\n                    'mouseenter',\n                    'mouseleave',\n                    'mousemove',\n                    'mouseover',\n                    'mouseup',\n                    'search',\n                    'touchend',\n                    'touchstart'\n                ];\n\n                this.$selection.on(stoppedEvents.join(' '), function (evt) {\n                    evt.stopPropagation();\n                });\n            };\n\n            return StopPropagation;\n        });\n\n        /*!\n * jQuery Mousewheel 3.1.13\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n */\n\n        (function (factory) {\n            if (typeof S2.define === 'function' && S2.define.amd) {\n                // AMD. Register as an anonymous module.\n                S2.define('jquery-mousewheel', ['jquery'], factory);\n            } else if (typeof exports === 'object') {\n                // Node/CommonJS style for Browserify\n                module.exports = factory;\n            } else {\n                // Browser globals\n                factory(jQuery);\n            }\n        }(function ($) {\n\n            var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],\n                toBind = ('onwheel' in document || document.documentMode >= 9) ?\n                    ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],\n                slice = Array.prototype.slice,\n                nullLowestDeltaTimeout, lowestDelta;\n\n            if ($.event.fixHooks) {\n                for (var i = toFix.length; i;) {\n                    $.event.fixHooks[toFix[--i]] = $.event.mouseHooks;\n                }\n            }\n\n            var special = $.event.special.mousewheel = {\n                version: '3.1.12',\n\n                setup: function () {\n                    if (this.addEventListener) {\n                        for (var i = toBind.length; i;) {\n                            this.addEventListener(toBind[--i], handler, false);\n                        }\n                    } else {\n                        this.onmousewheel = handler;\n                    }\n                    // Store the line height and page height for this particular element\n                    $.data(this, 'mousewheel-line-height', special.getLineHeight(this));\n                    $.data(this, 'mousewheel-page-height', special.getPageHeight(this));\n                },\n\n                teardown: function () {\n                    if (this.removeEventListener) {\n                        for (var i = toBind.length; i;) {\n                            this.removeEventListener(toBind[--i], handler, false);\n                        }\n                    } else {\n                        this.onmousewheel = null;\n                    }\n                    // Clean up the data we added to the element\n                    $.removeData(this, 'mousewheel-line-height');\n                    $.removeData(this, 'mousewheel-page-height');\n                },\n\n                getLineHeight: function (elem) {\n                    var $elem = $(elem),\n                        $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();\n                    if (!$parent.length) {\n                        $parent = $('body');\n                    }\n                    return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;\n                },\n\n                getPageHeight: function (elem) {\n                    return $(elem).height();\n                },\n\n                settings: {\n                    adjustOldDeltas: true, // see shouldAdjustOldDeltas() below\n                    normalizeOffset: true  // calls getBoundingClientRect for each event\n                }\n            };\n\n            $.fn.extend({\n                mousewheel: function (fn) {\n                    return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');\n                },\n\n                unmousewheel: function (fn) {\n                    return this.unbind('mousewheel', fn);\n                }\n            });\n\n\n            function handler(event) {\n                var orgEvent = event || window.event,\n                    args = slice.call(arguments, 1),\n                    delta = 0,\n                    deltaX = 0,\n                    deltaY = 0,\n                    absDelta = 0,\n                    offsetX = 0,\n                    offsetY = 0;\n                event = $.event.fix(orgEvent);\n                event.type = 'mousewheel';\n\n                // Old school scrollwheel delta\n                if ('detail' in orgEvent) {\n                    deltaY = orgEvent.detail * -1;\n                }\n                if ('wheelDelta' in orgEvent) {\n                    deltaY = orgEvent.wheelDelta;\n                }\n                if ('wheelDeltaY' in orgEvent) {\n                    deltaY = orgEvent.wheelDeltaY;\n                }\n                if ('wheelDeltaX' in orgEvent) {\n                    deltaX = orgEvent.wheelDeltaX * -1;\n                }\n\n                // Firefox < 17 horizontal scrolling related to DOMMouseScroll event\n                if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {\n                    deltaX = deltaY * -1;\n                    deltaY = 0;\n                }\n\n                // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy\n                delta = deltaY === 0 ? deltaX : deltaY;\n\n                // New school wheel delta (wheel event)\n                if ('deltaY' in orgEvent) {\n                    deltaY = orgEvent.deltaY * -1;\n                    delta = deltaY;\n                }\n                if ('deltaX' in orgEvent) {\n                    deltaX = orgEvent.deltaX;\n                    if (deltaY === 0) {\n                        delta = deltaX * -1;\n                    }\n                }\n\n                // No change actually happened, no reason to go any further\n                if (deltaY === 0 && deltaX === 0) {\n                    return;\n                }\n\n                // Need to convert lines and pages to pixels if we aren't already in pixels\n                // There are three delta modes:\n                //   * deltaMode 0 is by pixels, nothing to do\n                //   * deltaMode 1 is by lines\n                //   * deltaMode 2 is by pages\n                if (orgEvent.deltaMode === 1) {\n                    var lineHeight = $.data(this, 'mousewheel-line-height');\n                    delta *= lineHeight;\n                    deltaY *= lineHeight;\n                    deltaX *= lineHeight;\n                } else if (orgEvent.deltaMode === 2) {\n                    var pageHeight = $.data(this, 'mousewheel-page-height');\n                    delta *= pageHeight;\n                    deltaY *= pageHeight;\n                    deltaX *= pageHeight;\n                }\n\n                // Store lowest absolute delta to normalize the delta values\n                absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n\n                if (!lowestDelta || absDelta < lowestDelta) {\n                    lowestDelta = absDelta;\n\n                    // Adjust older deltas if necessary\n                    if (shouldAdjustOldDeltas(orgEvent, absDelta)) {\n                        lowestDelta /= 40;\n                    }\n                }\n\n                // Adjust older deltas if necessary\n                if (shouldAdjustOldDeltas(orgEvent, absDelta)) {\n                    // Divide all the things by 40!\n                    delta /= 40;\n                    deltaX /= 40;\n                    deltaY /= 40;\n                }\n\n                // Get a whole, normalized value for the deltas\n                delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);\n                deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);\n                deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);\n\n                // Normalise offsetX and offsetY properties\n                if (special.settings.normalizeOffset && this.getBoundingClientRect) {\n                    var boundingRect = this.getBoundingClientRect();\n                    offsetX = event.clientX - boundingRect.left;\n                    offsetY = event.clientY - boundingRect.top;\n                }\n\n                // Add information to the event object\n                event.deltaX = deltaX;\n                event.deltaY = deltaY;\n                event.deltaFactor = lowestDelta;\n                event.offsetX = offsetX;\n                event.offsetY = offsetY;\n                // Go ahead and set deltaMode to 0 since we converted to pixels\n                // Although this is a little odd since we overwrite the deltaX/Y\n                // properties with normalized deltas.\n                event.deltaMode = 0;\n\n                // Add event and delta to the front of the arguments\n                args.unshift(event, delta, deltaX, deltaY);\n\n                // Clearout lowestDelta after sometime to better\n                // handle multiple device types that give different\n                // a different lowestDelta\n                // Ex: trackpad = 3 and mouse wheel = 120\n                if (nullLowestDeltaTimeout) {\n                    clearTimeout(nullLowestDeltaTimeout);\n                }\n                nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);\n\n                return ($.event.dispatch || $.event.handle).apply(this, args);\n            }\n\n            function nullLowestDelta() {\n                lowestDelta = null;\n            }\n\n            function shouldAdjustOldDeltas(orgEvent, absDelta) {\n                // If this is an older event and the delta is divisable by 120,\n                // then we are assuming that the browser is treating this as an\n                // older mouse wheel event and that we should divide the deltas\n                // by 40 to try and get a more usable deltaFactor.\n                // Side note, this actually impacts the reported scroll distance\n                // in older browsers and can cause scrolling to be slower than native.\n                // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.\n                return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;\n            }\n\n        }));\n\n        S2.define('jquery.select2', [\n            'jquery',\n            'jquery-mousewheel',\n\n            './select2/core',\n            './select2/defaults',\n            './select2/utils'\n        ], function ($, _, Select2, Defaults, Utils) {\n            if ($.fn.select2 == null) {\n                // All methods that should return the element\n                var thisMethods = ['open', 'close', 'destroy'];\n\n                $.fn.select2 = function (options) {\n                    options = options || {};\n\n                    if (typeof options === 'object') {\n                        this.each(function () {\n                            var instanceOptions = $.extend(true, {}, options);\n\n                            var instance = new Select2($(this), instanceOptions);\n                        });\n\n                        return this;\n                    } else if (typeof options === 'string') {\n                        var ret;\n                        var args = Array.prototype.slice.call(arguments, 1);\n\n                        this.each(function () {\n                            var instance = Utils.GetData(this, 'select2');\n\n                            if (instance == null && window.console && console.error) {\n                                console.error(\n                                    'The select2(\\'' + options + '\\') method was called on an ' +\n                                    'element that is not using Select2.'\n                                );\n                            }\n\n                            ret = instance[options].apply(instance, args);\n                        });\n\n                        // Check if we should be returning `this`\n                        if ($.inArray(options, thisMethods) > -1) {\n                            return this;\n                        }\n\n                        return ret;\n                    } else {\n                        throw new Error('Invalid arguments for Select2: ' + options);\n                    }\n                };\n            }\n\n            if ($.fn.select2.defaults == null) {\n                $.fn.select2.defaults = Defaults;\n            }\n\n            return Select2;\n        });\n\n        // Return the AMD loader configuration so it can be used outside of this file\n        return {\n            define: S2.define,\n            require: S2.require\n        };\n    }());\n\n    // Autoload the jQuery bindings\n    // We know that all of the modules exist above this, so we're safe\n    var select2 = S2.require('jquery.select2');\n\n    // Hold the AMD module references on the jQuery function that was just loaded\n    // This allows Select2 to use the internal loader outside of this file, such\n    // as in the language files.\n    jQuery.fn.select2.amd = S2;\n\n    // Return the Select2 instance for anyone who is importing it.\n    return select2;\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/select2/js/select2.js",
    "content": "/*!\n * Select2 4.0.6-rc.1\n * https://select2.github.io\n *\n * Released under the MIT license\n * https://github.com/select2/select2/blob/master/LICENSE.md\n */\n;(function (factory) {\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 = function (root, jQuery) {\n            if (jQuery === undefined) {\n                // require('jQuery') returns a factory that requires window to\n                // build a jQuery instance, we normalize how we use modules\n                // that require this pattern but the window provided is a noop\n                // if it's defined (how jquery works)\n                if (typeof window !== 'undefined') {\n                    jQuery = require('jquery');\n                }\n                else {\n                    jQuery = require('jquery')(root);\n                }\n            }\n            factory(jQuery);\n            return jQuery;\n        };\n    } else {\n        // Browser globals\n        factory(jQuery);\n    }\n}(function (jQuery) {\n    // This is needed so we can catch the AMD loader configuration and use it\n    // The inner file should be wrapped (by `banner.start.js`) in a function that\n    // returns the AMD loader references.\n    var S2 = (function () {\n        // Restore the Select2 AMD loader so it can be used\n        // Needed mostly in the language files, where the loader is not inserted\n        if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {\n            var S2 = jQuery.fn.select2.amd;\n        }\n        var S2;\n        (function () {\n            if (!S2 || !S2.requirejs) {\n                if (!S2) {\n                    S2 = {};\n                } else {\n                    require = S2;\n                }\n                /**\n                 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n                 * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n                 */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n                /*global setTimeout: false */\n\n                var requirejs, require, define;\n                (function (undef) {\n                    var main, req, makeMap, handlers,\n                        defined = {},\n                        waiting = {},\n                        config = {},\n                        defining = {},\n                        hasOwn = Object.prototype.hasOwnProperty,\n                        aps = [].slice,\n                        jsSuffixRegExp = /\\.js$/;\n\n                    function hasProp(obj, prop) {\n                        return hasOwn.call(obj, prop);\n                    }\n\n                    /**\n                     * Given a relative module name, like ./something, normalize it to\n                     * a real name that can be mapped to a path.\n                     * @param {String} name the relative name\n                     * @param {String} baseName a real name that the name arg is relative\n                     * to.\n                     * @returns {String} normalized name\n                     */\n                    function normalize(name, baseName) {\n                        var nameParts, nameSegment, mapValue, foundMap, lastIndex,\n                            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n                            baseParts = baseName && baseName.split(\"/\"),\n                            map = config.map,\n                            starMap = (map && map['*']) || {};\n\n                        //Adjust any relative paths.\n                        if (name) {\n                            name = name.split('/');\n                            lastIndex = name.length - 1;\n\n                            // If wanting node ID compatibility, strip .js from end\n                            // of IDs. Have to do this here, and not in nameToUrl\n                            // because node allows either .js or non .js to map\n                            // to same file.\n                            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n                                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n                            }\n\n                            // Starts with a '.' so need the baseName\n                            if (name[0].charAt(0) === '.' && baseParts) {\n                                //Convert baseName to array, and lop off the last part,\n                                //so that . matches that 'directory' and not name of the baseName's\n                                //module. For instance, baseName of 'one/two/three', maps to\n                                //'one/two/three.js', but we want the directory, 'one/two' for\n                                //this normalization.\n                                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n                                name = normalizedBaseParts.concat(name);\n                            }\n\n                            //start trimDots\n                            for (i = 0; i < name.length; i++) {\n                                part = name[i];\n                                if (part === '.') {\n                                    name.splice(i, 1);\n                                    i -= 1;\n                                } else if (part === '..') {\n                                    // If at the start, or previous value is still ..,\n                                    // keep them so that when converted to a path it may\n                                    // still work when converted to a path, even though\n                                    // as an ID it is less than ideal. In larger point\n                                    // releases, may be better to just kick out an error.\n                                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n                                        continue;\n                                    } else if (i > 0) {\n                                        name.splice(i - 1, 2);\n                                        i -= 2;\n                                    }\n                                }\n                            }\n                            //end trimDots\n\n                            name = name.join('/');\n                        }\n\n                        //Apply map config if available.\n                        if ((baseParts || starMap) && map) {\n                            nameParts = name.split('/');\n\n                            for (i = nameParts.length; i > 0; i -= 1) {\n                                nameSegment = nameParts.slice(0, i).join(\"/\");\n\n                                if (baseParts) {\n                                    //Find the longest baseName segment match in the config.\n                                    //So, do joins on the biggest to smallest lengths of baseParts.\n                                    for (j = baseParts.length; j > 0; j -= 1) {\n                                        mapValue = map[baseParts.slice(0, j).join('/')];\n\n                                        //baseName segment has  config, find if it has one for\n                                        //this name.\n                                        if (mapValue) {\n                                            mapValue = mapValue[nameSegment];\n                                            if (mapValue) {\n                                                //Match, update name to the new value.\n                                                foundMap = mapValue;\n                                                foundI = i;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n\n                                if (foundMap) {\n                                    break;\n                                }\n\n                                //Check for a star map match, but just hold on to it,\n                                //if there is a shorter segment match later in a matching\n                                //config, then favor over this star map.\n                                if (!foundStarMap && starMap && starMap[nameSegment]) {\n                                    foundStarMap = starMap[nameSegment];\n                                    starI = i;\n                                }\n                            }\n\n                            if (!foundMap && foundStarMap) {\n                                foundMap = foundStarMap;\n                                foundI = starI;\n                            }\n\n                            if (foundMap) {\n                                nameParts.splice(0, foundI, foundMap);\n                                name = nameParts.join('/');\n                            }\n                        }\n\n                        return name;\n                    }\n\n                    function makeRequire(relName, forceSync) {\n                        return function () {\n                            //A version of a require function that passes a moduleName\n                            //value for items that may need to\n                            //look up paths relative to the moduleName\n                            var args = aps.call(arguments, 0);\n\n                            //If first arg is not require('string'), and there is only\n                            //one arg, it is the array form without a callback. Insert\n                            //a null so that the following concat is correct.\n                            if (typeof args[0] !== 'string' && args.length === 1) {\n                                args.push(null);\n                            }\n                            return req.apply(undef, args.concat([relName, forceSync]));\n                        };\n                    }\n\n                    function makeNormalize(relName) {\n                        return function (name) {\n                            return normalize(name, relName);\n                        };\n                    }\n\n                    function makeLoad(depName) {\n                        return function (value) {\n                            defined[depName] = value;\n                        };\n                    }\n\n                    function callDep(name) {\n                        if (hasProp(waiting, name)) {\n                            var args = waiting[name];\n                            delete waiting[name];\n                            defining[name] = true;\n                            main.apply(undef, args);\n                        }\n\n                        if (!hasProp(defined, name) && !hasProp(defining, name)) {\n                            throw new Error('No ' + name);\n                        }\n                        return defined[name];\n                    }\n\n                    //Turns a plugin!resource to [plugin, resource]\n                    //with the plugin being undefined if the name\n                    //did not have a plugin prefix.\n                    function splitPrefix(name) {\n                        var prefix,\n                            index = name ? name.indexOf('!') : -1;\n                        if (index > -1) {\n                            prefix = name.substring(0, index);\n                            name = name.substring(index + 1, name.length);\n                        }\n                        return [prefix, name];\n                    }\n\n                    //Creates a parts array for a relName where first part is plugin ID,\n                    //second part is resource ID. Assumes relName has already been normalized.\n                    function makeRelParts(relName) {\n                        return relName ? splitPrefix(relName) : [];\n                    }\n\n                    /**\n                     * Makes a name map, normalizing the name, and using a plugin\n                     * for normalization if necessary. Grabs a ref to plugin\n                     * too, as an optimization.\n                     */\n                    makeMap = function (name, relParts) {\n                        var plugin,\n                            parts = splitPrefix(name),\n                            prefix = parts[0],\n                            relResourceName = relParts[1];\n\n                        name = parts[1];\n\n                        if (prefix) {\n                            prefix = normalize(prefix, relResourceName);\n                            plugin = callDep(prefix);\n                        }\n\n                        //Normalize according\n                        if (prefix) {\n                            if (plugin && plugin.normalize) {\n                                name = plugin.normalize(name, makeNormalize(relResourceName));\n                            } else {\n                                name = normalize(name, relResourceName);\n                            }\n                        } else {\n                            name = normalize(name, relResourceName);\n                            parts = splitPrefix(name);\n                            prefix = parts[0];\n                            name = parts[1];\n                            if (prefix) {\n                                plugin = callDep(prefix);\n                            }\n                        }\n\n                        //Using ridiculous property names for space reasons\n                        return {\n                            f: prefix ? prefix + '!' + name : name, //fullName\n                            n: name,\n                            pr: prefix,\n                            p: plugin\n                        };\n                    };\n\n                    function makeConfig(name) {\n                        return function () {\n                            return (config && config.config && config.config[name]) || {};\n                        };\n                    }\n\n                    handlers = {\n                        require: function (name) {\n                            return makeRequire(name);\n                        },\n                        exports: function (name) {\n                            var e = defined[name];\n                            if (typeof e !== 'undefined') {\n                                return e;\n                            } else {\n                                return (defined[name] = {});\n                            }\n                        },\n                        module: function (name) {\n                            return {\n                                id: name,\n                                uri: '',\n                                exports: defined[name],\n                                config: makeConfig(name)\n                            };\n                        }\n                    };\n\n                    main = function (name, deps, callback, relName) {\n                        var cjsModule, depName, ret, map, i, relParts,\n                            args = [],\n                            callbackType = typeof callback,\n                            usingExports;\n\n                        //Use name if no relName\n                        relName = relName || name;\n                        relParts = makeRelParts(relName);\n\n                        //Call the callback to define the module, if necessary.\n                        if (callbackType === 'undefined' || callbackType === 'function') {\n                            //Pull out the defined dependencies and pass the ordered\n                            //values to the callback.\n                            //Default to [require, exports, module] if no deps\n                            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n                            for (i = 0; i < deps.length; i += 1) {\n                                map = makeMap(deps[i], relParts);\n                                depName = map.f;\n\n                                //Fast path CommonJS standard dependencies.\n                                if (depName === \"require\") {\n                                    args[i] = handlers.require(name);\n                                } else if (depName === \"exports\") {\n                                    //CommonJS module spec 1.1\n                                    args[i] = handlers.exports(name);\n                                    usingExports = true;\n                                } else if (depName === \"module\") {\n                                    //CommonJS module spec 1.1\n                                    cjsModule = args[i] = handlers.module(name);\n                                } else if (hasProp(defined, depName) ||\n                                    hasProp(waiting, depName) ||\n                                    hasProp(defining, depName)) {\n                                    args[i] = callDep(depName);\n                                } else if (map.p) {\n                                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n                                    args[i] = defined[depName];\n                                } else {\n                                    throw new Error(name + ' missing ' + depName);\n                                }\n                            }\n\n                            ret = callback ? callback.apply(defined[name], args) : undefined;\n\n                            if (name) {\n                                //If setting exports via \"module\" is in play,\n                                //favor that over return value and exports. After that,\n                                //favor a non-undefined return value over exports use.\n                                if (cjsModule && cjsModule.exports !== undef &&\n                                    cjsModule.exports !== defined[name]) {\n                                    defined[name] = cjsModule.exports;\n                                } else if (ret !== undef || !usingExports) {\n                                    //Use the return value from the function.\n                                    defined[name] = ret;\n                                }\n                            }\n                        } else if (name) {\n                            //May just be an object definition for the module. Only\n                            //worry about defining if have a module name.\n                            defined[name] = callback;\n                        }\n                    };\n\n                    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n                        if (typeof deps === \"string\") {\n                            if (handlers[deps]) {\n                                //callback in this case is really relName\n                                return handlers[deps](callback);\n                            }\n                            //Just return the module wanted. In this scenario, the\n                            //deps arg is the module name, and second arg (if passed)\n                            //is just the relName.\n                            //Normalize module name, if it contains . or ..\n                            return callDep(makeMap(deps, makeRelParts(callback)).f);\n                        } else if (!deps.splice) {\n                            //deps is a config object, not an array.\n                            config = deps;\n                            if (config.deps) {\n                                req(config.deps, config.callback);\n                            }\n                            if (!callback) {\n                                return;\n                            }\n\n                            if (callback.splice) {\n                                //callback is an array, which means it is a dependency list.\n                                //Adjust args if there are dependencies\n                                deps = callback;\n                                callback = relName;\n                                relName = null;\n                            } else {\n                                deps = undef;\n                            }\n                        }\n\n                        //Support require(['a'])\n                        callback = callback || function () {\n                        };\n\n                        //If relName is a function, it is an errback handler,\n                        //so remove it.\n                        if (typeof relName === 'function') {\n                            relName = forceSync;\n                            forceSync = alt;\n                        }\n\n                        //Simulate async callback;\n                        if (forceSync) {\n                            main(undef, deps, callback, relName);\n                        } else {\n                            //Using a non-zero value because of concern for what old browsers\n                            //do, and latest browsers \"upgrade\" to 4 if lower value is used:\n                            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n                            //If want a value immediately, use require('id') instead -- something\n                            //that works in almond on the global level, but not guaranteed and\n                            //unlikely to work in other AMD implementations.\n                            setTimeout(function () {\n                                main(undef, deps, callback, relName);\n                            }, 4);\n                        }\n\n                        return req;\n                    };\n\n                    /**\n                     * Just drops the config on the floor, but returns req in case\n                     * the config return value is used.\n                     */\n                    req.config = function (cfg) {\n                        return req(cfg);\n                    };\n\n                    /**\n                     * Expose module registry for debugging and tooling\n                     */\n                    requirejs._defined = defined;\n\n                    define = function (name, deps, callback) {\n                        if (typeof name !== 'string') {\n                            throw new Error('See almond README: incorrect module build, no module name');\n                        }\n\n                        //This module may not have dependencies\n                        if (!deps.splice) {\n                            //deps is not an array, so probably means\n                            //an object literal or factory function for\n                            //the value. Adjust args.\n                            callback = deps;\n                            deps = [];\n                        }\n\n                        if (!hasProp(defined, name) && !hasProp(waiting, name)) {\n                            waiting[name] = [name, deps, callback];\n                        }\n                    };\n\n                    define.amd = {\n                        jQuery: true\n                    };\n                }());\n\n                S2.requirejs = requirejs;\n                S2.require = require;\n                S2.define = define;\n            }\n        }());\n        S2.define(\"almond\", function () {\n        });\n\n        /* global jQuery:false, $:false */\n        S2.define('jquery', [], function () {\n            var _$ = jQuery || $;\n\n            if (_$ == null && console && console.error) {\n                console.error(\n                    'Select2: An instance of jQuery or a jQuery-compatible library was not ' +\n                    'found. Make sure that you are including jQuery before Select2 on your ' +\n                    'web page.'\n                );\n            }\n\n            return _$;\n        });\n\n        S2.define('select2/utils', [\n            'jquery'\n        ], function ($) {\n            var Utils = {};\n\n            Utils.Extend = function (ChildClass, SuperClass) {\n                var __hasProp = {}.hasOwnProperty;\n\n                function BaseConstructor() {\n                    this.constructor = ChildClass;\n                }\n\n                for (var key in SuperClass) {\n                    if (__hasProp.call(SuperClass, key)) {\n                        ChildClass[key] = SuperClass[key];\n                    }\n                }\n\n                BaseConstructor.prototype = SuperClass.prototype;\n                ChildClass.prototype = new BaseConstructor();\n                ChildClass.__super__ = SuperClass.prototype;\n\n                return ChildClass;\n            };\n\n            function getMethods(theClass) {\n                var proto = theClass.prototype;\n\n                var methods = [];\n\n                for (var methodName in proto) {\n                    var m = proto[methodName];\n\n                    if (typeof m !== 'function') {\n                        continue;\n                    }\n\n                    if (methodName === 'constructor') {\n                        continue;\n                    }\n\n                    methods.push(methodName);\n                }\n\n                return methods;\n            }\n\n            Utils.Decorate = function (SuperClass, DecoratorClass) {\n                var decoratedMethods = getMethods(DecoratorClass);\n                var superMethods = getMethods(SuperClass);\n\n                function DecoratedClass() {\n                    var unshift = Array.prototype.unshift;\n\n                    var argCount = DecoratorClass.prototype.constructor.length;\n\n                    var calledConstructor = SuperClass.prototype.constructor;\n\n                    if (argCount > 0) {\n                        unshift.call(arguments, SuperClass.prototype.constructor);\n\n                        calledConstructor = DecoratorClass.prototype.constructor;\n                    }\n\n                    calledConstructor.apply(this, arguments);\n                }\n\n                DecoratorClass.displayName = SuperClass.displayName;\n\n                function ctr() {\n                    this.constructor = DecoratedClass;\n                }\n\n                DecoratedClass.prototype = new ctr();\n\n                for (var m = 0; m < superMethods.length; m++) {\n                    var superMethod = superMethods[m];\n\n                    DecoratedClass.prototype[superMethod] =\n                        SuperClass.prototype[superMethod];\n                }\n\n                var calledMethod = function (methodName) {\n                    // Stub out the original method if it's not decorating an actual method\n                    var originalMethod = function () {\n                    };\n\n                    if (methodName in DecoratedClass.prototype) {\n                        originalMethod = DecoratedClass.prototype[methodName];\n                    }\n\n                    var decoratedMethod = DecoratorClass.prototype[methodName];\n\n                    return function () {\n                        var unshift = Array.prototype.unshift;\n\n                        unshift.call(arguments, originalMethod);\n\n                        return decoratedMethod.apply(this, arguments);\n                    };\n                };\n\n                for (var d = 0; d < decoratedMethods.length; d++) {\n                    var decoratedMethod = decoratedMethods[d];\n\n                    DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);\n                }\n\n                return DecoratedClass;\n            };\n\n            var Observable = function () {\n                this.listeners = {};\n            };\n\n            Observable.prototype.on = function (event, callback) {\n                this.listeners = this.listeners || {};\n\n                if (event in this.listeners) {\n                    this.listeners[event].push(callback);\n                } else {\n                    this.listeners[event] = [callback];\n                }\n            };\n\n            Observable.prototype.trigger = function (event) {\n                var slice = Array.prototype.slice;\n                var params = slice.call(arguments, 1);\n\n                this.listeners = this.listeners || {};\n\n                // Params should always come in as an array\n                if (params == null) {\n                    params = [];\n                }\n\n                // If there are no arguments to the event, use a temporary object\n                if (params.length === 0) {\n                    params.push({});\n                }\n\n                // Set the `_type` of the first object to the event\n                params[0]._type = event;\n\n                if (event in this.listeners) {\n                    this.invoke(this.listeners[event], slice.call(arguments, 1));\n                }\n\n                if ('*' in this.listeners) {\n                    this.invoke(this.listeners['*'], arguments);\n                }\n            };\n\n            Observable.prototype.invoke = function (listeners, params) {\n                for (var i = 0, len = listeners.length; i < len; i++) {\n                    listeners[i].apply(this, params);\n                }\n            };\n\n            Utils.Observable = Observable;\n\n            Utils.generateChars = function (length) {\n                var chars = '';\n\n                for (var i = 0; i < length; i++) {\n                    var randomChar = Math.floor(Math.random() * 36);\n                    chars += randomChar.toString(36);\n                }\n\n                return chars;\n            };\n\n            Utils.bind = function (func, context) {\n                return function () {\n                    func.apply(context, arguments);\n                };\n            };\n\n            Utils._convertData = function (data) {\n                for (var originalKey in data) {\n                    var keys = originalKey.split('-');\n\n                    var dataLevel = data;\n\n                    if (keys.length === 1) {\n                        continue;\n                    }\n\n                    for (var k = 0; k < keys.length; k++) {\n                        var key = keys[k];\n\n                        // Lowercase the first letter\n                        // By default, dash-separated becomes camelCase\n                        key = key.substring(0, 1).toLowerCase() + key.substring(1);\n\n                        if (!(key in dataLevel)) {\n                            dataLevel[key] = {};\n                        }\n\n                        if (k == keys.length - 1) {\n                            dataLevel[key] = data[originalKey];\n                        }\n\n                        dataLevel = dataLevel[key];\n                    }\n\n                    delete data[originalKey];\n                }\n\n                return data;\n            };\n\n            Utils.hasScroll = function (index, el) {\n                // Adapted from the function created by @ShadowScripter\n                // and adapted by @BillBarry on the Stack Exchange Code Review website.\n                // The original code can be found at\n                // http://codereview.stackexchange.com/q/13338\n                // and was designed to be used with the Sizzle selector engine.\n\n                var $el = $(el);\n                var overflowX = el.style.overflowX;\n                var overflowY = el.style.overflowY;\n\n                //Check both x and y declarations\n                if (overflowX === overflowY &&\n                    (overflowY === 'hidden' || overflowY === 'visible')) {\n                    return false;\n                }\n\n                if (overflowX === 'scroll' || overflowY === 'scroll') {\n                    return true;\n                }\n\n                return ($el.innerHeight() < el.scrollHeight ||\n                    $el.innerWidth() < el.scrollWidth);\n            };\n\n            Utils.escapeMarkup = function (markup) {\n                var replaceMap = {\n                    '\\\\': '&#92;',\n                    '&': '&amp;',\n                    '<': '&lt;',\n                    '>': '&gt;',\n                    '\"': '&quot;',\n                    '\\'': '&#39;',\n                    '/': '&#47;'\n                };\n\n                // Do not try to escape the markup if it's not a string\n                if (typeof markup !== 'string') {\n                    return markup;\n                }\n\n                return String(markup).replace(/[&<>\"'\\/\\\\]/g, function (match) {\n                    return replaceMap[match];\n                });\n            };\n\n            // Append an array of jQuery nodes to a given element.\n            Utils.appendMany = function ($element, $nodes) {\n                // jQuery 1.7.x does not support $.fn.append() with an array\n                // Fall back to a jQuery object collection using $.fn.add()\n                if ($.fn.jquery.substr(0, 3) === '1.7') {\n                    var $jqNodes = $();\n\n                    $.map($nodes, function (node) {\n                        $jqNodes = $jqNodes.add(node);\n                    });\n\n                    $nodes = $jqNodes;\n                }\n\n                $element.append($nodes);\n            };\n\n            // Cache objects in Utils.__cache instead of $.data (see #4346)\n            Utils.__cache = {};\n\n            var id = 0;\n            Utils.GetUniqueElementId = function (element) {\n                // Get a unique element Id. If element has no id,\n                // creates a new unique number, stores it in the id\n                // attribute and returns the new id.\n                // If an id already exists, it simply returns it.\n\n                var select2Id = element.getAttribute('data-select2-id');\n                if (select2Id == null) {\n                    // If element has id, use it.\n                    if (element.id) {\n                        select2Id = element.id;\n                        element.setAttribute('data-select2-id', select2Id);\n                    } else {\n                        element.setAttribute('data-select2-id', ++id);\n                        select2Id = id.toString();\n                    }\n                }\n                return select2Id;\n            };\n\n            Utils.StoreData = function (element, name, value) {\n                // Stores an item in the cache for a specified element.\n                // name is the cache key.\n                var id = Utils.GetUniqueElementId(element);\n                if (!Utils.__cache[id]) {\n                    Utils.__cache[id] = {};\n                }\n\n                Utils.__cache[id][name] = value;\n            };\n\n            Utils.GetData = function (element, name) {\n                // Retrieves a value from the cache by its key (name)\n                // name is optional. If no name specified, return\n                // all cache items for the specified element.\n                // and for a specified element.\n                var id = Utils.GetUniqueElementId(element);\n                if (name) {\n                    if (Utils.__cache[id]) {\n                        return Utils.__cache[id][name] != null ?\n                            Utils.__cache[id][name] :\n                            $(element).data(name); // Fallback to HTML5 data attribs.\n                    }\n                    return $(element).data(name); // Fallback to HTML5 data attribs.\n                } else {\n                    return Utils.__cache[id];\n                }\n            };\n\n            Utils.RemoveData = function (element) {\n                // Removes all cached items for a specified element.\n                var id = Utils.GetUniqueElementId(element);\n                if (Utils.__cache[id] != null) {\n                    delete Utils.__cache[id];\n                }\n            };\n\n            return Utils;\n        });\n\n        S2.define('select2/results', [\n            'jquery',\n            './utils'\n        ], function ($, Utils) {\n            function Results($element, options, dataAdapter) {\n                this.$element = $element;\n                this.data = dataAdapter;\n                this.options = options;\n\n                Results.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(Results, Utils.Observable);\n\n            Results.prototype.render = function () {\n                var $results = $(\n                    '<ul class=\"select2-results__options\" role=\"tree\"></ul>'\n                );\n\n                if (this.options.get('multiple')) {\n                    $results.attr('aria-multiselectable', 'true');\n                }\n\n                this.$results = $results;\n\n                return $results;\n            };\n\n            Results.prototype.clear = function () {\n                this.$results.empty();\n            };\n\n            Results.prototype.displayMessage = function (params) {\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                this.clear();\n                this.hideLoading();\n\n                var $message = $(\n                    '<li role=\"treeitem\" aria-live=\"assertive\"' +\n                    ' class=\"select2-results__option\"></li>'\n                );\n\n                var message = this.options.get('translations').get(params.message);\n\n                $message.append(\n                    escapeMarkup(\n                        message(params.args)\n                    )\n                );\n\n                $message[0].className += ' select2-results__message';\n\n                this.$results.append($message);\n            };\n\n            Results.prototype.hideMessages = function () {\n                this.$results.find('.select2-results__message').remove();\n            };\n\n            Results.prototype.append = function (data) {\n                this.hideLoading();\n\n                var $options = [];\n\n                if (data.results == null || data.results.length === 0) {\n                    if (this.$results.children().length === 0) {\n                        this.trigger('results:message', {\n                            message: 'noResults'\n                        });\n                    }\n\n                    return;\n                }\n\n                data.results = this.sort(data.results);\n\n                for (var d = 0; d < data.results.length; d++) {\n                    var item = data.results[d];\n\n                    var $option = this.option(item);\n\n                    $options.push($option);\n                }\n\n                this.$results.append($options);\n            };\n\n            Results.prototype.position = function ($results, $dropdown) {\n                var $resultsContainer = $dropdown.find('.select2-results');\n                $resultsContainer.append($results);\n            };\n\n            Results.prototype.sort = function (data) {\n                var sorter = this.options.get('sorter');\n\n                return sorter(data);\n            };\n\n            Results.prototype.highlightFirstItem = function () {\n                var $options = this.$results\n                    .find('.select2-results__option[aria-selected]');\n\n                var $selected = $options.filter('[aria-selected=true]');\n\n                // Check if there are any selected options\n                if ($selected.length > 0) {\n                    // If there are selected options, highlight the first\n                    $selected.first().trigger('mouseenter');\n                } else {\n                    // If there are no selected options, highlight the first option\n                    // in the dropdown\n                    $options.first().trigger('mouseenter');\n                }\n\n                this.ensureHighlightVisible();\n            };\n\n            Results.prototype.setClasses = function () {\n                var self = this;\n\n                this.data.current(function (selected) {\n                    var selectedIds = $.map(selected, function (s) {\n                        return s.id.toString();\n                    });\n\n                    var $options = self.$results\n                        .find('.select2-results__option[aria-selected]');\n\n                    $options.each(function () {\n                        var $option = $(this);\n\n                        var item = Utils.GetData(this, 'data');\n\n                        // id needs to be converted to a string when comparing\n                        var id = '' + item.id;\n\n                        if ((item.element != null && item.element.selected) ||\n                            (item.element == null && $.inArray(id, selectedIds) > -1)) {\n                            $option.attr('aria-selected', 'true');\n                        } else {\n                            $option.attr('aria-selected', 'false');\n                        }\n                    });\n\n                });\n            };\n\n            Results.prototype.showLoading = function (params) {\n                this.hideLoading();\n\n                var loadingMore = this.options.get('translations').get('searching');\n\n                var loading = {\n                    disabled: true,\n                    loading: true,\n                    text: loadingMore(params)\n                };\n                var $loading = this.option(loading);\n                $loading.className += ' loading-results';\n\n                this.$results.prepend($loading);\n            };\n\n            Results.prototype.hideLoading = function () {\n                this.$results.find('.loading-results').remove();\n            };\n\n            Results.prototype.option = function (data) {\n                var option = document.createElement('li');\n                option.className = 'select2-results__option';\n\n                var attrs = {\n                    'role': 'treeitem',\n                    'aria-selected': 'false'\n                };\n\n                if (data.disabled) {\n                    delete attrs['aria-selected'];\n                    attrs['aria-disabled'] = 'true';\n                }\n\n                if (data.id == null) {\n                    delete attrs['aria-selected'];\n                }\n\n                if (data._resultId != null) {\n                    option.id = data._resultId;\n                }\n\n                if (data.title) {\n                    option.title = data.title;\n                }\n\n                if (data.children) {\n                    attrs.role = 'group';\n                    attrs['aria-label'] = data.text;\n                    delete attrs['aria-selected'];\n                }\n\n                for (var attr in attrs) {\n                    var val = attrs[attr];\n\n                    option.setAttribute(attr, val);\n                }\n\n                if (data.children) {\n                    var $option = $(option);\n\n                    var label = document.createElement('strong');\n                    label.className = 'select2-results__group';\n\n                    var $label = $(label);\n                    this.template(data, label);\n\n                    var $children = [];\n\n                    for (var c = 0; c < data.children.length; c++) {\n                        var child = data.children[c];\n\n                        var $child = this.option(child);\n\n                        $children.push($child);\n                    }\n\n                    var $childrenContainer = $('<ul></ul>', {\n                        'class': 'select2-results__options select2-results__options--nested'\n                    });\n\n                    $childrenContainer.append($children);\n\n                    $option.append(label);\n                    $option.append($childrenContainer);\n                } else {\n                    this.template(data, option);\n                }\n\n                Utils.StoreData(option, 'data', data);\n\n                return option;\n            };\n\n            Results.prototype.bind = function (container, $container) {\n                var self = this;\n\n                var id = container.id + '-results';\n\n                this.$results.attr('id', id);\n\n                container.on('results:all', function (params) {\n                    self.clear();\n                    self.append(params.data);\n\n                    if (container.isOpen()) {\n                        self.setClasses();\n                        self.highlightFirstItem();\n                    }\n                });\n\n                container.on('results:append', function (params) {\n                    self.append(params.data);\n\n                    if (container.isOpen()) {\n                        self.setClasses();\n                    }\n                });\n\n                container.on('query', function (params) {\n                    self.hideMessages();\n                    self.showLoading(params);\n                });\n\n                container.on('select', function () {\n                    if (!container.isOpen()) {\n                        return;\n                    }\n\n                    self.setClasses();\n                    self.highlightFirstItem();\n                });\n\n                container.on('unselect', function () {\n                    if (!container.isOpen()) {\n                        return;\n                    }\n\n                    self.setClasses();\n                    self.highlightFirstItem();\n                });\n\n                container.on('open', function () {\n                    // When the dropdown is open, aria-expended=\"true\"\n                    self.$results.attr('aria-expanded', 'true');\n                    self.$results.attr('aria-hidden', 'false');\n\n                    self.setClasses();\n                    self.ensureHighlightVisible();\n                });\n\n                container.on('close', function () {\n                    // When the dropdown is closed, aria-expended=\"false\"\n                    self.$results.attr('aria-expanded', 'false');\n                    self.$results.attr('aria-hidden', 'true');\n                    self.$results.removeAttr('aria-activedescendant');\n                });\n\n                container.on('results:toggle', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    if ($highlighted.length === 0) {\n                        return;\n                    }\n\n                    $highlighted.trigger('mouseup');\n                });\n\n                container.on('results:select', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    if ($highlighted.length === 0) {\n                        return;\n                    }\n\n                    var data = Utils.GetData($highlighted[0], 'data');\n\n                    if ($highlighted.attr('aria-selected') == 'true') {\n                        self.trigger('close', {});\n                    } else {\n                        self.trigger('select', {\n                            data: data\n                        });\n                    }\n                });\n\n                container.on('results:previous', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    var $options = self.$results.find('[aria-selected]');\n\n                    var currentIndex = $options.index($highlighted);\n\n                    // If we are already at te top, don't move further\n                    // If no options, currentIndex will be -1\n                    if (currentIndex <= 0) {\n                        return;\n                    }\n\n                    var nextIndex = currentIndex - 1;\n\n                    // If none are highlighted, highlight the first\n                    if ($highlighted.length === 0) {\n                        nextIndex = 0;\n                    }\n\n                    var $next = $options.eq(nextIndex);\n\n                    $next.trigger('mouseenter');\n\n                    var currentOffset = self.$results.offset().top;\n                    var nextTop = $next.offset().top;\n                    var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);\n\n                    if (nextIndex === 0) {\n                        self.$results.scrollTop(0);\n                    } else if (nextTop - currentOffset < 0) {\n                        self.$results.scrollTop(nextOffset);\n                    }\n                });\n\n                container.on('results:next', function () {\n                    var $highlighted = self.getHighlightedResults();\n\n                    var $options = self.$results.find('[aria-selected]');\n\n                    var currentIndex = $options.index($highlighted);\n\n                    var nextIndex = currentIndex + 1;\n\n                    // If we are at the last option, stay there\n                    if (nextIndex >= $options.length) {\n                        return;\n                    }\n\n                    var $next = $options.eq(nextIndex);\n\n                    $next.trigger('mouseenter');\n\n                    var currentOffset = self.$results.offset().top +\n                        self.$results.outerHeight(false);\n                    var nextBottom = $next.offset().top + $next.outerHeight(false);\n                    var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;\n\n                    if (nextIndex === 0) {\n                        self.$results.scrollTop(0);\n                    } else if (nextBottom > currentOffset) {\n                        self.$results.scrollTop(nextOffset);\n                    }\n                });\n\n                container.on('results:focus', function (params) {\n                    params.element.addClass('select2-results__option--highlighted');\n                });\n\n                container.on('results:message', function (params) {\n                    self.displayMessage(params);\n                });\n\n                if ($.fn.mousewheel) {\n                    this.$results.on('mousewheel', function (e) {\n                        var top = self.$results.scrollTop();\n\n                        var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;\n\n                        var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;\n                        var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();\n\n                        if (isAtTop) {\n                            self.$results.scrollTop(0);\n\n                            e.preventDefault();\n                            e.stopPropagation();\n                        } else if (isAtBottom) {\n                            self.$results.scrollTop(\n                                self.$results.get(0).scrollHeight - self.$results.height()\n                            );\n\n                            e.preventDefault();\n                            e.stopPropagation();\n                        }\n                    });\n                }\n\n                this.$results.on('mouseup', '.select2-results__option[aria-selected]',\n                    function (evt) {\n                        var $this = $(this);\n\n                        var data = Utils.GetData(this, 'data');\n\n                        if ($this.attr('aria-selected') === 'true') {\n                            if (self.options.get('multiple')) {\n                                self.trigger('unselect', {\n                                    originalEvent: evt,\n                                    data: data\n                                });\n                            } else {\n                                self.trigger('close', {});\n                            }\n\n                            return;\n                        }\n\n                        self.trigger('select', {\n                            originalEvent: evt,\n                            data: data\n                        });\n                    });\n\n                this.$results.on('mouseenter', '.select2-results__option[aria-selected]',\n                    function (evt) {\n                        var data = Utils.GetData(this, 'data');\n\n                        self.getHighlightedResults()\n                            .removeClass('select2-results__option--highlighted');\n\n                        self.trigger('results:focus', {\n                            data: data,\n                            element: $(this)\n                        });\n                    });\n            };\n\n            Results.prototype.getHighlightedResults = function () {\n                var $highlighted = this.$results\n                    .find('.select2-results__option--highlighted');\n\n                return $highlighted;\n            };\n\n            Results.prototype.destroy = function () {\n                this.$results.remove();\n            };\n\n            Results.prototype.ensureHighlightVisible = function () {\n                var $highlighted = this.getHighlightedResults();\n\n                if ($highlighted.length === 0) {\n                    return;\n                }\n\n                var $options = this.$results.find('[aria-selected]');\n\n                var currentIndex = $options.index($highlighted);\n\n                var currentOffset = this.$results.offset().top;\n                var nextTop = $highlighted.offset().top;\n                var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);\n\n                var offsetDelta = nextTop - currentOffset;\n                nextOffset -= $highlighted.outerHeight(false) * 2;\n\n                if (currentIndex <= 2) {\n                    this.$results.scrollTop(0);\n                } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {\n                    this.$results.scrollTop(nextOffset);\n                }\n            };\n\n            Results.prototype.template = function (result, container) {\n                var template = this.options.get('templateResult');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                var content = template(result, container);\n\n                if (content == null) {\n                    container.style.display = 'none';\n                } else if (typeof content === 'string') {\n                    container.innerHTML = escapeMarkup(content);\n                } else {\n                    $(container).append(content);\n                }\n            };\n\n            return Results;\n        });\n\n        S2.define('select2/keys', [], function () {\n            var KEYS = {\n                BACKSPACE: 8,\n                TAB: 9,\n                ENTER: 13,\n                SHIFT: 16,\n                CTRL: 17,\n                ALT: 18,\n                ESC: 27,\n                SPACE: 32,\n                PAGE_UP: 33,\n                PAGE_DOWN: 34,\n                END: 35,\n                HOME: 36,\n                LEFT: 37,\n                UP: 38,\n                RIGHT: 39,\n                DOWN: 40,\n                DELETE: 46\n            };\n\n            return KEYS;\n        });\n\n        S2.define('select2/selection/base', [\n            'jquery',\n            '../utils',\n            '../keys'\n        ], function ($, Utils, KEYS) {\n            function BaseSelection($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                BaseSelection.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(BaseSelection, Utils.Observable);\n\n            BaseSelection.prototype.render = function () {\n                var $selection = $(\n                    '<span class=\"select2-selection\" role=\"combobox\" ' +\n                    ' aria-haspopup=\"true\" aria-expanded=\"false\">' +\n                    '</span>'\n                );\n\n                this._tabindex = 0;\n\n                if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {\n                    this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');\n                } else if (this.$element.attr('tabindex') != null) {\n                    this._tabindex = this.$element.attr('tabindex');\n                }\n\n                $selection.attr('title', this.$element.attr('title'));\n                $selection.attr('tabindex', this._tabindex);\n\n                this.$selection = $selection;\n\n                return $selection;\n            };\n\n            BaseSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                var id = container.id + '-container';\n                var resultsId = container.id + '-results';\n\n                this.container = container;\n\n                this.$selection.on('focus', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this.$selection.on('blur', function (evt) {\n                    self._handleBlur(evt);\n                });\n\n                this.$selection.on('keydown', function (evt) {\n                    self.trigger('keypress', evt);\n\n                    if (evt.which === KEYS.SPACE) {\n                        evt.preventDefault();\n                    }\n                });\n\n                container.on('results:focus', function (params) {\n                    self.$selection.attr('aria-activedescendant', params.data._resultId);\n                });\n\n                container.on('selection:update', function (params) {\n                    self.update(params.data);\n                });\n\n                container.on('open', function () {\n                    // When the dropdown is open, aria-expanded=\"true\"\n                    self.$selection.attr('aria-expanded', 'true');\n                    self.$selection.attr('aria-owns', resultsId);\n\n                    self._attachCloseHandler(container);\n                });\n\n                container.on('close', function () {\n                    // When the dropdown is closed, aria-expanded=\"false\"\n                    self.$selection.attr('aria-expanded', 'false');\n                    self.$selection.removeAttr('aria-activedescendant');\n                    self.$selection.removeAttr('aria-owns');\n\n                    self.$selection.focus();\n                    window.setTimeout(function () {\n                        self.$selection.focus();\n                    }, 0);\n\n                    self._detachCloseHandler(container);\n                });\n\n                container.on('enable', function () {\n                    self.$selection.attr('tabindex', self._tabindex);\n                });\n\n                container.on('disable', function () {\n                    self.$selection.attr('tabindex', '-1');\n                });\n            };\n\n            BaseSelection.prototype._handleBlur = function (evt) {\n                var self = this;\n\n                // This needs to be delayed as the active element is the body when the tab\n                // key is pressed, possibly along with others.\n                window.setTimeout(function () {\n                    // Don't trigger `blur` if the focus is still in the selection\n                    if (\n                        (document.activeElement == self.$selection[0]) ||\n                        ($.contains(self.$selection[0], document.activeElement))\n                    ) {\n                        return;\n                    }\n\n                    self.trigger('blur', evt);\n                }, 1);\n            };\n\n            BaseSelection.prototype._attachCloseHandler = function (container) {\n                var self = this;\n\n                $(document.body).on('mousedown.select2.' + container.id, function (e) {\n                    var $target = $(e.target);\n\n                    var $select = $target.closest('.select2');\n\n                    var $all = $('.select2.select2-container--open');\n\n                    $all.each(function () {\n                        var $this = $(this);\n\n                        if (this == $select[0]) {\n                            return;\n                        }\n\n                        var $element = Utils.GetData(this, 'element');\n\n                        $element.select2('close');\n                    });\n                });\n            };\n\n            BaseSelection.prototype._detachCloseHandler = function (container) {\n                $(document.body).off('mousedown.select2.' + container.id);\n            };\n\n            BaseSelection.prototype.position = function ($selection, $container) {\n                var $selectionContainer = $container.find('.selection');\n                $selectionContainer.append($selection);\n            };\n\n            BaseSelection.prototype.destroy = function () {\n                this._detachCloseHandler(this.container);\n            };\n\n            BaseSelection.prototype.update = function (data) {\n                throw new Error('The `update` method must be defined in child classes.');\n            };\n\n            return BaseSelection;\n        });\n\n        S2.define('select2/selection/single', [\n            'jquery',\n            './base',\n            '../utils',\n            '../keys'\n        ], function ($, BaseSelection, Utils, KEYS) {\n            function SingleSelection() {\n                SingleSelection.__super__.constructor.apply(this, arguments);\n            }\n\n            Utils.Extend(SingleSelection, BaseSelection);\n\n            SingleSelection.prototype.render = function () {\n                var $selection = SingleSelection.__super__.render.call(this);\n\n                $selection.addClass('select2-selection--single');\n\n                $selection.html(\n                    '<span class=\"select2-selection__rendered\"></span>' +\n                    '<span class=\"select2-selection__arrow\" role=\"presentation\">' +\n                    '<b role=\"presentation\"></b>' +\n                    '</span>'\n                );\n\n                return $selection;\n            };\n\n            SingleSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                SingleSelection.__super__.bind.apply(this, arguments);\n\n                var id = container.id + '-container';\n\n                this.$selection.find('.select2-selection__rendered')\n                    .attr('id', id)\n                    .attr('role', 'textbox')\n                    .attr('aria-readonly', 'true');\n                this.$selection.attr('aria-labelledby', id);\n\n                this.$selection.on('mousedown', function (evt) {\n                    // Only respond to left clicks\n                    if (evt.which !== 1) {\n                        return;\n                    }\n\n                    self.trigger('toggle', {\n                        originalEvent: evt\n                    });\n                });\n\n                this.$selection.on('focus', function (evt) {\n                    // User focuses on the container\n                });\n\n                this.$selection.on('blur', function (evt) {\n                    // User exits the container\n                });\n\n                container.on('focus', function (evt) {\n                    if (!container.isOpen()) {\n                        self.$selection.focus();\n                    }\n                });\n            };\n\n            SingleSelection.prototype.clear = function () {\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                $rendered.empty();\n                $rendered.removeAttr('title'); // clear tooltip on empty\n            };\n\n            SingleSelection.prototype.display = function (data, container) {\n                var template = this.options.get('templateSelection');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                return escapeMarkup(template(data, container));\n            };\n\n            SingleSelection.prototype.selectionContainer = function () {\n                return $('<span></span>');\n            };\n\n            SingleSelection.prototype.update = function (data) {\n                if (data.length === 0) {\n                    this.clear();\n                    return;\n                }\n\n                var selection = data[0];\n\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                var formatted = this.display(selection, $rendered);\n\n                $rendered.empty().append(formatted);\n                $rendered.attr('title', selection.title || selection.text);\n            };\n\n            return SingleSelection;\n        });\n\n        S2.define('select2/selection/multiple', [\n            'jquery',\n            './base',\n            '../utils'\n        ], function ($, BaseSelection, Utils) {\n            function MultipleSelection($element, options) {\n                MultipleSelection.__super__.constructor.apply(this, arguments);\n            }\n\n            Utils.Extend(MultipleSelection, BaseSelection);\n\n            MultipleSelection.prototype.render = function () {\n                var $selection = MultipleSelection.__super__.render.call(this);\n\n                $selection.addClass('select2-selection--multiple');\n\n                $selection.html(\n                    '<ul class=\"select2-selection__rendered\"></ul>'\n                );\n\n                return $selection;\n            };\n\n            MultipleSelection.prototype.bind = function (container, $container) {\n                var self = this;\n\n                MultipleSelection.__super__.bind.apply(this, arguments);\n\n                this.$selection.on('click', function (evt) {\n                    self.trigger('toggle', {\n                        originalEvent: evt\n                    });\n                });\n\n                this.$selection.on(\n                    'click',\n                    '.select2-selection__choice__remove',\n                    function (evt) {\n                        // Ignore the event if it is disabled\n                        if (self.options.get('disabled')) {\n                            return;\n                        }\n\n                        var $remove = $(this);\n                        var $selection = $remove.parent();\n\n                        var data = Utils.GetData($selection[0], 'data');\n\n                        self.trigger('unselect', {\n                            originalEvent: evt,\n                            data: data\n                        });\n                    }\n                );\n            };\n\n            MultipleSelection.prototype.clear = function () {\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n                $rendered.empty();\n                $rendered.removeAttr('title');\n            };\n\n            MultipleSelection.prototype.display = function (data, container) {\n                var template = this.options.get('templateSelection');\n                var escapeMarkup = this.options.get('escapeMarkup');\n\n                return escapeMarkup(template(data, container));\n            };\n\n            MultipleSelection.prototype.selectionContainer = function () {\n                var $container = $(\n                    '<li class=\"select2-selection__choice\">' +\n                    '<span class=\"select2-selection__choice__remove\" role=\"presentation\">' +\n                    '&times;' +\n                    '</span>' +\n                    '</li>'\n                );\n\n                return $container;\n            };\n\n            MultipleSelection.prototype.update = function (data) {\n                this.clear();\n\n                if (data.length === 0) {\n                    return;\n                }\n\n                var $selections = [];\n\n                for (var d = 0; d < data.length; d++) {\n                    var selection = data[d];\n\n                    var $selection = this.selectionContainer();\n                    var formatted = this.display(selection, $selection);\n\n                    $selection.append(formatted);\n                    $selection.attr('title', selection.title || selection.text);\n\n                    Utils.StoreData($selection[0], 'data', selection);\n\n                    $selections.push($selection);\n                }\n\n                var $rendered = this.$selection.find('.select2-selection__rendered');\n\n                Utils.appendMany($rendered, $selections);\n            };\n\n            return MultipleSelection;\n        });\n\n        S2.define('select2/selection/placeholder', [\n            '../utils'\n        ], function (Utils) {\n            function Placeholder(decorated, $element, options) {\n                this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n                decorated.call(this, $element, options);\n            }\n\n            Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {\n                if (typeof placeholder === 'string') {\n                    placeholder = {\n                        id: '',\n                        text: placeholder\n                    };\n                }\n\n                return placeholder;\n            };\n\n            Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {\n                var $placeholder = this.selectionContainer();\n\n                $placeholder.html(this.display(placeholder));\n                $placeholder.addClass('select2-selection__placeholder')\n                    .removeClass('select2-selection__choice');\n\n                return $placeholder;\n            };\n\n            Placeholder.prototype.update = function (decorated, data) {\n                var singlePlaceholder = (\n                    data.length == 1 && data[0].id != this.placeholder.id\n                );\n                var multipleSelections = data.length > 1;\n\n                if (multipleSelections || singlePlaceholder) {\n                    return decorated.call(this, data);\n                }\n\n                this.clear();\n\n                var $placeholder = this.createPlaceholder(this.placeholder);\n\n                this.$selection.find('.select2-selection__rendered').append($placeholder);\n            };\n\n            return Placeholder;\n        });\n\n        S2.define('select2/selection/allowClear', [\n            'jquery',\n            '../keys',\n            '../utils'\n        ], function ($, KEYS, Utils) {\n            function AllowClear() {\n            }\n\n            AllowClear.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                if (this.placeholder == null) {\n                    if (this.options.get('debug') && window.console && console.error) {\n                        console.error(\n                            'Select2: The `allowClear` option should be used in combination ' +\n                            'with the `placeholder` option.'\n                        );\n                    }\n                }\n\n                this.$selection.on('mousedown', '.select2-selection__clear',\n                    function (evt) {\n                        self._handleClear(evt);\n                    });\n\n                container.on('keypress', function (evt) {\n                    self._handleKeyboardClear(evt, container);\n                });\n            };\n\n            AllowClear.prototype._handleClear = function (_, evt) {\n                // Ignore the event if it is disabled\n                if (this.options.get('disabled')) {\n                    return;\n                }\n\n                var $clear = this.$selection.find('.select2-selection__clear');\n\n                // Ignore the event if nothing has been selected\n                if ($clear.length === 0) {\n                    return;\n                }\n\n                evt.stopPropagation();\n\n                var data = Utils.GetData($clear[0], 'data');\n\n                var previousVal = this.$element.val();\n                this.$element.val(this.placeholder.id);\n\n                var unselectData = {\n                    data: data\n                };\n                this.trigger('clear', unselectData);\n                if (unselectData.prevented) {\n                    this.$element.val(previousVal);\n                    return;\n                }\n\n                for (var d = 0; d < data.length; d++) {\n                    unselectData = {\n                        data: data[d]\n                    };\n\n                    // Trigger the `unselect` event, so people can prevent it from being\n                    // cleared.\n                    this.trigger('unselect', unselectData);\n\n                    // If the event was prevented, don't clear it out.\n                    if (unselectData.prevented) {\n                        this.$element.val(previousVal);\n                        return;\n                    }\n                }\n\n                this.$element.trigger('change');\n\n                this.trigger('toggle', {});\n            };\n\n            AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {\n                if (container.isOpen()) {\n                    return;\n                }\n\n                if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {\n                    this._handleClear(evt);\n                }\n            };\n\n            AllowClear.prototype.update = function (decorated, data) {\n                decorated.call(this, data);\n\n                if (this.$selection.find('.select2-selection__placeholder').length > 0 ||\n                    data.length === 0) {\n                    return;\n                }\n\n                var $remove = $(\n                    '<span class=\"select2-selection__clear\">' +\n                    '&times;' +\n                    '</span>'\n                );\n                Utils.StoreData($remove[0], 'data', data);\n\n                this.$selection.find('.select2-selection__rendered').prepend($remove);\n            };\n\n            return AllowClear;\n        });\n\n        S2.define('select2/selection/search', [\n            'jquery',\n            '../utils',\n            '../keys'\n        ], function ($, Utils, KEYS) {\n            function Search(decorated, $element, options) {\n                decorated.call(this, $element, options);\n            }\n\n            Search.prototype.render = function (decorated) {\n                var $search = $(\n                    '<li class=\"select2-search select2-search--inline\">' +\n                    '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n                    ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"none\"' +\n                    ' spellcheck=\"false\" role=\"textbox\" aria-autocomplete=\"list\" />' +\n                    '</li>'\n                );\n\n                this.$searchContainer = $search;\n                this.$search = $search.find('input');\n\n                var $rendered = decorated.call(this);\n\n                this._transferTabIndex();\n\n                return $rendered;\n            };\n\n            Search.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('open', function () {\n                    self.$search.trigger('focus');\n                });\n\n                container.on('close', function () {\n                    self.$search.val('');\n                    self.$search.removeAttr('aria-activedescendant');\n                    self.$search.trigger('focus');\n                });\n\n                container.on('enable', function () {\n                    self.$search.prop('disabled', false);\n\n                    self._transferTabIndex();\n                });\n\n                container.on('disable', function () {\n                    self.$search.prop('disabled', true);\n                });\n\n                container.on('focus', function (evt) {\n                    self.$search.trigger('focus');\n                });\n\n                container.on('results:focus', function (params) {\n                    self.$search.attr('aria-activedescendant', params.id);\n                });\n\n                this.$selection.on('focusin', '.select2-search--inline', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this.$selection.on('focusout', '.select2-search--inline', function (evt) {\n                    self._handleBlur(evt);\n                });\n\n                this.$selection.on('keydown', '.select2-search--inline', function (evt) {\n                    evt.stopPropagation();\n\n                    self.trigger('keypress', evt);\n\n                    self._keyUpPrevented = evt.isDefaultPrevented();\n\n                    var key = evt.which;\n\n                    if (key === KEYS.BACKSPACE && self.$search.val() === '') {\n                        var $previousChoice = self.$searchContainer\n                            .prev('.select2-selection__choice');\n\n                        if ($previousChoice.length > 0) {\n                            var item = Utils.GetData($previousChoice[0], 'data');\n\n                            self.searchRemoveChoice(item);\n\n                            evt.preventDefault();\n                        }\n                    }\n                });\n\n                // Try to detect the IE version should the `documentMode` property that\n                // is stored on the document. This is only implemented in IE and is\n                // slightly cleaner than doing a user agent check.\n                // This property is not available in Edge, but Edge also doesn't have\n                // this bug.\n                var msie = document.documentMode;\n                var disableInputEvents = msie && msie <= 11;\n\n                // Workaround for browsers which do not support the `input` event\n                // This will prevent double-triggering of events for browsers which support\n                // both the `keyup` and `input` events.\n                this.$selection.on(\n                    'input.searchcheck',\n                    '.select2-search--inline',\n                    function (evt) {\n                        // IE will trigger the `input` event when a placeholder is used on a\n                        // search box. To get around this issue, we are forced to ignore all\n                        // `input` events in IE and keep using `keyup`.\n                        if (disableInputEvents) {\n                            self.$selection.off('input.search input.searchcheck');\n                            return;\n                        }\n\n                        // Unbind the duplicated `keyup` event\n                        self.$selection.off('keyup.search');\n                    }\n                );\n\n                this.$selection.on(\n                    'keyup.search input.search',\n                    '.select2-search--inline',\n                    function (evt) {\n                        // IE will trigger the `input` event when a placeholder is used on a\n                        // search box. To get around this issue, we are forced to ignore all\n                        // `input` events in IE and keep using `keyup`.\n                        if (disableInputEvents && evt.type === 'input') {\n                            self.$selection.off('input.search input.searchcheck');\n                            return;\n                        }\n\n                        var key = evt.which;\n\n                        // We can freely ignore events from modifier keys\n                        if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {\n                            return;\n                        }\n\n                        // Tabbing will be handled during the `keydown` phase\n                        if (key == KEYS.TAB) {\n                            return;\n                        }\n\n                        self.handleSearch(evt);\n                    }\n                );\n            };\n\n            /**\n             * This method will transfer the tabindex attribute from the rendered\n             * selection to the search box. This allows for the search box to be used as\n             * the primary focus instead of the selection container.\n             *\n             * @private\n             */\n            Search.prototype._transferTabIndex = function (decorated) {\n                this.$search.attr('tabindex', this.$selection.attr('tabindex'));\n                this.$selection.attr('tabindex', '-1');\n            };\n\n            Search.prototype.createPlaceholder = function (decorated, placeholder) {\n                this.$search.attr('placeholder', placeholder.text);\n            };\n\n            Search.prototype.update = function (decorated, data) {\n                var searchHadFocus = this.$search[0] == document.activeElement;\n\n                this.$search.attr('placeholder', '');\n\n                decorated.call(this, data);\n\n                this.$selection.find('.select2-selection__rendered')\n                    .append(this.$searchContainer);\n\n                this.resizeSearch();\n                if (searchHadFocus) {\n                    var isTagInput = this.$element.find('[data-select2-tag]').length;\n                    if (isTagInput) {\n                        // fix IE11 bug where tag input lost focus\n                        this.$element.focus();\n                    } else {\n                        this.$search.focus();\n                    }\n                }\n            };\n\n            Search.prototype.handleSearch = function () {\n                this.resizeSearch();\n\n                if (!this._keyUpPrevented) {\n                    var input = this.$search.val();\n\n                    this.trigger('query', {\n                        term: input\n                    });\n                }\n\n                this._keyUpPrevented = false;\n            };\n\n            Search.prototype.searchRemoveChoice = function (decorated, item) {\n                this.trigger('unselect', {\n                    data: item\n                });\n\n                this.$search.val(item.text);\n                this.handleSearch();\n            };\n\n            Search.prototype.resizeSearch = function () {\n                this.$search.css('width', '25px');\n\n                var width = '';\n\n                if (this.$search.attr('placeholder') !== '') {\n                    width = this.$selection.find('.select2-selection__rendered').innerWidth();\n                } else {\n                    var minimumWidth = this.$search.val().length + 1;\n\n                    width = (minimumWidth * 0.75) + 'em';\n                }\n\n                this.$search.css('width', width);\n            };\n\n            return Search;\n        });\n\n        S2.define('select2/selection/eventRelay', [\n            'jquery'\n        ], function ($) {\n            function EventRelay() {\n            }\n\n            EventRelay.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n                var relayEvents = [\n                    'open', 'opening',\n                    'close', 'closing',\n                    'select', 'selecting',\n                    'unselect', 'unselecting',\n                    'clear', 'clearing'\n                ];\n\n                var preventableEvents = [\n                    'opening', 'closing', 'selecting', 'unselecting', 'clearing'\n                ];\n\n                decorated.call(this, container, $container);\n\n                container.on('*', function (name, params) {\n                    // Ignore events that should not be relayed\n                    if ($.inArray(name, relayEvents) === -1) {\n                        return;\n                    }\n\n                    // The parameters should always be an object\n                    params = params || {};\n\n                    // Generate the jQuery event for the Select2 event\n                    var evt = $.Event('select2:' + name, {\n                        params: params\n                    });\n\n                    self.$element.trigger(evt);\n\n                    // Only handle preventable events if it was one\n                    if ($.inArray(name, preventableEvents) === -1) {\n                        return;\n                    }\n\n                    params.prevented = evt.isDefaultPrevented();\n                });\n            };\n\n            return EventRelay;\n        });\n\n        S2.define('select2/translation', [\n            'jquery',\n            'require'\n        ], function ($, require) {\n            function Translation(dict) {\n                this.dict = dict || {};\n            }\n\n            Translation.prototype.all = function () {\n                return this.dict;\n            };\n\n            Translation.prototype.get = function (key) {\n                return this.dict[key];\n            };\n\n            Translation.prototype.extend = function (translation) {\n                this.dict = $.extend({}, translation.all(), this.dict);\n            };\n\n            // Static functions\n\n            Translation._cache = {};\n\n            Translation.loadPath = function (path) {\n                if (!(path in Translation._cache)) {\n                    var translations = require(path);\n\n                    Translation._cache[path] = translations;\n                }\n\n                return new Translation(Translation._cache[path]);\n            };\n\n            return Translation;\n        });\n\n        S2.define('select2/diacritics', [], function () {\n            var diacritics = {\n                '\\u24B6': 'A',\n                '\\uFF21': 'A',\n                '\\u00C0': 'A',\n                '\\u00C1': 'A',\n                '\\u00C2': 'A',\n                '\\u1EA6': 'A',\n                '\\u1EA4': 'A',\n                '\\u1EAA': 'A',\n                '\\u1EA8': 'A',\n                '\\u00C3': 'A',\n                '\\u0100': 'A',\n                '\\u0102': 'A',\n                '\\u1EB0': 'A',\n                '\\u1EAE': 'A',\n                '\\u1EB4': 'A',\n                '\\u1EB2': 'A',\n                '\\u0226': 'A',\n                '\\u01E0': 'A',\n                '\\u00C4': 'A',\n                '\\u01DE': 'A',\n                '\\u1EA2': 'A',\n                '\\u00C5': 'A',\n                '\\u01FA': 'A',\n                '\\u01CD': 'A',\n                '\\u0200': 'A',\n                '\\u0202': 'A',\n                '\\u1EA0': 'A',\n                '\\u1EAC': 'A',\n                '\\u1EB6': 'A',\n                '\\u1E00': 'A',\n                '\\u0104': 'A',\n                '\\u023A': 'A',\n                '\\u2C6F': 'A',\n                '\\uA732': 'AA',\n                '\\u00C6': 'AE',\n                '\\u01FC': 'AE',\n                '\\u01E2': 'AE',\n                '\\uA734': 'AO',\n                '\\uA736': 'AU',\n                '\\uA738': 'AV',\n                '\\uA73A': 'AV',\n                '\\uA73C': 'AY',\n                '\\u24B7': 'B',\n                '\\uFF22': 'B',\n                '\\u1E02': 'B',\n                '\\u1E04': 'B',\n                '\\u1E06': 'B',\n                '\\u0243': 'B',\n                '\\u0182': 'B',\n                '\\u0181': 'B',\n                '\\u24B8': 'C',\n                '\\uFF23': 'C',\n                '\\u0106': 'C',\n                '\\u0108': 'C',\n                '\\u010A': 'C',\n                '\\u010C': 'C',\n                '\\u00C7': 'C',\n                '\\u1E08': 'C',\n                '\\u0187': 'C',\n                '\\u023B': 'C',\n                '\\uA73E': 'C',\n                '\\u24B9': 'D',\n                '\\uFF24': 'D',\n                '\\u1E0A': 'D',\n                '\\u010E': 'D',\n                '\\u1E0C': 'D',\n                '\\u1E10': 'D',\n                '\\u1E12': 'D',\n                '\\u1E0E': 'D',\n                '\\u0110': 'D',\n                '\\u018B': 'D',\n                '\\u018A': 'D',\n                '\\u0189': 'D',\n                '\\uA779': 'D',\n                '\\u01F1': 'DZ',\n                '\\u01C4': 'DZ',\n                '\\u01F2': 'Dz',\n                '\\u01C5': 'Dz',\n                '\\u24BA': 'E',\n                '\\uFF25': 'E',\n                '\\u00C8': 'E',\n                '\\u00C9': 'E',\n                '\\u00CA': 'E',\n                '\\u1EC0': 'E',\n                '\\u1EBE': 'E',\n                '\\u1EC4': 'E',\n                '\\u1EC2': 'E',\n                '\\u1EBC': 'E',\n                '\\u0112': 'E',\n                '\\u1E14': 'E',\n                '\\u1E16': 'E',\n                '\\u0114': 'E',\n                '\\u0116': 'E',\n                '\\u00CB': 'E',\n                '\\u1EBA': 'E',\n                '\\u011A': 'E',\n                '\\u0204': 'E',\n                '\\u0206': 'E',\n                '\\u1EB8': 'E',\n                '\\u1EC6': 'E',\n                '\\u0228': 'E',\n                '\\u1E1C': 'E',\n                '\\u0118': 'E',\n                '\\u1E18': 'E',\n                '\\u1E1A': 'E',\n                '\\u0190': 'E',\n                '\\u018E': 'E',\n                '\\u24BB': 'F',\n                '\\uFF26': 'F',\n                '\\u1E1E': 'F',\n                '\\u0191': 'F',\n                '\\uA77B': 'F',\n                '\\u24BC': 'G',\n                '\\uFF27': 'G',\n                '\\u01F4': 'G',\n                '\\u011C': 'G',\n                '\\u1E20': 'G',\n                '\\u011E': 'G',\n                '\\u0120': 'G',\n                '\\u01E6': 'G',\n                '\\u0122': 'G',\n                '\\u01E4': 'G',\n                '\\u0193': 'G',\n                '\\uA7A0': 'G',\n                '\\uA77D': 'G',\n                '\\uA77E': 'G',\n                '\\u24BD': 'H',\n                '\\uFF28': 'H',\n                '\\u0124': 'H',\n                '\\u1E22': 'H',\n                '\\u1E26': 'H',\n                '\\u021E': 'H',\n                '\\u1E24': 'H',\n                '\\u1E28': 'H',\n                '\\u1E2A': 'H',\n                '\\u0126': 'H',\n                '\\u2C67': 'H',\n                '\\u2C75': 'H',\n                '\\uA78D': 'H',\n                '\\u24BE': 'I',\n                '\\uFF29': 'I',\n                '\\u00CC': 'I',\n                '\\u00CD': 'I',\n                '\\u00CE': 'I',\n                '\\u0128': 'I',\n                '\\u012A': 'I',\n                '\\u012C': 'I',\n                '\\u0130': 'I',\n                '\\u00CF': 'I',\n                '\\u1E2E': 'I',\n                '\\u1EC8': 'I',\n                '\\u01CF': 'I',\n                '\\u0208': 'I',\n                '\\u020A': 'I',\n                '\\u1ECA': 'I',\n                '\\u012E': 'I',\n                '\\u1E2C': 'I',\n                '\\u0197': 'I',\n                '\\u24BF': 'J',\n                '\\uFF2A': 'J',\n                '\\u0134': 'J',\n                '\\u0248': 'J',\n                '\\u24C0': 'K',\n                '\\uFF2B': 'K',\n                '\\u1E30': 'K',\n                '\\u01E8': 'K',\n                '\\u1E32': 'K',\n                '\\u0136': 'K',\n                '\\u1E34': 'K',\n                '\\u0198': 'K',\n                '\\u2C69': 'K',\n                '\\uA740': 'K',\n                '\\uA742': 'K',\n                '\\uA744': 'K',\n                '\\uA7A2': 'K',\n                '\\u24C1': 'L',\n                '\\uFF2C': 'L',\n                '\\u013F': 'L',\n                '\\u0139': 'L',\n                '\\u013D': 'L',\n                '\\u1E36': 'L',\n                '\\u1E38': 'L',\n                '\\u013B': 'L',\n                '\\u1E3C': 'L',\n                '\\u1E3A': 'L',\n                '\\u0141': 'L',\n                '\\u023D': 'L',\n                '\\u2C62': 'L',\n                '\\u2C60': 'L',\n                '\\uA748': 'L',\n                '\\uA746': 'L',\n                '\\uA780': 'L',\n                '\\u01C7': 'LJ',\n                '\\u01C8': 'Lj',\n                '\\u24C2': 'M',\n                '\\uFF2D': 'M',\n                '\\u1E3E': 'M',\n                '\\u1E40': 'M',\n                '\\u1E42': 'M',\n                '\\u2C6E': 'M',\n                '\\u019C': 'M',\n                '\\u24C3': 'N',\n                '\\uFF2E': 'N',\n                '\\u01F8': 'N',\n                '\\u0143': 'N',\n                '\\u00D1': 'N',\n                '\\u1E44': 'N',\n                '\\u0147': 'N',\n                '\\u1E46': 'N',\n                '\\u0145': 'N',\n                '\\u1E4A': 'N',\n                '\\u1E48': 'N',\n                '\\u0220': 'N',\n                '\\u019D': 'N',\n                '\\uA790': 'N',\n                '\\uA7A4': 'N',\n                '\\u01CA': 'NJ',\n                '\\u01CB': 'Nj',\n                '\\u24C4': 'O',\n                '\\uFF2F': 'O',\n                '\\u00D2': 'O',\n                '\\u00D3': 'O',\n                '\\u00D4': 'O',\n                '\\u1ED2': 'O',\n                '\\u1ED0': 'O',\n                '\\u1ED6': 'O',\n                '\\u1ED4': 'O',\n                '\\u00D5': 'O',\n                '\\u1E4C': 'O',\n                '\\u022C': 'O',\n                '\\u1E4E': 'O',\n                '\\u014C': 'O',\n                '\\u1E50': 'O',\n                '\\u1E52': 'O',\n                '\\u014E': 'O',\n                '\\u022E': 'O',\n                '\\u0230': 'O',\n                '\\u00D6': 'O',\n                '\\u022A': 'O',\n                '\\u1ECE': 'O',\n                '\\u0150': 'O',\n                '\\u01D1': 'O',\n                '\\u020C': 'O',\n                '\\u020E': 'O',\n                '\\u01A0': 'O',\n                '\\u1EDC': 'O',\n                '\\u1EDA': 'O',\n                '\\u1EE0': 'O',\n                '\\u1EDE': 'O',\n                '\\u1EE2': 'O',\n                '\\u1ECC': 'O',\n                '\\u1ED8': 'O',\n                '\\u01EA': 'O',\n                '\\u01EC': 'O',\n                '\\u00D8': 'O',\n                '\\u01FE': 'O',\n                '\\u0186': 'O',\n                '\\u019F': 'O',\n                '\\uA74A': 'O',\n                '\\uA74C': 'O',\n                '\\u01A2': 'OI',\n                '\\uA74E': 'OO',\n                '\\u0222': 'OU',\n                '\\u24C5': 'P',\n                '\\uFF30': 'P',\n                '\\u1E54': 'P',\n                '\\u1E56': 'P',\n                '\\u01A4': 'P',\n                '\\u2C63': 'P',\n                '\\uA750': 'P',\n                '\\uA752': 'P',\n                '\\uA754': 'P',\n                '\\u24C6': 'Q',\n                '\\uFF31': 'Q',\n                '\\uA756': 'Q',\n                '\\uA758': 'Q',\n                '\\u024A': 'Q',\n                '\\u24C7': 'R',\n                '\\uFF32': 'R',\n                '\\u0154': 'R',\n                '\\u1E58': 'R',\n                '\\u0158': 'R',\n                '\\u0210': 'R',\n                '\\u0212': 'R',\n                '\\u1E5A': 'R',\n                '\\u1E5C': 'R',\n                '\\u0156': 'R',\n                '\\u1E5E': 'R',\n                '\\u024C': 'R',\n                '\\u2C64': 'R',\n                '\\uA75A': 'R',\n                '\\uA7A6': 'R',\n                '\\uA782': 'R',\n                '\\u24C8': 'S',\n                '\\uFF33': 'S',\n                '\\u1E9E': 'S',\n                '\\u015A': 'S',\n                '\\u1E64': 'S',\n                '\\u015C': 'S',\n                '\\u1E60': 'S',\n                '\\u0160': 'S',\n                '\\u1E66': 'S',\n                '\\u1E62': 'S',\n                '\\u1E68': 'S',\n                '\\u0218': 'S',\n                '\\u015E': 'S',\n                '\\u2C7E': 'S',\n                '\\uA7A8': 'S',\n                '\\uA784': 'S',\n                '\\u24C9': 'T',\n                '\\uFF34': 'T',\n                '\\u1E6A': 'T',\n                '\\u0164': 'T',\n                '\\u1E6C': 'T',\n                '\\u021A': 'T',\n                '\\u0162': 'T',\n                '\\u1E70': 'T',\n                '\\u1E6E': 'T',\n                '\\u0166': 'T',\n                '\\u01AC': 'T',\n                '\\u01AE': 'T',\n                '\\u023E': 'T',\n                '\\uA786': 'T',\n                '\\uA728': 'TZ',\n                '\\u24CA': 'U',\n                '\\uFF35': 'U',\n                '\\u00D9': 'U',\n                '\\u00DA': 'U',\n                '\\u00DB': 'U',\n                '\\u0168': 'U',\n                '\\u1E78': 'U',\n                '\\u016A': 'U',\n                '\\u1E7A': 'U',\n                '\\u016C': 'U',\n                '\\u00DC': 'U',\n                '\\u01DB': 'U',\n                '\\u01D7': 'U',\n                '\\u01D5': 'U',\n                '\\u01D9': 'U',\n                '\\u1EE6': 'U',\n                '\\u016E': 'U',\n                '\\u0170': 'U',\n                '\\u01D3': 'U',\n                '\\u0214': 'U',\n                '\\u0216': 'U',\n                '\\u01AF': 'U',\n                '\\u1EEA': 'U',\n                '\\u1EE8': 'U',\n                '\\u1EEE': 'U',\n                '\\u1EEC': 'U',\n                '\\u1EF0': 'U',\n                '\\u1EE4': 'U',\n                '\\u1E72': 'U',\n                '\\u0172': 'U',\n                '\\u1E76': 'U',\n                '\\u1E74': 'U',\n                '\\u0244': 'U',\n                '\\u24CB': 'V',\n                '\\uFF36': 'V',\n                '\\u1E7C': 'V',\n                '\\u1E7E': 'V',\n                '\\u01B2': 'V',\n                '\\uA75E': 'V',\n                '\\u0245': 'V',\n                '\\uA760': 'VY',\n                '\\u24CC': 'W',\n                '\\uFF37': 'W',\n                '\\u1E80': 'W',\n                '\\u1E82': 'W',\n                '\\u0174': 'W',\n                '\\u1E86': 'W',\n                '\\u1E84': 'W',\n                '\\u1E88': 'W',\n                '\\u2C72': 'W',\n                '\\u24CD': 'X',\n                '\\uFF38': 'X',\n                '\\u1E8A': 'X',\n                '\\u1E8C': 'X',\n                '\\u24CE': 'Y',\n                '\\uFF39': 'Y',\n                '\\u1EF2': 'Y',\n                '\\u00DD': 'Y',\n                '\\u0176': 'Y',\n                '\\u1EF8': 'Y',\n                '\\u0232': 'Y',\n                '\\u1E8E': 'Y',\n                '\\u0178': 'Y',\n                '\\u1EF6': 'Y',\n                '\\u1EF4': 'Y',\n                '\\u01B3': 'Y',\n                '\\u024E': 'Y',\n                '\\u1EFE': 'Y',\n                '\\u24CF': 'Z',\n                '\\uFF3A': 'Z',\n                '\\u0179': 'Z',\n                '\\u1E90': 'Z',\n                '\\u017B': 'Z',\n                '\\u017D': 'Z',\n                '\\u1E92': 'Z',\n                '\\u1E94': 'Z',\n                '\\u01B5': 'Z',\n                '\\u0224': 'Z',\n                '\\u2C7F': 'Z',\n                '\\u2C6B': 'Z',\n                '\\uA762': 'Z',\n                '\\u24D0': 'a',\n                '\\uFF41': 'a',\n                '\\u1E9A': 'a',\n                '\\u00E0': 'a',\n                '\\u00E1': 'a',\n                '\\u00E2': 'a',\n                '\\u1EA7': 'a',\n                '\\u1EA5': 'a',\n                '\\u1EAB': 'a',\n                '\\u1EA9': 'a',\n                '\\u00E3': 'a',\n                '\\u0101': 'a',\n                '\\u0103': 'a',\n                '\\u1EB1': 'a',\n                '\\u1EAF': 'a',\n                '\\u1EB5': 'a',\n                '\\u1EB3': 'a',\n                '\\u0227': 'a',\n                '\\u01E1': 'a',\n                '\\u00E4': 'a',\n                '\\u01DF': 'a',\n                '\\u1EA3': 'a',\n                '\\u00E5': 'a',\n                '\\u01FB': 'a',\n                '\\u01CE': 'a',\n                '\\u0201': 'a',\n                '\\u0203': 'a',\n                '\\u1EA1': 'a',\n                '\\u1EAD': 'a',\n                '\\u1EB7': 'a',\n                '\\u1E01': 'a',\n                '\\u0105': 'a',\n                '\\u2C65': 'a',\n                '\\u0250': 'a',\n                '\\uA733': 'aa',\n                '\\u00E6': 'ae',\n                '\\u01FD': 'ae',\n                '\\u01E3': 'ae',\n                '\\uA735': 'ao',\n                '\\uA737': 'au',\n                '\\uA739': 'av',\n                '\\uA73B': 'av',\n                '\\uA73D': 'ay',\n                '\\u24D1': 'b',\n                '\\uFF42': 'b',\n                '\\u1E03': 'b',\n                '\\u1E05': 'b',\n                '\\u1E07': 'b',\n                '\\u0180': 'b',\n                '\\u0183': 'b',\n                '\\u0253': 'b',\n                '\\u24D2': 'c',\n                '\\uFF43': 'c',\n                '\\u0107': 'c',\n                '\\u0109': 'c',\n                '\\u010B': 'c',\n                '\\u010D': 'c',\n                '\\u00E7': 'c',\n                '\\u1E09': 'c',\n                '\\u0188': 'c',\n                '\\u023C': 'c',\n                '\\uA73F': 'c',\n                '\\u2184': 'c',\n                '\\u24D3': 'd',\n                '\\uFF44': 'd',\n                '\\u1E0B': 'd',\n                '\\u010F': 'd',\n                '\\u1E0D': 'd',\n                '\\u1E11': 'd',\n                '\\u1E13': 'd',\n                '\\u1E0F': 'd',\n                '\\u0111': 'd',\n                '\\u018C': 'd',\n                '\\u0256': 'd',\n                '\\u0257': 'd',\n                '\\uA77A': 'd',\n                '\\u01F3': 'dz',\n                '\\u01C6': 'dz',\n                '\\u24D4': 'e',\n                '\\uFF45': 'e',\n                '\\u00E8': 'e',\n                '\\u00E9': 'e',\n                '\\u00EA': 'e',\n                '\\u1EC1': 'e',\n                '\\u1EBF': 'e',\n                '\\u1EC5': 'e',\n                '\\u1EC3': 'e',\n                '\\u1EBD': 'e',\n                '\\u0113': 'e',\n                '\\u1E15': 'e',\n                '\\u1E17': 'e',\n                '\\u0115': 'e',\n                '\\u0117': 'e',\n                '\\u00EB': 'e',\n                '\\u1EBB': 'e',\n                '\\u011B': 'e',\n                '\\u0205': 'e',\n                '\\u0207': 'e',\n                '\\u1EB9': 'e',\n                '\\u1EC7': 'e',\n                '\\u0229': 'e',\n                '\\u1E1D': 'e',\n                '\\u0119': 'e',\n                '\\u1E19': 'e',\n                '\\u1E1B': 'e',\n                '\\u0247': 'e',\n                '\\u025B': 'e',\n                '\\u01DD': 'e',\n                '\\u24D5': 'f',\n                '\\uFF46': 'f',\n                '\\u1E1F': 'f',\n                '\\u0192': 'f',\n                '\\uA77C': 'f',\n                '\\u24D6': 'g',\n                '\\uFF47': 'g',\n                '\\u01F5': 'g',\n                '\\u011D': 'g',\n                '\\u1E21': 'g',\n                '\\u011F': 'g',\n                '\\u0121': 'g',\n                '\\u01E7': 'g',\n                '\\u0123': 'g',\n                '\\u01E5': 'g',\n                '\\u0260': 'g',\n                '\\uA7A1': 'g',\n                '\\u1D79': 'g',\n                '\\uA77F': 'g',\n                '\\u24D7': 'h',\n                '\\uFF48': 'h',\n                '\\u0125': 'h',\n                '\\u1E23': 'h',\n                '\\u1E27': 'h',\n                '\\u021F': 'h',\n                '\\u1E25': 'h',\n                '\\u1E29': 'h',\n                '\\u1E2B': 'h',\n                '\\u1E96': 'h',\n                '\\u0127': 'h',\n                '\\u2C68': 'h',\n                '\\u2C76': 'h',\n                '\\u0265': 'h',\n                '\\u0195': 'hv',\n                '\\u24D8': 'i',\n                '\\uFF49': 'i',\n                '\\u00EC': 'i',\n                '\\u00ED': 'i',\n                '\\u00EE': 'i',\n                '\\u0129': 'i',\n                '\\u012B': 'i',\n                '\\u012D': 'i',\n                '\\u00EF': 'i',\n                '\\u1E2F': 'i',\n                '\\u1EC9': 'i',\n                '\\u01D0': 'i',\n                '\\u0209': 'i',\n                '\\u020B': 'i',\n                '\\u1ECB': 'i',\n                '\\u012F': 'i',\n                '\\u1E2D': 'i',\n                '\\u0268': 'i',\n                '\\u0131': 'i',\n                '\\u24D9': 'j',\n                '\\uFF4A': 'j',\n                '\\u0135': 'j',\n                '\\u01F0': 'j',\n                '\\u0249': 'j',\n                '\\u24DA': 'k',\n                '\\uFF4B': 'k',\n                '\\u1E31': 'k',\n                '\\u01E9': 'k',\n                '\\u1E33': 'k',\n                '\\u0137': 'k',\n                '\\u1E35': 'k',\n                '\\u0199': 'k',\n                '\\u2C6A': 'k',\n                '\\uA741': 'k',\n                '\\uA743': 'k',\n                '\\uA745': 'k',\n                '\\uA7A3': 'k',\n                '\\u24DB': 'l',\n                '\\uFF4C': 'l',\n                '\\u0140': 'l',\n                '\\u013A': 'l',\n                '\\u013E': 'l',\n                '\\u1E37': 'l',\n                '\\u1E39': 'l',\n                '\\u013C': 'l',\n                '\\u1E3D': 'l',\n                '\\u1E3B': 'l',\n                '\\u017F': 'l',\n                '\\u0142': 'l',\n                '\\u019A': 'l',\n                '\\u026B': 'l',\n                '\\u2C61': 'l',\n                '\\uA749': 'l',\n                '\\uA781': 'l',\n                '\\uA747': 'l',\n                '\\u01C9': 'lj',\n                '\\u24DC': 'm',\n                '\\uFF4D': 'm',\n                '\\u1E3F': 'm',\n                '\\u1E41': 'm',\n                '\\u1E43': 'm',\n                '\\u0271': 'm',\n                '\\u026F': 'm',\n                '\\u24DD': 'n',\n                '\\uFF4E': 'n',\n                '\\u01F9': 'n',\n                '\\u0144': 'n',\n                '\\u00F1': 'n',\n                '\\u1E45': 'n',\n                '\\u0148': 'n',\n                '\\u1E47': 'n',\n                '\\u0146': 'n',\n                '\\u1E4B': 'n',\n                '\\u1E49': 'n',\n                '\\u019E': 'n',\n                '\\u0272': 'n',\n                '\\u0149': 'n',\n                '\\uA791': 'n',\n                '\\uA7A5': 'n',\n                '\\u01CC': 'nj',\n                '\\u24DE': 'o',\n                '\\uFF4F': 'o',\n                '\\u00F2': 'o',\n                '\\u00F3': 'o',\n                '\\u00F4': 'o',\n                '\\u1ED3': 'o',\n                '\\u1ED1': 'o',\n                '\\u1ED7': 'o',\n                '\\u1ED5': 'o',\n                '\\u00F5': 'o',\n                '\\u1E4D': 'o',\n                '\\u022D': 'o',\n                '\\u1E4F': 'o',\n                '\\u014D': 'o',\n                '\\u1E51': 'o',\n                '\\u1E53': 'o',\n                '\\u014F': 'o',\n                '\\u022F': 'o',\n                '\\u0231': 'o',\n                '\\u00F6': 'o',\n                '\\u022B': 'o',\n                '\\u1ECF': 'o',\n                '\\u0151': 'o',\n                '\\u01D2': 'o',\n                '\\u020D': 'o',\n                '\\u020F': 'o',\n                '\\u01A1': 'o',\n                '\\u1EDD': 'o',\n                '\\u1EDB': 'o',\n                '\\u1EE1': 'o',\n                '\\u1EDF': 'o',\n                '\\u1EE3': 'o',\n                '\\u1ECD': 'o',\n                '\\u1ED9': 'o',\n                '\\u01EB': 'o',\n                '\\u01ED': 'o',\n                '\\u00F8': 'o',\n                '\\u01FF': 'o',\n                '\\u0254': 'o',\n                '\\uA74B': 'o',\n                '\\uA74D': 'o',\n                '\\u0275': 'o',\n                '\\u01A3': 'oi',\n                '\\u0223': 'ou',\n                '\\uA74F': 'oo',\n                '\\u24DF': 'p',\n                '\\uFF50': 'p',\n                '\\u1E55': 'p',\n                '\\u1E57': 'p',\n                '\\u01A5': 'p',\n                '\\u1D7D': 'p',\n                '\\uA751': 'p',\n                '\\uA753': 'p',\n                '\\uA755': 'p',\n                '\\u24E0': 'q',\n                '\\uFF51': 'q',\n                '\\u024B': 'q',\n                '\\uA757': 'q',\n                '\\uA759': 'q',\n                '\\u24E1': 'r',\n                '\\uFF52': 'r',\n                '\\u0155': 'r',\n                '\\u1E59': 'r',\n                '\\u0159': 'r',\n                '\\u0211': 'r',\n                '\\u0213': 'r',\n                '\\u1E5B': 'r',\n                '\\u1E5D': 'r',\n                '\\u0157': 'r',\n                '\\u1E5F': 'r',\n                '\\u024D': 'r',\n                '\\u027D': 'r',\n                '\\uA75B': 'r',\n                '\\uA7A7': 'r',\n                '\\uA783': 'r',\n                '\\u24E2': 's',\n                '\\uFF53': 's',\n                '\\u00DF': 's',\n                '\\u015B': 's',\n                '\\u1E65': 's',\n                '\\u015D': 's',\n                '\\u1E61': 's',\n                '\\u0161': 's',\n                '\\u1E67': 's',\n                '\\u1E63': 's',\n                '\\u1E69': 's',\n                '\\u0219': 's',\n                '\\u015F': 's',\n                '\\u023F': 's',\n                '\\uA7A9': 's',\n                '\\uA785': 's',\n                '\\u1E9B': 's',\n                '\\u24E3': 't',\n                '\\uFF54': 't',\n                '\\u1E6B': 't',\n                '\\u1E97': 't',\n                '\\u0165': 't',\n                '\\u1E6D': 't',\n                '\\u021B': 't',\n                '\\u0163': 't',\n                '\\u1E71': 't',\n                '\\u1E6F': 't',\n                '\\u0167': 't',\n                '\\u01AD': 't',\n                '\\u0288': 't',\n                '\\u2C66': 't',\n                '\\uA787': 't',\n                '\\uA729': 'tz',\n                '\\u24E4': 'u',\n                '\\uFF55': 'u',\n                '\\u00F9': 'u',\n                '\\u00FA': 'u',\n                '\\u00FB': 'u',\n                '\\u0169': 'u',\n                '\\u1E79': 'u',\n                '\\u016B': 'u',\n                '\\u1E7B': 'u',\n                '\\u016D': 'u',\n                '\\u00FC': 'u',\n                '\\u01DC': 'u',\n                '\\u01D8': 'u',\n                '\\u01D6': 'u',\n                '\\u01DA': 'u',\n                '\\u1EE7': 'u',\n                '\\u016F': 'u',\n                '\\u0171': 'u',\n                '\\u01D4': 'u',\n                '\\u0215': 'u',\n                '\\u0217': 'u',\n                '\\u01B0': 'u',\n                '\\u1EEB': 'u',\n                '\\u1EE9': 'u',\n                '\\u1EEF': 'u',\n                '\\u1EED': 'u',\n                '\\u1EF1': 'u',\n                '\\u1EE5': 'u',\n                '\\u1E73': 'u',\n                '\\u0173': 'u',\n                '\\u1E77': 'u',\n                '\\u1E75': 'u',\n                '\\u0289': 'u',\n                '\\u24E5': 'v',\n                '\\uFF56': 'v',\n                '\\u1E7D': 'v',\n                '\\u1E7F': 'v',\n                '\\u028B': 'v',\n                '\\uA75F': 'v',\n                '\\u028C': 'v',\n                '\\uA761': 'vy',\n                '\\u24E6': 'w',\n                '\\uFF57': 'w',\n                '\\u1E81': 'w',\n                '\\u1E83': 'w',\n                '\\u0175': 'w',\n                '\\u1E87': 'w',\n                '\\u1E85': 'w',\n                '\\u1E98': 'w',\n                '\\u1E89': 'w',\n                '\\u2C73': 'w',\n                '\\u24E7': 'x',\n                '\\uFF58': 'x',\n                '\\u1E8B': 'x',\n                '\\u1E8D': 'x',\n                '\\u24E8': 'y',\n                '\\uFF59': 'y',\n                '\\u1EF3': 'y',\n                '\\u00FD': 'y',\n                '\\u0177': 'y',\n                '\\u1EF9': 'y',\n                '\\u0233': 'y',\n                '\\u1E8F': 'y',\n                '\\u00FF': 'y',\n                '\\u1EF7': 'y',\n                '\\u1E99': 'y',\n                '\\u1EF5': 'y',\n                '\\u01B4': 'y',\n                '\\u024F': 'y',\n                '\\u1EFF': 'y',\n                '\\u24E9': 'z',\n                '\\uFF5A': 'z',\n                '\\u017A': 'z',\n                '\\u1E91': 'z',\n                '\\u017C': 'z',\n                '\\u017E': 'z',\n                '\\u1E93': 'z',\n                '\\u1E95': 'z',\n                '\\u01B6': 'z',\n                '\\u0225': 'z',\n                '\\u0240': 'z',\n                '\\u2C6C': 'z',\n                '\\uA763': 'z',\n                '\\u0386': '\\u0391',\n                '\\u0388': '\\u0395',\n                '\\u0389': '\\u0397',\n                '\\u038A': '\\u0399',\n                '\\u03AA': '\\u0399',\n                '\\u038C': '\\u039F',\n                '\\u038E': '\\u03A5',\n                '\\u03AB': '\\u03A5',\n                '\\u038F': '\\u03A9',\n                '\\u03AC': '\\u03B1',\n                '\\u03AD': '\\u03B5',\n                '\\u03AE': '\\u03B7',\n                '\\u03AF': '\\u03B9',\n                '\\u03CA': '\\u03B9',\n                '\\u0390': '\\u03B9',\n                '\\u03CC': '\\u03BF',\n                '\\u03CD': '\\u03C5',\n                '\\u03CB': '\\u03C5',\n                '\\u03B0': '\\u03C5',\n                '\\u03C9': '\\u03C9',\n                '\\u03C2': '\\u03C3'\n            };\n\n            return diacritics;\n        });\n\n        S2.define('select2/data/base', [\n            '../utils'\n        ], function (Utils) {\n            function BaseAdapter($element, options) {\n                BaseAdapter.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(BaseAdapter, Utils.Observable);\n\n            BaseAdapter.prototype.current = function (callback) {\n                throw new Error('The `current` method must be defined in child classes.');\n            };\n\n            BaseAdapter.prototype.query = function (params, callback) {\n                throw new Error('The `query` method must be defined in child classes.');\n            };\n\n            BaseAdapter.prototype.bind = function (container, $container) {\n                // Can be implemented in subclasses\n            };\n\n            BaseAdapter.prototype.destroy = function () {\n                // Can be implemented in subclasses\n            };\n\n            BaseAdapter.prototype.generateResultId = function (container, data) {\n                var id = container.id + '-result-';\n\n                id += Utils.generateChars(4);\n\n                if (data.id != null) {\n                    id += '-' + data.id.toString();\n                } else {\n                    id += '-' + Utils.generateChars(4);\n                }\n                return id;\n            };\n\n            return BaseAdapter;\n        });\n\n        S2.define('select2/data/select', [\n            './base',\n            '../utils',\n            'jquery'\n        ], function (BaseAdapter, Utils, $) {\n            function SelectAdapter($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                SelectAdapter.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(SelectAdapter, BaseAdapter);\n\n            SelectAdapter.prototype.current = function (callback) {\n                var data = [];\n                var self = this;\n\n                this.$element.find(':selected').each(function () {\n                    var $option = $(this);\n\n                    var option = self.item($option);\n\n                    data.push(option);\n                });\n\n                callback(data);\n            };\n\n            SelectAdapter.prototype.select = function (data) {\n                var self = this;\n\n                data.selected = true;\n\n                // If data.element is a DOM node, use it instead\n                if ($(data.element).is('option')) {\n                    data.element.selected = true;\n\n                    this.$element.trigger('change');\n\n                    return;\n                }\n\n                if (this.$element.prop('multiple')) {\n                    this.current(function (currentData) {\n                        var val = [];\n\n                        data = [data];\n                        data.push.apply(data, currentData);\n\n                        for (var d = 0; d < data.length; d++) {\n                            var id = data[d].id;\n\n                            if ($.inArray(id, val) === -1) {\n                                val.push(id);\n                            }\n                        }\n\n                        self.$element.val(val);\n                        self.$element.trigger('change');\n                    });\n                } else {\n                    var val = data.id;\n\n                    this.$element.val(val);\n                    this.$element.trigger('change');\n                }\n            };\n\n            SelectAdapter.prototype.unselect = function (data) {\n                var self = this;\n\n                if (!this.$element.prop('multiple')) {\n                    return;\n                }\n\n                data.selected = false;\n\n                if ($(data.element).is('option')) {\n                    data.element.selected = false;\n\n                    this.$element.trigger('change');\n\n                    return;\n                }\n\n                this.current(function (currentData) {\n                    var val = [];\n\n                    for (var d = 0; d < currentData.length; d++) {\n                        var id = currentData[d].id;\n\n                        if (id !== data.id && $.inArray(id, val) === -1) {\n                            val.push(id);\n                        }\n                    }\n\n                    self.$element.val(val);\n\n                    self.$element.trigger('change');\n                });\n            };\n\n            SelectAdapter.prototype.bind = function (container, $container) {\n                var self = this;\n\n                this.container = container;\n\n                container.on('select', function (params) {\n                    self.select(params.data);\n                });\n\n                container.on('unselect', function (params) {\n                    self.unselect(params.data);\n                });\n            };\n\n            SelectAdapter.prototype.destroy = function () {\n                // Remove anything added to child elements\n                this.$element.find('*').each(function () {\n                    // Remove any custom data set by Select2\n                    Utils.RemoveData(this);\n                });\n            };\n\n            SelectAdapter.prototype.query = function (params, callback) {\n                var data = [];\n                var self = this;\n\n                var $options = this.$element.children();\n\n                $options.each(function () {\n                    var $option = $(this);\n\n                    if (!$option.is('option') && !$option.is('optgroup')) {\n                        return;\n                    }\n\n                    var option = self.item($option);\n\n                    var matches = self.matches(params, option);\n\n                    if (matches !== null) {\n                        data.push(matches);\n                    }\n                });\n\n                callback({\n                    results: data\n                });\n            };\n\n            SelectAdapter.prototype.addOptions = function ($options) {\n                Utils.appendMany(this.$element, $options);\n            };\n\n            SelectAdapter.prototype.option = function (data) {\n                var option;\n\n                if (data.children) {\n                    option = document.createElement('optgroup');\n                    option.label = data.text;\n                } else {\n                    option = document.createElement('option');\n\n                    if (option.textContent !== undefined) {\n                        option.textContent = data.text;\n                    } else {\n                        option.innerText = data.text;\n                    }\n                }\n\n                if (data.id !== undefined) {\n                    option.value = data.id;\n                }\n\n                if (data.disabled) {\n                    option.disabled = true;\n                }\n\n                if (data.selected) {\n                    option.selected = true;\n                }\n\n                if (data.title) {\n                    option.title = data.title;\n                }\n\n                var $option = $(option);\n\n                var normalizedData = this._normalizeItem(data);\n                normalizedData.element = option;\n\n                // Override the option's data with the combined data\n                Utils.StoreData(option, 'data', normalizedData);\n\n                return $option;\n            };\n\n            SelectAdapter.prototype.item = function ($option) {\n                var data = {};\n\n                data = Utils.GetData($option[0], 'data');\n\n                if (data != null) {\n                    return data;\n                }\n\n                if ($option.is('option')) {\n                    data = {\n                        id: $option.val(),\n                        text: $option.text(),\n                        disabled: $option.prop('disabled'),\n                        selected: $option.prop('selected'),\n                        title: $option.prop('title')\n                    };\n                } else if ($option.is('optgroup')) {\n                    data = {\n                        text: $option.prop('label'),\n                        children: [],\n                        title: $option.prop('title')\n                    };\n\n                    var $children = $option.children('option');\n                    var children = [];\n\n                    for (var c = 0; c < $children.length; c++) {\n                        var $child = $($children[c]);\n\n                        var child = this.item($child);\n\n                        children.push(child);\n                    }\n\n                    data.children = children;\n                }\n\n                data = this._normalizeItem(data);\n                data.element = $option[0];\n\n                Utils.StoreData($option[0], 'data', data);\n\n                return data;\n            };\n\n            SelectAdapter.prototype._normalizeItem = function (item) {\n                if (item !== Object(item)) {\n                    item = {\n                        id: item,\n                        text: item\n                    };\n                }\n\n                item = $.extend({}, {\n                    text: ''\n                }, item);\n\n                var defaults = {\n                    selected: false,\n                    disabled: false\n                };\n\n                if (item.id != null) {\n                    item.id = item.id.toString();\n                }\n\n                if (item.text != null) {\n                    item.text = item.text.toString();\n                }\n\n                if (item._resultId == null && item.id && this.container != null) {\n                    item._resultId = this.generateResultId(this.container, item);\n                }\n\n                return $.extend({}, defaults, item);\n            };\n\n            SelectAdapter.prototype.matches = function (params, data) {\n                var matcher = this.options.get('matcher');\n\n                return matcher(params, data);\n            };\n\n            return SelectAdapter;\n        });\n\n        S2.define('select2/data/array', [\n            './select',\n            '../utils',\n            'jquery'\n        ], function (SelectAdapter, Utils, $) {\n            function ArrayAdapter($element, options) {\n                var data = options.get('data') || [];\n\n                ArrayAdapter.__super__.constructor.call(this, $element, options);\n\n                this.addOptions(this.convertToOptions(data));\n            }\n\n            Utils.Extend(ArrayAdapter, SelectAdapter);\n\n            ArrayAdapter.prototype.select = function (data) {\n                var $option = this.$element.find('option').filter(function (i, elm) {\n                    return elm.value == data.id.toString();\n                });\n\n                if ($option.length === 0) {\n                    $option = this.option(data);\n\n                    this.addOptions($option);\n                }\n\n                ArrayAdapter.__super__.select.call(this, data);\n            };\n\n            ArrayAdapter.prototype.convertToOptions = function (data) {\n                var self = this;\n\n                var $existing = this.$element.find('option');\n                var existingIds = $existing.map(function () {\n                    return self.item($(this)).id;\n                }).get();\n\n                var $options = [];\n\n                // Filter out all items except for the one passed in the argument\n                function onlyItem(item) {\n                    return function () {\n                        return $(this).val() == item.id;\n                    };\n                }\n\n                for (var d = 0; d < data.length; d++) {\n                    var item = this._normalizeItem(data[d]);\n\n                    // Skip items which were pre-loaded, only merge the data\n                    if ($.inArray(item.id, existingIds) >= 0) {\n                        var $existingOption = $existing.filter(onlyItem(item));\n\n                        var existingData = this.item($existingOption);\n                        var newData = $.extend(true, {}, item, existingData);\n\n                        var $newOption = this.option(newData);\n\n                        $existingOption.replaceWith($newOption);\n\n                        continue;\n                    }\n\n                    var $option = this.option(item);\n\n                    if (item.children) {\n                        var $children = this.convertToOptions(item.children);\n\n                        Utils.appendMany($option, $children);\n                    }\n\n                    $options.push($option);\n                }\n\n                return $options;\n            };\n\n            return ArrayAdapter;\n        });\n\n        S2.define('select2/data/ajax', [\n            './array',\n            '../utils',\n            'jquery'\n        ], function (ArrayAdapter, Utils, $) {\n            function AjaxAdapter($element, options) {\n                this.ajaxOptions = this._applyDefaults(options.get('ajax'));\n\n                if (this.ajaxOptions.processResults != null) {\n                    this.processResults = this.ajaxOptions.processResults;\n                }\n\n                AjaxAdapter.__super__.constructor.call(this, $element, options);\n            }\n\n            Utils.Extend(AjaxAdapter, ArrayAdapter);\n\n            AjaxAdapter.prototype._applyDefaults = function (options) {\n                var defaults = {\n                    data: function (params) {\n                        return $.extend({}, params, {\n                            q: params.term\n                        });\n                    },\n                    transport: function (params, success, failure) {\n                        var $request = $.ajax(params);\n\n                        $request.then(success);\n                        $request.fail(failure);\n\n                        return $request;\n                    }\n                };\n\n                return $.extend({}, defaults, options, true);\n            };\n\n            AjaxAdapter.prototype.processResults = function (results) {\n                return results;\n            };\n\n            AjaxAdapter.prototype.query = function (params, callback) {\n                var matches = [];\n                var self = this;\n\n                if (this._request != null) {\n                    // JSONP requests cannot always be aborted\n                    if ($.isFunction(this._request.abort)) {\n                        this._request.abort();\n                    }\n\n                    this._request = null;\n                }\n\n                var options = $.extend({\n                    type: 'GET'\n                }, this.ajaxOptions);\n\n                if (typeof options.url === 'function') {\n                    options.url = options.url.call(this.$element, params);\n                }\n\n                if (typeof options.data === 'function') {\n                    options.data = options.data.call(this.$element, params);\n                }\n\n                function request() {\n                    var $request = options.transport(options, function (data) {\n                        var results = self.processResults(data, params);\n\n                        if (self.options.get('debug') && window.console && console.error) {\n                            // Check to make sure that the response included a `results` key.\n                            if (!results || !results.results || !$.isArray(results.results)) {\n                                console.error(\n                                    'Select2: The AJAX results did not return an array in the ' +\n                                    '`results` key of the response.'\n                                );\n                            }\n                        }\n\n                        callback(results);\n                    }, function () {\n                        // Attempt to detect if a request was aborted\n                        // Only works if the transport exposes a status property\n                        if ('status' in $request &&\n                            ($request.status === 0 || $request.status === '0')) {\n                            return;\n                        }\n\n                        self.trigger('results:message', {\n                            message: 'errorLoading'\n                        });\n                    });\n\n                    self._request = $request;\n                }\n\n                if (this.ajaxOptions.delay && params.term != null) {\n                    if (this._queryTimeout) {\n                        window.clearTimeout(this._queryTimeout);\n                    }\n\n                    this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);\n                } else {\n                    request();\n                }\n            };\n\n            return AjaxAdapter;\n        });\n\n        S2.define('select2/data/tags', [\n            'jquery'\n        ], function ($) {\n            function Tags(decorated, $element, options) {\n                var tags = options.get('tags');\n\n                var createTag = options.get('createTag');\n\n                if (createTag !== undefined) {\n                    this.createTag = createTag;\n                }\n\n                var insertTag = options.get('insertTag');\n\n                if (insertTag !== undefined) {\n                    this.insertTag = insertTag;\n                }\n\n                decorated.call(this, $element, options);\n\n                if ($.isArray(tags)) {\n                    for (var t = 0; t < tags.length; t++) {\n                        var tag = tags[t];\n                        var item = this._normalizeItem(tag);\n\n                        var $option = this.option(item);\n\n                        this.$element.append($option);\n                    }\n                }\n            }\n\n            Tags.prototype.query = function (decorated, params, callback) {\n                var self = this;\n\n                this._removeOldTags();\n\n                if (params.term == null || params.page != null) {\n                    decorated.call(this, params, callback);\n                    return;\n                }\n\n                function wrapper(obj, child) {\n                    var data = obj.results;\n\n                    for (var i = 0; i < data.length; i++) {\n                        var option = data[i];\n\n                        var checkChildren = (\n                            option.children != null &&\n                            !wrapper({\n                                results: option.children\n                            }, true)\n                        );\n\n                        var optionText = (option.text || '').toUpperCase();\n                        var paramsTerm = (params.term || '').toUpperCase();\n\n                        var checkText = optionText === paramsTerm;\n\n                        if (checkText || checkChildren) {\n                            if (child) {\n                                return false;\n                            }\n\n                            obj.data = data;\n                            callback(obj);\n\n                            return;\n                        }\n                    }\n\n                    if (child) {\n                        return true;\n                    }\n\n                    var tag = self.createTag(params);\n\n                    if (tag != null) {\n                        var $option = self.option(tag);\n                        $option.attr('data-select2-tag', true);\n\n                        self.addOptions([$option]);\n\n                        self.insertTag(data, tag);\n                    }\n\n                    obj.results = data;\n\n                    callback(obj);\n                }\n\n                decorated.call(this, params, wrapper);\n            };\n\n            Tags.prototype.createTag = function (decorated, params) {\n                var term = $.trim(params.term);\n\n                if (term === '') {\n                    return null;\n                }\n\n                return {\n                    id: term,\n                    text: term\n                };\n            };\n\n            Tags.prototype.insertTag = function (_, data, tag) {\n                data.unshift(tag);\n            };\n\n            Tags.prototype._removeOldTags = function (_) {\n                var tag = this._lastTag;\n\n                var $options = this.$element.find('option[data-select2-tag]');\n\n                $options.each(function () {\n                    if (this.selected) {\n                        return;\n                    }\n\n                    $(this).remove();\n                });\n            };\n\n            return Tags;\n        });\n\n        S2.define('select2/data/tokenizer', [\n            'jquery'\n        ], function ($) {\n            function Tokenizer(decorated, $element, options) {\n                var tokenizer = options.get('tokenizer');\n\n                if (tokenizer !== undefined) {\n                    this.tokenizer = tokenizer;\n                }\n\n                decorated.call(this, $element, options);\n            }\n\n            Tokenizer.prototype.bind = function (decorated, container, $container) {\n                decorated.call(this, container, $container);\n\n                this.$search = container.dropdown.$search || container.selection.$search ||\n                    $container.find('.select2-search__field');\n            };\n\n            Tokenizer.prototype.query = function (decorated, params, callback) {\n                var self = this;\n\n                function createAndSelect(data) {\n                    // Normalize the data object so we can use it for checks\n                    var item = self._normalizeItem(data);\n\n                    // Check if the data object already exists as a tag\n                    // Select it if it doesn't\n                    var $existingOptions = self.$element.find('option').filter(function () {\n                        return $(this).val() === item.id;\n                    });\n\n                    // If an existing option wasn't found for it, create the option\n                    if (!$existingOptions.length) {\n                        var $option = self.option(item);\n                        $option.attr('data-select2-tag', true);\n\n                        self._removeOldTags();\n                        self.addOptions([$option]);\n                    }\n\n                    // Select the item, now that we know there is an option for it\n                    select(item);\n                }\n\n                function select(data) {\n                    self.trigger('select', {\n                        data: data\n                    });\n                }\n\n                params.term = params.term || '';\n\n                var tokenData = this.tokenizer(params, this.options, createAndSelect);\n\n                if (tokenData.term !== params.term) {\n                    // Replace the search term if we have the search box\n                    if (this.$search.length) {\n                        this.$search.val(tokenData.term);\n                        this.$search.focus();\n                    }\n\n                    params.term = tokenData.term;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            Tokenizer.prototype.tokenizer = function (_, params, options, callback) {\n                var separators = options.get('tokenSeparators') || [];\n                var term = params.term;\n                var i = 0;\n\n                var createTag = this.createTag || function (params) {\n                    return {\n                        id: params.term,\n                        text: params.term\n                    };\n                };\n\n                while (i < term.length) {\n                    var termChar = term[i];\n\n                    if ($.inArray(termChar, separators) === -1) {\n                        i++;\n\n                        continue;\n                    }\n\n                    var part = term.substr(0, i);\n                    var partParams = $.extend({}, params, {\n                        term: part\n                    });\n\n                    var data = createTag(partParams);\n\n                    if (data == null) {\n                        i++;\n                        continue;\n                    }\n\n                    callback(data);\n\n                    // Reset the term to not include the tokenized portion\n                    term = term.substr(i + 1) || '';\n                    i = 0;\n                }\n\n                return {\n                    term: term\n                };\n            };\n\n            return Tokenizer;\n        });\n\n        S2.define('select2/data/minimumInputLength', [], function () {\n            function MinimumInputLength(decorated, $e, options) {\n                this.minimumInputLength = options.get('minimumInputLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MinimumInputLength.prototype.query = function (decorated, params, callback) {\n                params.term = params.term || '';\n\n                if (params.term.length < this.minimumInputLength) {\n                    this.trigger('results:message', {\n                        message: 'inputTooShort',\n                        args: {\n                            minimum: this.minimumInputLength,\n                            input: params.term,\n                            params: params\n                        }\n                    });\n\n                    return;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            return MinimumInputLength;\n        });\n\n        S2.define('select2/data/maximumInputLength', [], function () {\n            function MaximumInputLength(decorated, $e, options) {\n                this.maximumInputLength = options.get('maximumInputLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MaximumInputLength.prototype.query = function (decorated, params, callback) {\n                params.term = params.term || '';\n\n                if (this.maximumInputLength > 0 &&\n                    params.term.length > this.maximumInputLength) {\n                    this.trigger('results:message', {\n                        message: 'inputTooLong',\n                        args: {\n                            maximum: this.maximumInputLength,\n                            input: params.term,\n                            params: params\n                        }\n                    });\n\n                    return;\n                }\n\n                decorated.call(this, params, callback);\n            };\n\n            return MaximumInputLength;\n        });\n\n        S2.define('select2/data/maximumSelectionLength', [], function () {\n            function MaximumSelectionLength(decorated, $e, options) {\n                this.maximumSelectionLength = options.get('maximumSelectionLength');\n\n                decorated.call(this, $e, options);\n            }\n\n            MaximumSelectionLength.prototype.query =\n                function (decorated, params, callback) {\n                    var self = this;\n\n                    this.current(function (currentData) {\n                        var count = currentData != null ? currentData.length : 0;\n                        if (self.maximumSelectionLength > 0 &&\n                            count >= self.maximumSelectionLength) {\n                            self.trigger('results:message', {\n                                message: 'maximumSelected',\n                                args: {\n                                    maximum: self.maximumSelectionLength\n                                }\n                            });\n                            return;\n                        }\n                        decorated.call(self, params, callback);\n                    });\n                };\n\n            return MaximumSelectionLength;\n        });\n\n        S2.define('select2/dropdown', [\n            'jquery',\n            './utils'\n        ], function ($, Utils) {\n            function Dropdown($element, options) {\n                this.$element = $element;\n                this.options = options;\n\n                Dropdown.__super__.constructor.call(this);\n            }\n\n            Utils.Extend(Dropdown, Utils.Observable);\n\n            Dropdown.prototype.render = function () {\n                var $dropdown = $(\n                    '<span class=\"select2-dropdown\">' +\n                    '<span class=\"select2-results\"></span>' +\n                    '</span>'\n                );\n\n                $dropdown.attr('dir', this.options.get('dir'));\n\n                this.$dropdown = $dropdown;\n\n                return $dropdown;\n            };\n\n            Dropdown.prototype.bind = function () {\n                // Should be implemented in subclasses\n            };\n\n            Dropdown.prototype.position = function ($dropdown, $container) {\n                // Should be implmented in subclasses\n            };\n\n            Dropdown.prototype.destroy = function () {\n                // Remove the dropdown from the DOM\n                this.$dropdown.remove();\n            };\n\n            return Dropdown;\n        });\n\n        S2.define('select2/dropdown/search', [\n            'jquery',\n            '../utils'\n        ], function ($, Utils) {\n            function Search() {\n            }\n\n            Search.prototype.render = function (decorated) {\n                var $rendered = decorated.call(this);\n\n                var $search = $(\n                    '<span class=\"select2-search select2-search--dropdown\">' +\n                    '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n                    ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"none\"' +\n                    ' spellcheck=\"false\" role=\"textbox\" />' +\n                    '</span>'\n                );\n\n                this.$searchContainer = $search;\n                this.$search = $search.find('input');\n\n                $rendered.prepend($search);\n\n                return $rendered;\n            };\n\n            Search.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                this.$search.on('keydown', function (evt) {\n                    self.trigger('keypress', evt);\n\n                    self._keyUpPrevented = evt.isDefaultPrevented();\n                });\n\n                // Workaround for browsers which do not support the `input` event\n                // This will prevent double-triggering of events for browsers which support\n                // both the `keyup` and `input` events.\n                this.$search.on('input', function (evt) {\n                    // Unbind the duplicated `keyup` event\n                    $(this).off('keyup');\n                });\n\n                this.$search.on('keyup input', function (evt) {\n                    self.handleSearch(evt);\n                });\n\n                container.on('open', function () {\n                    self.$search.attr('tabindex', 0);\n\n                    self.$search.focus();\n\n                    window.setTimeout(function () {\n                        self.$search.focus();\n                    }, 0);\n                });\n\n                container.on('close', function () {\n                    self.$search.attr('tabindex', -1);\n\n                    self.$search.val('');\n                    self.$search.blur();\n                });\n\n                container.on('focus', function () {\n                    if (!container.isOpen()) {\n                        self.$search.focus();\n                    }\n                });\n\n                container.on('results:all', function (params) {\n                    if (params.query.term == null || params.query.term === '') {\n                        var showSearch = self.showSearch(params);\n\n                        if (showSearch) {\n                            self.$searchContainer.removeClass('select2-search--hide');\n                        } else {\n                            self.$searchContainer.addClass('select2-search--hide');\n                        }\n                    }\n                });\n            };\n\n            Search.prototype.handleSearch = function (evt) {\n                if (!this._keyUpPrevented) {\n                    var input = this.$search.val();\n\n                    this.trigger('query', {\n                        term: input\n                    });\n                }\n\n                this._keyUpPrevented = false;\n            };\n\n            Search.prototype.showSearch = function (_, params) {\n                return true;\n            };\n\n            return Search;\n        });\n\n        S2.define('select2/dropdown/hidePlaceholder', [], function () {\n            function HidePlaceholder(decorated, $element, options, dataAdapter) {\n                this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n                decorated.call(this, $element, options, dataAdapter);\n            }\n\n            HidePlaceholder.prototype.append = function (decorated, data) {\n                data.results = this.removePlaceholder(data.results);\n\n                decorated.call(this, data);\n            };\n\n            HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {\n                if (typeof placeholder === 'string') {\n                    placeholder = {\n                        id: '',\n                        text: placeholder\n                    };\n                }\n\n                return placeholder;\n            };\n\n            HidePlaceholder.prototype.removePlaceholder = function (_, data) {\n                var modifiedData = data.slice(0);\n\n                for (var d = data.length - 1; d >= 0; d--) {\n                    var item = data[d];\n\n                    if (this.placeholder.id === item.id) {\n                        modifiedData.splice(d, 1);\n                    }\n                }\n\n                return modifiedData;\n            };\n\n            return HidePlaceholder;\n        });\n\n        S2.define('select2/dropdown/infiniteScroll', [\n            'jquery'\n        ], function ($) {\n            function InfiniteScroll(decorated, $element, options, dataAdapter) {\n                this.lastParams = {};\n\n                decorated.call(this, $element, options, dataAdapter);\n\n                this.$loadingMore = this.createLoadingMore();\n                this.loading = false;\n            }\n\n            InfiniteScroll.prototype.append = function (decorated, data) {\n                this.$loadingMore.remove();\n                this.loading = false;\n\n                decorated.call(this, data);\n\n                if (this.showLoadingMore(data)) {\n                    this.$results.append(this.$loadingMore);\n                }\n            };\n\n            InfiniteScroll.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('query', function (params) {\n                    self.lastParams = params;\n                    self.loading = true;\n                });\n\n                container.on('query:append', function (params) {\n                    self.lastParams = params;\n                    self.loading = true;\n                });\n\n                this.$results.on('scroll', function () {\n                    var isLoadMoreVisible = $.contains(\n                        document.documentElement,\n                        self.$loadingMore[0]\n                    );\n\n                    if (self.loading || !isLoadMoreVisible) {\n                        return;\n                    }\n\n                    var currentOffset = self.$results.offset().top +\n                        self.$results.outerHeight(false);\n                    var loadingMoreOffset = self.$loadingMore.offset().top +\n                        self.$loadingMore.outerHeight(false);\n\n                    if (currentOffset + 50 >= loadingMoreOffset) {\n                        self.loadMore();\n                    }\n                });\n            };\n\n            InfiniteScroll.prototype.loadMore = function () {\n                this.loading = true;\n\n                var params = $.extend({}, {page: 1}, this.lastParams);\n\n                params.page++;\n\n                this.trigger('query:append', params);\n            };\n\n            InfiniteScroll.prototype.showLoadingMore = function (_, data) {\n                return data.pagination && data.pagination.more;\n            };\n\n            InfiniteScroll.prototype.createLoadingMore = function () {\n                var $option = $(\n                    '<li ' +\n                    'class=\"select2-results__option select2-results__option--load-more\"' +\n                    'role=\"treeitem\" aria-disabled=\"true\"></li>'\n                );\n\n                var message = this.options.get('translations').get('loadingMore');\n\n                $option.html(message(this.lastParams));\n\n                return $option;\n            };\n\n            return InfiniteScroll;\n        });\n\n        S2.define('select2/dropdown/attachBody', [\n            'jquery',\n            '../utils'\n        ], function ($, Utils) {\n            function AttachBody(decorated, $element, options) {\n                this.$dropdownParent = options.get('dropdownParent') || $(document.body);\n\n                decorated.call(this, $element, options);\n            }\n\n            AttachBody.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                var setupResultsEvents = false;\n\n                decorated.call(this, container, $container);\n\n                container.on('open', function () {\n                    self._showDropdown();\n                    self._attachPositioningHandler(container);\n\n                    if (!setupResultsEvents) {\n                        setupResultsEvents = true;\n\n                        container.on('results:all', function () {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n\n                        container.on('results:append', function () {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n                    }\n                });\n\n                container.on('close', function () {\n                    self._hideDropdown();\n                    self._detachPositioningHandler(container);\n                });\n\n                this.$dropdownContainer.on('mousedown', function (evt) {\n                    evt.stopPropagation();\n                });\n            };\n\n            AttachBody.prototype.destroy = function (decorated) {\n                decorated.call(this);\n\n                this.$dropdownContainer.remove();\n            };\n\n            AttachBody.prototype.position = function (decorated, $dropdown, $container) {\n                // Clone all of the container classes\n                $dropdown.attr('class', $container.attr('class'));\n\n                $dropdown.removeClass('select2');\n                $dropdown.addClass('select2-container--open');\n\n                $dropdown.css({\n                    position: 'absolute',\n                    top: -999999\n                });\n\n                this.$container = $container;\n            };\n\n            AttachBody.prototype.render = function (decorated) {\n                var $container = $('<span></span>');\n\n                var $dropdown = decorated.call(this);\n                $container.append($dropdown);\n\n                this.$dropdownContainer = $container;\n\n                return $container;\n            };\n\n            AttachBody.prototype._hideDropdown = function (decorated) {\n                this.$dropdownContainer.detach();\n            };\n\n            AttachBody.prototype._attachPositioningHandler =\n                function (decorated, container) {\n                    var self = this;\n\n                    var scrollEvent = 'scroll.select2.' + container.id;\n                    var resizeEvent = 'resize.select2.' + container.id;\n                    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n                    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n                    $watchers.each(function () {\n                        Utils.StoreData(this, 'select2-scroll-position', {\n                            x: $(this).scrollLeft(),\n                            y: $(this).scrollTop()\n                        });\n                    });\n\n                    $watchers.on(scrollEvent, function (ev) {\n                        var position = Utils.GetData(this, 'select2-scroll-position');\n                        $(this).scrollTop(position.y);\n                    });\n\n                    $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,\n                        function (e) {\n                            self._positionDropdown();\n                            self._resizeDropdown();\n                        });\n                };\n\n            AttachBody.prototype._detachPositioningHandler =\n                function (decorated, container) {\n                    var scrollEvent = 'scroll.select2.' + container.id;\n                    var resizeEvent = 'resize.select2.' + container.id;\n                    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n                    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n                    $watchers.off(scrollEvent);\n\n                    $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);\n                };\n\n            AttachBody.prototype._positionDropdown = function () {\n                var $window = $(window);\n\n                var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');\n                var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');\n\n                var newDirection = null;\n\n                var offset = this.$container.offset();\n\n                offset.bottom = offset.top + this.$container.outerHeight(false);\n\n                var container = {\n                    height: this.$container.outerHeight(false)\n                };\n\n                container.top = offset.top;\n                container.bottom = offset.top + container.height;\n\n                var dropdown = {\n                    height: this.$dropdown.outerHeight(false)\n                };\n\n                var viewport = {\n                    top: $window.scrollTop(),\n                    bottom: $window.scrollTop() + $window.height()\n                };\n\n                var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);\n                var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);\n\n                var css = {\n                    left: offset.left,\n                    top: container.bottom\n                };\n\n                // Determine what the parent element is to use for calciulating the offset\n                var $offsetParent = this.$dropdownParent;\n\n                // For statically positoned elements, we need to get the element\n                // that is determining the offset\n                if ($offsetParent.css('position') === 'static') {\n                    $offsetParent = $offsetParent.offsetParent();\n                }\n\n                var parentOffset = $offsetParent.offset();\n\n                css.top -= parentOffset.top;\n                css.left -= parentOffset.left;\n\n                if (!isCurrentlyAbove && !isCurrentlyBelow) {\n                    newDirection = 'below';\n                }\n\n                if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {\n                    newDirection = 'above';\n                } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {\n                    newDirection = 'below';\n                }\n\n                if (newDirection == 'above' ||\n                    (isCurrentlyAbove && newDirection !== 'below')) {\n                    css.top = container.top - parentOffset.top - dropdown.height;\n                }\n\n                if (newDirection != null) {\n                    this.$dropdown\n                        .removeClass('select2-dropdown--below select2-dropdown--above')\n                        .addClass('select2-dropdown--' + newDirection);\n                    this.$container\n                        .removeClass('select2-container--below select2-container--above')\n                        .addClass('select2-container--' + newDirection);\n                }\n\n                this.$dropdownContainer.css(css);\n            };\n\n            AttachBody.prototype._resizeDropdown = function () {\n                var css = {\n                    width: this.$container.outerWidth(false) + 'px'\n                };\n\n                if (this.options.get('dropdownAutoWidth')) {\n                    css.minWidth = css.width;\n                    css.position = 'relative';\n                    css.width = 'auto';\n                }\n\n                this.$dropdown.css(css);\n            };\n\n            AttachBody.prototype._showDropdown = function (decorated) {\n                this.$dropdownContainer.appendTo(this.$dropdownParent);\n\n                this._positionDropdown();\n                this._resizeDropdown();\n            };\n\n            return AttachBody;\n        });\n\n        S2.define('select2/dropdown/minimumResultsForSearch', [], function () {\n            function countResults(data) {\n                var count = 0;\n\n                for (var d = 0; d < data.length; d++) {\n                    var item = data[d];\n\n                    if (item.children) {\n                        count += countResults(item.children);\n                    } else {\n                        count++;\n                    }\n                }\n\n                return count;\n            }\n\n            function MinimumResultsForSearch(decorated, $element, options, dataAdapter) {\n                this.minimumResultsForSearch = options.get('minimumResultsForSearch');\n\n                if (this.minimumResultsForSearch < 0) {\n                    this.minimumResultsForSearch = Infinity;\n                }\n\n                decorated.call(this, $element, options, dataAdapter);\n            }\n\n            MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {\n                if (countResults(params.data.results) < this.minimumResultsForSearch) {\n                    return false;\n                }\n\n                return decorated.call(this, params);\n            };\n\n            return MinimumResultsForSearch;\n        });\n\n        S2.define('select2/dropdown/selectOnClose', [\n            '../utils'\n        ], function (Utils) {\n            function SelectOnClose() {\n            }\n\n            SelectOnClose.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('close', function (params) {\n                    self._handleSelectOnClose(params);\n                });\n            };\n\n            SelectOnClose.prototype._handleSelectOnClose = function (_, params) {\n                if (params && params.originalSelect2Event != null) {\n                    var event = params.originalSelect2Event;\n\n                    // Don't select an item if the close event was triggered from a select or\n                    // unselect event\n                    if (event._type === 'select' || event._type === 'unselect') {\n                        return;\n                    }\n                }\n\n                var $highlightedResults = this.getHighlightedResults();\n\n                // Only select highlighted results\n                if ($highlightedResults.length < 1) {\n                    return;\n                }\n\n                var data = Utils.GetData($highlightedResults[0], 'data');\n\n                // Don't re-select already selected resulte\n                if (\n                    (data.element != null && data.element.selected) ||\n                    (data.element == null && data.selected)\n                ) {\n                    return;\n                }\n\n                this.trigger('select', {\n                    data: data\n                });\n            };\n\n            return SelectOnClose;\n        });\n\n        S2.define('select2/dropdown/closeOnSelect', [], function () {\n            function CloseOnSelect() {\n            }\n\n            CloseOnSelect.prototype.bind = function (decorated, container, $container) {\n                var self = this;\n\n                decorated.call(this, container, $container);\n\n                container.on('select', function (evt) {\n                    self._selectTriggered(evt);\n                });\n\n                container.on('unselect', function (evt) {\n                    self._selectTriggered(evt);\n                });\n            };\n\n            CloseOnSelect.prototype._selectTriggered = function (_, evt) {\n                var originalEvent = evt.originalEvent;\n\n                // Don't close if the control key is being held\n                if (originalEvent && originalEvent.ctrlKey) {\n                    return;\n                }\n\n                this.trigger('close', {\n                    originalEvent: originalEvent,\n                    originalSelect2Event: evt\n                });\n            };\n\n            return CloseOnSelect;\n        });\n\n        S2.define('select2/i18n/en', [], function () {\n            // English\n            return {\n                errorLoading: function () {\n                    return 'The results could not be loaded.';\n                },\n                inputTooLong: function (args) {\n                    var overChars = args.input.length - args.maximum;\n\n                    var message = 'Please delete ' + overChars + ' character';\n\n                    if (overChars != 1) {\n                        message += 's';\n                    }\n\n                    return message;\n                },\n                inputTooShort: function (args) {\n                    var remainingChars = args.minimum - args.input.length;\n\n                    var message = 'Please enter ' + remainingChars + ' or more characters';\n\n                    return message;\n                },\n                loadingMore: function () {\n                    return 'Loading more results…';\n                },\n                maximumSelected: function (args) {\n                    var message = 'You can only select ' + args.maximum + ' item';\n\n                    if (args.maximum != 1) {\n                        message += 's';\n                    }\n\n                    return message;\n                },\n                noResults: function () {\n                    return 'No results found';\n                },\n                searching: function () {\n                    return 'Searching…';\n                }\n            };\n        });\n\n        S2.define('select2/defaults', [\n            'jquery',\n            'require',\n\n            './results',\n\n            './selection/single',\n            './selection/multiple',\n            './selection/placeholder',\n            './selection/allowClear',\n            './selection/search',\n            './selection/eventRelay',\n\n            './utils',\n            './translation',\n            './diacritics',\n\n            './data/select',\n            './data/array',\n            './data/ajax',\n            './data/tags',\n            './data/tokenizer',\n            './data/minimumInputLength',\n            './data/maximumInputLength',\n            './data/maximumSelectionLength',\n\n            './dropdown',\n            './dropdown/search',\n            './dropdown/hidePlaceholder',\n            './dropdown/infiniteScroll',\n            './dropdown/attachBody',\n            './dropdown/minimumResultsForSearch',\n            './dropdown/selectOnClose',\n            './dropdown/closeOnSelect',\n\n            './i18n/en'\n        ], function ($, require,\n                     ResultsList,\n                     SingleSelection, MultipleSelection, Placeholder, AllowClear,\n                     SelectionSearch, EventRelay,\n                     Utils, Translation, DIACRITICS,\n                     SelectData, ArrayData, AjaxData, Tags, Tokenizer,\n                     MinimumInputLength, MaximumInputLength, MaximumSelectionLength,\n                     Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,\n                     AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,\n                     EnglishTranslation) {\n            function Defaults() {\n                this.reset();\n            }\n\n            Defaults.prototype.apply = function (options) {\n                options = $.extend(true, {}, this.defaults, options);\n\n                if (options.dataAdapter == null) {\n                    if (options.ajax != null) {\n                        options.dataAdapter = AjaxData;\n                    } else if (options.data != null) {\n                        options.dataAdapter = ArrayData;\n                    } else {\n                        options.dataAdapter = SelectData;\n                    }\n\n                    if (options.minimumInputLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MinimumInputLength\n                        );\n                    }\n\n                    if (options.maximumInputLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MaximumInputLength\n                        );\n                    }\n\n                    if (options.maximumSelectionLength > 0) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            MaximumSelectionLength\n                        );\n                    }\n\n                    if (options.tags) {\n                        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);\n                    }\n\n                    if (options.tokenSeparators != null || options.tokenizer != null) {\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            Tokenizer\n                        );\n                    }\n\n                    if (options.query != null) {\n                        var Query = require(options.amdBase + 'compat/query');\n\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            Query\n                        );\n                    }\n\n                    if (options.initSelection != null) {\n                        var InitSelection = require(options.amdBase + 'compat/initSelection');\n\n                        options.dataAdapter = Utils.Decorate(\n                            options.dataAdapter,\n                            InitSelection\n                        );\n                    }\n                }\n\n                if (options.resultsAdapter == null) {\n                    options.resultsAdapter = ResultsList;\n\n                    if (options.ajax != null) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            InfiniteScroll\n                        );\n                    }\n\n                    if (options.placeholder != null) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            HidePlaceholder\n                        );\n                    }\n\n                    if (options.selectOnClose) {\n                        options.resultsAdapter = Utils.Decorate(\n                            options.resultsAdapter,\n                            SelectOnClose\n                        );\n                    }\n                }\n\n                if (options.dropdownAdapter == null) {\n                    if (options.multiple) {\n                        options.dropdownAdapter = Dropdown;\n                    } else {\n                        var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);\n\n                        options.dropdownAdapter = SearchableDropdown;\n                    }\n\n                    if (options.minimumResultsForSearch !== 0) {\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            MinimumResultsForSearch\n                        );\n                    }\n\n                    if (options.closeOnSelect) {\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            CloseOnSelect\n                        );\n                    }\n\n                    if (\n                        options.dropdownCssClass != null ||\n                        options.dropdownCss != null ||\n                        options.adaptDropdownCssClass != null\n                    ) {\n                        var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');\n\n                        options.dropdownAdapter = Utils.Decorate(\n                            options.dropdownAdapter,\n                            DropdownCSS\n                        );\n                    }\n\n                    options.dropdownAdapter = Utils.Decorate(\n                        options.dropdownAdapter,\n                        AttachBody\n                    );\n                }\n\n                if (options.selectionAdapter == null) {\n                    if (options.multiple) {\n                        options.selectionAdapter = MultipleSelection;\n                    } else {\n                        options.selectionAdapter = SingleSelection;\n                    }\n\n                    // Add the placeholder mixin if a placeholder was specified\n                    if (options.placeholder != null) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            Placeholder\n                        );\n                    }\n\n                    if (options.allowClear) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            AllowClear\n                        );\n                    }\n\n                    if (options.multiple) {\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            SelectionSearch\n                        );\n                    }\n\n                    if (\n                        options.containerCssClass != null ||\n                        options.containerCss != null ||\n                        options.adaptContainerCssClass != null\n                    ) {\n                        var ContainerCSS = require(options.amdBase + 'compat/containerCss');\n\n                        options.selectionAdapter = Utils.Decorate(\n                            options.selectionAdapter,\n                            ContainerCSS\n                        );\n                    }\n\n                    options.selectionAdapter = Utils.Decorate(\n                        options.selectionAdapter,\n                        EventRelay\n                    );\n                }\n\n                if (typeof options.language === 'string') {\n                    // Check if the language is specified with a region\n                    if (options.language.indexOf('-') > 0) {\n                        // Extract the region information if it is included\n                        var languageParts = options.language.split('-');\n                        var baseLanguage = languageParts[0];\n\n                        options.language = [options.language, baseLanguage];\n                    } else {\n                        options.language = [options.language];\n                    }\n                }\n\n                if ($.isArray(options.language)) {\n                    var languages = new Translation();\n                    options.language.push('en');\n\n                    var languageNames = options.language;\n\n                    for (var l = 0; l < languageNames.length; l++) {\n                        var name = languageNames[l];\n                        var language = {};\n\n                        try {\n                            // Try to load it with the original name\n                            language = Translation.loadPath(name);\n                        } catch (e) {\n                            try {\n                                // If we couldn't load it, check if it wasn't the full path\n                                name = this.defaults.amdLanguageBase + name;\n                                language = Translation.loadPath(name);\n                            } catch (ex) {\n                                // The translation could not be loaded at all. Sometimes this is\n                                // because of a configuration problem, other times this can be\n                                // because of how Select2 helps load all possible translation files.\n                                if (options.debug && window.console && console.warn) {\n                                    console.warn(\n                                        'Select2: The language file for \"' + name + '\" could not be ' +\n                                        'automatically loaded. A fallback will be used instead.'\n                                    );\n                                }\n\n                                continue;\n                            }\n                        }\n\n                        languages.extend(language);\n                    }\n\n                    options.translations = languages;\n                } else {\n                    var baseTranslation = Translation.loadPath(\n                        this.defaults.amdLanguageBase + 'en'\n                    );\n                    var customTranslation = new Translation(options.language);\n\n                    customTranslation.extend(baseTranslation);\n\n                    options.translations = customTranslation;\n                }\n\n                return options;\n            };\n\n            Defaults.prototype.reset = function () {\n                function stripDiacritics(text) {\n                    // Used 'uni range + named function' from http://jsperf.com/diacritics/18\n                    function match(a) {\n                        return DIACRITICS[a] || a;\n                    }\n\n                    return text.replace(/[^\\u0000-\\u007E]/g, match);\n                }\n\n                function matcher(params, data) {\n                    // Always return the object if there is nothing to compare\n                    if ($.trim(params.term) === '') {\n                        return data;\n                    }\n\n                    // Do a recursive check for options with children\n                    if (data.children && data.children.length > 0) {\n                        // Clone the data object if there are children\n                        // This is required as we modify the object to remove any non-matches\n                        var match = $.extend(true, {}, data);\n\n                        // Check each child of the option\n                        for (var c = data.children.length - 1; c >= 0; c--) {\n                            var child = data.children[c];\n\n                            var matches = matcher(params, child);\n\n                            // If there wasn't a match, remove the object in the array\n                            if (matches == null) {\n                                match.children.splice(c, 1);\n                            }\n                        }\n\n                        // If any children matched, return the new object\n                        if (match.children.length > 0) {\n                            return match;\n                        }\n\n                        // If there were no matching children, check just the plain object\n                        return matcher(params, match);\n                    }\n\n                    var original = stripDiacritics(data.text).toUpperCase();\n                    var term = stripDiacritics(params.term).toUpperCase();\n\n                    // Check if the text contains the term\n                    if (original.indexOf(term) > -1) {\n                        return data;\n                    }\n\n                    // If it doesn't contain the term, don't return anything\n                    return null;\n                }\n\n                this.defaults = {\n                    amdBase: './',\n                    amdLanguageBase: './i18n/',\n                    closeOnSelect: true,\n                    debug: false,\n                    dropdownAutoWidth: false,\n                    escapeMarkup: Utils.escapeMarkup,\n                    language: EnglishTranslation,\n                    matcher: matcher,\n                    minimumInputLength: 0,\n                    maximumInputLength: 0,\n                    maximumSelectionLength: 0,\n                    minimumResultsForSearch: 0,\n                    selectOnClose: false,\n                    sorter: function (data) {\n                        return data;\n                    },\n                    templateResult: function (result) {\n                        return result.text;\n                    },\n                    templateSelection: function (selection) {\n                        return selection.text;\n                    },\n                    theme: 'default',\n                    width: 'resolve'\n                };\n            };\n\n            Defaults.prototype.set = function (key, value) {\n                var camelKey = $.camelCase(key);\n\n                var data = {};\n                data[camelKey] = value;\n\n                var convertedData = Utils._convertData(data);\n\n                $.extend(true, this.defaults, convertedData);\n            };\n\n            var defaults = new Defaults();\n\n            return defaults;\n        });\n\n        S2.define('select2/options', [\n            'require',\n            'jquery',\n            './defaults',\n            './utils'\n        ], function (require, $, Defaults, Utils) {\n            function Options(options, $element) {\n                this.options = options;\n\n                if ($element != null) {\n                    this.fromElement($element);\n                }\n\n                this.options = Defaults.apply(this.options);\n\n                if ($element && $element.is('input')) {\n                    var InputCompat = require(this.get('amdBase') + 'compat/inputData');\n\n                    this.options.dataAdapter = Utils.Decorate(\n                        this.options.dataAdapter,\n                        InputCompat\n                    );\n                }\n            }\n\n            Options.prototype.fromElement = function ($e) {\n                var excludedData = ['select2'];\n\n                if (this.options.multiple == null) {\n                    this.options.multiple = $e.prop('multiple');\n                }\n\n                if (this.options.disabled == null) {\n                    this.options.disabled = $e.prop('disabled');\n                }\n\n                if (this.options.language == null) {\n                    if ($e.prop('lang')) {\n                        this.options.language = $e.prop('lang').toLowerCase();\n                    } else if ($e.closest('[lang]').prop('lang')) {\n                        this.options.language = $e.closest('[lang]').prop('lang');\n                    }\n                }\n\n                if (this.options.dir == null) {\n                    if ($e.prop('dir')) {\n                        this.options.dir = $e.prop('dir');\n                    } else if ($e.closest('[dir]').prop('dir')) {\n                        this.options.dir = $e.closest('[dir]').prop('dir');\n                    } else {\n                        this.options.dir = 'ltr';\n                    }\n                }\n\n                $e.prop('disabled', this.options.disabled);\n                $e.prop('multiple', this.options.multiple);\n\n                if (Utils.GetData($e[0], 'select2Tags')) {\n                    if (this.options.debug && window.console && console.warn) {\n                        console.warn(\n                            'Select2: The `data-select2-tags` attribute has been changed to ' +\n                            'use the `data-data` and `data-tags=\"true\"` attributes and will be ' +\n                            'removed in future versions of Select2.'\n                        );\n                    }\n\n                    Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));\n                    Utils.StoreData($e[0], 'tags', true);\n                }\n\n                if (Utils.GetData($e[0], 'ajaxUrl')) {\n                    if (this.options.debug && window.console && console.warn) {\n                        console.warn(\n                            'Select2: The `data-ajax-url` attribute has been changed to ' +\n                            '`data-ajax--url` and support for the old attribute will be removed' +\n                            ' in future versions of Select2.'\n                        );\n                    }\n\n                    $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));\n                    Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));\n\n                }\n\n                var dataset = {};\n\n                // Prefer the element's `dataset` attribute if it exists\n                // jQuery 1.x does not correctly handle data attributes with multiple dashes\n                if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {\n                    dataset = $.extend(true, {}, $e[0].dataset, Utils.GetData($e[0]));\n                } else {\n                    dataset = Utils.GetData($e[0]);\n                }\n\n                var data = $.extend(true, {}, dataset);\n\n                data = Utils._convertData(data);\n\n                for (var key in data) {\n                    if ($.inArray(key, excludedData) > -1) {\n                        continue;\n                    }\n\n                    if ($.isPlainObject(this.options[key])) {\n                        $.extend(this.options[key], data[key]);\n                    } else {\n                        this.options[key] = data[key];\n                    }\n                }\n\n                return this;\n            };\n\n            Options.prototype.get = function (key) {\n                return this.options[key];\n            };\n\n            Options.prototype.set = function (key, val) {\n                this.options[key] = val;\n            };\n\n            return Options;\n        });\n\n        S2.define('select2/core', [\n            'jquery',\n            './options',\n            './utils',\n            './keys'\n        ], function ($, Options, Utils, KEYS) {\n            var Select2 = function ($element, options) {\n                if (Utils.GetData($element[0], 'select2') != null) {\n                    Utils.GetData($element[0], 'select2').destroy();\n                }\n\n                this.$element = $element;\n\n                this.id = this._generateId($element);\n\n                options = options || {};\n\n                this.options = new Options(options, $element);\n\n                Select2.__super__.constructor.call(this);\n\n                // Set up the tabindex\n\n                var tabindex = $element.attr('tabindex') || 0;\n                Utils.StoreData($element[0], 'old-tabindex', tabindex);\n                $element.attr('tabindex', '-1');\n\n                // Set up containers and adapters\n\n                var DataAdapter = this.options.get('dataAdapter');\n                this.dataAdapter = new DataAdapter($element, this.options);\n\n                var $container = this.render();\n\n                this._placeContainer($container);\n\n                var SelectionAdapter = this.options.get('selectionAdapter');\n                this.selection = new SelectionAdapter($element, this.options);\n                this.$selection = this.selection.render();\n\n                this.selection.position(this.$selection, $container);\n\n                var DropdownAdapter = this.options.get('dropdownAdapter');\n                this.dropdown = new DropdownAdapter($element, this.options);\n                this.$dropdown = this.dropdown.render();\n\n                this.dropdown.position(this.$dropdown, $container);\n\n                var ResultsAdapter = this.options.get('resultsAdapter');\n                this.results = new ResultsAdapter($element, this.options, this.dataAdapter);\n                this.$results = this.results.render();\n\n                this.results.position(this.$results, this.$dropdown);\n\n                // Bind events\n\n                var self = this;\n\n                // Bind the container to all of the adapters\n                this._bindAdapters();\n\n                // Register any DOM event handlers\n                this._registerDomEvents();\n\n                // Register any internal event handlers\n                this._registerDataEvents();\n                this._registerSelectionEvents();\n                this._registerDropdownEvents();\n                this._registerResultsEvents();\n                this._registerEvents();\n\n                // Set the initial state\n                this.dataAdapter.current(function (initialData) {\n                    self.trigger('selection:update', {\n                        data: initialData\n                    });\n                });\n\n                // Hide the original select\n                $element.addClass('select2-hidden-accessible');\n                $element.attr('aria-hidden', 'true');\n\n                // Synchronize any monitored attributes\n                this._syncAttributes();\n\n                Utils.StoreData($element[0], 'select2', this);\n\n                // Ensure backwards compatibility with $element.data('select2').\n                $element.data('select2', this);\n            };\n\n            Utils.Extend(Select2, Utils.Observable);\n\n            Select2.prototype._generateId = function ($element) {\n                var id = '';\n\n                if ($element.attr('id') != null) {\n                    id = $element.attr('id');\n                } else if ($element.attr('name') != null) {\n                    id = $element.attr('name') + '-' + Utils.generateChars(2);\n                } else {\n                    id = Utils.generateChars(4);\n                }\n\n                id = id.replace(/(:|\\.|\\[|\\]|,)/g, '');\n                id = 'select2-' + id;\n\n                return id;\n            };\n\n            Select2.prototype._placeContainer = function ($container) {\n                $container.insertAfter(this.$element);\n\n                var width = this._resolveWidth(this.$element, this.options.get('width'));\n\n                if (width != null) {\n                    $container.css('width', width);\n                }\n            };\n\n            Select2.prototype._resolveWidth = function ($element, method) {\n                var WIDTH = /^width:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;\n\n                if (method == 'resolve') {\n                    var styleWidth = this._resolveWidth($element, 'style');\n\n                    if (styleWidth != null) {\n                        return styleWidth;\n                    }\n\n                    return this._resolveWidth($element, 'element');\n                }\n\n                if (method == 'element') {\n                    var elementWidth = $element.outerWidth(false);\n\n                    if (elementWidth <= 0) {\n                        return 'auto';\n                    }\n\n                    return elementWidth + 'px';\n                }\n\n                if (method == 'style') {\n                    var style = $element.attr('style');\n\n                    if (typeof(style) !== 'string') {\n                        return null;\n                    }\n\n                    var attrs = style.split(';');\n\n                    for (var i = 0, l = attrs.length; i < l; i = i + 1) {\n                        var attr = attrs[i].replace(/\\s/g, '');\n                        var matches = attr.match(WIDTH);\n\n                        if (matches !== null && matches.length >= 1) {\n                            return matches[1];\n                        }\n                    }\n\n                    return null;\n                }\n\n                return method;\n            };\n\n            Select2.prototype._bindAdapters = function () {\n                this.dataAdapter.bind(this, this.$container);\n                this.selection.bind(this, this.$container);\n\n                this.dropdown.bind(this, this.$container);\n                this.results.bind(this, this.$container);\n            };\n\n            Select2.prototype._registerDomEvents = function () {\n                var self = this;\n\n                this.$element.on('change.select2', function () {\n                    self.dataAdapter.current(function (data) {\n                        self.trigger('selection:update', {\n                            data: data\n                        });\n                    });\n                });\n\n                this.$element.on('focus.select2', function (evt) {\n                    self.trigger('focus', evt);\n                });\n\n                this._syncA = Utils.bind(this._syncAttributes, this);\n                this._syncS = Utils.bind(this._syncSubtree, this);\n\n                if (this.$element[0].attachEvent) {\n                    this.$element[0].attachEvent('onpropertychange', this._syncA);\n                }\n\n                var observer = window.MutationObserver ||\n                    window.WebKitMutationObserver ||\n                    window.MozMutationObserver\n                ;\n\n                if (observer != null) {\n                    this._observer = new observer(function (mutations) {\n                        $.each(mutations, self._syncA);\n                        $.each(mutations, self._syncS);\n                    });\n                    this._observer.observe(this.$element[0], {\n                        attributes: true,\n                        childList: true,\n                        subtree: false\n                    });\n                } else if (this.$element[0].addEventListener) {\n                    this.$element[0].addEventListener(\n                        'DOMAttrModified',\n                        self._syncA,\n                        false\n                    );\n                    this.$element[0].addEventListener(\n                        'DOMNodeInserted',\n                        self._syncS,\n                        false\n                    );\n                    this.$element[0].addEventListener(\n                        'DOMNodeRemoved',\n                        self._syncS,\n                        false\n                    );\n                }\n            };\n\n            Select2.prototype._registerDataEvents = function () {\n                var self = this;\n\n                this.dataAdapter.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerSelectionEvents = function () {\n                var self = this;\n                var nonRelayEvents = ['toggle', 'focus'];\n\n                this.selection.on('toggle', function () {\n                    self.toggleDropdown();\n                });\n\n                this.selection.on('focus', function (params) {\n                    self.focus(params);\n                });\n\n                this.selection.on('*', function (name, params) {\n                    if ($.inArray(name, nonRelayEvents) !== -1) {\n                        return;\n                    }\n\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerDropdownEvents = function () {\n                var self = this;\n\n                this.dropdown.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerResultsEvents = function () {\n                var self = this;\n\n                this.results.on('*', function (name, params) {\n                    self.trigger(name, params);\n                });\n            };\n\n            Select2.prototype._registerEvents = function () {\n                var self = this;\n\n                this.on('open', function () {\n                    self.$container.addClass('select2-container--open');\n                });\n\n                this.on('close', function () {\n                    self.$container.removeClass('select2-container--open');\n                });\n\n                this.on('enable', function () {\n                    self.$container.removeClass('select2-container--disabled');\n                });\n\n                this.on('disable', function () {\n                    self.$container.addClass('select2-container--disabled');\n                });\n\n                this.on('blur', function () {\n                    self.$container.removeClass('select2-container--focus');\n                });\n\n                this.on('query', function (params) {\n                    if (!self.isOpen()) {\n                        self.trigger('open', {});\n                    }\n\n                    this.dataAdapter.query(params, function (data) {\n                        self.trigger('results:all', {\n                            data: data,\n                            query: params\n                        });\n                    });\n                });\n\n                this.on('query:append', function (params) {\n                    this.dataAdapter.query(params, function (data) {\n                        self.trigger('results:append', {\n                            data: data,\n                            query: params\n                        });\n                    });\n                });\n\n                this.on('keypress', function (evt) {\n                    var key = evt.which;\n\n                    if (self.isOpen()) {\n                        if (key === KEYS.ESC || key === KEYS.TAB ||\n                            (key === KEYS.UP && evt.altKey)) {\n                            self.close();\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.ENTER) {\n                            self.trigger('results:select', {});\n\n                            evt.preventDefault();\n                        } else if ((key === KEYS.SPACE && evt.ctrlKey)) {\n                            self.trigger('results:toggle', {});\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.UP) {\n                            self.trigger('results:previous', {});\n\n                            evt.preventDefault();\n                        } else if (key === KEYS.DOWN) {\n                            self.trigger('results:next', {});\n\n                            evt.preventDefault();\n                        }\n                    } else {\n                        if (key === KEYS.ENTER || key === KEYS.SPACE ||\n                            (key === KEYS.DOWN && evt.altKey)) {\n                            self.open();\n\n                            evt.preventDefault();\n                        }\n                    }\n                });\n            };\n\n            Select2.prototype._syncAttributes = function () {\n                this.options.set('disabled', this.$element.prop('disabled'));\n\n                if (this.options.get('disabled')) {\n                    if (this.isOpen()) {\n                        this.close();\n                    }\n\n                    this.trigger('disable', {});\n                } else {\n                    this.trigger('enable', {});\n                }\n            };\n\n            Select2.prototype._syncSubtree = function (evt, mutations) {\n                var changed = false;\n                var self = this;\n\n                // Ignore any mutation events raised for elements that aren't options or\n                // optgroups. This handles the case when the select element is destroyed\n                if (\n                    evt && evt.target && (\n                        evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'\n                    )\n                ) {\n                    return;\n                }\n\n                if (!mutations) {\n                    // If mutation events aren't supported, then we can only assume that the\n                    // change affected the selections\n                    changed = true;\n                } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {\n                    for (var n = 0; n < mutations.addedNodes.length; n++) {\n                        var node = mutations.addedNodes[n];\n\n                        if (node.selected) {\n                            changed = true;\n                        }\n                    }\n                } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {\n                    changed = true;\n                }\n\n                // Only re-pull the data if we think there is a change\n                if (changed) {\n                    this.dataAdapter.current(function (currentData) {\n                        self.trigger('selection:update', {\n                            data: currentData\n                        });\n                    });\n                }\n            };\n\n            /**\n             * Override the trigger method to automatically trigger pre-events when\n             * there are events that can be prevented.\n             */\n            Select2.prototype.trigger = function (name, args) {\n                var actualTrigger = Select2.__super__.trigger;\n                var preTriggerMap = {\n                    'open': 'opening',\n                    'close': 'closing',\n                    'select': 'selecting',\n                    'unselect': 'unselecting',\n                    'clear': 'clearing'\n                };\n\n                if (args === undefined) {\n                    args = {};\n                }\n\n                if (name in preTriggerMap) {\n                    var preTriggerName = preTriggerMap[name];\n                    var preTriggerArgs = {\n                        prevented: false,\n                        name: name,\n                        args: args\n                    };\n\n                    actualTrigger.call(this, preTriggerName, preTriggerArgs);\n\n                    if (preTriggerArgs.prevented) {\n                        args.prevented = true;\n\n                        return;\n                    }\n                }\n\n                actualTrigger.call(this, name, args);\n            };\n\n            Select2.prototype.toggleDropdown = function () {\n                if (this.options.get('disabled')) {\n                    return;\n                }\n\n                if (this.isOpen()) {\n                    this.close();\n                } else {\n                    this.open();\n                }\n            };\n\n            Select2.prototype.open = function () {\n                if (this.isOpen()) {\n                    return;\n                }\n\n                this.trigger('query', {});\n            };\n\n            Select2.prototype.close = function () {\n                if (!this.isOpen()) {\n                    return;\n                }\n\n                this.trigger('close', {});\n            };\n\n            Select2.prototype.isOpen = function () {\n                return this.$container.hasClass('select2-container--open');\n            };\n\n            Select2.prototype.hasFocus = function () {\n                return this.$container.hasClass('select2-container--focus');\n            };\n\n            Select2.prototype.focus = function (data) {\n                // No need to re-trigger focus events if we are already focused\n                if (this.hasFocus()) {\n                    return;\n                }\n\n                this.$container.addClass('select2-container--focus');\n                this.trigger('focus', {});\n            };\n\n            Select2.prototype.enable = function (args) {\n                if (this.options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `select2(\"enable\")` method has been deprecated and will' +\n                        ' be removed in later Select2 versions. Use $element.prop(\"disabled\")' +\n                        ' instead.'\n                    );\n                }\n\n                if (args == null || args.length === 0) {\n                    args = [true];\n                }\n\n                var disabled = !args[0];\n\n                this.$element.prop('disabled', disabled);\n            };\n\n            Select2.prototype.data = function () {\n                if (this.options.get('debug') &&\n                    arguments.length > 0 && window.console && console.warn) {\n                    console.warn(\n                        'Select2: Data can no longer be set using `select2(\"data\")`. You ' +\n                        'should consider setting the value instead using `$element.val()`.'\n                    );\n                }\n\n                var data = [];\n\n                this.dataAdapter.current(function (currentData) {\n                    data = currentData;\n                });\n\n                return data;\n            };\n\n            Select2.prototype.val = function (args) {\n                if (this.options.get('debug') && window.console && console.warn) {\n                    console.warn(\n                        'Select2: The `select2(\"val\")` method has been deprecated and will be' +\n                        ' removed in later Select2 versions. Use $element.val() instead.'\n                    );\n                }\n\n                if (args == null || args.length === 0) {\n                    return this.$element.val();\n                }\n\n                var newVal = args[0];\n\n                if ($.isArray(newVal)) {\n                    newVal = $.map(newVal, function (obj) {\n                        return obj.toString();\n                    });\n                }\n\n                this.$element.val(newVal).trigger('change');\n            };\n\n            Select2.prototype.destroy = function () {\n                this.$container.remove();\n\n                if (this.$element[0].detachEvent) {\n                    this.$element[0].detachEvent('onpropertychange', this._syncA);\n                }\n\n                if (this._observer != null) {\n                    this._observer.disconnect();\n                    this._observer = null;\n                } else if (this.$element[0].removeEventListener) {\n                    this.$element[0]\n                        .removeEventListener('DOMAttrModified', this._syncA, false);\n                    this.$element[0]\n                        .removeEventListener('DOMNodeInserted', this._syncS, false);\n                    this.$element[0]\n                        .removeEventListener('DOMNodeRemoved', this._syncS, false);\n                }\n\n                this._syncA = null;\n                this._syncS = null;\n\n                this.$element.off('.select2');\n                this.$element.attr('tabindex',\n                    Utils.GetData(this.$element[0], 'old-tabindex'));\n\n                this.$element.removeClass('select2-hidden-accessible');\n                this.$element.attr('aria-hidden', 'false');\n                Utils.RemoveData(this.$element[0]);\n                this.$element.removeData('select2');\n\n                this.dataAdapter.destroy();\n                this.selection.destroy();\n                this.dropdown.destroy();\n                this.results.destroy();\n\n                this.dataAdapter = null;\n                this.selection = null;\n                this.dropdown = null;\n                this.results = null;\n            };\n\n            Select2.prototype.render = function () {\n                var $container = $(\n                    '<span class=\"select2 select2-container\">' +\n                    '<span class=\"selection\"></span>' +\n                    '<span class=\"dropdown-wrapper\" aria-hidden=\"true\"></span>' +\n                    '</span>'\n                );\n\n                $container.attr('dir', this.options.get('dir'));\n\n                this.$container = $container;\n\n                this.$container.addClass('select2-container--' + this.options.get('theme'));\n\n                Utils.StoreData($container[0], 'element', this.$element);\n\n                return $container;\n            };\n\n            return Select2;\n        });\n\n        S2.define('jquery-mousewheel', [\n            'jquery'\n        ], function ($) {\n            // Used to shim jQuery.mousewheel for non-full builds.\n            return $;\n        });\n\n        S2.define('jquery.select2', [\n            'jquery',\n            'jquery-mousewheel',\n\n            './select2/core',\n            './select2/defaults',\n            './select2/utils'\n        ], function ($, _, Select2, Defaults, Utils) {\n            if ($.fn.select2 == null) {\n                // All methods that should return the element\n                var thisMethods = ['open', 'close', 'destroy'];\n\n                $.fn.select2 = function (options) {\n                    options = options || {};\n\n                    if (typeof options === 'object') {\n                        this.each(function () {\n                            var instanceOptions = $.extend(true, {}, options);\n\n                            var instance = new Select2($(this), instanceOptions);\n                        });\n\n                        return this;\n                    } else if (typeof options === 'string') {\n                        var ret;\n                        var args = Array.prototype.slice.call(arguments, 1);\n\n                        this.each(function () {\n                            var instance = Utils.GetData(this, 'select2');\n\n                            if (instance == null && window.console && console.error) {\n                                console.error(\n                                    'The select2(\\'' + options + '\\') method was called on an ' +\n                                    'element that is not using Select2.'\n                                );\n                            }\n\n                            ret = instance[options].apply(instance, args);\n                        });\n\n                        // Check if we should be returning `this`\n                        if ($.inArray(options, thisMethods) > -1) {\n                            return this;\n                        }\n\n                        return ret;\n                    } else {\n                        throw new Error('Invalid arguments for Select2: ' + options);\n                    }\n                };\n            }\n\n            if ($.fn.select2.defaults == null) {\n                $.fn.select2.defaults = Defaults;\n            }\n\n            return Select2;\n        });\n\n        // Return the AMD loader configuration so it can be used outside of this file\n        return {\n            define: S2.define,\n            require: S2.require\n        };\n    }());\n\n    // Autoload the jQuery bindings\n    // We know that all of the modules exist above this, so we're safe\n    var select2 = S2.require('jquery.select2');\n\n    // Hold the AMD module references on the jQuery function that was just loaded\n    // This allows Select2 to use the internal loader outside of this file, such\n    // as in the language files.\n    jQuery.fn.select2.amd = S2;\n\n    // Return the Select2 instance for anyone who is importing it.\n    return select2;\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/simditor/hotkeys.js",
    "content": "(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define('simple-hotkeys', [\"jquery\",\n      \"simple-module\"], function ($, SimpleModule) {\n      return (root.returnExportsGlobal = factory($, SimpleModule));\n    });\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(require(\"jquery\"),\n      require(\"simple-module\"));\n  } else {\n    root.simple = root.simple || {};\n    root.simple['hotkeys'] = factory(jQuery,\n      SimpleModule);\n  }\n}(this, function ($, SimpleModule) {\n\nvar Hotkeys, hotkeys,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nHotkeys = (function(_super) {\n  __extends(Hotkeys, _super);\n\n  function Hotkeys() {\n    return Hotkeys.__super__.constructor.apply(this, arguments);\n  }\n\n  Hotkeys.count = 0;\n\n  Hotkeys.keyNameMap = {\n    8: \"Backspace\",\n    9: \"Tab\",\n    13: \"Enter\",\n    16: \"Shift\",\n    17: \"Control\",\n    18: \"Alt\",\n    19: \"Pause\",\n    20: \"CapsLock\",\n    27: \"Esc\",\n    32: \"Spacebar\",\n    33: \"PageUp\",\n    34: \"PageDown\",\n    35: \"End\",\n    36: \"Home\",\n    37: \"Left\",\n    38: \"Up\",\n    39: \"Right\",\n    40: \"Down\",\n    45: \"Insert\",\n    46: \"Del\",\n    91: \"Meta\",\n    93: \"Meta\",\n    48: \"0\",\n    49: \"1\",\n    50: \"2\",\n    51: \"3\",\n    52: \"4\",\n    53: \"5\",\n    54: \"6\",\n    55: \"7\",\n    56: \"8\",\n    57: \"9\",\n    65: \"A\",\n    66: \"B\",\n    67: \"C\",\n    68: \"D\",\n    69: \"E\",\n    70: \"F\",\n    71: \"G\",\n    72: \"H\",\n    73: \"I\",\n    74: \"J\",\n    75: \"K\",\n    76: \"L\",\n    77: \"M\",\n    78: \"N\",\n    79: \"O\",\n    80: \"P\",\n    81: \"Q\",\n    82: \"R\",\n    83: \"S\",\n    84: \"T\",\n    85: \"U\",\n    86: \"V\",\n    87: \"W\",\n    88: \"X\",\n    89: \"Y\",\n    90: \"Z\",\n    96: \"0\",\n    97: \"1\",\n    98: \"2\",\n    99: \"3\",\n    100: \"4\",\n    101: \"5\",\n    102: \"6\",\n    103: \"7\",\n    104: \"8\",\n    105: \"9\",\n    106: \"Multiply\",\n    107: \"Add\",\n    109: \"Subtract\",\n    110: \"Decimal\",\n    111: \"Divide\",\n    112: \"F1\",\n    113: \"F2\",\n    114: \"F3\",\n    115: \"F4\",\n    116: \"F5\",\n    117: \"F6\",\n    118: \"F7\",\n    119: \"F8\",\n    120: \"F9\",\n    121: \"F10\",\n    122: \"F11\",\n    123: \"F12\",\n    124: \"F13\",\n    125: \"F14\",\n    126: \"F15\",\n    127: \"F16\",\n    128: \"F17\",\n    129: \"F18\",\n    130: \"F19\",\n    131: \"F20\",\n    132: \"F21\",\n    133: \"F22\",\n    134: \"F23\",\n    135: \"F24\",\n    59: \";\",\n    61: \"=\",\n    186: \";\",\n    187: \"=\",\n    188: \",\",\n    190: \".\",\n    191: \"/\",\n    192: \"`\",\n    219: \"[\",\n    220: \"\\\\\",\n    221: \"]\",\n    222: \"'\"\n  };\n\n  Hotkeys.aliases = {\n    \"escape\": \"esc\",\n    \"delete\": \"del\",\n    \"return\": \"enter\",\n    \"ctrl\": \"control\",\n    \"space\": \"spacebar\",\n    \"ins\": \"insert\",\n    \"cmd\": \"meta\",\n    \"command\": \"meta\",\n    \"wins\": \"meta\",\n    \"windows\": \"meta\"\n  };\n\n  Hotkeys.normalize = function(shortcut) {\n    var i, key, keyname, keys, _i, _len;\n    keys = shortcut.toLowerCase().replace(/\\s+/gi, \"\").split(\"+\");\n    for (i = _i = 0, _len = keys.length; _i < _len; i = ++_i) {\n      key = keys[i];\n      keys[i] = this.aliases[key] || key;\n    }\n    keyname = keys.pop();\n    keys.sort().push(keyname);\n    return keys.join(\"_\");\n  };\n\n  Hotkeys.prototype.opts = {\n    el: document\n  };\n\n  Hotkeys.prototype._init = function() {\n    this.id = ++this.constructor.count;\n    this._map = {};\n    this._delegate = typeof this.opts.el === \"string\" ? document : this.opts.el;\n    return $(this._delegate).on(\"keydown.simple-hotkeys-\" + this.id, this.opts.el, (function(_this) {\n      return function(e) {\n        var _ref;\n        return (_ref = _this._getHander(e)) != null ? _ref.call(_this, e) : void 0;\n      };\n    })(this));\n  };\n\n  Hotkeys.prototype._getHander = function(e) {\n    var keyname, shortcut;\n    if (!(keyname = this.constructor.keyNameMap[e.which])) {\n      return;\n    }\n    shortcut = \"\";\n    if (e.altKey) {\n      shortcut += \"alt_\";\n    }\n    if (e.ctrlKey) {\n      shortcut += \"control_\";\n    }\n    if (e.metaKey) {\n      shortcut += \"meta_\";\n    }\n    if (e.shiftKey) {\n      shortcut += \"shift_\";\n    }\n    shortcut += keyname.toLowerCase();\n    return this._map[shortcut];\n  };\n\n  Hotkeys.prototype.respondTo = function(subject) {\n    if (typeof subject === 'string') {\n      return this._map[this.constructor.normalize(subject)] != null;\n    } else {\n      return this._getHander(subject) != null;\n    }\n  };\n\n  Hotkeys.prototype.add = function(shortcut, handler) {\n    this._map[this.constructor.normalize(shortcut)] = handler;\n    return this;\n  };\n\n  Hotkeys.prototype.remove = function(shortcut) {\n    delete this._map[this.constructor.normalize(shortcut)];\n    return this;\n  };\n\n  Hotkeys.prototype.destroy = function() {\n    $(this._delegate).off(\".simple-hotkeys-\" + this.id);\n    this._map = {};\n    return this;\n  };\n\n  return Hotkeys;\n\n})(SimpleModule);\n\nhotkeys = function(opts) {\n  return new Hotkeys(opts);\n};\n\n\nreturn hotkeys;\n\n\n}));\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/simditor/module.js",
    "content": "(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define('simple-module', [\"jquery\"], function ($) {\n      return (root.returnExportsGlobal = factory($));\n    });\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(require(\"jquery\"));\n  } else {\n    root['SimpleModule'] = factory(jQuery);\n  }\n}(this, function ($) {\n\nvar Module,\n  __slice = [].slice;\n\nModule = (function() {\n  Module.extend = function(obj) {\n    var key, val, _ref;\n    if (!((obj != null) && typeof obj === 'object')) {\n      return;\n    }\n    for (key in obj) {\n      val = obj[key];\n      if (key !== 'included' && key !== 'extended') {\n        this[key] = val;\n      }\n    }\n    return (_ref = obj.extended) != null ? _ref.call(this) : void 0;\n  };\n\n  Module.include = function(obj) {\n    var key, val, _ref;\n    if (!((obj != null) && typeof obj === 'object')) {\n      return;\n    }\n    for (key in obj) {\n      val = obj[key];\n      if (key !== 'included' && key !== 'extended') {\n        this.prototype[key] = val;\n      }\n    }\n    return (_ref = obj.included) != null ? _ref.call(this) : void 0;\n  };\n\n  Module.connect = function(cls) {\n    if (typeof cls !== 'function') {\n      return;\n    }\n    if (!cls.pluginName) {\n      throw new Error('Module.connect: cannot connect plugin without pluginName');\n      return;\n    }\n    cls.prototype._connected = true;\n    if (!this._connectedClasses) {\n      this._connectedClasses = [];\n    }\n    this._connectedClasses.push(cls);\n    if (cls.pluginName) {\n      return this[cls.pluginName] = cls;\n    }\n  };\n\n  Module.prototype.opts = {};\n\n  function Module(opts) {\n    var cls, instance, instances, name, _base, _i, _len;\n    this.opts = $.extend({}, this.opts, opts);\n    (_base = this.constructor)._connectedClasses || (_base._connectedClasses = []);\n    instances = (function() {\n      var _i, _len, _ref, _results;\n      _ref = this.constructor._connectedClasses;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        cls = _ref[_i];\n        name = cls.pluginName.charAt(0).toLowerCase() + cls.pluginName.slice(1);\n        if (cls.prototype._connected) {\n          cls.prototype._module = this;\n        }\n        _results.push(this[name] = new cls());\n      }\n      return _results;\n    }).call(this);\n    if (this._connected) {\n      this.opts = $.extend({}, this.opts, this._module.opts);\n    } else {\n      this._init();\n      for (_i = 0, _len = instances.length; _i < _len; _i++) {\n        instance = instances[_i];\n        if (typeof instance._init === \"function\") {\n          instance._init();\n        }\n      }\n    }\n    this.trigger('initialized');\n  }\n\n  Module.prototype._init = function() {};\n\n  Module.prototype.on = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    (_ref = $(this)).on.apply(_ref, args);\n    return this;\n  };\n\n  Module.prototype.one = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    (_ref = $(this)).one.apply(_ref, args);\n    return this;\n  };\n\n  Module.prototype.off = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    (_ref = $(this)).off.apply(_ref, args);\n    return this;\n  };\n\n  Module.prototype.trigger = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    (_ref = $(this)).trigger.apply(_ref, args);\n    return this;\n  };\n\n  Module.prototype.triggerHandler = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    return (_ref = $(this)).triggerHandler.apply(_ref, args);\n  };\n\n  Module.prototype._t = function() {\n    var args, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    return (_ref = this.constructor)._t.apply(_ref, args);\n  };\n\n  Module._t = function() {\n    var args, key, result, _ref;\n    key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n    result = ((_ref = this.i18n[this.locale]) != null ? _ref[key] : void 0) || '';\n    if (!(args.length > 0)) {\n      return result;\n    }\n    result = result.replace(/([^%]|^)%(?:(\\d+)\\$)?s/g, function(p0, p, position) {\n      if (position) {\n        return p + args[parseInt(position) - 1];\n      } else {\n        return p + args.shift();\n      }\n    });\n    return result.replace(/%%s/g, '%s');\n  };\n\n  Module.i18n = {\n    'zh-CN': {}\n  };\n\n  Module.locale = 'zh-CN';\n\n  return Module;\n\n})();\n\n\nreturn Module;\n\n\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/simditor/simditor.js",
    "content": "(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define('simditor', [\"jquery\",\n      \"simple-module\",\n      \"simple-hotkeys\",\n      \"simple-uploader\"], function ($, SimpleModule, simpleHotkeys, simpleUploader) {\n      return (root.returnExportsGlobal = factory($, SimpleModule, simpleHotkeys, simpleUploader));\n    });\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(require(\"jquery\"),\n      require(\"simple-module\"),\n      require(\"simple-hotkeys\"),\n      require(\"simple-uploader\"));\n  } else {\n    root['Simditor'] = factory(jQuery,\n      SimpleModule,\n      simple.hotkeys,\n      simple.uploader);\n  }\n}(this, function ($, SimpleModule, simpleHotkeys, simpleUploader) {\n\nvar Selection,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nSelection = (function(_super) {\n  __extends(Selection, _super);\n\n  function Selection() {\n    return Selection.__super__.constructor.apply(this, arguments);\n  }\n\n  Selection.pluginName = 'Selection';\n\n  Selection.prototype._init = function() {\n    this.editor = this._module;\n    return this.sel = document.getSelection();\n  };\n\n  Selection.prototype.clear = function() {\n    var e;\n    try {\n      return this.sel.removeAllRanges();\n    } catch (_error) {\n      e = _error;\n    }\n  };\n\n  Selection.prototype.getRange = function() {\n    if (!this.editor.inputManager.focused || !this.sel.rangeCount) {\n      return null;\n    }\n    return this.sel.getRangeAt(0);\n  };\n\n  Selection.prototype.selectRange = function(range) {\n    this.clear();\n    this.sel.addRange(range);\n    if (!this.editor.inputManager.focused && (this.editor.util.browser.firefox || this.editor.util.browser.msie)) {\n      this.editor.body.focus();\n    }\n    return range;\n  };\n\n  Selection.prototype.rangeAtEndOf = function(node, range) {\n    var endNode, endNodeLength, result;\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (!((range != null) && range.collapsed)) {\n      return;\n    }\n    node = $(node)[0];\n    endNode = range.endContainer;\n    endNodeLength = this.editor.util.getNodeLength(endNode);\n    if (!(range.endOffset === endNodeLength - 1 && $(endNode).contents().last().is('br')) && range.endOffset !== endNodeLength) {\n      return false;\n    }\n    if (node === endNode) {\n      return true;\n    } else if (!$.contains(node, endNode)) {\n      return false;\n    }\n    result = true;\n    $(endNode).parentsUntil(node).addBack().each((function(_this) {\n      return function(i, n) {\n        var $lastChild, nodes;\n        nodes = $(n).parent().contents().filter(function() {\n          return !(this !== n && this.nodeType === 3 && !this.nodeValue);\n        });\n        $lastChild = nodes.last();\n        if (!($lastChild.get(0) === n || ($lastChild.is('br') && $lastChild.prev().get(0) === n))) {\n          result = false;\n          return false;\n        }\n      };\n    })(this));\n    return result;\n  };\n\n  Selection.prototype.rangeAtStartOf = function(node, range) {\n    var result, startNode;\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (!((range != null) && range.collapsed)) {\n      return;\n    }\n    node = $(node)[0];\n    startNode = range.startContainer;\n    if (range.startOffset !== 0) {\n      return false;\n    }\n    if (node === startNode) {\n      return true;\n    } else if (!$.contains(node, startNode)) {\n      return false;\n    }\n    result = true;\n    $(startNode).parentsUntil(node).addBack().each((function(_this) {\n      return function(i, n) {\n        var nodes;\n        nodes = $(n).parent().contents().filter(function() {\n          return !(this !== n && this.nodeType === 3 && !this.nodeValue);\n        });\n        if (nodes.first().get(0) !== n) {\n          return result = false;\n        }\n      };\n    })(this));\n    return result;\n  };\n\n  Selection.prototype.insertNode = function(node, range) {\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (range == null) {\n      return;\n    }\n    node = $(node)[0];\n    range.insertNode(node);\n    return this.setRangeAfter(node, range);\n  };\n\n  Selection.prototype.setRangeAfter = function(node, range) {\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (range == null) {\n      return;\n    }\n    node = $(node)[0];\n    range.setEndAfter(node);\n    range.collapse(false);\n    return this.selectRange(range);\n  };\n\n  Selection.prototype.setRangeBefore = function(node, range) {\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (range == null) {\n      return;\n    }\n    node = $(node)[0];\n    range.setEndBefore(node);\n    range.collapse(false);\n    return this.selectRange(range);\n  };\n\n  Selection.prototype.setRangeAtStartOf = function(node, range) {\n    if (range == null) {\n      range = this.getRange();\n    }\n    node = $(node).get(0);\n    range.setEnd(node, 0);\n    range.collapse(false);\n    return this.selectRange(range);\n  };\n\n  Selection.prototype.setRangeAtEndOf = function(node, range) {\n    var $lastNode, $node, contents, lastChild, lastText, nodeLength;\n    if (range == null) {\n      range = this.getRange();\n    }\n    $node = $(node);\n    node = $node.get(0);\n    if ($node.is('pre')) {\n      contents = $node.contents();\n      if (contents.length > 0) {\n        lastChild = contents.last();\n        lastText = lastChild.text();\n        if (lastText.charAt(lastText.length - 1) === '\\n') {\n          range.setEnd(lastChild[0], this.editor.util.getNodeLength(lastChild[0]) - 1);\n        } else {\n          range.setEnd(lastChild[0], this.editor.util.getNodeLength(lastChild[0]));\n        }\n      } else {\n        range.setEnd(node, 0);\n      }\n    } else {\n      nodeLength = this.editor.util.getNodeLength(node);\n      if (node.nodeType !== 3 && nodeLength > 0) {\n        $lastNode = $(node).contents().last();\n        if ($lastNode.is('br')) {\n          nodeLength -= 1;\n        } else if ($lastNode[0].nodeType !== 3 && this.editor.util.isEmptyNode($lastNode)) {\n          $lastNode.append(this.editor.util.phBr);\n          node = $lastNode[0];\n          nodeLength = 0;\n        }\n      }\n      range.setEnd(node, nodeLength);\n    }\n    range.collapse(false);\n    return this.selectRange(range);\n  };\n\n  Selection.prototype.deleteRangeContents = function(range) {\n    var endRange, startRange;\n    if (range == null) {\n      range = this.getRange();\n    }\n    startRange = range.cloneRange();\n    endRange = range.cloneRange();\n    startRange.collapse(true);\n    endRange.collapse(false);\n    if (!range.collapsed && this.rangeAtStartOf(this.editor.body, startRange) && this.rangeAtEndOf(this.editor.body, endRange)) {\n      this.editor.body.empty();\n      range.setStart(this.editor.body[0], 0);\n      range.collapse(true);\n      this.selectRange(range);\n    } else {\n      range.deleteContents();\n    }\n    return range;\n  };\n\n  Selection.prototype.breakBlockEl = function(el, range) {\n    var $el;\n    if (range == null) {\n      range = this.getRange();\n    }\n    $el = $(el);\n    if (!range.collapsed) {\n      return $el;\n    }\n    range.setStartBefore($el.get(0));\n    if (range.collapsed) {\n      return $el;\n    }\n    return $el.before(range.extractContents());\n  };\n\n  Selection.prototype.save = function(range) {\n    var endCaret, endRange, startCaret;\n    if (range == null) {\n      range = this.getRange();\n    }\n    if (this._selectionSaved) {\n      return;\n    }\n    endRange = range.cloneRange();\n    endRange.collapse(false);\n    startCaret = $('<span/>').addClass('simditor-caret-start');\n    endCaret = $('<span/>').addClass('simditor-caret-end');\n    endRange.insertNode(endCaret[0]);\n    range.insertNode(startCaret[0]);\n    this.clear();\n    return this._selectionSaved = true;\n  };\n\n  Selection.prototype.restore = function() {\n    var endCaret, endContainer, endOffset, range, startCaret, startContainer, startOffset;\n    if (!this._selectionSaved) {\n      return false;\n    }\n    startCaret = this.editor.body.find('.simditor-caret-start');\n    endCaret = this.editor.body.find('.simditor-caret-end');\n    if (startCaret.length && endCaret.length) {\n      startContainer = startCaret.parent();\n      startOffset = startContainer.contents().index(startCaret);\n      endContainer = endCaret.parent();\n      endOffset = endContainer.contents().index(endCaret);\n      if (startContainer[0] === endContainer[0]) {\n        endOffset -= 1;\n      }\n      range = document.createRange();\n      range.setStart(startContainer.get(0), startOffset);\n      range.setEnd(endContainer.get(0), endOffset);\n      startCaret.remove();\n      endCaret.remove();\n      this.selectRange(range);\n    } else {\n      startCaret.remove();\n      endCaret.remove();\n    }\n    this._selectionSaved = false;\n    return range;\n  };\n\n  return Selection;\n\n})(SimpleModule);\n\nvar Formatter,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\nFormatter = (function(_super) {\n  __extends(Formatter, _super);\n\n  function Formatter() {\n    return Formatter.__super__.constructor.apply(this, arguments);\n  }\n\n  Formatter.pluginName = 'Formatter';\n\n  Formatter.prototype._init = function() {\n    this.editor = this._module;\n    this._allowedTags = ['br', 'a', 'img', 'b', 'strong', 'i', 'u', 'font', 'p', 'ul', 'ol', 'li', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'hr'];\n    this._allowedAttributes = {\n      img: ['src', 'alt', 'width', 'height', 'data-image-src', 'data-image-size', 'data-image-name', 'data-non-image'],\n      a: ['href', 'target'],\n      font: ['color'],\n      pre: ['data-lang', 'class'],\n      p: ['data-indent'],\n      h1: ['data-indent'],\n      h2: ['data-indent'],\n      h3: ['data-indent'],\n      h4: ['data-indent']\n    };\n    return this.editor.body.on('click', 'a', (function(_this) {\n      return function(e) {\n        return false;\n      };\n    })(this));\n  };\n\n  Formatter.prototype.decorate = function($el) {\n    if ($el == null) {\n      $el = this.editor.body;\n    }\n    return this.editor.trigger('decorate', [$el]);\n  };\n\n  Formatter.prototype.undecorate = function($el) {\n    if ($el == null) {\n      $el = this.editor.body.clone();\n    }\n    this.editor.trigger('undecorate', [$el]);\n    return $.trim($el.html());\n  };\n\n  Formatter.prototype.autolink = function($el) {\n    var $node, findLinkNode, lastIndex, linkNodes, match, re, replaceEls, text, uri, _i, _len;\n    if ($el == null) {\n      $el = this.editor.body;\n    }\n    linkNodes = [];\n    findLinkNode = function($parentNode) {\n      return $parentNode.contents().each(function(i, node) {\n        var $node, text;\n        $node = $(node);\n        if ($node.is('a') || $node.closest('a, pre', $el).length) {\n          return;\n        }\n        if ($node.contents().length) {\n          return findLinkNode($node);\n        } else if ((text = $node.text()) && /https?:\\/\\/|www\\./ig.test(text)) {\n          return linkNodes.push($node);\n        }\n      });\n    };\n    findLinkNode($el);\n    re = /(https?:\\/\\/|www\\.)[\\w\\-\\.\\?&=\\/#%:,@\\!\\+]+/ig;\n    for (_i = 0, _len = linkNodes.length; _i < _len; _i++) {\n      $node = linkNodes[_i];\n      text = $node.text();\n      replaceEls = [];\n      match = null;\n      lastIndex = 0;\n      while ((match = re.exec(text)) !== null) {\n        replaceEls.push(document.createTextNode(text.substring(lastIndex, match.index)));\n        lastIndex = re.lastIndex;\n        uri = /^(http(s)?:\\/\\/|\\/)/.test(match[0]) ? match[0] : 'http://' + match[0];\n        replaceEls.push($('<a href=\"' + uri + '\" rel=\"nofollow\"></a>').text(match[0])[0]);\n      }\n      replaceEls.push(document.createTextNode(text.substring(lastIndex)));\n      $node.replaceWith($(replaceEls));\n    }\n    return $el;\n  };\n\n  Formatter.prototype.format = function($el) {\n    var $node, blockNode, n, node, _i, _j, _len, _len1, _ref, _ref1;\n    if ($el == null) {\n      $el = this.editor.body;\n    }\n    if ($el.is(':empty')) {\n      $el.append('<p>' + this.editor.util.phBr + '</p>');\n      return $el;\n    }\n    _ref = $el.contents();\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      n = _ref[_i];\n      this.cleanNode(n, true);\n    }\n    _ref1 = $el.contents();\n    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n      node = _ref1[_j];\n      $node = $(node);\n      if ($node.is('br')) {\n        if (typeof blockNode !== \"undefined\" && blockNode !== null) {\n          blockNode = null;\n        }\n        $node.remove();\n      } else if (this.editor.util.isBlockNode(node)) {\n        if ($node.is('li')) {\n          if (blockNode && blockNode.is('ul, ol')) {\n            blockNode.append(node);\n          } else {\n            blockNode = $('<ul/>').insertBefore(node);\n            blockNode.append(node);\n          }\n        } else {\n          blockNode = null;\n        }\n      } else {\n        if (!blockNode || blockNode.is('ul, ol')) {\n          blockNode = $('<p/>').insertBefore(node);\n        }\n        blockNode.append(node);\n      }\n    }\n    return $el;\n  };\n\n  Formatter.prototype.cleanNode = function(node, recursive) {\n    var $childImg, $node, $p, $td, allowedAttributes, attr, contents, isDecoration, n, text, textNode, _i, _j, _len, _len1, _ref, _ref1;\n    $node = $(node);\n    if (!($node.length > 0)) {\n      return;\n    }\n    if ($node[0].nodeType === 3) {\n      text = $node.text().replace(/(\\r\\n|\\n|\\r)/gm, '');\n      if (text) {\n        textNode = document.createTextNode(text);\n        $node.replaceWith(textNode);\n      } else {\n        $node.remove();\n      }\n      return;\n    }\n    contents = $node.contents();\n    isDecoration = $node.is('[class^=\"simditor-\"]');\n    if ($node.is(this._allowedTags.join(',')) || isDecoration) {\n      if ($node.is('a') && ($childImg = $node.find('img')).length > 0) {\n        $node.replaceWith($childImg);\n        $node = $childImg;\n        contents = null;\n      }\n      if ($node.is('img') && $node.hasClass('uploading')) {\n        $node.remove();\n      }\n      if (!isDecoration) {\n        allowedAttributes = this._allowedAttributes[$node[0].tagName.toLowerCase()];\n        _ref = $.makeArray($node[0].attributes);\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          attr = _ref[_i];\n          if (!((allowedAttributes != null) && (_ref1 = attr.name, __indexOf.call(allowedAttributes, _ref1) >= 0))) {\n            $node.removeAttr(attr.name);\n          }\n        }\n      }\n    } else if ($node[0].nodeType === 1 && !$node.is(':empty')) {\n      if ($node.is('div, article, dl, header, footer, tr')) {\n        $node.append('<br/>');\n        contents.first().unwrap();\n      } else if ($node.is('table')) {\n        $p = $('<p/>');\n        $node.find('tr').each((function(_this) {\n          return function(i, tr) {\n            return $p.append($(tr).text() + '<br/>');\n          };\n        })(this));\n        $node.replaceWith($p);\n        contents = null;\n      } else if ($node.is('thead, tfoot')) {\n        $node.remove();\n        contents = null;\n      } else if ($node.is('th')) {\n        $td = $('<td/>').append($node.contents());\n        $node.replaceWith($td);\n      } else {\n        contents.first().unwrap();\n      }\n    } else {\n      $node.remove();\n      contents = null;\n    }\n    if (recursive && (contents != null) && !$node.is('pre')) {\n      for (_j = 0, _len1 = contents.length; _j < _len1; _j++) {\n        n = contents[_j];\n        this.cleanNode(n, true);\n      }\n    }\n    return null;\n  };\n\n  Formatter.prototype.clearHtml = function(html, lineBreak) {\n    var container, contents, result;\n    if (lineBreak == null) {\n      lineBreak = true;\n    }\n    container = $('<div/>').append(html);\n    contents = container.contents();\n    result = '';\n    contents.each((function(_this) {\n      return function(i, node) {\n        var $node, children;\n        if (node.nodeType === 3) {\n          return result += node.nodeValue;\n        } else if (node.nodeType === 1) {\n          $node = $(node);\n          children = $node.contents();\n          if (children.length > 0) {\n            result += _this.clearHtml(children);\n          }\n          if (lineBreak && i < contents.length - 1 && $node.is('br, p, div, li, tr, pre, address, artticle, aside, dl, figcaption, footer, h1, h2, h3, h4, header')) {\n            return result += '\\n';\n          }\n        }\n      };\n    })(this));\n    return result;\n  };\n\n  Formatter.prototype.beautify = function($contents) {\n    var uselessP;\n    uselessP = function($el) {\n      return !!($el.is('p') && !$el.text() && $el.children(':not(br)').length < 1);\n    };\n    return $contents.each((function(_this) {\n      return function(i, el) {\n        var $el;\n        $el = $(el);\n        if ($el.is(':not(img, br, col, td, hr, [class^=\"simditor-\"]):empty')) {\n          $el.remove();\n        }\n        if (uselessP($el)) {\n          $el.remove();\n        }\n        return $el.find(':not(img, br, col, td, hr, [class^=\"simditor-\"]):empty').remove();\n      };\n    })(this));\n  };\n\n  return Formatter;\n\n})(SimpleModule);\n\nvar InputManager,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\nInputManager = (function(_super) {\n  __extends(InputManager, _super);\n\n  function InputManager() {\n    return InputManager.__super__.constructor.apply(this, arguments);\n  }\n\n  InputManager.pluginName = 'InputManager';\n\n  InputManager.prototype.opts = {\n    pasteImage: false\n  };\n\n  InputManager.prototype._modifierKeys = [16, 17, 18, 91, 93, 224];\n\n  InputManager.prototype._arrowKeys = [37, 38, 39, 40];\n\n  InputManager.prototype._init = function() {\n    var submitKey;\n    this.editor = this._module;\n    if (this.opts.pasteImage && typeof this.opts.pasteImage !== 'string') {\n      this.opts.pasteImage = 'inline';\n    }\n    this._keystrokeHandlers = {};\n    this.hotkeys = simpleHotkeys({\n      el: this.editor.body\n    });\n    this._pasteArea = $('<div/>').css({\n      width: '1px',\n      height: '1px',\n      overflow: 'hidden',\n      position: 'fixed',\n      right: '0',\n      bottom: '100px'\n    }).attr({\n      tabIndex: '-1',\n      contentEditable: true\n    }).addClass('simditor-paste-area').appendTo(this.editor.el);\n    this._cleanPasteArea = $('<textarea/>').css({\n      width: '1px',\n      height: '1px',\n      overflow: 'hidden',\n      position: 'fixed',\n      right: '0',\n      bottom: '101px'\n    }).attr({\n      tabIndex: '-1'\n    }).addClass('simditor-clean-paste-area').appendTo(this.editor.el);\n    $(document).on('selectionchange.simditor' + this.editor.id, (function(_this) {\n      return function(e) {\n        if (!_this.focused) {\n          return;\n        }\n        if (_this._selectionTimer) {\n          clearTimeout(_this._selectionTimer);\n          _this._selectionTimer = null;\n        }\n        return _this._selectionTimer = setTimeout(function() {\n          return _this.editor.trigger('selectionchanged');\n        }, 20);\n      };\n    })(this));\n    this.editor.on('valuechanged', (function(_this) {\n      return function() {\n        if (!_this.editor.util.closestBlockEl() && _this.focused) {\n          _this.editor.selection.save();\n          _this.editor.formatter.format();\n          _this.editor.selection.restore();\n        }\n        _this.editor.body.find('hr, pre, .simditor-table').each(function(i, el) {\n          var $el, formatted;\n          $el = $(el);\n          if ($el.parent().is('blockquote') || $el.parent()[0] === _this.editor.body[0]) {\n            formatted = false;\n            if ($el.next().length === 0) {\n              $('<p/>').append(_this.editor.util.phBr).insertAfter($el);\n              formatted = true;\n            }\n            if ($el.prev().length === 0) {\n              $('<p/>').append(_this.editor.util.phBr).insertBefore($el);\n              formatted = true;\n            }\n            if (formatted) {\n              return setTimeout(function() {\n                return _this.editor.trigger('valuechanged');\n              }, 10);\n            }\n          }\n        });\n        _this.editor.body.find('pre:empty').append(_this.editor.util.phBr);\n        if (!_this.editor.util.supportSelectionChange && _this.focused) {\n          return _this.editor.trigger('selectionchanged');\n        }\n      };\n    })(this));\n    this.editor.on('selectionchanged', (function(_this) {\n      return function(e) {\n        return _this.editor.undoManager.update();\n      };\n    })(this));\n    this.editor.body.on('keydown', $.proxy(this._onKeyDown, this)).on('keypress', $.proxy(this._onKeyPress, this)).on('keyup', $.proxy(this._onKeyUp, this)).on('mouseup', $.proxy(this._onMouseUp, this)).on('focus', $.proxy(this._onFocus, this)).on('blur', $.proxy(this._onBlur, this)).on('paste', $.proxy(this._onPaste, this)).on('drop', $.proxy(this._onDrop, this));\n    if (this.editor.util.browser.firefox) {\n      this.addShortcut('cmd+left', (function(_this) {\n        return function(e) {\n          e.preventDefault();\n          _this.editor.selection.sel.modify('move', 'backward', 'lineboundary');\n          return false;\n        };\n      })(this));\n      this.addShortcut('cmd+right', (function(_this) {\n        return function(e) {\n          e.preventDefault();\n          _this.editor.selection.sel.modify('move', 'forward', 'lineboundary');\n          return false;\n        };\n      })(this));\n      this.addShortcut('cmd+a', (function(_this) {\n        return function(e) {\n          var $children, firstBlock, lastBlock, range;\n          $children = _this.editor.body.children();\n          if (!($children.length > 0)) {\n            return;\n          }\n          firstBlock = $children.first().get(0);\n          lastBlock = $children.last().get(0);\n          range = document.createRange();\n          range.setStart(firstBlock, 0);\n          range.setEnd(lastBlock, _this.editor.util.getNodeLength(lastBlock));\n          _this.editor.selection.selectRange(range);\n          return false;\n        };\n      })(this));\n    }\n    submitKey = this.editor.util.os.mac ? 'cmd+enter' : 'ctrl+enter';\n    this.addShortcut(submitKey, (function(_this) {\n      return function(e) {\n        _this.editor.el.closest('form').find('button:submit').click();\n        return false;\n      };\n    })(this));\n    if (this.editor.textarea.attr('autofocus')) {\n      return setTimeout((function(_this) {\n        return function() {\n          return _this.editor.focus();\n        };\n      })(this), 0);\n    }\n  };\n\n  InputManager.prototype._onFocus = function(e) {\n    this.editor.el.addClass('focus').removeClass('error');\n    this.focused = true;\n    this.lastCaretPosition = null;\n    return setTimeout((function(_this) {\n      return function() {\n        _this.editor.triggerHandler('focus');\n        return _this.editor.trigger('selectionchanged');\n      };\n    })(this), 0);\n  };\n\n  InputManager.prototype._onBlur = function(e) {\n    var _ref;\n    this.editor.el.removeClass('focus');\n    this.editor.sync();\n    this.focused = false;\n    this.lastCaretPosition = (_ref = this.editor.undoManager.currentState()) != null ? _ref.caret : void 0;\n    return this.editor.triggerHandler('blur');\n  };\n\n  InputManager.prototype._onMouseUp = function(e) {\n    if (!this.editor.util.supportSelectionChange) {\n      return setTimeout((function(_this) {\n        return function() {\n          return _this.editor.trigger('selectionchanged');\n        };\n      })(this), 0);\n    }\n  };\n\n  InputManager.prototype._onKeyDown = function(e) {\n    var $blockEl, metaKey, result, _base, _ref, _ref1;\n    if (this.editor.triggerHandler(e) === false) {\n      return false;\n    }\n    if (this.hotkeys.respondTo(e)) {\n      return;\n    }\n    if (e.which in this._keystrokeHandlers) {\n      result = typeof (_base = this._keystrokeHandlers[e.which])['*'] === \"function\" ? _base['*'](e) : void 0;\n      if (result) {\n        this.editor.trigger('valuechanged');\n        return false;\n      }\n      this.editor.util.traverseUp((function(_this) {\n        return function(node) {\n          var handler, _ref;\n          if (node.nodeType !== 1) {\n            return;\n          }\n          handler = (_ref = _this._keystrokeHandlers[e.which]) != null ? _ref[node.tagName.toLowerCase()] : void 0;\n          result = typeof handler === \"function\" ? handler(e, $(node)) : void 0;\n          if (result === true || result === false) {\n            return false;\n          }\n        };\n      })(this));\n      if (result) {\n        this.editor.trigger('valuechanged');\n        return false;\n      }\n    }\n    if ((_ref = e.which, __indexOf.call(this._modifierKeys, _ref) >= 0) || (_ref1 = e.which, __indexOf.call(this._arrowKeys, _ref1) >= 0)) {\n      return;\n    }\n    metaKey = this.editor.util.metaKey(e);\n    $blockEl = this.editor.util.closestBlockEl();\n    if (metaKey && e.which === 86) {\n      return;\n    }\n    if (this.editor.util.browser.webkit && e.which === 8 && this.editor.selection.rangeAtStartOf($blockEl)) {\n      setTimeout((function(_this) {\n        return function() {\n          var $newBlockEl;\n          if (!_this.focused) {\n            return;\n          }\n          $newBlockEl = _this.editor.util.closestBlockEl();\n          _this.editor.selection.save();\n          _this.editor.formatter.cleanNode($newBlockEl, true);\n          _this.editor.selection.restore();\n          return _this.editor.trigger('valuechanged');\n        };\n      })(this), 10);\n      this.typing = true;\n    } else if (this._typing) {\n      if (this._typing !== true) {\n        clearTimeout(this._typing);\n      }\n      this._typing = setTimeout((function(_this) {\n        return function() {\n          _this.editor.trigger('valuechanged');\n          return _this._typing = false;\n        };\n      })(this), 200);\n    } else {\n      setTimeout((function(_this) {\n        return function() {\n          return _this.editor.trigger('valuechanged');\n        };\n      })(this), 10);\n      this._typing = true;\n    }\n    return null;\n  };\n\n  InputManager.prototype._onKeyPress = function(e) {\n    if (this.editor.triggerHandler(e) === false) {\n      return false;\n    }\n  };\n\n  InputManager.prototype._onKeyUp = function(e) {\n    var p, _ref;\n    if (this.editor.triggerHandler(e) === false) {\n      return false;\n    }\n    if (!this.editor.util.supportSelectionChange && (_ref = e.which, __indexOf.call(this._arrowKeys, _ref) >= 0)) {\n      this.editor.trigger('selectionchanged');\n      return;\n    }\n    if ((e.which === 8 || e.which === 46) && this.editor.util.isEmptyNode(this.editor.body)) {\n      this.editor.body.empty();\n      p = $('<p/>').append(this.editor.util.phBr).appendTo(this.editor.body);\n      this.editor.selection.setRangeAtStartOf(p);\n    }\n  };\n\n  InputManager.prototype._onPaste = function(e) {\n    var $blockEl, cleanPaste, imageFile, pasteItem, range, uploadOpt, _ref;\n    if (this.editor.triggerHandler(e) === false) {\n      return false;\n    }\n    range = this.editor.selection.deleteRangeContents();\n    if (!range.collapsed) {\n      range.collapse(true);\n    }\n    $blockEl = this.editor.util.closestBlockEl();\n    cleanPaste = $blockEl.is('pre, table');\n    if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.items && e.originalEvent.clipboardData.items.length > 0) {\n      pasteItem = e.originalEvent.clipboardData.items[0];\n      if (/^image\\//.test(pasteItem.type) && !cleanPaste) {\n        imageFile = pasteItem.getAsFile();\n        if (!((imageFile != null) && this.opts.pasteImage)) {\n          return;\n        }\n        if (!imageFile.name) {\n          imageFile.name = \"Clipboard Image.png\";\n        }\n        uploadOpt = {};\n        uploadOpt[this.opts.pasteImage] = true;\n        if ((_ref = this.editor.uploader) != null) {\n          _ref.upload(imageFile, uploadOpt);\n        }\n        return false;\n      }\n    }\n    this.editor.selection.save(range);\n    if (cleanPaste) {\n      this._cleanPasteArea.focus();\n      if (this.editor.util.browser.firefox) {\n        e.preventDefault();\n        this._cleanPasteArea.val(e.originalEvent.clipboardData.getData('text/plain'));\n      } else if (this.editor.util.browser.msie && this.editor.util.browser.version === 10) {\n        e.preventDefault();\n        this._cleanPasteArea.val(window.clipboardData.getData('Text'));\n      }\n    } else {\n      this._pasteArea.focus();\n      if (this.editor.util.browser.msie && this.editor.util.browser.version === 10) {\n        e.preventDefault();\n        this._pasteArea.html(window.clipboardData.getData('Text'));\n      }\n    }\n    return setTimeout((function(_this) {\n      return function() {\n        var $img, blob, children, insertPosition, lastLine, line, lines, node, pasteContent, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref1, _ref2, _ref3;\n        if (_this._pasteArea.is(':empty') && !_this._cleanPasteArea.val()) {\n          pasteContent = null;\n        } else if (cleanPaste) {\n          pasteContent = _this._cleanPasteArea.val();\n        } else {\n          pasteContent = $('<div/>').append(_this._pasteArea.contents());\n          pasteContent.find('table colgroup').remove();\n          _this.editor.formatter.format(pasteContent);\n          _this.editor.formatter.decorate(pasteContent);\n          _this.editor.formatter.beautify(pasteContent.children());\n          pasteContent = pasteContent.contents();\n        }\n        _this._pasteArea.empty();\n        _this._cleanPasteArea.val('');\n        range = _this.editor.selection.restore();\n        if (_this.editor.triggerHandler('pasting', [pasteContent]) === false) {\n          return;\n        }\n        if (!pasteContent) {\n          return;\n        } else if (cleanPaste) {\n          if ($blockEl.is('table')) {\n            lines = pasteContent.split('\\n');\n            lastLine = lines.pop();\n            for (_i = 0, _len = lines.length; _i < _len; _i++) {\n              line = lines[_i];\n              _this.editor.selection.insertNode(document.createTextNode(line));\n              _this.editor.selection.insertNode($('<br/>'));\n            }\n            _this.editor.selection.insertNode(document.createTextNode(lastLine));\n          } else {\n            pasteContent = $('<div/>').text(pasteContent);\n            _ref1 = pasteContent.contents();\n            for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n              node = _ref1[_j];\n              _this.editor.selection.insertNode($(node)[0], range);\n            }\n          }\n        } else if ($blockEl.is(_this.editor.body)) {\n          for (_k = 0, _len2 = pasteContent.length; _k < _len2; _k++) {\n            node = pasteContent[_k];\n            _this.editor.selection.insertNode(node, range);\n          }\n        } else if (pasteContent.length < 1) {\n          return;\n        } else if (pasteContent.length === 1) {\n          if (pasteContent.is('p')) {\n            children = pasteContent.contents();\n            if (children.length === 1 && children.is('img')) {\n              $img = children;\n              if (/^data:image/.test($img.attr('src'))) {\n                if (!_this.opts.pasteImage) {\n                  return;\n                }\n                blob = _this.editor.util.dataURLtoBlob($img.attr(\"src\"));\n                blob.name = \"Clipboard Image.png\";\n                uploadOpt = {};\n                uploadOpt[_this.opts.pasteImage] = true;\n                if ((_ref2 = _this.editor.uploader) != null) {\n                  _ref2.upload(blob, uploadOpt);\n                }\n                return;\n              } else if ($img.is('img[src^=\"webkit-fake-url://\"]')) {\n                return;\n              }\n            }\n            for (_l = 0, _len3 = children.length; _l < _len3; _l++) {\n              node = children[_l];\n              _this.editor.selection.insertNode(node, range);\n            }\n          } else if ($blockEl.is('p') && _this.editor.util.isEmptyNode($blockEl)) {\n            $blockEl.replaceWith(pasteContent);\n            _this.editor.selection.setRangeAtEndOf(pasteContent, range);\n          } else if (pasteContent.is('ul, ol')) {\n            if (pasteContent.find('li').length === 1) {\n              pasteContent = $('<div/>').text(pasteContent.text());\n              _ref3 = pasteContent.contents();\n              for (_m = 0, _len4 = _ref3.length; _m < _len4; _m++) {\n                node = _ref3[_m];\n                _this.editor.selection.insertNode($(node)[0], range);\n              }\n            } else if ($blockEl.is('li')) {\n              $blockEl.parent().after(pasteContent);\n              _this.editor.selection.setRangeAtEndOf(pasteContent, range);\n            } else {\n              $blockEl.after(pasteContent);\n              _this.editor.selection.setRangeAtEndOf(pasteContent, range);\n            }\n          } else {\n            $blockEl.after(pasteContent);\n            _this.editor.selection.setRangeAtEndOf(pasteContent, range);\n          }\n        } else {\n          if ($blockEl.is('li')) {\n            $blockEl = $blockEl.parent();\n          }\n          if (_this.editor.selection.rangeAtStartOf($blockEl, range)) {\n            insertPosition = 'before';\n          } else if (_this.editor.selection.rangeAtEndOf($blockEl, range)) {\n            insertPosition = 'after';\n          } else {\n            _this.editor.selection.breakBlockEl($blockEl, range);\n            insertPosition = 'before';\n          }\n          $blockEl[insertPosition](pasteContent);\n          _this.editor.selection.setRangeAtEndOf(pasteContent.last(), range);\n        }\n        return _this.editor.trigger('valuechanged');\n      };\n    })(this), 10);\n  };\n\n  InputManager.prototype._onDrop = function(e) {\n    if (this.editor.triggerHandler(e) === false) {\n      return false;\n    }\n    return setTimeout((function(_this) {\n      return function() {\n        return _this.editor.trigger('valuechanged');\n      };\n    })(this), 0);\n  };\n\n  InputManager.prototype.addKeystrokeHandler = function(key, node, handler) {\n    if (!this._keystrokeHandlers[key]) {\n      this._keystrokeHandlers[key] = {};\n    }\n    return this._keystrokeHandlers[key][node] = handler;\n  };\n\n  InputManager.prototype.addShortcut = function(keys, handler) {\n    return this.hotkeys.add(keys, $.proxy(handler, this));\n  };\n\n  return InputManager;\n\n})(SimpleModule);\n\nvar Keystroke,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nKeystroke = (function(_super) {\n  __extends(Keystroke, _super);\n\n  function Keystroke() {\n    return Keystroke.__super__.constructor.apply(this, arguments);\n  }\n\n  Keystroke.pluginName = 'Keystroke';\n\n  Keystroke.prototype._init = function() {\n    var titleEnterHandler;\n    this.editor = this._module;\n    if (this.editor.util.browser.safari) {\n      this.editor.inputManager.addKeystrokeHandler('13', '*', (function(_this) {\n        return function(e) {\n          var $blockEl, $br;\n          if (!e.shiftKey) {\n            return;\n          }\n          $blockEl = _this.editor.util.closestBlockEl();\n          if ($blockEl.is('pre')) {\n            return;\n          }\n          $br = $('<br/>');\n          if (_this.editor.selection.rangeAtEndOf($blockEl)) {\n            _this.editor.selection.insertNode($br);\n            _this.editor.selection.insertNode($('<br/>'));\n            _this.editor.selection.setRangeBefore($br);\n          } else {\n            _this.editor.selection.insertNode($br);\n          }\n          return true;\n        };\n      })(this));\n    }\n    if (this.editor.util.browser.webkit || this.editor.util.browser.msie) {\n      titleEnterHandler = (function(_this) {\n        return function(e, $node) {\n          var $p;\n          if (!_this.editor.selection.rangeAtEndOf($node)) {\n            return;\n          }\n          $p = $('<p/>').append(_this.editor.util.phBr).insertAfter($node);\n          _this.editor.selection.setRangeAtStartOf($p);\n          return true;\n        };\n      })(this);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h1', titleEnterHandler);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h2', titleEnterHandler);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h3', titleEnterHandler);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h4', titleEnterHandler);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h5', titleEnterHandler);\n      this.editor.inputManager.addKeystrokeHandler('13', 'h6', titleEnterHandler);\n    }\n    this.editor.inputManager.addKeystrokeHandler('8', '*', (function(_this) {\n      return function(e) {\n        var $prevBlockEl, $rootBlock;\n        $rootBlock = _this.editor.util.furthestBlockEl();\n        $prevBlockEl = $rootBlock.prev();\n        if ($prevBlockEl.is('hr') && _this.editor.selection.rangeAtStartOf($rootBlock)) {\n          _this.editor.selection.save();\n          $prevBlockEl.remove();\n          _this.editor.selection.restore();\n          return true;\n        }\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('9', '*', (function(_this) {\n      return function(e) {\n        var codeButton;\n        codeButton = _this.editor.toolbar.findButton('code');\n        if (!(_this.editor.opts.tabIndent || (codeButton && codeButton.active))) {\n          return;\n        }\n        if (e.shiftKey) {\n          _this.editor.util.outdent();\n        } else {\n          _this.editor.util.indent();\n        }\n        return true;\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('13', 'li', (function(_this) {\n      return function(e, $node) {\n        var $cloneNode, listEl, newBlockEl, newListEl;\n        $cloneNode = $node.clone();\n        $cloneNode.find('ul, ol').remove();\n        if (!(_this.editor.util.isEmptyNode($cloneNode) && $node.is(_this.editor.util.closestBlockEl()))) {\n          return;\n        }\n        listEl = $node.parent();\n        if ($node.next('li').length > 0) {\n          if (!_this.editor.util.isEmptyNode($node)) {\n            return;\n          }\n          if (listEl.parent('li').length > 0) {\n            newBlockEl = $('<li/>').append(_this.editor.util.phBr).insertAfter(listEl.parent('li'));\n            newListEl = $('<' + listEl[0].tagName + '/>').append($node.nextAll('li'));\n            newBlockEl.append(newListEl);\n          } else {\n            newBlockEl = $('<p/>').append(_this.editor.util.phBr).insertAfter(listEl);\n            newListEl = $('<' + listEl[0].tagName + '/>').append($node.nextAll('li'));\n            newBlockEl.after(newListEl);\n          }\n        } else {\n          if (listEl.parent('li').length > 0) {\n            newBlockEl = $('<li/>').insertAfter(listEl.parent('li'));\n            if ($node.contents().length > 0) {\n              newBlockEl.append($node.contents());\n            } else {\n              newBlockEl.append(_this.editor.util.phBr);\n            }\n          } else {\n            newBlockEl = $('<p/>').append(_this.editor.util.phBr).insertAfter(listEl);\n            if ($node.children('ul, ol').length > 0) {\n              newBlockEl.after($node.children('ul, ol'));\n            }\n          }\n        }\n        if ($node.prev('li').length) {\n          $node.remove();\n        } else {\n          listEl.remove();\n        }\n        _this.editor.selection.setRangeAtStartOf(newBlockEl);\n        return true;\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('13', 'pre', (function(_this) {\n      return function(e, $node) {\n        var $p, breakNode, range;\n        e.preventDefault();\n        if (e.shiftKey) {\n          $p = $('<p/>').append(_this.editor.util.phBr).insertAfter($node);\n          _this.editor.selection.setRangeAtStartOf($p);\n          return true;\n        }\n        range = _this.editor.selection.getRange();\n        breakNode = null;\n        range.deleteContents();\n        if (!_this.editor.util.browser.msie && _this.editor.selection.rangeAtEndOf($node)) {\n          breakNode = document.createTextNode('\\n\\n');\n          range.insertNode(breakNode);\n          range.setEnd(breakNode, 1);\n        } else {\n          breakNode = document.createTextNode('\\n');\n          range.insertNode(breakNode);\n          range.setStartAfter(breakNode);\n        }\n        range.collapse(false);\n        _this.editor.selection.selectRange(range);\n        return true;\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('13', 'blockquote', (function(_this) {\n      return function(e, $node) {\n        var $closestBlock, range;\n        $closestBlock = _this.editor.util.closestBlockEl();\n        if (!($closestBlock.is('p') && !$closestBlock.next().length && _this.editor.util.isEmptyNode($closestBlock))) {\n          return;\n        }\n        $node.after($closestBlock);\n        range = document.createRange();\n        _this.editor.selection.setRangeAtStartOf($closestBlock, range);\n        return true;\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('8', 'li', (function(_this) {\n      return function(e, $node) {\n        var $br, $childList, $newLi, $prevChildList, $prevNode, $textNode, range, text;\n        $childList = $node.children('ul, ol');\n        $prevNode = $node.prev('li');\n        if (!($childList.length > 0 && $prevNode.length > 0)) {\n          return false;\n        }\n        text = '';\n        $textNode = null;\n        $node.contents().each(function(i, n) {\n          if (n.nodeType === 1 && /UL|OL/.test(n.nodeName)) {\n            return false;\n          }\n          if (n.nodeType === 1 && /BR/.test(n.nodeName)) {\n            return;\n          }\n          if (n.nodeType === 3 && n.nodeValue) {\n            text += n.nodeValue;\n          } else if (n.nodeType === 1) {\n            text += $(n).text();\n          }\n          return $textNode = $(n);\n        });\n        if ($textNode && text.length === 1 && _this.editor.util.browser.firefox && !$textNode.next('br').length) {\n          $br = $(_this.editor.util.phBr).insertAfter($textNode);\n          $textNode.remove();\n          _this.editor.selection.setRangeBefore($br);\n          return true;\n        } else if (text.length > 0) {\n          return false;\n        }\n        range = document.createRange();\n        $prevChildList = $prevNode.children('ul, ol');\n        if ($prevChildList.length > 0) {\n          $newLi = $('<li/>').append(_this.editor.util.phBr).appendTo($prevChildList);\n          $prevChildList.append($childList.children('li'));\n          $node.remove();\n          _this.editor.selection.setRangeAtEndOf($newLi, range);\n        } else {\n          _this.editor.selection.setRangeAtEndOf($prevNode, range);\n          $prevNode.append($childList);\n          $node.remove();\n          _this.editor.selection.selectRange(range);\n        }\n        return true;\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('8', 'pre', (function(_this) {\n      return function(e, $node) {\n        var $newNode, codeStr, range;\n        if (!_this.editor.selection.rangeAtStartOf($node)) {\n          return;\n        }\n        codeStr = $node.html().replace('\\n', '<br/>');\n        $newNode = $('<p/>').append(codeStr || _this.editor.util.phBr).insertAfter($node);\n        $node.remove();\n        range = document.createRange();\n        _this.editor.selection.setRangeAtStartOf($newNode, range);\n        return true;\n      };\n    })(this));\n    return this.editor.inputManager.addKeystrokeHandler('8', 'blockquote', (function(_this) {\n      return function(e, $node) {\n        var $firstChild, range;\n        if (!_this.editor.selection.rangeAtStartOf($node)) {\n          return;\n        }\n        $firstChild = $node.children().first().unwrap();\n        range = document.createRange();\n        _this.editor.selection.setRangeAtStartOf($firstChild, range);\n        return true;\n      };\n    })(this));\n  };\n\n  return Keystroke;\n\n})(SimpleModule);\n\nvar UndoManager,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nUndoManager = (function(_super) {\n  __extends(UndoManager, _super);\n\n  function UndoManager() {\n    return UndoManager.__super__.constructor.apply(this, arguments);\n  }\n\n  UndoManager.pluginName = 'UndoManager';\n\n  UndoManager.prototype._index = -1;\n\n  UndoManager.prototype._capacity = 50;\n\n  UndoManager.prototype._timer = null;\n\n  UndoManager.prototype._init = function() {\n    var redoShortcut, undoShortcut;\n    this.editor = this._module;\n    this._stack = [];\n    if (this.editor.util.os.mac) {\n      undoShortcut = 'cmd+z';\n      redoShortcut = 'shift+cmd+z';\n    } else if (this.editor.util.os.win) {\n      undoShortcut = 'ctrl+z';\n      redoShortcut = 'ctrl+y';\n    } else {\n      undoShortcut = 'ctrl+z';\n      redoShortcut = 'shift+ctrl+z';\n    }\n    this.editor.inputManager.addShortcut(undoShortcut, (function(_this) {\n      return function(e) {\n        e.preventDefault();\n        _this.undo();\n        return false;\n      };\n    })(this));\n    this.editor.inputManager.addShortcut(redoShortcut, (function(_this) {\n      return function(e) {\n        e.preventDefault();\n        _this.redo();\n        return false;\n      };\n    })(this));\n    return this.editor.on('valuechanged', (function(_this) {\n      return function(e, src) {\n        if (src === 'undo') {\n          return;\n        }\n        if (_this._timer) {\n          clearTimeout(_this._timer);\n          _this._timer = null;\n        }\n        return _this._timer = setTimeout(function() {\n          _this._pushUndoState();\n          return _this._timer = null;\n        }, 200);\n      };\n    })(this));\n  };\n\n  UndoManager.prototype._pushUndoState = function() {\n    var currentState, html;\n    if (this.editor.triggerHandler('pushundostate') === false) {\n      return;\n    }\n    currentState = this.currentState();\n    html = this.editor.body.html();\n    if (currentState && currentState.html === html) {\n      return;\n    }\n    this._index += 1;\n    this._stack.length = this._index;\n    this._stack.push({\n      html: html,\n      caret: this.caretPosition()\n    });\n    if (this._stack.length > this._capacity) {\n      this._stack.shift();\n      return this._index -= 1;\n    }\n  };\n\n  UndoManager.prototype.currentState = function() {\n    if (this._stack.length && this._index > -1) {\n      return this._stack[this._index];\n    } else {\n      return null;\n    }\n  };\n\n  UndoManager.prototype.undo = function() {\n    var state;\n    if (this._index < 1 || this._stack.length < 2) {\n      return;\n    }\n    this.editor.hidePopover();\n    this._index -= 1;\n    state = this._stack[this._index];\n    this.editor.body.html(state.html);\n    this.caretPosition(state.caret);\n    this.editor.body.find('.selected').removeClass('selected');\n    this.editor.sync();\n    return this.editor.trigger('valuechanged', ['undo']);\n  };\n\n  UndoManager.prototype.redo = function() {\n    var state;\n    if (this._index < 0 || this._stack.length < this._index + 2) {\n      return;\n    }\n    this.editor.hidePopover();\n    this._index += 1;\n    state = this._stack[this._index];\n    this.editor.body.html(state.html);\n    this.caretPosition(state.caret);\n    this.editor.body.find('.selected').removeClass('selected');\n    this.editor.sync();\n    return this.editor.trigger('valuechanged', ['undo']);\n  };\n\n  UndoManager.prototype.update = function() {\n    var currentState, html;\n    if (this._timer) {\n      return;\n    }\n    currentState = this.currentState();\n    if (!currentState) {\n      return;\n    }\n    html = this.editor.body.html();\n    currentState.html = html;\n    return currentState.caret = this.caretPosition();\n  };\n\n  UndoManager.prototype._getNodeOffset = function(node, index) {\n    var $parent, merging, offset;\n    if (index) {\n      $parent = $(node);\n    } else {\n      $parent = $(node).parent();\n    }\n    offset = 0;\n    merging = false;\n    $parent.contents().each((function(_this) {\n      return function(i, child) {\n        if (index === i || node === child) {\n          return false;\n        }\n        if (child.nodeType === 3) {\n          if (!merging) {\n            offset += 1;\n            merging = true;\n          }\n        } else {\n          offset += 1;\n          merging = false;\n        }\n        return null;\n      };\n    })(this));\n    return offset;\n  };\n\n  UndoManager.prototype._getNodePosition = function(node, offset) {\n    var position, prevNode;\n    if (node.nodeType === 3) {\n      prevNode = node.previousSibling;\n      while (prevNode && prevNode.nodeType === 3) {\n        node = prevNode;\n        offset += this.editor.util.getNodeLength(prevNode);\n        prevNode = prevNode.previousSibling;\n      }\n    } else {\n      offset = this._getNodeOffset(node, offset);\n    }\n    position = [];\n    position.unshift(offset);\n    this.editor.util.traverseUp((function(_this) {\n      return function(n) {\n        return position.unshift(_this._getNodeOffset(n));\n      };\n    })(this), node);\n    return position;\n  };\n\n  UndoManager.prototype._getNodeByPosition = function(position) {\n    var child, childNodes, i, node, offset, _i, _len, _ref;\n    node = this.editor.body[0];\n    _ref = position.slice(0, position.length - 1);\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      offset = _ref[i];\n      childNodes = node.childNodes;\n      if (offset > childNodes.length - 1) {\n        if (i === position.length - 2 && $(node).is('pre')) {\n          child = document.createTextNode('');\n          node.appendChild(child);\n          childNodes = node.childNodes;\n        } else {\n          node = null;\n          break;\n        }\n      }\n      node = childNodes[offset];\n    }\n    return node;\n  };\n\n  UndoManager.prototype.caretPosition = function(caret) {\n    var endContainer, endOffset, range, startContainer, startOffset;\n    if (!caret) {\n      range = this.editor.selection.getRange();\n      if (!(this.editor.inputManager.focused && (range != null))) {\n        return {};\n      }\n      caret = {\n        start: [],\n        end: null,\n        collapsed: true\n      };\n      caret.start = this._getNodePosition(range.startContainer, range.startOffset);\n      if (!range.collapsed) {\n        caret.end = this._getNodePosition(range.endContainer, range.endOffset);\n        caret.collapsed = false;\n      }\n      return caret;\n    } else {\n      if (!this.editor.inputManager.focused) {\n        this.editor.body.focus();\n      }\n      if (!caret.start) {\n        this.editor.body.blur();\n        return;\n      }\n      startContainer = this._getNodeByPosition(caret.start);\n      startOffset = caret.start[caret.start.length - 1];\n      if (caret.collapsed) {\n        endContainer = startContainer;\n        endOffset = startOffset;\n      } else {\n        endContainer = this._getNodeByPosition(caret.end);\n        endOffset = caret.start[caret.start.length - 1];\n      }\n      if (!startContainer || !endContainer) {\n        throw new Error('simditor: invalid caret state');\n        return;\n      }\n      range = document.createRange();\n      range.setStart(startContainer, startOffset);\n      range.setEnd(endContainer, endOffset);\n      return this.editor.selection.selectRange(range);\n    }\n  };\n\n  return UndoManager;\n\n})(SimpleModule);\n\nvar Util,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nUtil = (function(_super) {\n  __extends(Util, _super);\n\n  function Util() {\n    return Util.__super__.constructor.apply(this, arguments);\n  }\n\n  Util.pluginName = 'Util';\n\n  Util.prototype._init = function() {\n    this.editor = this._module;\n    if (this.browser.msie && this.browser.version < 11) {\n      return this.phBr = '';\n    }\n  };\n\n  Util.prototype.phBr = '<br/>';\n\n  Util.prototype.os = (function() {\n    var os;\n    os = {};\n    if (/Mac/.test(navigator.appVersion)) {\n      os.mac = true;\n    } else if (/Linux/.test(navigator.appVersion)) {\n      os.linux = true;\n    } else if (/Win/.test(navigator.appVersion)) {\n      os.win = true;\n    } else if (/X11/.test(navigator.appVersion)) {\n      os.unix = true;\n    }\n    if (/Mobi/.test(navigator.appVersion)) {\n      os.mobile = true;\n    }\n    return os;\n  })();\n\n  Util.prototype.browser = (function() {\n    var chrome, firefox, ie, safari, ua, _ref, _ref1, _ref2, _ref3;\n    ua = navigator.userAgent;\n    ie = /(msie|trident)/i.test(ua);\n    chrome = /chrome|crios/i.test(ua);\n    safari = /safari/i.test(ua) && !chrome;\n    firefox = /firefox/i.test(ua);\n    if (ie) {\n      return {\n        msie: true,\n        version: ((_ref = ua.match(/(msie |rv:)(\\d+(\\.\\d+)?)/i)) != null ? _ref[2] : void 0) * 1\n      };\n    } else if (chrome) {\n      return {\n        webkit: true,\n        chrome: true,\n        version: ((_ref1 = ua.match(/(?:chrome|crios)\\/(\\d+(\\.\\d+)?)/i)) != null ? _ref1[1] : void 0) * 1\n      };\n    } else if (safari) {\n      return {\n        webkit: true,\n        safari: true,\n        version: ((_ref2 = ua.match(/version\\/(\\d+(\\.\\d+)?)/i)) != null ? _ref2[1] : void 0) * 1\n      };\n    } else if (firefox) {\n      return {\n        mozilla: true,\n        firefox: true,\n        version: ((_ref3 = ua.match(/firefox\\/(\\d+(\\.\\d+)?)/i)) != null ? _ref3[1] : void 0) * 1\n      };\n    } else {\n      return {};\n    }\n  })();\n\n  Util.prototype.supportSelectionChange = (function() {\n    var e, onselectionchange;\n    onselectionchange = document.onselectionchange;\n    if (onselectionchange !== void 0) {\n      try {\n        document.onselectionchange = 0;\n        return document.onselectionchange === null;\n      } catch (_error) {\n        e = _error;\n      } finally {\n        document.onselectionchange = onselectionchange;\n      }\n    }\n    return false;\n  })();\n\n  Util.prototype.reflow = function(el) {\n    if (el == null) {\n      el = document;\n    }\n    return $(el)[0].offsetHeight;\n  };\n\n  Util.prototype.metaKey = function(e) {\n    var isMac;\n    isMac = /Mac/.test(navigator.userAgent);\n    if (isMac) {\n      return e.metaKey;\n    } else {\n      return e.ctrlKey;\n    }\n  };\n\n  Util.prototype.isEmptyNode = function(node) {\n    var $node;\n    $node = $(node);\n    return $node.is(':empty') || (!$node.text() && !$node.find(':not(br, span, div)').length);\n  };\n\n  Util.prototype.isBlockNode = function(node) {\n    node = $(node)[0];\n    if (!node || node.nodeType === 3) {\n      return false;\n    }\n    return /^(div|p|ul|ol|li|blockquote|hr|pre|h1|h2|h3|h4|table)$/.test(node.nodeName.toLowerCase());\n  };\n\n  Util.prototype.closestBlockEl = function(node) {\n    var $node, blockEl, range;\n    if (node == null) {\n      range = this.editor.selection.getRange();\n      node = range != null ? range.commonAncestorContainer : void 0;\n    }\n    $node = $(node);\n    if (!$node.length) {\n      return null;\n    }\n    blockEl = $node.parentsUntil(this.editor.body).addBack();\n    blockEl = blockEl.filter((function(_this) {\n      return function(i) {\n        return _this.isBlockNode(blockEl.eq(i));\n      };\n    })(this));\n    if (blockEl.length) {\n      return blockEl.last();\n    } else {\n      return null;\n    }\n  };\n\n  Util.prototype.furthestNode = function(node, filter) {\n    var $node, blockEl, range;\n    if (node == null) {\n      range = this.editor.selection.getRange();\n      node = range != null ? range.commonAncestorContainer : void 0;\n    }\n    $node = $(node);\n    if (!$node.length) {\n      return null;\n    }\n    blockEl = $node.parentsUntil(this.editor.body).addBack();\n    blockEl = blockEl.filter((function(_this) {\n      return function(i) {\n        var $n;\n        $n = blockEl.eq(i);\n        if ($.isFunction(filter)) {\n          return filter($n);\n        } else {\n          return $n.is(filter);\n        }\n      };\n    })(this));\n    if (blockEl.length) {\n      return blockEl.first();\n    } else {\n      return null;\n    }\n  };\n\n  Util.prototype.furthestBlockEl = function(node) {\n    return this.furthestNode(node, this.isBlockNode);\n  };\n\n  Util.prototype.getNodeLength = function(node) {\n    switch (node.nodeType) {\n      case 7:\n      case 10:\n        return 0;\n      case 3:\n      case 8:\n        return node.length;\n      default:\n        return node.childNodes.length;\n    }\n  };\n\n  Util.prototype.traverseUp = function(callback, node) {\n    var n, nodes, range, result, _i, _len, _results;\n    if (node == null) {\n      range = this.editor.selection.getRange();\n      node = range != null ? range.commonAncestorContainer : void 0;\n    }\n    if ((node == null) || !$.contains(this.editor.body[0], node)) {\n      return false;\n    }\n    nodes = $(node).parentsUntil(this.editor.body).get();\n    nodes.unshift(node);\n    _results = [];\n    for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n      n = nodes[_i];\n      result = callback(n);\n      if (result === false) {\n        break;\n      } else {\n        _results.push(void 0);\n      }\n    }\n    return _results;\n  };\n\n  Util.prototype.indent = function() {\n    var $blockEl, $childList, $nextTd, $parentLi, $td, indentLevel, range, spaceNode, tagName, _ref;\n    $blockEl = this.editor.util.closestBlockEl();\n    if (!($blockEl && $blockEl.length > 0)) {\n      return false;\n    }\n    if ($blockEl.is('pre')) {\n      spaceNode = document.createTextNode('\\u00A0\\u00A0');\n      this.editor.selection.insertNode(spaceNode);\n    } else if ($blockEl.is('li')) {\n      $parentLi = $blockEl.prev('li');\n      if ($parentLi.length < 1) {\n        return false;\n      }\n      this.editor.selection.save();\n      tagName = $blockEl.parent()[0].tagName;\n      $childList = $parentLi.children('ul, ol');\n      if ($childList.length > 0) {\n        $childList.append($blockEl);\n      } else {\n        $('<' + tagName + '/>').append($blockEl).appendTo($parentLi);\n      }\n      this.editor.selection.restore();\n    } else if ($blockEl.is('p, h1, h2, h3, h4')) {\n      indentLevel = (_ref = $blockEl.attr('data-indent')) != null ? _ref : 0;\n      indentLevel = indentLevel * 1 + 1;\n      if (indentLevel > 10) {\n        indentLevel = 10;\n      }\n      $blockEl.attr('data-indent', indentLevel);\n    } else if ($blockEl.is('table')) {\n      range = this.editor.selection.getRange();\n      $td = $(range.commonAncestorContainer).closest('td');\n      $nextTd = $td.next('td');\n      if (!($nextTd.length > 0)) {\n        $nextTd = $td.parent('tr').next('tr').find('td:first');\n      }\n      if (!($td.length > 0 && $nextTd.length > 0)) {\n        return false;\n      }\n      this.editor.selection.setRangeAtEndOf($nextTd);\n    } else {\n      spaceNode = document.createTextNode('\\u00A0\\u00A0\\u00A0\\u00A0');\n      this.editor.selection.insertNode(spaceNode);\n    }\n    this.editor.trigger('valuechanged');\n    return true;\n  };\n\n  Util.prototype.outdent = function() {\n    var $blockEl, $parent, $parentLi, $prevTd, $td, button, indentLevel, range, _ref;\n    $blockEl = this.editor.util.closestBlockEl();\n    if (!($blockEl && $blockEl.length > 0)) {\n      return false;\n    }\n    if ($blockEl.is('pre')) {\n      return false;\n    } else if ($blockEl.is('li')) {\n      $parent = $blockEl.parent();\n      $parentLi = $parent.parent('li');\n      if ($parentLi.length < 1) {\n        button = this.editor.toolbar.findButton($parent[0].tagName.toLowerCase());\n        if (button != null) {\n          button.command();\n        }\n        return false;\n      }\n      this.editor.selection.save();\n      if ($blockEl.next('li').length > 0) {\n        $('<' + $parent[0].tagName + '/>').append($blockEl.nextAll('li')).appendTo($blockEl);\n      }\n      $blockEl.insertAfter($parentLi);\n      if ($parent.children('li').length < 1) {\n        $parent.remove();\n      }\n      this.editor.selection.restore();\n    } else if ($blockEl.is('p, h1, h2, h3, h4')) {\n      indentLevel = (_ref = $blockEl.attr('data-indent')) != null ? _ref : 0;\n      indentLevel = indentLevel * 1 - 1;\n      if (indentLevel < 0) {\n        indentLevel = 0;\n      }\n      $blockEl.attr('data-indent', indentLevel);\n    } else if ($blockEl.is('table')) {\n      range = this.editor.selection.getRange();\n      $td = $(range.commonAncestorContainer).closest('td');\n      $prevTd = $td.prev('td');\n      if (!($prevTd.length > 0)) {\n        $prevTd = $td.parent('tr').prev('tr').find('td:last');\n      }\n      if (!($td.length > 0 && $prevTd.length > 0)) {\n        return false;\n      }\n      this.editor.selection.setRangeAtEndOf($prevTd);\n    } else {\n      return false;\n    }\n    this.editor.trigger('valuechanged');\n    return true;\n  };\n\n  Util.prototype.dataURLtoBlob = function(dataURL) {\n    var BlobBuilder, arrayBuffer, bb, byteString, hasArrayBufferViewSupport, hasBlobConstructor, i, intArray, mimeString, _i, _ref;\n    hasBlobConstructor = window.Blob && (function() {\n      var e;\n      try {\n        return Boolean(new Blob());\n      } catch (_error) {\n        e = _error;\n        return false;\n      }\n    })();\n    hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && (function() {\n      var e;\n      try {\n        return new Blob([new Uint8Array(100)]).size === 100;\n      } catch (_error) {\n        e = _error;\n        return false;\n      }\n    })();\n    BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;\n    if (!((hasBlobConstructor || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array)) {\n      return false;\n    }\n    if (dataURL.split(',')[0].indexOf('base64') >= 0) {\n      byteString = atob(dataURL.split(',')[1]);\n    } else {\n      byteString = decodeURIComponent(dataURL.split(',')[1]);\n    }\n    arrayBuffer = new ArrayBuffer(byteString.length);\n    intArray = new Uint8Array(arrayBuffer);\n    for (i = _i = 0, _ref = byteString.length; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {\n      intArray[i] = byteString.charCodeAt(i);\n    }\n    mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0];\n    if (hasBlobConstructor) {\n      return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], {\n        type: mimeString\n      });\n    }\n    bb = new BlobBuilder();\n    bb.append(arrayBuffer);\n    return bb.getBlob(mimeString);\n  };\n\n  return Util;\n\n})(SimpleModule);\n\nvar Toolbar,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nToolbar = (function(_super) {\n  __extends(Toolbar, _super);\n\n  function Toolbar() {\n    return Toolbar.__super__.constructor.apply(this, arguments);\n  }\n\n  Toolbar.pluginName = 'Toolbar';\n\n  Toolbar.prototype.opts = {\n    toolbar: true,\n    toolbarFloat: true,\n    toolbarHidden: false,\n    toolbarFloatOffset: 0\n  };\n\n  Toolbar.prototype._tpl = {\n    wrapper: '<div class=\"simditor-toolbar\"><ul></ul></div>',\n    separator: '<li><span class=\"separator\"></span></li>'\n  };\n\n  Toolbar.prototype._init = function() {\n    var toolbarHeight;\n    this.editor = this._module;\n    if (!this.opts.toolbar) {\n      return;\n    }\n    if (!$.isArray(this.opts.toolbar)) {\n      this.opts.toolbar = ['bold', 'italic', 'underline', 'strikethrough', '|', 'ol', 'ul', 'blockquote', 'code', '|', 'link', 'image', '|', 'indent', 'outdent'];\n    }\n    this._render();\n    this.list.on('click', (function(_this) {\n      return function(e) {\n        return false;\n      };\n    })(this));\n    this.wrapper.on('mousedown', (function(_this) {\n      return function(e) {\n        return _this.list.find('.menu-on').removeClass('.menu-on');\n      };\n    })(this));\n    $(document).on('mousedown.simditor' + this.editor.id, (function(_this) {\n      return function(e) {\n        return _this.list.find('.menu-on').removeClass('.menu-on');\n      };\n    })(this));\n    if (!this.opts.toolbarHidden && this.opts.toolbarFloat) {\n      this.wrapper.width(this.wrapper.outerWidth());\n      this.wrapper.css('top', this.opts.toolbarFloatOffset);\n      toolbarHeight = this.wrapper.outerHeight();\n      if (!this.editor.util.os.mobile) {\n        $(window).on('resize.simditor-' + this.editor.id, (function(_this) {\n          return function(e) {\n            _this.wrapper.css('position', 'static');\n            _this.editor.util.reflow(_this.wrapper);\n            _this.wrapper.css('left', _this.wrapper.offset().left);\n            return _this.wrapper.css('position', '');\n          };\n        })(this)).resize();\n      }\n      $(window).on('scroll.simditor-' + this.editor.id, (function(_this) {\n        return function(e) {\n          var bottomEdge, scrollTop, topEdge;\n          topEdge = _this.editor.wrapper.offset().top;\n          bottomEdge = topEdge + _this.editor.wrapper.outerHeight() - 80;\n          scrollTop = $(document).scrollTop() + _this.opts.toolbarFloatOffset;\n          if (scrollTop <= topEdge || scrollTop >= bottomEdge) {\n            _this.editor.wrapper.removeClass('toolbar-floating').css('padding-top', '');\n            if (_this.editor.util.os.mobile) {\n              return _this.wrapper.css('top', _this.opts.toolbarFloatOffset);\n            }\n          } else {\n            _this.editor.wrapper.addClass('toolbar-floating').css('padding-top', toolbarHeight);\n            if (_this.editor.util.os.mobile) {\n              return _this.wrapper.css('top', scrollTop - topEdge + _this.opts.toolbarFloatOffset);\n            }\n          }\n        };\n      })(this));\n    }\n    this.editor.on('selectionchanged', (function(_this) {\n      return function() {\n        return _this.toolbarStatus();\n      };\n    })(this));\n    this.editor.on('destroy', (function(_this) {\n      return function() {\n        return _this.buttons.length = 0;\n      };\n    })(this));\n    return $(document).on('mousedown.simditor-' + this.editor.id, (function(_this) {\n      return function(e) {\n        return _this.list.find('li.menu-on').removeClass('menu-on');\n      };\n    })(this));\n  };\n\n  Toolbar.prototype._render = function() {\n    var name, _i, _len, _ref;\n    this.buttons = [];\n    this.wrapper = $(this._tpl.wrapper).prependTo(this.editor.wrapper);\n    this.list = this.wrapper.find('ul');\n    _ref = this.opts.toolbar;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      name = _ref[_i];\n      if (name === '|') {\n        $(this._tpl.separator).appendTo(this.list);\n        continue;\n      }\n      if (!this.constructor.buttons[name]) {\n        throw new Error('simditor: invalid toolbar button \"' + name + '\"');\n        continue;\n      }\n      this.buttons.push(new this.constructor.buttons[name]({\n        editor: this.editor\n      }));\n    }\n    if (this.opts.toolbarHidden) {\n      return this.wrapper.hide();\n    } else {\n      return this.editor.placeholderEl.css('top', this.wrapper.outerHeight());\n    }\n  };\n\n  Toolbar.prototype.toolbarStatus = function(name) {\n    var buttons;\n    if (!this.editor.inputManager.focused) {\n      return;\n    }\n    buttons = this.buttons.slice(0);\n    return this.editor.util.traverseUp((function(_this) {\n      return function(node) {\n        var button, i, removeButtons, _i, _j, _len, _len1;\n        removeButtons = [];\n        for (i = _i = 0, _len = buttons.length; _i < _len; i = ++_i) {\n          button = buttons[i];\n          if ((name != null) && button.name !== name) {\n            continue;\n          }\n          if (!button.status || button.status($(node)) === true) {\n            removeButtons.push(button);\n          }\n        }\n        for (_j = 0, _len1 = removeButtons.length; _j < _len1; _j++) {\n          button = removeButtons[_j];\n          i = $.inArray(button, buttons);\n          buttons.splice(i, 1);\n        }\n        if (buttons.length === 0) {\n          return false;\n        }\n      };\n    })(this));\n  };\n\n  Toolbar.prototype.findButton = function(name) {\n    var button;\n    button = this.list.find('.toolbar-item-' + name).data('button');\n    return button != null ? button : null;\n  };\n\n  Toolbar.addButton = function(btn) {\n    return this.buttons[btn.prototype.name] = btn;\n  };\n\n  Toolbar.buttons = {};\n\n  return Toolbar;\n\n})(SimpleModule);\n\nvar Simditor,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nSimditor = (function(_super) {\n  __extends(Simditor, _super);\n\n  function Simditor() {\n    return Simditor.__super__.constructor.apply(this, arguments);\n  }\n\n  Simditor.connect(Util);\n\n  Simditor.connect(InputManager);\n\n  Simditor.connect(UndoManager);\n\n  Simditor.connect(Keystroke);\n\n  Simditor.connect(Formatter);\n\n  Simditor.connect(Selection);\n\n  Simditor.connect(Toolbar);\n\n  Simditor.count = 0;\n\n  Simditor.prototype.opts = {\n    textarea: null,\n    placeholder: '',\n    defaultImage: 'images/image.png',\n    params: {},\n    upload: false,\n    tabIndent: true\n  };\n\n  Simditor.prototype._init = function() {\n    var e, editor, form, uploadOpts;\n    this.textarea = $(this.opts.textarea);\n    this.opts.placeholder = this.opts.placeholder || this.textarea.attr('placeholder');\n    if (!this.textarea.length) {\n      throw new Error('simditor: param textarea is required.');\n      return;\n    }\n    editor = this.textarea.data('simditor');\n    if (editor != null) {\n      editor.destroy();\n    }\n    this.id = ++Simditor.count;\n    this._render();\n    if (this.opts.upload && simpleUploader) {\n      uploadOpts = typeof this.opts.upload === 'object' ? this.opts.upload : {};\n      this.uploader = simpleUploader(uploadOpts);\n    }\n    form = this.textarea.closest('form');\n    if (form.length) {\n      form.on('submit.simditor-' + this.id, (function(_this) {\n        return function() {\n          return _this.sync();\n        };\n      })(this));\n      form.on('reset.simditor-' + this.id, (function(_this) {\n        return function() {\n          return _this.setValue('');\n        };\n      })(this));\n    }\n    this.on('initialized', (function(_this) {\n      return function() {\n        if (_this.opts.placeholder) {\n          _this.on('valuechanged', function() {\n            return _this._placeholder();\n          });\n        }\n        return _this.setValue(_this.textarea.val().trim() || '');\n      };\n    })(this));\n    if (this.util.browser.mozilla) {\n      this.util.reflow();\n      try {\n        document.execCommand(\"enableObjectResizing\", false, false);\n        return document.execCommand(\"enableInlineTableEditing\", false, false);\n      } catch (_error) {\n        e = _error;\n      }\n    }\n  };\n\n  Simditor.prototype._tpl = \"<div class=\\\"simditor\\\">\\n  <div class=\\\"simditor-wrapper\\\">\\n    <div class=\\\"simditor-placeholder\\\"></div>\\n    <div class=\\\"simditor-body\\\" contenteditable=\\\"true\\\">\\n    </div>\\n  </div>\\n</div>\";\n\n  Simditor.prototype._render = function() {\n    var key, val, _ref, _results;\n    this.el = $(this._tpl).insertBefore(this.textarea);\n    this.wrapper = this.el.find('.simditor-wrapper');\n    this.body = this.wrapper.find('.simditor-body');\n    this.placeholderEl = this.wrapper.find('.simditor-placeholder').append(this.opts.placeholder);\n    this.el.append(this.textarea).data('simditor', this);\n    this.textarea.data('simditor', this).hide().blur();\n    this.body.attr('tabindex', this.textarea.attr('tabindex'));\n    if (this.util.os.mac) {\n      this.el.addClass('simditor-mac');\n    } else if (this.util.os.linux) {\n      this.el.addClass('simditor-linux');\n    }\n    if (this.util.os.mobile) {\n      this.el.addClass('simditor-mobile');\n    }\n    if (this.opts.params) {\n      _ref = this.opts.params;\n      _results = [];\n      for (key in _ref) {\n        val = _ref[key];\n        _results.push($('<input/>', {\n          type: 'hidden',\n          name: key,\n          value: val\n        }).insertAfter(this.textarea));\n      }\n      return _results;\n    }\n  };\n\n  Simditor.prototype._placeholder = function() {\n    var children, _ref;\n    children = this.body.children();\n    if (children.length === 0 || (children.length === 1 && this.util.isEmptyNode(children) && ((_ref = children.data('indent')) != null ? _ref : 0) < 1)) {\n      return this.placeholderEl.show();\n    } else {\n      return this.placeholderEl.hide();\n    }\n  };\n\n  Simditor.prototype.setValue = function(val) {\n    this.hidePopover();\n    this.textarea.val(val);\n    this.body.html(val);\n    this.formatter.format();\n    this.formatter.decorate();\n    this.util.reflow(this.body);\n    this.inputManager.lastCaretPosition = null;\n    return this.trigger('valuechanged');\n  };\n\n  Simditor.prototype.getValue = function() {\n    return this.sync();\n  };\n\n  Simditor.prototype.sync = function() {\n    var children, cloneBody, emptyP, firstP, lastP, val;\n    cloneBody = this.body.clone();\n    this.formatter.undecorate(cloneBody);\n    this.formatter.format(cloneBody);\n    this.formatter.autolink(cloneBody);\n    children = cloneBody.children();\n    lastP = children.last('p');\n    firstP = children.first('p');\n    while (lastP.is('p') && this.util.isEmptyNode(lastP)) {\n      emptyP = lastP;\n      lastP = lastP.prev('p');\n      emptyP.remove();\n    }\n    while (firstP.is('p') && this.util.isEmptyNode(firstP)) {\n      emptyP = firstP;\n      firstP = lastP.next('p');\n      emptyP.remove();\n    }\n    cloneBody.find('img.uploading').remove();\n    val = $.trim(cloneBody.html());\n    this.textarea.val(val);\n    return val;\n  };\n\n  Simditor.prototype.focus = function() {\n    var $blockEl, range;\n    if (this.inputManager.lastCaretPosition) {\n      return this.undoManager.caretPosition(this.inputManager.lastCaretPosition);\n    } else {\n      $blockEl = this.body.find('p, li, pre, h1, h2, h3, h4, td').first();\n      if (!($blockEl.length > 0)) {\n        return;\n      }\n      range = document.createRange();\n      this.selection.setRangeAtStartOf($blockEl, range);\n      return this.body.focus();\n    }\n  };\n\n  Simditor.prototype.blur = function() {\n    return this.body.blur();\n  };\n\n  Simditor.prototype.hidePopover = function() {\n    return this.el.find('.simditor-popover').each((function(_this) {\n      return function(i, popover) {\n        popover = $(popover).data('popover');\n        if (popover.active) {\n          return popover.hide();\n        }\n      };\n    })(this));\n  };\n\n  Simditor.prototype.destroy = function() {\n    this.triggerHandler('destroy');\n    this.textarea.closest('form').off('.simditor .simditor-' + this.id);\n    this.selection.clear();\n    this.inputManager.focused = false;\n    this.textarea.insertBefore(this.el).hide().val('').removeData('simditor');\n    this.el.remove();\n    $(document).off('.simditor-' + this.id);\n    $(window).off('.simditor-' + this.id);\n    return this.off();\n  };\n\n  return Simditor;\n\n})(SimpleModule);\n\nSimditor.i18n = {\n  'zh-CN': {\n    'blockquote': '引用',\n    'bold': '加粗文字',\n    'code': '插入代码',\n    'color': '文字颜色',\n    'hr': '分隔线',\n    'image': '插入图片',\n    'localImage': '本地图片',\n    'externalImage': '外链图片',\n    'uploadImage': '上传图片',\n    'uploadFailed': '上传失败了',\n    'uploadError': '上传出错了',\n    'imageUrl': '图片地址',\n    'imageSize': '图片尺寸',\n    'restoreImageSize': '还原图片尺寸',\n    'uploading': '正在上传',\n    'indent': '向右缩进',\n    'outdent': '向左缩进',\n    'italic': '斜体文字',\n    'link': '插入链接',\n    'text': '文本',\n    'linkText': '链接文字',\n    'linkUrl': '地址',\n    'removeLink': '移除链接',\n    'ol': '有序列表',\n    'ul': '无序列表',\n    'strikethrough': '删除线文字',\n    'table': '表格',\n    'deleteRow': '删除行',\n    'insertRowAbove': '在上面插入行',\n    'insertRowBelow': '在下面插入行',\n    'deleteColumn': '删除列',\n    'insertColumnLeft': '在左边插入列',\n    'insertColumnRight': '在右边插入列',\n    'deleteTable': '删除表格',\n    'title': '标题',\n    'normalText': '普通文本',\n    'underline': '下划线文字'\n  }\n};\n\nvar Button,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __slice = [].slice;\n\nButton = (function(_super) {\n  __extends(Button, _super);\n\n  Button.prototype._tpl = {\n    item: '<li><a tabindex=\"-1\" unselectable=\"on\" class=\"toolbar-item\" href=\"javascript:;\"><span></span></a></li>',\n    menuWrapper: '<div class=\"toolbar-menu\"></div>',\n    menuItem: '<li><a tabindex=\"-1\" unselectable=\"on\" class=\"menu-item\" href=\"javascript:;\"><span></span></a></li>',\n    separator: '<li><span class=\"separator\"></span></li>'\n  };\n\n  Button.prototype.name = '';\n\n  Button.prototype.icon = '';\n\n  Button.prototype.title = '';\n\n  Button.prototype.text = '';\n\n  Button.prototype.htmlTag = '';\n\n  Button.prototype.disableTag = '';\n\n  Button.prototype.menu = false;\n\n  Button.prototype.active = false;\n\n  Button.prototype.disabled = false;\n\n  Button.prototype.needFocus = true;\n\n  Button.prototype.shortcut = null;\n\n  function Button(opts) {\n    this.editor = opts.editor;\n    this.title = this._t(this.name);\n    Button.__super__.constructor.call(this, opts);\n  }\n\n  Button.prototype._init = function() {\n    var tag, _i, _len, _ref, _results;\n    this.render();\n    this.el.on('mousedown', (function(_this) {\n      return function(e) {\n        var exceed, param;\n        e.preventDefault();\n        if (_this.el.hasClass('disabled') || (_this.needFocus && !_this.editor.inputManager.focused)) {\n          return false;\n        }\n        if (_this.menu) {\n          _this.wrapper.toggleClass('menu-on').siblings('li').removeClass('menu-on');\n          if (_this.wrapper.is('.menu-on')) {\n            exceed = _this.menuWrapper.offset().left + _this.menuWrapper.outerWidth() + 5 - _this.editor.wrapper.offset().left - _this.editor.wrapper.outerWidth();\n            if (exceed > 0) {\n              _this.menuWrapper.css({\n                'left': 'auto',\n                'right': 0\n              });\n            }\n            _this.trigger('menuexpand');\n          }\n          return false;\n        }\n        param = _this.el.data('param');\n        _this.command(param);\n        return false;\n      };\n    })(this));\n    this.wrapper.on('click', 'a.menu-item', (function(_this) {\n      return function(e) {\n        var btn, param;\n        e.preventDefault();\n        btn = $(e.currentTarget);\n        _this.wrapper.removeClass('menu-on');\n        if (btn.hasClass('disabled') || (_this.needFocus && !_this.editor.inputManager.focused)) {\n          return false;\n        }\n        _this.editor.toolbar.wrapper.removeClass('menu-on');\n        param = btn.data('param');\n        _this.command(param);\n        return false;\n      };\n    })(this));\n    this.wrapper.on('mousedown', 'a.menu-item', (function(_this) {\n      return function(e) {\n        return false;\n      };\n    })(this));\n    this.editor.on('blur', (function(_this) {\n      return function() {\n        _this.setActive(false);\n        return _this.setDisabled(false);\n      };\n    })(this));\n    if (this.shortcut != null) {\n      this.editor.inputManager.addShortcut(this.shortcut, (function(_this) {\n        return function(e) {\n          _this.el.mousedown();\n          return false;\n        };\n      })(this));\n    }\n    _ref = this.htmlTag.split(',');\n    _results = [];\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      tag = _ref[_i];\n      tag = $.trim(tag);\n      if (tag && $.inArray(tag, this.editor.formatter._allowedTags) < 0) {\n        _results.push(this.editor.formatter._allowedTags.push(tag));\n      } else {\n        _results.push(void 0);\n      }\n    }\n    return _results;\n  };\n\n  Button.prototype.render = function() {\n    this.wrapper = $(this._tpl.item).appendTo(this.editor.toolbar.list);\n    this.el = this.wrapper.find('a.toolbar-item');\n    this.el.attr('title', this.title).addClass('toolbar-item-' + this.name).data('button', this);\n    this.el.find('span').addClass(this.icon ? 'fa fa-' + this.icon : '').text(this.text);\n    if (!this.menu) {\n      return;\n    }\n    this.menuWrapper = $(this._tpl.menuWrapper).appendTo(this.wrapper);\n    this.menuWrapper.addClass('toolbar-menu-' + this.name);\n    return this.renderMenu();\n  };\n\n  Button.prototype.renderMenu = function() {\n    var $menuBtntnEl, $menuItemEl, menuItem, _i, _len, _ref, _ref1, _results;\n    if (!$.isArray(this.menu)) {\n      return;\n    }\n    this.menuEl = $('<ul/>').appendTo(this.menuWrapper);\n    _ref = this.menu;\n    _results = [];\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      menuItem = _ref[_i];\n      if (menuItem === '|') {\n        $(this._tpl.separator).appendTo(this.menuEl);\n        continue;\n      }\n      $menuItemEl = $(this._tpl.menuItem).appendTo(this.menuEl);\n      _results.push($menuBtntnEl = $menuItemEl.find('a.menu-item').attr({\n        'title': (_ref1 = menuItem.title) != null ? _ref1 : menuItem.text,\n        'data-param': menuItem.param\n      }).addClass('menu-item-' + menuItem.name).find('span').text(menuItem.text));\n    }\n    return _results;\n  };\n\n  Button.prototype.setActive = function(active) {\n    if (active === this.active) {\n      return;\n    }\n    this.active = active;\n    this.el.toggleClass('active', this.active);\n    return this.editor.toolbar.trigger('buttonstatus', [this]);\n  };\n\n  Button.prototype.setDisabled = function(disabled) {\n    if (disabled === this.disabled) {\n      return;\n    }\n    this.disabled = disabled;\n    this.el.toggleClass('disabled', this.disabled);\n    return this.editor.toolbar.trigger('buttonstatus', [this]);\n  };\n\n  Button.prototype.status = function($node) {\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    if ($node != null) {\n      this.setActive($node.is(this.htmlTag));\n    }\n    return this.active;\n  };\n\n  Button.prototype.command = function(param) {};\n\n  Button.prototype._t = function() {\n    var args, result, _ref;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    result = Button.__super__._t.apply(this, args);\n    if (!result) {\n      result = (_ref = this.editor)._t.apply(_ref, args);\n    }\n    return result;\n  };\n\n  return Button;\n\n})(SimpleModule);\n\nSimditor.Button = Button;\n\nvar Popover,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nPopover = (function(_super) {\n  __extends(Popover, _super);\n\n  Popover.prototype.offset = {\n    top: 4,\n    left: 0\n  };\n\n  Popover.prototype.target = null;\n\n  Popover.prototype.active = false;\n\n  function Popover(opts) {\n    this.button = opts.button;\n    this.editor = opts.button.editor;\n    Popover.__super__.constructor.call(this, opts);\n  }\n\n  Popover.prototype._init = function() {\n    this.el = $('<div class=\"simditor-popover\"></div>').appendTo(this.editor.el).data('popover', this);\n    this.render();\n    this.el.on('mouseenter', (function(_this) {\n      return function(e) {\n        return _this.el.addClass('hover');\n      };\n    })(this));\n    return this.el.on('mouseleave', (function(_this) {\n      return function(e) {\n        return _this.el.removeClass('hover');\n      };\n    })(this));\n  };\n\n  Popover.prototype.render = function() {};\n\n  Popover.prototype.show = function($target, position) {\n    if (position == null) {\n      position = 'bottom';\n    }\n    if ($target == null) {\n      return;\n    }\n    this.el.siblings('.simditor-popover').each((function(_this) {\n      return function(i, popover) {\n        popover = $(popover).data('popover');\n        if (popover.active) {\n          return popover.hide();\n        }\n      };\n    })(this));\n    this.target = $target.addClass('selected');\n    if (this.active) {\n      this.refresh(position);\n      return this.trigger('popovershow');\n    } else {\n      this.active = true;\n      this.el.css({\n        left: -9999\n      }).show();\n      return setTimeout((function(_this) {\n        return function() {\n          _this.refresh(position);\n          return _this.trigger('popovershow');\n        };\n      })(this), 0);\n    }\n  };\n\n  Popover.prototype.hide = function() {\n    if (!this.active) {\n      return;\n    }\n    if (this.target) {\n      this.target.removeClass('selected');\n    }\n    this.target = null;\n    this.active = false;\n    this.el.hide();\n    return this.trigger('popoverhide');\n  };\n\n  Popover.prototype.refresh = function(position) {\n    var editorOffset, left, targetH, targetOffset, top;\n    if (position == null) {\n      position = 'bottom';\n    }\n    if (!this.active) {\n      return;\n    }\n    editorOffset = this.editor.el.offset();\n    targetOffset = this.target.offset();\n    targetH = this.target.outerHeight();\n    if (position === 'bottom') {\n      top = targetOffset.top - editorOffset.top + targetH;\n    } else if (position === 'top') {\n      top = targetOffset.top - editorOffset.top - this.el.height();\n    }\n    left = Math.min(targetOffset.left - editorOffset.left, this.editor.wrapper.width() - this.el.outerWidth() - 10);\n    return this.el.css({\n      top: top + this.offset.top,\n      left: left + this.offset.left\n    });\n  };\n\n  Popover.prototype.destroy = function() {\n    this.target = null;\n    this.active = false;\n    this.editor.off('.linkpopover');\n    return this.el.remove();\n  };\n\n  return Popover;\n\n})(SimpleModule);\n\nSimditor.Popover = Popover;\n\nvar TitleButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nTitleButton = (function(_super) {\n  __extends(TitleButton, _super);\n\n  function TitleButton() {\n    return TitleButton.__super__.constructor.apply(this, arguments);\n  }\n\n  TitleButton.prototype.name = 'title';\n\n  TitleButton.prototype.htmlTag = 'h1, h2, h3, h4';\n\n  TitleButton.prototype.disableTag = 'pre, table';\n\n  TitleButton.prototype._init = function() {\n    this.menu = [\n      {\n        name: 'normal',\n        text: this._t('normalText'),\n        param: 'p'\n      }, '|', {\n        name: 'h1',\n        text: this._t('title') + ' 1',\n        param: 'h1'\n      }, {\n        name: 'h2',\n        text: this._t('title') + ' 2',\n        param: 'h2'\n      }, {\n        name: 'h3',\n        text: this._t('title') + ' 3',\n        param: 'h3'\n      }, {\n        name: 'h4',\n        text: this._t('title') + ' 4',\n        param: 'h4'\n      }, {\n        name: 'h5',\n        text: this._t('title') + ' 5',\n        param: 'h5'\n      }\n    ];\n    return TitleButton.__super__._init.call(this);\n  };\n\n  TitleButton.prototype.setActive = function(active, param) {\n    TitleButton.__super__.setActive.call(this, active);\n    this.el.removeClass('active-p active-h1 active-h2 active-h3');\n    if (active) {\n      return this.el.addClass('active active-' + param);\n    }\n  };\n\n  TitleButton.prototype.status = function($node) {\n    var param, _ref;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    if ($node != null) {\n      param = (_ref = $node[0].tagName) != null ? _ref.toLowerCase() : void 0;\n      this.setActive($node.is(this.htmlTag), param);\n    }\n    return this.active;\n  };\n\n  TitleButton.prototype.command = function(param) {\n    var $contents, $endBlock, $startBlock, endNode, node, range, results, startNode, _i, _len, _ref;\n    range = this.editor.selection.getRange();\n    startNode = range.startContainer;\n    endNode = range.endContainer;\n    $startBlock = this.editor.util.closestBlockEl(startNode);\n    $endBlock = this.editor.util.closestBlockEl(endNode);\n    this.editor.selection.save();\n    range.setStartBefore($startBlock[0]);\n    range.setEndAfter($endBlock[0]);\n    $contents = $(range.extractContents());\n    results = [];\n    $contents.children().each((function(_this) {\n      return function(i, el) {\n        var c, converted, _i, _len, _results;\n        converted = _this._convertEl(el, param);\n        _results = [];\n        for (_i = 0, _len = converted.length; _i < _len; _i++) {\n          c = converted[_i];\n          _results.push(results.push(c));\n        }\n        return _results;\n      };\n    })(this));\n    _ref = results.reverse();\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      node = _ref[_i];\n      range.insertNode(node[0]);\n    }\n    this.editor.selection.restore();\n    return this.editor.trigger('valuechanged');\n  };\n\n  TitleButton.prototype._convertEl = function(el, param) {\n    var $block, $el, results;\n    $el = $(el);\n    results = [];\n    if ($el.is(param)) {\n      results.push($el);\n    } else {\n      $block = $('<' + param + '/>').append($el.contents());\n      results.push($block);\n    }\n    return results;\n  };\n\n  return TitleButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(TitleButton);\n\nvar BoldButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nBoldButton = (function(_super) {\n  __extends(BoldButton, _super);\n\n  function BoldButton() {\n    return BoldButton.__super__.constructor.apply(this, arguments);\n  }\n\n  BoldButton.prototype.name = 'bold';\n\n  BoldButton.prototype.icon = 'bold';\n\n  BoldButton.prototype.htmlTag = 'b, strong';\n\n  BoldButton.prototype.disableTag = 'pre';\n\n  BoldButton.prototype.shortcut = 'cmd+b';\n\n  BoldButton.prototype._init = function() {\n    if (this.editor.util.os.mac) {\n      this.title = this.title + ' ( Cmd + b )';\n    } else {\n      this.title = this.title + ' ( Ctrl + b )';\n      this.shortcut = 'ctrl+b';\n    }\n    return BoldButton.__super__._init.call(this);\n  };\n\n  BoldButton.prototype.status = function($node) {\n    var active;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    active = document.queryCommandState('bold') === true;\n    this.setActive(active);\n    return active;\n  };\n\n  BoldButton.prototype.command = function() {\n    document.execCommand('bold');\n    this.editor.trigger('valuechanged');\n    return $(document).trigger('selectionchange');\n  };\n\n  return BoldButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(BoldButton);\n\nvar ItalicButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nItalicButton = (function(_super) {\n  __extends(ItalicButton, _super);\n\n  function ItalicButton() {\n    return ItalicButton.__super__.constructor.apply(this, arguments);\n  }\n\n  ItalicButton.prototype.name = 'italic';\n\n  ItalicButton.prototype.icon = 'italic';\n\n  ItalicButton.prototype.htmlTag = 'i';\n\n  ItalicButton.prototype.disableTag = 'pre';\n\n  ItalicButton.prototype.shortcut = 'cmd+i';\n\n  ItalicButton.prototype._init = function() {\n    if (this.editor.util.os.mac) {\n      this.title = this.title + ' ( Cmd + i )';\n    } else {\n      this.title = this.title + ' ( Ctrl + i )';\n      this.shortcut = 'ctrl+i';\n    }\n    return ItalicButton.__super__._init.call(this);\n  };\n\n  ItalicButton.prototype.status = function($node) {\n    var active;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return this.disabled;\n    }\n    active = document.queryCommandState('italic') === true;\n    this.setActive(active);\n    return active;\n  };\n\n  ItalicButton.prototype.command = function() {\n    document.execCommand('italic');\n    this.editor.trigger('valuechanged');\n    return $(document).trigger('selectionchange');\n  };\n\n  return ItalicButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(ItalicButton);\n\nvar UnderlineButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nUnderlineButton = (function(_super) {\n  __extends(UnderlineButton, _super);\n\n  function UnderlineButton() {\n    return UnderlineButton.__super__.constructor.apply(this, arguments);\n  }\n\n  UnderlineButton.prototype.name = 'underline';\n\n  UnderlineButton.prototype.icon = 'underline';\n\n  UnderlineButton.prototype.htmlTag = 'u';\n\n  UnderlineButton.prototype.disableTag = 'pre';\n\n  UnderlineButton.prototype.shortcut = 'cmd+u';\n\n  UnderlineButton.prototype.render = function() {\n    if (this.editor.util.os.mac) {\n      this.title = this.title + ' ( Cmd + u )';\n    } else {\n      this.title = this.title + ' ( Ctrl + u )';\n      this.shortcut = 'ctrl+u';\n    }\n    return UnderlineButton.__super__.render.call(this);\n  };\n\n  UnderlineButton.prototype.status = function($node) {\n    var active;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return this.disabled;\n    }\n    active = document.queryCommandState('underline') === true;\n    this.setActive(active);\n    return active;\n  };\n\n  UnderlineButton.prototype.command = function() {\n    document.execCommand('underline');\n    this.editor.trigger('valuechanged');\n    return $(document).trigger('selectionchange');\n  };\n\n  return UnderlineButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(UnderlineButton);\n\nvar ColorButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __slice = [].slice;\n\nColorButton = (function(_super) {\n  __extends(ColorButton, _super);\n\n  function ColorButton() {\n    return ColorButton.__super__.constructor.apply(this, arguments);\n  }\n\n  ColorButton.prototype.name = 'color';\n\n  ColorButton.prototype.icon = 'font';\n\n  ColorButton.prototype.disableTag = 'pre';\n\n  ColorButton.prototype.menu = true;\n\n  ColorButton.prototype.render = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    return ColorButton.__super__.render.apply(this, args);\n  };\n\n  ColorButton.prototype.renderMenu = function() {\n    $('<ul class=\"color-list\">\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-1\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-2\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-3\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-4\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-5\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-6\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-7\" data-color=\"\"></a></li>\\n  <li><a href=\"javascript:;\" class=\"font-color font-color-default\" data-color=\"\"></a></li>\\n</ul>').appendTo(this.menuWrapper);\n    this.menuWrapper.on('mousedown', '.color-list', function(e) {\n      return false;\n    });\n    return this.menuWrapper.on('click', '.font-color', (function(_this) {\n      return function(e) {\n        var $link, $p, hex, rgb;\n        _this.wrapper.removeClass('menu-on');\n        $link = $(e.currentTarget);\n        if ($link.hasClass('font-color-default')) {\n          $p = _this.editor.body.find('p, li');\n          if (!($p.length > 0)) {\n            return;\n          }\n          rgb = window.getComputedStyle($p[0], null).getPropertyValue('color');\n          hex = _this._convertRgbToHex(rgb);\n        } else {\n          rgb = window.getComputedStyle($link[0], null).getPropertyValue('background-color');\n          hex = _this._convertRgbToHex(rgb);\n        }\n        if (!hex) {\n          return;\n        }\n        document.execCommand('foreColor', false, hex);\n        return _this.editor.trigger('valuechanged');\n      };\n    })(this));\n  };\n\n  ColorButton.prototype._convertRgbToHex = function(rgb) {\n    var match, re, rgbToHex;\n    re = /rgb\\((\\d+),\\s?(\\d+),\\s?(\\d+)\\)/g;\n    match = re.exec(rgb);\n    if (!match) {\n      return '';\n    }\n    rgbToHex = function(r, g, b) {\n      var componentToHex;\n      componentToHex = function(c) {\n        var hex;\n        hex = c.toString(16);\n        if (hex.length === 1) {\n          return '0' + hex;\n        } else {\n          return hex;\n        }\n      };\n      return \"#\" + componentToHex(r) + componentToHex(g) + componentToHex(b);\n    };\n    return rgbToHex(match[1] * 1, match[2] * 1, match[3] * 1);\n  };\n\n  return ColorButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(ColorButton);\n\nvar ListButton, OrderListButton, UnorderListButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nListButton = (function(_super) {\n  __extends(ListButton, _super);\n\n  function ListButton() {\n    return ListButton.__super__.constructor.apply(this, arguments);\n  }\n\n  ListButton.prototype.type = '';\n\n  ListButton.prototype.disableTag = 'pre, table';\n\n  ListButton.prototype.status = function($node) {\n    var anotherType;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    if ($node == null) {\n      return this.active;\n    }\n    anotherType = this.type === 'ul' ? 'ol' : 'ul';\n    if ($node.is(anotherType)) {\n      this.setActive(false);\n      return true;\n    } else {\n      this.setActive($node.is(this.htmlTag));\n      return this.active;\n    }\n  };\n\n  ListButton.prototype.command = function(param) {\n    var $contents, $endBlock, $furthestEnd, $furthestStart, $parent, $startBlock, endLevel, endNode, getListLevel, node, range, results, startLevel, startNode, _i, _len, _ref;\n    range = this.editor.selection.getRange();\n    startNode = range.startContainer;\n    endNode = range.endContainer;\n    $startBlock = this.editor.util.closestBlockEl(startNode);\n    $endBlock = this.editor.util.closestBlockEl(endNode);\n    this.editor.selection.save();\n    range.setStartBefore($startBlock[0]);\n    range.setEndAfter($endBlock[0]);\n    if ($startBlock.is('li') && $endBlock.is('li')) {\n      $furthestStart = this.editor.util.furthestNode($startBlock, 'ul, ol');\n      $furthestEnd = this.editor.util.furthestNode($endBlock, 'ul, ol');\n      if ($furthestStart.is($furthestEnd)) {\n        getListLevel = function($li) {\n          var lvl;\n          lvl = 1;\n          while (!$li.parent().is($furthestStart)) {\n            lvl += 1;\n            $li = $li.parent();\n          }\n          return lvl;\n        };\n        startLevel = getListLevel($startBlock);\n        endLevel = getListLevel($endBlock);\n        if (startLevel > endLevel) {\n          $parent = $endBlock.parent();\n        } else {\n          $parent = $startBlock.parent();\n        }\n        range.setStartBefore($parent[0]);\n        range.setEndAfter($parent[0]);\n      } else {\n        range.setStartBefore($furthestStart[0]);\n        range.setEndAfter($furthestEnd[0]);\n      }\n    }\n    $contents = $(range.extractContents());\n    results = [];\n    $contents.children().each((function(_this) {\n      return function(i, el) {\n        var c, converted, _i, _len, _results;\n        converted = _this._convertEl(el);\n        _results = [];\n        for (_i = 0, _len = converted.length; _i < _len; _i++) {\n          c = converted[_i];\n          if (results.length && results[results.length - 1].is(_this.type) && c.is(_this.type)) {\n            _results.push(results[results.length - 1].append(c.children()));\n          } else {\n            _results.push(results.push(c));\n          }\n        }\n        return _results;\n      };\n    })(this));\n    _ref = results.reverse();\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      node = _ref[_i];\n      range.insertNode(node[0]);\n    }\n    this.editor.selection.restore();\n    return this.editor.trigger('valuechanged');\n  };\n\n  ListButton.prototype._convertEl = function(el) {\n    var $el, anotherType, block, child, children, results, _i, _len, _ref;\n    $el = $(el);\n    results = [];\n    anotherType = this.type === 'ul' ? 'ol' : 'ul';\n    if ($el.is(this.type)) {\n      $el.children('li').each((function(_this) {\n        return function(i, li) {\n          var $childList, $li, block;\n          $li = $(li);\n          $childList = $li.children('ul, ol').remove();\n          block = $('<p/>').append($(li).html() || _this.editor.util.phBr);\n          results.push(block);\n          if ($childList.length > 0) {\n            return results.push($childList);\n          }\n        };\n      })(this));\n    } else if ($el.is(anotherType)) {\n      block = $('<' + this.type + '/>').append($el.html());\n      results.push(block);\n    } else if ($el.is('blockquote')) {\n      _ref = $el.children().get();\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        child = _ref[_i];\n        children = this._convertEl(child);\n      }\n      $.merge(results, children);\n    } else if ($el.is('table')) {\n\n    } else {\n      block = $('<' + this.type + '><li></li></' + this.type + '>');\n      block.find('li').append($el.html() || this.editor.util.phBr);\n      results.push(block);\n    }\n    return results;\n  };\n\n  return ListButton;\n\n})(Button);\n\nOrderListButton = (function(_super) {\n  __extends(OrderListButton, _super);\n\n  function OrderListButton() {\n    return OrderListButton.__super__.constructor.apply(this, arguments);\n  }\n\n  OrderListButton.prototype.type = 'ol';\n\n  OrderListButton.prototype.name = 'ol';\n\n  OrderListButton.prototype.icon = 'list-ol';\n\n  OrderListButton.prototype.htmlTag = 'ol';\n\n  OrderListButton.prototype.shortcut = 'cmd+/';\n\n  OrderListButton.prototype._init = function() {\n    if (this.editor.util.os.mac) {\n      this.title = this.title + ' ( Cmd + / )';\n    } else {\n      this.title = this.title + ' ( ctrl + / )';\n      this.shortcut = 'ctrl+/';\n    }\n    return OrderListButton.__super__._init.call(this);\n  };\n\n  return OrderListButton;\n\n})(ListButton);\n\nUnorderListButton = (function(_super) {\n  __extends(UnorderListButton, _super);\n\n  function UnorderListButton() {\n    return UnorderListButton.__super__.constructor.apply(this, arguments);\n  }\n\n  UnorderListButton.prototype.type = 'ul';\n\n  UnorderListButton.prototype.name = 'ul';\n\n  UnorderListButton.prototype.icon = 'list-ul';\n\n  UnorderListButton.prototype.htmlTag = 'ul';\n\n  UnorderListButton.prototype.shortcut = 'cmd+.';\n\n  UnorderListButton.prototype._init = function() {\n    if (this.editor.util.os.mac) {\n      this.title = this.title + ' ( Cmd + . )';\n    } else {\n      this.title = this.title + ' ( Ctrl + . )';\n      this.shortcut = 'ctrl+.';\n    }\n    return UnorderListButton.__super__._init.call(this);\n  };\n\n  return UnorderListButton;\n\n})(ListButton);\n\nSimditor.Toolbar.addButton(OrderListButton);\n\nSimditor.Toolbar.addButton(UnorderListButton);\n\nvar BlockquoteButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nBlockquoteButton = (function(_super) {\n  __extends(BlockquoteButton, _super);\n\n  function BlockquoteButton() {\n    return BlockquoteButton.__super__.constructor.apply(this, arguments);\n  }\n\n  BlockquoteButton.prototype.name = 'blockquote';\n\n  BlockquoteButton.prototype.icon = 'quote-left';\n\n  BlockquoteButton.prototype.htmlTag = 'blockquote';\n\n  BlockquoteButton.prototype.disableTag = 'pre, table';\n\n  BlockquoteButton.prototype.command = function() {\n    var $contents, $endBlock, $startBlock, endNode, node, range, results, startNode, _i, _len, _ref;\n    range = this.editor.selection.getRange();\n    startNode = range.startContainer;\n    endNode = range.endContainer;\n    $startBlock = this.editor.util.furthestBlockEl(startNode);\n    $endBlock = this.editor.util.furthestBlockEl(endNode);\n    this.editor.selection.save();\n    range.setStartBefore($startBlock[0]);\n    range.setEndAfter($endBlock[0]);\n    $contents = $(range.extractContents());\n    results = [];\n    $contents.children().each((function(_this) {\n      return function(i, el) {\n        var c, converted, _i, _len, _results;\n        converted = _this._convertEl(el);\n        _results = [];\n        for (_i = 0, _len = converted.length; _i < _len; _i++) {\n          c = converted[_i];\n          if (results.length && results[results.length - 1].is(_this.htmlTag) && c.is(_this.htmlTag)) {\n            _results.push(results[results.length - 1].append(c.children()));\n          } else {\n            _results.push(results.push(c));\n          }\n        }\n        return _results;\n      };\n    })(this));\n    _ref = results.reverse();\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      node = _ref[_i];\n      range.insertNode(node[0]);\n    }\n    this.editor.selection.restore();\n    return this.editor.trigger('valuechanged');\n  };\n\n  BlockquoteButton.prototype._convertEl = function(el) {\n    var $el, block, results;\n    $el = $(el);\n    results = [];\n    if ($el.is(this.htmlTag)) {\n      $el.children().each((function(_this) {\n        return function(i, node) {\n          return results.push($(node));\n        };\n      })(this));\n    } else {\n      block = $('<' + this.htmlTag + '/>').append($el);\n      results.push(block);\n    }\n    return results;\n  };\n\n  return BlockquoteButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(BlockquoteButton);\n\nvar CodeButton, CodePopover,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __slice = [].slice;\n\nCodeButton = (function(_super) {\n  __extends(CodeButton, _super);\n\n  function CodeButton() {\n    return CodeButton.__super__.constructor.apply(this, arguments);\n  }\n\n  CodeButton.prototype.name = 'code';\n\n  CodeButton.prototype.icon = 'code';\n\n  CodeButton.prototype.htmlTag = 'pre';\n\n  CodeButton.prototype.disableTag = 'li, table';\n\n  CodeButton.prototype._init = function() {\n    CodeButton.__super__._init.call(this);\n    this.editor.on('decorate', (function(_this) {\n      return function(e, $el) {\n        return $el.find('pre').each(function(i, pre) {\n          return _this.decorate($(pre));\n        });\n      };\n    })(this));\n    return this.editor.on('undecorate', (function(_this) {\n      return function(e, $el) {\n        return $el.find('pre').each(function(i, pre) {\n          return _this.undecorate($(pre));\n        });\n      };\n    })(this));\n  };\n\n  CodeButton.prototype.render = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    CodeButton.__super__.render.apply(this, args);\n    return this.popover = new CodePopover({\n      button: this\n    });\n  };\n\n  CodeButton.prototype.status = function($node) {\n    var result;\n    result = CodeButton.__super__.status.call(this, $node);\n    if (this.active) {\n      this.popover.show($node);\n    } else if (this.editor.util.isBlockNode($node)) {\n      this.popover.hide();\n    }\n    return result;\n  };\n\n  CodeButton.prototype.decorate = function($pre) {\n    var lang;\n    lang = $pre.attr('data-lang');\n    $pre.removeClass();\n    if (lang && lang !== -1) {\n      return $pre.addClass('lang-' + lang);\n    }\n  };\n\n  CodeButton.prototype.undecorate = function($pre) {\n    var lang;\n    lang = $pre.attr('data-lang');\n    $pre.removeClass();\n    if (lang && lang !== -1) {\n      return $pre.addClass('lang-' + lang);\n    }\n  };\n\n  CodeButton.prototype.command = function() {\n    var $contents, $endBlock, $startBlock, endNode, node, range, results, startNode, _i, _len, _ref;\n    range = this.editor.selection.getRange();\n    startNode = range.startContainer;\n    endNode = range.endContainer;\n    $startBlock = this.editor.util.closestBlockEl(startNode);\n    $endBlock = this.editor.util.closestBlockEl(endNode);\n    range.setStartBefore($startBlock[0]);\n    range.setEndAfter($endBlock[0]);\n    $contents = $(range.extractContents());\n    results = [];\n    $contents.children().each((function(_this) {\n      return function(i, el) {\n        var c, converted, _i, _len, _results;\n        converted = _this._convertEl(el);\n        _results = [];\n        for (_i = 0, _len = converted.length; _i < _len; _i++) {\n          c = converted[_i];\n          if (results.length && results[results.length - 1].is(_this.htmlTag) && c.is(_this.htmlTag)) {\n            _results.push(results[results.length - 1].append(c.contents()));\n          } else {\n            _results.push(results.push(c));\n          }\n        }\n        return _results;\n      };\n    })(this));\n    _ref = results.reverse();\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      node = _ref[_i];\n      range.insertNode(node[0]);\n    }\n    this.editor.selection.setRangeAtEndOf(results[0]);\n    return this.editor.trigger('valuechanged');\n  };\n\n  CodeButton.prototype._convertEl = function(el) {\n    var $el, block, codeStr, results;\n    $el = $(el);\n    results = [];\n    if ($el.is(this.htmlTag)) {\n      block = $('<p/>').append($el.html().replace('\\n', '<br/>'));\n      results.push(block);\n    } else {\n      if (!$el.text() && $el.children().length === 1 && $el.children().is('br')) {\n        codeStr = '\\n';\n      } else {\n        codeStr = this.editor.formatter.clearHtml($el);\n      }\n      block = $('<' + this.htmlTag + '/>').text(codeStr);\n      results.push(block);\n    }\n    return results;\n  };\n\n  return CodeButton;\n\n})(Button);\n\nCodePopover = (function(_super) {\n  __extends(CodePopover, _super);\n\n  function CodePopover() {\n    return CodePopover.__super__.constructor.apply(this, arguments);\n  }\n\n  CodePopover.prototype._tpl = \"<div class=\\\"code-settings\\\">\\n  <div class=\\\"settings-field\\\">\\n    <select class=\\\"select-lang\\\">\\n      <option value=\\\"-1\\\">选择程序语言</option>\\n      <option value=\\\"bash\\\">Bash</option>\\n      <option value=\\\"c++\\\">C++</option>\\n      <option value=\\\"cs\\\">C#</option>\\n      <option value=\\\"css\\\">CSS</option>\\n      <option value=\\\"erlang\\\">Erlang</option>\\n      <option value=\\\"less\\\">Less</option>\\n      <option value=\\\"scss\\\">Sass</option>\\n      <option value=\\\"diff\\\">Diff</option>\\n      <option value=\\\"coffeeScript\\\">CoffeeScript</option>\\n      <option value=\\\"html\\\">Html,XML</option>\\n      <option value=\\\"json\\\">JSON</option>\\n      <option value=\\\"java\\\">Java</option>\\n      <option value=\\\"js\\\">JavaScript</option>\\n      <option value=\\\"markdown\\\">Markdown</option>\\n      <option value=\\\"oc\\\">Objective C</option>\\n      <option value=\\\"php\\\">PHP</option>\\n      <option value=\\\"perl\\\">Perl</option>\\n      <option value=\\\"python\\\">Python</option>\\n      <option value=\\\"ruby\\\">Ruby</option>\\n      <option value=\\\"sql\\\">SQL</option>\\n    </select>\\n  </div>\\n</div>\";\n\n  CodePopover.prototype.render = function() {\n    this.el.addClass('code-popover').append(this._tpl);\n    this.selectEl = this.el.find('.select-lang');\n    return this.selectEl.on('change', (function(_this) {\n      return function(e) {\n        var selected;\n        _this.lang = _this.selectEl.val();\n        selected = _this.target.hasClass('selected');\n        _this.target.removeClass().removeAttr('data-lang');\n        if (_this.lang !== -1) {\n          _this.target.addClass('lang-' + _this.lang);\n          _this.target.attr('data-lang', _this.lang);\n        }\n        if (selected) {\n          return _this.target.addClass('selected');\n        }\n      };\n    })(this));\n  };\n\n  CodePopover.prototype.show = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    CodePopover.__super__.show.apply(this, args);\n    this.lang = this.target.attr('data-lang');\n    if (this.lang != null) {\n      return this.selectEl.val(this.lang);\n    } else {\n      return this.selectEl.val(-1);\n    }\n  };\n\n  return CodePopover;\n\n})(Popover);\n\nSimditor.Toolbar.addButton(CodeButton);\n\nvar LinkButton, LinkPopover,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __slice = [].slice;\n\nLinkButton = (function(_super) {\n  __extends(LinkButton, _super);\n\n  function LinkButton() {\n    return LinkButton.__super__.constructor.apply(this, arguments);\n  }\n\n  LinkButton.prototype.name = 'link';\n\n  LinkButton.prototype.icon = 'link';\n\n  LinkButton.prototype.htmlTag = 'a';\n\n  LinkButton.prototype.disableTag = 'pre';\n\n  LinkButton.prototype.render = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    LinkButton.__super__.render.apply(this, args);\n    return this.popover = new LinkPopover({\n      button: this\n    });\n  };\n\n  LinkButton.prototype.status = function($node) {\n    var showPopover;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    if ($node == null) {\n      return this.active;\n    }\n    showPopover = true;\n    if (!$node.is(this.htmlTag) || $node.is('[class^=\"simditor-\"]')) {\n      this.setActive(false);\n      showPopover = false;\n    } else if (this.editor.selection.rangeAtEndOf($node)) {\n      this.setActive(true);\n      showPopover = false;\n    } else {\n      this.setActive(true);\n    }\n    if (showPopover) {\n      this.popover.show($node);\n    } else if (this.editor.util.isBlockNode($node)) {\n      this.popover.hide();\n    }\n    return this.active;\n  };\n\n  LinkButton.prototype.command = function() {\n    var $contents, $endBlock, $link, $newBlock, $startBlock, endNode, linkText, range, startNode, txtNode;\n    range = this.editor.selection.getRange();\n    if (this.active) {\n      $link = $(range.commonAncestorContainer).closest('a');\n      txtNode = document.createTextNode($link.text());\n      $link.replaceWith(txtNode);\n      range.selectNode(txtNode);\n    } else {\n      startNode = range.startContainer;\n      endNode = range.endContainer;\n      $startBlock = this.editor.util.closestBlockEl(startNode);\n      $endBlock = this.editor.util.closestBlockEl(endNode);\n      $contents = $(range.extractContents());\n      linkText = this.editor.formatter.clearHtml($contents.contents(), false);\n      $link = $('<a/>', {\n        href: 'http://www.example.com',\n        target: '_blank',\n        text: linkText || this._t('linkText')\n      });\n      if ($startBlock[0] === $endBlock[0]) {\n        range.insertNode($link[0]);\n      } else {\n        $newBlock = $('<p/>').append($link);\n        range.insertNode($newBlock[0]);\n      }\n      range.selectNodeContents($link[0]);\n      this.popover.one('popovershow', (function(_this) {\n        return function() {\n          if (linkText) {\n            _this.popover.urlEl.focus();\n            return _this.popover.urlEl[0].select();\n          } else {\n            _this.popover.textEl.focus();\n            return _this.popover.textEl[0].select();\n          }\n        };\n      })(this));\n    }\n    this.editor.selection.selectRange(range);\n    return this.editor.trigger('valuechanged');\n  };\n\n  return LinkButton;\n\n})(Button);\n\nLinkPopover = (function(_super) {\n  __extends(LinkPopover, _super);\n\n  function LinkPopover() {\n    return LinkPopover.__super__.constructor.apply(this, arguments);\n  }\n\n  LinkPopover.prototype.render = function() {\n    var tpl;\n    tpl = \"<div class=\\\"link-settings\\\">\\n  <div class=\\\"settings-field\\\">\\n    <label>\" + (this._t('text')) + \"</label>\\n    <input class=\\\"link-text\\\" type=\\\"text\\\"/>\\n    <a class=\\\"btn-unlink\\\" href=\\\"javascript:;\\\" title=\\\"\" + (this._t('removeLink')) + \"\\\" tabindex=\\\"-1\\\"><span class=\\\"fa fa-unlink\\\"></span></a>\\n  </div>\\n  <div class=\\\"settings-field\\\">\\n    <label>\" + (this._t('linkUrl')) + \"</label>\\n    <input class=\\\"link-url\\\" type=\\\"text\\\"/>\\n  </div>\\n</div>\";\n    this.el.addClass('link-popover').append(tpl);\n    this.textEl = this.el.find('.link-text');\n    this.urlEl = this.el.find('.link-url');\n    this.unlinkEl = this.el.find('.btn-unlink');\n    this.textEl.on('keyup', (function(_this) {\n      return function(e) {\n        if (e.which === 13) {\n          return;\n        }\n        return _this.target.text(_this.textEl.val());\n      };\n    })(this));\n    this.urlEl.on('keyup', (function(_this) {\n      return function(e) {\n        var val;\n        if (e.which === 13) {\n          return;\n        }\n        val = _this.urlEl.val();\n        if (!(/https?:\\/\\/|^\\//ig.test(val) || !val)) {\n          val = 'http://' + val;\n        }\n        return _this.target.attr('href', val);\n      };\n    })(this));\n    $([this.urlEl[0], this.textEl[0]]).on('keydown', (function(_this) {\n      return function(e) {\n        if (e.which === 13 || e.which === 27 || (!e.shiftKey && e.which === 9 && $(e.target).hasClass('link-url'))) {\n          e.preventDefault();\n          return setTimeout(function() {\n            var range;\n            range = document.createRange();\n            _this.editor.selection.setRangeAfter(_this.target, range);\n            _this.hide();\n            return _this.editor.trigger('valuechanged');\n          }, 0);\n        }\n      };\n    })(this));\n    return this.unlinkEl.on('click', (function(_this) {\n      return function(e) {\n        var range, txtNode;\n        txtNode = document.createTextNode(_this.target.text());\n        _this.target.replaceWith(txtNode);\n        _this.hide();\n        range = document.createRange();\n        _this.editor.selection.setRangeAfter(txtNode, range);\n        return _this.editor.trigger('valuechanged');\n      };\n    })(this));\n  };\n\n  LinkPopover.prototype.show = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    LinkPopover.__super__.show.apply(this, args);\n    this.textEl.val(this.target.text());\n    return this.urlEl.val(this.target.attr('href'));\n  };\n\n  return LinkPopover;\n\n})(Popover);\n\nSimditor.Toolbar.addButton(LinkButton);\n\nvar ImageButton, ImagePopover,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __slice = [].slice;\n\nImageButton = (function(_super) {\n  __extends(ImageButton, _super);\n\n  function ImageButton() {\n    return ImageButton.__super__.constructor.apply(this, arguments);\n  }\n\n  ImageButton.prototype.name = 'image';\n\n  ImageButton.prototype.icon = 'picture-o';\n\n  ImageButton.prototype.htmlTag = 'img';\n\n  ImageButton.prototype.disableTag = 'pre, table';\n\n  ImageButton.prototype.defaultImage = '';\n\n  ImageButton.prototype.needFocus = false;\n\n  ImageButton.prototype._init = function() {\n    if (this.editor.uploader != null) {\n      this.menu = [\n        {\n          name: 'upload-image',\n          text: this._t('localImage')\n        }, {\n          name: 'external-image',\n          text: this._t('externalImage')\n        }\n      ];\n    } else {\n      this.menu = false;\n    }\n    this.defaultImage = this.editor.opts.defaultImage;\n    this.editor.body.on('click', 'img:not([data-non-image])', (function(_this) {\n      return function(e) {\n        var $img, range;\n        $img = $(e.currentTarget);\n        range = document.createRange();\n        range.selectNode($img[0]);\n        _this.editor.selection.selectRange(range);\n        if (!_this.editor.util.supportSelectionChange) {\n          _this.editor.trigger('selectionchanged');\n        }\n        return false;\n      };\n    })(this));\n    this.editor.body.on('mouseup', 'img:not([data-non-image])', (function(_this) {\n      return function(e) {\n        return false;\n      };\n    })(this));\n    this.editor.on('selectionchanged.image', (function(_this) {\n      return function() {\n        var $contents, $img, range;\n        range = _this.editor.selection.getRange();\n        if (range == null) {\n          return;\n        }\n        $contents = $(range.cloneContents()).contents();\n        if ($contents.length === 1 && $contents.is('img:not([data-non-image])')) {\n          $img = $(range.startContainer).contents().eq(range.startOffset);\n          return _this.popover.show($img);\n        } else {\n          return _this.popover.hide();\n        }\n      };\n    })(this));\n    this.editor.on('valuechanged.image', (function(_this) {\n      return function() {\n        var $masks;\n        $masks = _this.editor.wrapper.find('.simditor-image-loading');\n        if (!($masks.length > 0)) {\n          return;\n        }\n        return $masks.each(function(i, mask) {\n          var $img, $mask, file;\n          $mask = $(mask);\n          $img = $mask.data('img');\n          if (!($img && $img.parent().length > 0)) {\n            $mask.remove();\n            if ($img) {\n              file = $img.data('file');\n              if (file) {\n                _this.editor.uploader.cancel(file);\n                if (_this.editor.body.find('img.uploading').length < 1) {\n                  return _this.editor.uploader.trigger('uploadready', [file]);\n                }\n              }\n            }\n          }\n        });\n      };\n    })(this));\n    return ImageButton.__super__._init.call(this);\n  };\n\n  ImageButton.prototype.render = function() {\n    var args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    ImageButton.__super__.render.apply(this, args);\n    return this.popover = new ImagePopover({\n      button: this\n    });\n  };\n\n  ImageButton.prototype.renderMenu = function() {\n    var $input, $uploadItem, createInput;\n    ImageButton.__super__.renderMenu.call(this);\n    $uploadItem = this.menuEl.find('.menu-item-upload-image');\n    $input = null;\n    createInput = (function(_this) {\n      return function() {\n        if ($input) {\n          $input.remove();\n        }\n        return $input = $('<input type=\"file\" title=\"' + _this._t('uploadImage') + '\" accept=\"image/*\">').appendTo($uploadItem);\n      };\n    })(this);\n    createInput();\n    $uploadItem.on('click mousedown', 'input[type=file]', (function(_this) {\n      return function(e) {\n        return e.stopPropagation();\n      };\n    })(this));\n    $uploadItem.on('change', 'input[type=file]', (function(_this) {\n      return function(e) {\n        if (_this.editor.inputManager.focused) {\n          _this.editor.uploader.upload($input, {\n            inline: true\n          });\n          createInput();\n        } else {\n          _this.editor.one('focus', function(e) {\n            _this.editor.uploader.upload($input, {\n              inline: true\n            });\n            return createInput();\n          });\n          _this.editor.focus();\n        }\n        return _this.wrapper.removeClass('menu-on');\n      };\n    })(this));\n    return this._initUploader();\n  };\n\n  ImageButton.prototype._initUploader = function() {\n    if (this.editor.uploader == null) {\n      this.el.find('.btn-upload').remove();\n      return;\n    }\n    this.editor.uploader.on('beforeupload', (function(_this) {\n      return function(e, file) {\n        var $img;\n        if (!file.inline) {\n          return;\n        }\n        if (file.img) {\n          $img = $(file.img);\n        } else {\n          $img = _this.createImage(file.name);\n          file.img = $img;\n        }\n        $img.addClass('uploading');\n        $img.data('file', file);\n        return _this.editor.uploader.readImageFile(file.obj, function(img) {\n          var src;\n          if (!$img.hasClass('uploading')) {\n            return;\n          }\n          src = img ? img.src : _this.defaultImage;\n          return _this.loadImage($img, src, function() {\n            if (_this.popover.active) {\n              _this.popover.refresh();\n              return _this.popover.srcEl.val(_this._t('uploading')).prop('disabled', true);\n            }\n          });\n        });\n      };\n    })(this));\n    this.editor.uploader.on('uploadprogress', (function(_this) {\n      return function(e, file, loaded, total) {\n        var $img, $mask, $txt, percent;\n        if (!file.inline) {\n          return;\n        }\n        percent = loaded / total;\n        percent = (percent * 100).toFixed(0);\n        if (percent > 99) {\n          percent = 99;\n        }\n        $mask = file.img.data('mask');\n        if ($mask) {\n          $img = $mask.data('img');\n          $txt = $mask.find('span');\n          if ($img && $img.parent().length > 0 && percent !== $txt.text()) {\n            return $txt.text(percent);\n          } else {\n            return $mask.remove();\n          }\n        }\n      };\n    })(this));\n    this.editor.uploader.on('uploadsuccess', (function(_this) {\n      return function(e, file, result) {\n        var $img, $mask, msg;\n        if (!file.inline) {\n          return;\n        }\n        $img = file.img;\n        $img.removeData('file');\n        $img.removeClass('uploading');\n        $mask = $img.data('mask');\n        if ($mask) {\n          $mask.remove();\n        }\n        $img.removeData('mask');\n        if (result.success === false) {\n          msg = result.msg || _this._t('uploadFailed');\n          alert(msg);\n          $img.attr('src', _this.defaultImage);\n        } else {\n          $img.attr('src', result.file_path);\n        }\n        if (_this.popover.active) {\n          _this.popover.srcEl.prop('disabled', false);\n          _this.popover.srcEl.val(result.file_path);\n        }\n        _this.editor.trigger('valuechanged');\n        if (_this.editor.body.find('img.uploading').length < 1) {\n          return _this.editor.uploader.trigger('uploadready', [file, result]);\n        }\n      };\n    })(this));\n    return this.editor.uploader.on('uploaderror', (function(_this) {\n      return function(e, file, xhr) {\n        var $img, $mask, msg, result;\n        if (!file.inline) {\n          return;\n        }\n        if (xhr.statusText === 'abort') {\n          return;\n        }\n        if (xhr.responseText) {\n          try {\n            result = $.parseJSON(xhr.responseText);\n            msg = result.msg;\n          } catch (_error) {\n            e = _error;\n            msg = _this._t('uploadError');\n          }\n          alert(msg);\n        }\n        $img = file.img;\n        $img.removeData('file');\n        $img.removeClass('uploading');\n        $mask = $img.data('mask');\n        if ($mask) {\n          $mask.remove();\n        }\n        $img.removeData('mask');\n        $img.attr('src', _this.defaultImage);\n        if (_this.popover.active) {\n          _this.popover.srcEl.prop('disabled', false);\n          _this.popover.srcEl.val(_this.defaultImage);\n        }\n        _this.editor.trigger('valuechanged');\n        if (_this.editor.body.find('img.uploading').length < 1) {\n          return _this.editor.uploader.trigger('uploadready', [file, result]);\n        }\n      };\n    })(this));\n  };\n\n  ImageButton.prototype.status = function($node) {\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n  };\n\n  ImageButton.prototype.loadImage = function($img, src, callback) {\n    var $mask, img;\n    $mask = $img.data('mask');\n    if (!$mask) {\n      $mask = $('<div class=\"simditor-image-loading\"><span></span></div>').hide().appendTo(this.editor.wrapper);\n      if ($img.hasClass('uploading')) {\n        $mask.addClass('uploading');\n      }\n      $img.data('mask', $mask);\n      $mask.data('img', $img);\n    }\n    img = new Image();\n    img.onload = (function(_this) {\n      return function() {\n        var height, imgOffset, width, wrapperOffset;\n        if ($mask.hasClass('uploading') && !$img.hasClass('uploading')) {\n          return;\n        }\n        width = img.width;\n        height = img.height;\n        $img.attr({\n          src: src,\n          'data-image-size': width + ',' + height\n        });\n        if ($img.hasClass('uploading')) {\n          _this.editor.util.reflow(_this.editor.body);\n          wrapperOffset = _this.editor.wrapper.offset();\n          imgOffset = $img.offset();\n          $mask.css({\n            top: imgOffset.top - wrapperOffset.top,\n            left: imgOffset.left - wrapperOffset.left,\n            width: $img.width(),\n            height: $img.height()\n          }).show();\n        } else {\n          $mask.remove();\n          $img.removeData('mask');\n        }\n        return callback(img);\n      };\n    })(this);\n    img.onerror = (function(_this) {\n      return function() {\n        callback(false);\n        $mask.remove();\n        return $img.removeData('mask');\n      };\n    })(this);\n    return img.src = src;\n  };\n\n  ImageButton.prototype.createImage = function(name) {\n    var $block, $img, $nextBlock, range;\n    if (name == null) {\n      name = 'Image';\n    }\n    if (!this.editor.inputManager.focused) {\n      this.editor.focus();\n    }\n    range = this.editor.selection.getRange();\n    range.deleteContents();\n    $block = this.editor.util.closestBlockEl();\n    if ($block.is('p') && !this.editor.util.isEmptyNode($block)) {\n      $block = $('<p/>').append(this.editor.util.phBr).insertAfter($block);\n      this.editor.selection.setRangeAtStartOf($block, range);\n    }\n    $img = $('<img/>').attr('alt', name);\n    range.insertNode($img[0]);\n    $nextBlock = $block.next('p');\n    if (!($nextBlock.length > 0)) {\n      $nextBlock = $('<p/>').append(this.editor.util.phBr).insertAfter($block);\n    }\n    this.editor.selection.setRangeAtStartOf($nextBlock);\n    return $img;\n  };\n\n  ImageButton.prototype.command = function(src) {\n    var $img;\n    $img = this.createImage();\n    return this.loadImage($img, src || this.defaultImage, (function(_this) {\n      return function() {\n        _this.editor.trigger('valuechanged');\n        _this.editor.util.reflow($img);\n        $img.click();\n        return _this.popover.one('popovershow', function() {\n          _this.popover.srcEl.focus();\n          return _this.popover.srcEl[0].select();\n        });\n      };\n    })(this));\n  };\n\n  return ImageButton;\n\n})(Button);\n\nImagePopover = (function(_super) {\n  __extends(ImagePopover, _super);\n\n  function ImagePopover() {\n    return ImagePopover.__super__.constructor.apply(this, arguments);\n  }\n\n  ImagePopover.prototype.offset = {\n    top: 6,\n    left: -4\n  };\n\n  ImagePopover.prototype.render = function() {\n    var tpl;\n    tpl = \"<div class=\\\"link-settings\\\">\\n  <div class=\\\"settings-field\\\">\\n    <label>\" + (this._t('imageUrl')) + \"</label>\\n    <input class=\\\"image-src\\\" type=\\\"text\\\" tabindex=\\\"1\\\" />\\n    <a class=\\\"btn-upload\\\" href=\\\"javascript:;\\\" title=\\\"\" + (this._t('uploadImage')) + \"\\\" tabindex=\\\"-1\\\">\\n      <span class=\\\"fa fa-upload\\\"></span>\\n    </a>\\n  </div>\\n  <div class=\\\"settings-field\\\">\\n    <label>\" + (this._t('imageSize')) + \"</label>\\n    <input class=\\\"image-size\\\" id=\\\"image-width\\\" type=\\\"text\\\" tabindex=\\\"2\\\" />\\n    <span class=\\\"times\\\">×</span>\\n    <input class=\\\"image-size\\\" id=\\\"image-height\\\" type=\\\"text\\\" tabindex=\\\"3\\\" />\\n    <a class=\\\"btn-restore\\\" href=\\\"javascript:;\\\" title=\\\"\" + (this._t('restoreImageSize')) + \"\\\" tabindex=\\\"-1\\\">\\n      <span class=\\\"fa fa-reply\\\"></span>\\n    </a>\\n  </div>\\n</div>\";\n    this.el.addClass('image-popover').append(tpl);\n    this.srcEl = this.el.find('.image-src');\n    this.srcEl.on('keydown', (function(_this) {\n      return function(e) {\n        var hideAndFocus, src;\n        if (!(e.which === 13 || e.which === 27)) {\n          return;\n        }\n        e.preventDefault();\n        hideAndFocus = function() {\n          _this.button.editor.body.focus();\n          _this.button.editor.selection.setRangeAfter(_this.target);\n          return _this.hide();\n        };\n        if (e.which === 13 && !_this.target.hasClass('uploading')) {\n          src = _this.srcEl.val();\n          if (/^data:image/.test(src) && !_this.editor.uploader) {\n            hideAndFocus();\n            return;\n          }\n          return _this.button.loadImage(_this.target, src, function(success) {\n            var blob;\n            if (!success) {\n              return;\n            }\n            if (/^data:image/.test(src)) {\n              blob = _this.editor.util.dataURLtoBlob(src);\n              blob.name = \"Base64 Image.png\";\n              return _this.editor.uploader.upload(blob, {\n                inline: true,\n                img: _this.target\n              });\n            } else {\n              hideAndFocus();\n              return _this.editor.trigger('valuechanged');\n            }\n          });\n        } else {\n          return hideAndFocus();\n        }\n      };\n    })(this));\n    this.widthEl = this.el.find('#image-width');\n    this.heightEl = this.el.find('#image-height');\n    this.el.find('.image-size').on('blur', (function(_this) {\n      return function(e) {\n        _this._resizeImg($(e.currentTarget));\n        return _this.el.data('popover').refresh();\n      };\n    })(this));\n    this.el.find('.image-size').on('keyup', (function(_this) {\n      return function(e) {\n        var inputEl;\n        inputEl = $(e.currentTarget);\n        if (!(e.which === 13 || e.which === 27 || e.which === 9)) {\n          return _this._resizeImg(inputEl, true);\n        }\n      };\n    })(this));\n    this.el.find('.image-size').on('keydown', (function(_this) {\n      return function(e) {\n        var inputEl;\n        inputEl = $(e.currentTarget);\n        if (e.which === 13 || e.which === 27) {\n          e.preventDefault();\n          if (e.which === 13) {\n            _this._resizeImg(inputEl);\n          } else {\n            _this._restoreImg();\n          }\n          _this.button.editor.body.focus();\n          _this.button.editor.selection.setRangeAfter(_this.target);\n          return _this.hide();\n        } else if (e.which === 9) {\n          return _this.el.data('popover').refresh();\n        }\n      };\n    })(this));\n    this.el.find('.btn-restore').on('click', (function(_this) {\n      return function(e) {\n        _this._restoreImg();\n        return _this.el.data('popover').refresh();\n      };\n    })(this));\n    this.editor.on('valuechanged', (function(_this) {\n      return function(e) {\n        if (_this.active) {\n          return _this.refresh();\n        }\n      };\n    })(this));\n    return this._initUploader();\n  };\n\n  ImagePopover.prototype._initUploader = function() {\n    var $uploadBtn, createInput;\n    $uploadBtn = this.el.find('.btn-upload');\n    if (this.editor.uploader == null) {\n      $uploadBtn.remove();\n      return;\n    }\n    createInput = (function(_this) {\n      return function() {\n        if (_this.input) {\n          _this.input.remove();\n        }\n        return _this.input = $('<input type=\"file\" title=\"' + _this._t('uploadImage') + '\" accept=\"image/*\">').appendTo($uploadBtn);\n      };\n    })(this);\n    createInput();\n    this.el.on('click mousedown', 'input[type=file]', (function(_this) {\n      return function(e) {\n        return e.stopPropagation();\n      };\n    })(this));\n    return this.el.on('change', 'input[type=file]', (function(_this) {\n      return function(e) {\n        _this.editor.uploader.upload(_this.input, {\n          inline: true,\n          img: _this.target\n        });\n        return createInput();\n      };\n    })(this));\n  };\n\n  ImagePopover.prototype._resizeImg = function(inputEl, onlySetVal) {\n    var height, value, width;\n    if (onlySetVal == null) {\n      onlySetVal = false;\n    }\n    value = inputEl.val() * 1;\n    if (!($.isNumeric(value) || value < 0)) {\n      return;\n    }\n    if (inputEl.is(this.widthEl)) {\n      height = this.height * value / this.width;\n      this.heightEl.val(height);\n    } else {\n      width = this.width * value / this.height;\n      this.widthEl.val(width);\n    }\n    if (!onlySetVal) {\n      return this.target.attr({\n        width: width || value,\n        height: height || value\n      });\n    }\n  };\n\n  ImagePopover.prototype._restoreImg = function() {\n    var size, _ref;\n    size = ((_ref = this.target.data('image-size')) != null ? _ref.split(\",\") : void 0) || [this.width, this.height];\n    this.target.attr({\n      width: size[0] * 1,\n      height: size[1] * 1\n    });\n    this.widthEl.val(size[0]);\n    return this.heightEl.val(size[1]);\n  };\n\n  ImagePopover.prototype.show = function() {\n    var $img, args;\n    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];\n    ImagePopover.__super__.show.apply(this, args);\n    $img = this.target;\n    this.width = $img.width();\n    this.height = $img.height();\n    if ($img.hasClass('uploading')) {\n      return this.srcEl.val(this._t('uploading')).prop('disabled', true);\n    } else {\n      this.srcEl.val($img.attr('src')).prop('disabled', false);\n      this.widthEl.val(this.width);\n      return this.heightEl.val(this.height);\n    }\n  };\n\n  return ImagePopover;\n\n})(Popover);\n\nSimditor.Toolbar.addButton(ImageButton);\n\nvar IndentButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nIndentButton = (function(_super) {\n  __extends(IndentButton, _super);\n\n  function IndentButton() {\n    return IndentButton.__super__.constructor.apply(this, arguments);\n  }\n\n  IndentButton.prototype.name = 'indent';\n\n  IndentButton.prototype.icon = 'indent';\n\n  IndentButton.prototype._init = function() {\n    this.title = this._t(this.name) + ' (Tab)';\n    return IndentButton.__super__._init.call(this);\n  };\n\n  IndentButton.prototype.status = function($node) {\n    return true;\n  };\n\n  IndentButton.prototype.command = function() {\n    return this.editor.util.indent();\n  };\n\n  return IndentButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(IndentButton);\n\nvar OutdentButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nOutdentButton = (function(_super) {\n  __extends(OutdentButton, _super);\n\n  function OutdentButton() {\n    return OutdentButton.__super__.constructor.apply(this, arguments);\n  }\n\n  OutdentButton.prototype.name = 'outdent';\n\n  OutdentButton.prototype.icon = 'outdent';\n\n  OutdentButton.prototype._init = function() {\n    this.title = this._t(this.name) + ' (Shift + Tab)';\n    return OutdentButton.__super__._init.call(this);\n  };\n\n  OutdentButton.prototype.status = function($node) {\n    return true;\n  };\n\n  OutdentButton.prototype.command = function() {\n    return this.editor.util.outdent();\n  };\n\n  return OutdentButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(OutdentButton);\n\nvar HrButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nHrButton = (function(_super) {\n  __extends(HrButton, _super);\n\n  function HrButton() {\n    return HrButton.__super__.constructor.apply(this, arguments);\n  }\n\n  HrButton.prototype.name = 'hr';\n\n  HrButton.prototype.icon = 'minus';\n\n  HrButton.prototype.htmlTag = 'hr';\n\n  HrButton.prototype.status = function($node) {\n    return true;\n  };\n\n  HrButton.prototype.command = function() {\n    var $hr, $newBlock, $nextBlock, $rootBlock;\n    $rootBlock = this.editor.util.furthestBlockEl();\n    $nextBlock = $rootBlock.next();\n    if ($nextBlock.length > 0) {\n      this.editor.selection.save();\n    } else {\n      $newBlock = $('<p/>').append(this.editor.util.phBr);\n    }\n    $hr = $('<hr/>').insertAfter($rootBlock);\n    if ($newBlock) {\n      $newBlock.insertAfter($hr);\n      this.editor.selection.setRangeAtStartOf($newBlock);\n    } else {\n      this.editor.selection.restore();\n    }\n    return this.editor.trigger('valuechanged');\n  };\n\n  return HrButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(HrButton);\n\nvar TableButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nTableButton = (function(_super) {\n  __extends(TableButton, _super);\n\n  function TableButton() {\n    return TableButton.__super__.constructor.apply(this, arguments);\n  }\n\n  TableButton.prototype.name = 'table';\n\n  TableButton.prototype.icon = 'table';\n\n  TableButton.prototype.htmlTag = 'table';\n\n  TableButton.prototype.disableTag = 'pre, li, blockquote';\n\n  TableButton.prototype.menu = true;\n\n  TableButton.prototype._init = function() {\n    TableButton.__super__._init.call(this);\n    $.merge(this.editor.formatter._allowedTags, ['tbody', 'tr', 'td', 'colgroup', 'col']);\n    $.extend(this.editor.formatter._allowedAttributes, {\n      td: ['rowspan', 'colspan'],\n      col: ['width']\n    });\n    this._initShortcuts();\n    this.editor.on('decorate', (function(_this) {\n      return function(e, $el) {\n        return $el.find('table').each(function(i, table) {\n          return _this.decorate($(table));\n        });\n      };\n    })(this));\n    this.editor.on('undecorate', (function(_this) {\n      return function(e, $el) {\n        return $el.find('table').each(function(i, table) {\n          return _this.undecorate($(table));\n        });\n      };\n    })(this));\n    this.editor.on('selectionchanged.table', (function(_this) {\n      return function(e) {\n        var $container, range;\n        _this.editor.body.find('.simditor-table td').removeClass('active');\n        range = _this.editor.selection.getRange();\n        if (range == null) {\n          return;\n        }\n        $container = $(range.commonAncestorContainer);\n        if (range.collapsed && $container.is('.simditor-table')) {\n          if (_this.editor.selection.rangeAtStartOf($container)) {\n            $container = $container.find('td:first');\n          } else {\n            $container = $container.find('td:last');\n          }\n          _this.editor.selection.setRangeAtEndOf($container);\n        }\n        return $container.closest('td', _this.editor.body).addClass('active');\n      };\n    })(this));\n    this.editor.on('blur.table', (function(_this) {\n      return function(e) {\n        return _this.editor.body.find('.simditor-table td').removeClass('active');\n      };\n    })(this));\n    this.editor.inputManager.addKeystrokeHandler('38', 'td', (function(_this) {\n      return function(e, $node) {\n        var $prevTr, $tr, index;\n        $tr = $node.parent('tr');\n        $prevTr = $tr.prev('tr');\n        if (!($prevTr.length > 0)) {\n          return true;\n        }\n        index = $tr.find('td').index($node);\n        _this.editor.selection.setRangeAtEndOf($prevTr.find('td').eq(index));\n        return true;\n      };\n    })(this));\n    return this.editor.inputManager.addKeystrokeHandler('40', 'td', (function(_this) {\n      return function(e, $node) {\n        var $nextTr, $tr, index;\n        $tr = $node.parent('tr');\n        $nextTr = $tr.next('tr');\n        if (!($nextTr.length > 0)) {\n          return true;\n        }\n        index = $tr.find('td').index($node);\n        _this.editor.selection.setRangeAtEndOf($nextTr.find('td').eq(index));\n        return true;\n      };\n    })(this));\n  };\n\n  TableButton.prototype.initResize = function($table) {\n    var $colgroup, $resizeHandle, $wrapper;\n    $wrapper = $table.parent('.simditor-table');\n    $colgroup = $table.find('colgroup');\n    if ($colgroup.length < 1) {\n      $colgroup = $('<colgroup/>').prependTo($table);\n      $table.find('tr:first td').each((function(_this) {\n        return function(i, td) {\n          var $col;\n          return $col = $('<col/>').appendTo($colgroup);\n        };\n      })(this));\n      this.refreshTableWidth($table);\n    }\n    $resizeHandle = $('<div class=\"simditor-resize-handle\" contenteditable=\"false\"></div>').appendTo($wrapper);\n    $wrapper.on('mousemove', 'td', (function(_this) {\n      return function(e) {\n        var $col, $td, index, x, _ref, _ref1;\n        if ($wrapper.hasClass('resizing')) {\n          return;\n        }\n        $td = $(e.currentTarget);\n        x = e.pageX - $(e.currentTarget).offset().left;\n        if (x < 5 && $td.prev().length > 0) {\n          $td = $td.prev();\n        }\n        if ($td.next('td').length < 1) {\n          $resizeHandle.hide();\n          return;\n        }\n        if ((_ref = $resizeHandle.data('td')) != null ? _ref.is($td) : void 0) {\n          $resizeHandle.show();\n          return;\n        }\n        index = $td.parent().find('td').index($td);\n        $col = $colgroup.find('col').eq(index);\n        if ((_ref1 = $resizeHandle.data('col')) != null ? _ref1.is($col) : void 0) {\n          $resizeHandle.show();\n          return;\n        }\n        return $resizeHandle.css('left', $td.position().left + $td.outerWidth() - 5).data('td', $td).data('col', $col).show();\n      };\n    })(this));\n    $wrapper.on('mouseleave', (function(_this) {\n      return function(e) {\n        return $resizeHandle.hide();\n      };\n    })(this));\n    return $wrapper.on('mousedown', '.simditor-resize-handle', (function(_this) {\n      return function(e) {\n        var $handle, $leftCol, $leftTd, $rightCol, $rightTd, minWidth, startHandleLeft, startLeftWidth, startRightWidth, startX, tableWidth;\n        $handle = $(e.currentTarget);\n        $leftTd = $handle.data('td');\n        $leftCol = $handle.data('col');\n        $rightTd = $leftTd.next('td');\n        $rightCol = $leftCol.next('col');\n        startX = e.pageX;\n        startLeftWidth = $leftTd.outerWidth() * 1;\n        startRightWidth = $rightTd.outerWidth() * 1;\n        startHandleLeft = parseFloat($handle.css('left'));\n        tableWidth = $leftTd.closest('table').width();\n        minWidth = 50;\n        $(document).on('mousemove.simditor-resize-table', function(e) {\n          var deltaX, leftWidth, rightWidth;\n          deltaX = e.pageX - startX;\n          leftWidth = startLeftWidth + deltaX;\n          rightWidth = startRightWidth - deltaX;\n          if (leftWidth < minWidth) {\n            leftWidth = minWidth;\n            deltaX = minWidth - startLeftWidth;\n            rightWidth = startRightWidth - deltaX;\n          } else if (rightWidth < minWidth) {\n            rightWidth = minWidth;\n            deltaX = startRightWidth - minWidth;\n            leftWidth = startLeftWidth + deltaX;\n          }\n          $leftCol.attr('width', (leftWidth / tableWidth * 100) + '%');\n          $rightCol.attr('width', (rightWidth / tableWidth * 100) + '%');\n          return $handle.css('left', startHandleLeft + deltaX);\n        });\n        $(document).one('mouseup.simditor-resize-table', function(e) {\n          $(document).off('.simditor-resize-table');\n          return $wrapper.removeClass('resizing');\n        });\n        $wrapper.addClass('resizing');\n        return false;\n      };\n    })(this));\n  };\n\n  TableButton.prototype._initShortcuts = function() {\n    this.editor.inputManager.addShortcut('ctrl+alt+up', (function(_this) {\n      return function(e) {\n        _this.editMenu.find('.menu-item[data-param=insertRowAbove]').click();\n        return false;\n      };\n    })(this));\n    this.editor.inputManager.addShortcut('ctrl+alt+down', (function(_this) {\n      return function(e) {\n        _this.editMenu.find('.menu-item[data-param=insertRowBelow]').click();\n        return false;\n      };\n    })(this));\n    this.editor.inputManager.addShortcut('ctrl+alt+left', (function(_this) {\n      return function(e) {\n        _this.editMenu.find('.menu-item[data-param=insertColLeft]').click();\n        return false;\n      };\n    })(this));\n    return this.editor.inputManager.addShortcut('ctrl+alt+right', (function(_this) {\n      return function(e) {\n        _this.editMenu.find('.menu-item[data-param=insertColRight]').click();\n        return false;\n      };\n    })(this));\n  };\n\n  TableButton.prototype.decorate = function($table) {\n    if ($table.parent('.simditor-table').length > 0) {\n      this.undecorate($table);\n    }\n    $table.wrap('<div class=\"simditor-table\"></div>');\n    this.initResize($table);\n    return $table.parent();\n  };\n\n  TableButton.prototype.undecorate = function($table) {\n    if (!($table.parent('.simditor-table').length > 0)) {\n      return;\n    }\n    return $table.parent().replaceWith($table);\n  };\n\n  TableButton.prototype.renderMenu = function() {\n    $(\"<div class=\\\"menu-create-table\\\">\\n</div>\\n<div class=\\\"menu-edit-table\\\">\\n  <ul>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"deleteRow\\\"><span>\" + (this._t('deleteRow')) + \" ( Ctrl + Alt + → )</span></a></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"insertRowAbove\\\"><span>\" + (this._t('insertRowAbove')) + \" ( Ctrl + Alt + ↑ )</span></a></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"insertRowBelow\\\"><span>\" + (this._t('insertRowBelow')) + \" ( Ctrl + Alt + ↓ )</span></a></li>\\n    <li><span class=\\\"separator\\\"></span></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"deleteCol\\\"><span>\" + (this._t('deleteColumn')) + \"</span></a></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"insertColLeft\\\"><span>\" + (this._t('insertColumnLeft')) + \" ( Ctrl + Alt + ← )</span></a></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"insertColRight\\\"><span>\" + (this._t('insertColumnRight')) + \" ( Ctrl + Alt + → )</span></a></li>\\n    <li><span class=\\\"separator\\\"></span></li>\\n    <li><a tabindex=\\\"-1\\\" unselectable=\\\"on\\\" class=\\\"menu-item\\\" href=\\\"javascript:;\\\" data-param=\\\"deleteTable\\\"><span>\" + (this._t('deleteTable')) + \"</span></a></li>\\n  </ul>\\n</div>\").appendTo(this.menuWrapper);\n    this.createMenu = this.menuWrapper.find('.menu-create-table');\n    this.editMenu = this.menuWrapper.find('.menu-edit-table');\n    this.createTable(6, 6).appendTo(this.createMenu);\n    this.createMenu.on('mouseenter', 'td', (function(_this) {\n      return function(e) {\n        var $td, $tr, num;\n        _this.createMenu.find('td').removeClass('selected');\n        $td = $(e.currentTarget);\n        $tr = $td.parent();\n        num = $tr.find('td').index($td) + 1;\n        return $tr.prevAll('tr').addBack().find('td:lt(' + num + ')').addClass('selected');\n      };\n    })(this));\n    this.createMenu.on('mouseleave', (function(_this) {\n      return function(e) {\n        return $(e.currentTarget).find('td').removeClass('selected');\n      };\n    })(this));\n    return this.createMenu.on('mousedown', 'td', (function(_this) {\n      return function(e) {\n        var $closestBlock, $table, $td, $tr, colNum, rowNum;\n        _this.wrapper.removeClass('menu-on');\n        if (!_this.editor.inputManager.focused) {\n          return;\n        }\n        $td = $(e.currentTarget);\n        $tr = $td.parent();\n        colNum = $tr.find('td').index($td) + 1;\n        rowNum = $tr.prevAll('tr').length + 1;\n        $table = _this.createTable(rowNum, colNum, true);\n        $closestBlock = _this.editor.util.closestBlockEl();\n        if (_this.editor.util.isEmptyNode($closestBlock)) {\n          $closestBlock.replaceWith($table);\n        } else {\n          $closestBlock.after($table);\n        }\n        _this.decorate($table);\n        _this.editor.selection.setRangeAtStartOf($table.find('td:first'));\n        _this.editor.trigger('valuechanged');\n        return false;\n      };\n    })(this));\n  };\n\n  TableButton.prototype.createTable = function(row, col, phBr) {\n    var $table, $tbody, $td, $tr, c, r, _i, _j;\n    $table = $('<table/>');\n    $tbody = $('<tbody/>').appendTo($table);\n    for (r = _i = 0; 0 <= row ? _i < row : _i > row; r = 0 <= row ? ++_i : --_i) {\n      $tr = $('<tr/>').appendTo($tbody);\n      for (c = _j = 0; 0 <= col ? _j < col : _j > col; c = 0 <= col ? ++_j : --_j) {\n        $td = $('<td/>').appendTo($tr);\n        if (phBr) {\n          $td.append(this.editor.util.phBr);\n        }\n      }\n    }\n    return $table;\n  };\n\n  TableButton.prototype.refreshTableWidth = function($table) {\n    var cols, tableWidth;\n    tableWidth = $table.width();\n    cols = $table.find('col');\n    return $table.find('tr:first td').each((function(_this) {\n      return function(i, td) {\n        var $col;\n        $col = cols.eq(i);\n        return $col.attr('width', ($(td).outerWidth() / tableWidth * 100) + '%');\n      };\n    })(this));\n  };\n\n  TableButton.prototype.setActive = function(active) {\n    TableButton.__super__.setActive.call(this, active);\n    if (active) {\n      this.createMenu.hide();\n      return this.editMenu.show();\n    } else {\n      this.createMenu.show();\n      return this.editMenu.hide();\n    }\n  };\n\n  TableButton.prototype.deleteRow = function($td) {\n    var $newTr, $tr, index;\n    $tr = $td.parent('tr');\n    if ($tr.siblings('tr').length < 1) {\n      return this.deleteTable($td);\n    } else {\n      $newTr = $tr.next('tr');\n      if (!($newTr.length > 0)) {\n        $newTr = $tr.prev('tr');\n      }\n      index = $tr.find('td').index($td);\n      $tr.remove();\n      return this.editor.selection.setRangeAtEndOf($newTr.find('td').eq(index));\n    }\n  };\n\n  TableButton.prototype.insertRow = function($td, direction) {\n    var $newTr, $table, $tr, colNum, i, index, _i;\n    if (direction == null) {\n      direction = 'after';\n    }\n    $tr = $td.parent('tr');\n    $table = $tr.closest('table');\n    colNum = 0;\n    $table.find('tr').each((function(_this) {\n      return function(i, tr) {\n        return colNum = Math.max(colNum, $(tr).find('td').length);\n      };\n    })(this));\n    $newTr = $('<tr/>');\n    for (i = _i = 1; 1 <= colNum ? _i <= colNum : _i >= colNum; i = 1 <= colNum ? ++_i : --_i) {\n      $('<td/>').append(this.editor.util.phBr).appendTo($newTr);\n    }\n    $tr[direction]($newTr);\n    index = $tr.find('td').index($td);\n    return this.editor.selection.setRangeAtStartOf($newTr.find('td').eq(index));\n  };\n\n  TableButton.prototype.deleteCol = function($td) {\n    var $newTd, $table, $tr, index;\n    $tr = $td.parent('tr');\n    if ($tr.siblings('tr').length < 1 && $td.siblings('td').length < 1) {\n      return this.deleteTable($td);\n    } else {\n      index = $tr.find('td').index($td);\n      $newTd = $td.next('td');\n      if (!($newTd.length > 0)) {\n        $newTd = $tr.prev('td');\n      }\n      $table = $tr.closest('table');\n      $table.find('col').eq(index).remove();\n      $table.find('tr').each((function(_this) {\n        return function(i, tr) {\n          return $(tr).find('td').eq(index).remove();\n        };\n      })(this));\n      this.refreshTableWidth($table);\n      return this.editor.selection.setRangeAtEndOf($newTd);\n    }\n  };\n\n  TableButton.prototype.insertCol = function($td, direction) {\n    var $col, $newCol, $newTd, $table, $tr, index, tableWidth, width;\n    if (direction == null) {\n      direction = 'after';\n    }\n    $tr = $td.parent('tr');\n    index = $tr.find('td').index($td);\n    $table = $td.closest('table');\n    $col = $table.find('col').eq(index);\n    $table.find('tr').each((function(_this) {\n      return function(i, tr) {\n        var $newTd;\n        $newTd = $('<td/>').append(_this.editor.util.phBr);\n        return $(tr).find('td').eq(index)[direction]($newTd);\n      };\n    })(this));\n    $newCol = $('<col/>');\n    $col[direction]($newCol);\n    tableWidth = $table.width();\n    width = Math.max(parseFloat($col.attr('width')) / 2, 50 / tableWidth * 100);\n    $col.attr('width', width + '%');\n    $newCol.attr('width', width + '%');\n    this.refreshTableWidth($table);\n    $newTd = direction === 'after' ? $td.next('td') : $td.prev('td');\n    return this.editor.selection.setRangeAtStartOf($newTd);\n  };\n\n  TableButton.prototype.deleteTable = function($td) {\n    var $block, $table;\n    $table = $td.closest('.simditor-table');\n    $block = $table.next('p');\n    $table.remove();\n    if ($block.length > 0) {\n      return this.editor.selection.setRangeAtStartOf($block);\n    }\n  };\n\n  TableButton.prototype.command = function(param) {\n    var $td, range;\n    range = this.editor.selection.getRange();\n    $td = $(range.commonAncestorContainer).closest('td');\n    if (!($td.length > 0)) {\n      return;\n    }\n    if (param === 'deleteRow') {\n      this.deleteRow($td);\n    } else if (param === 'insertRowAbove') {\n      this.insertRow($td, 'before');\n    } else if (param === 'insertRowBelow') {\n      this.insertRow($td);\n    } else if (param === 'deleteCol') {\n      this.deleteCol($td);\n    } else if (param === 'insertColLeft') {\n      this.insertCol($td, 'before');\n    } else if (param === 'insertColRight') {\n      this.insertCol($td);\n    } else if (param === 'deleteTable') {\n      this.deleteTable($td);\n    } else {\n      return;\n    }\n    return this.editor.trigger('valuechanged');\n  };\n\n  return TableButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(TableButton);\n\nvar StrikethroughButton,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nStrikethroughButton = (function(_super) {\n  __extends(StrikethroughButton, _super);\n\n  function StrikethroughButton() {\n    return StrikethroughButton.__super__.constructor.apply(this, arguments);\n  }\n\n  StrikethroughButton.prototype.name = 'strikethrough';\n\n  StrikethroughButton.prototype.icon = 'strikethrough';\n\n  StrikethroughButton.prototype.htmlTag = 'strike';\n\n  StrikethroughButton.prototype.disableTag = 'pre';\n\n  StrikethroughButton.prototype.status = function($node) {\n    var active;\n    if ($node != null) {\n      this.setDisabled($node.is(this.disableTag));\n    }\n    if (this.disabled) {\n      return true;\n    }\n    active = document.queryCommandState('strikethrough') === true;\n    this.setActive(active);\n    return active;\n  };\n\n  StrikethroughButton.prototype.command = function() {\n    document.execCommand('strikethrough');\n    this.editor.trigger('valuechanged');\n    return $(document).trigger('selectionchange');\n  };\n\n  return StrikethroughButton;\n\n})(Button);\n\nSimditor.Toolbar.addButton(StrikethroughButton);\n\nreturn Simditor;\n\n}));\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/simditor/uploader.js",
    "content": "(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define('simple-uploader', [\"jquery\",\n      \"simple-module\"], function ($, SimpleModule) {\n      return (root.returnExportsGlobal = factory($, SimpleModule));\n    });\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(require(\"jquery\"),\n      require(\"simple-module\"));\n  } else {\n    root.simple = root.simple || {};\n    root.simple['uploader'] = factory(jQuery,\n      SimpleModule);\n  }\n}(this, function ($, SimpleModule) {\n\nvar Uploader, uploader,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nUploader = (function(_super) {\n  __extends(Uploader, _super);\n\n  function Uploader() {\n    return Uploader.__super__.constructor.apply(this, arguments);\n  }\n\n  Uploader.count = 0;\n\n  Uploader.prototype.opts = {\n    url: '',\n    params: null,\n    fileKey: 'upload_file',\n    connectionCount: 3\n  };\n\n  Uploader.prototype._init = function() {\n    this.files = [];\n    this.queue = [];\n    this.id = ++Uploader.count;\n    this.on('uploadcomplete', (function(_this) {\n      return function(e, file) {\n        _this.files.splice($.inArray(file, _this.files), 1);\n        if (_this.queue.length > 0 && _this.files.length < _this.opts.connectionCount) {\n          return _this.upload(_this.queue.shift());\n        } else {\n          return _this.uploading = false;\n        }\n      };\n    })(this));\n    return $(window).on('beforeunload.uploader-' + this.id, (function(_this) {\n      return function(e) {\n        if (!_this.uploading) {\n          return;\n        }\n        e.originalEvent.returnValue = _this._t('leaveConfirm');\n        return _this._t('leaveConfirm');\n      };\n    })(this));\n  };\n\n  Uploader.prototype.generateId = (function() {\n    var id;\n    id = 0;\n    return function() {\n      return id += 1;\n    };\n  })();\n\n  Uploader.prototype.upload = function(file, opts) {\n    var f, key, _i, _len;\n    if (opts == null) {\n      opts = {};\n    }\n    if (file == null) {\n      return;\n    }\n    if ($.isArray(file)) {\n      for (_i = 0, _len = file.length; _i < _len; _i++) {\n        f = file[_i];\n        this.upload(f, opts);\n      }\n    } else if ($(file).is('input:file')) {\n      key = $(file).attr('name');\n      if (key) {\n        opts.fileKey = key;\n      }\n      this.upload($.makeArray($(file)[0].files), opts);\n    } else if (!file.id || !file.obj) {\n      file = this.getFile(file);\n    }\n    if (!(file && file.obj)) {\n      return;\n    }\n    $.extend(file, opts);\n    if (this.files.length >= this.opts.connectionCount) {\n      this.queue.push(file);\n      return;\n    }\n    if (this.triggerHandler('beforeupload', [file]) === false) {\n      return;\n    }\n    this.files.push(file);\n    this._xhrUpload(file);\n    return this.uploading = true;\n  };\n\n  Uploader.prototype.getFile = function(fileObj) {\n    var name, _ref, _ref1;\n    if (fileObj instanceof window.File || fileObj instanceof window.Blob) {\n      name = (_ref = fileObj.fileName) != null ? _ref : fileObj.name;\n    } else {\n      return null;\n    }\n    return {\n      id: this.generateId(),\n      url: this.opts.url,\n      params: this.opts.params,\n      fileKey: this.opts.fileKey,\n      name: name,\n      size: (_ref1 = fileObj.fileSize) != null ? _ref1 : fileObj.size,\n      ext: name ? name.split('.').pop().toLowerCase() : '',\n      obj: fileObj\n    };\n  };\n\n  Uploader.prototype._xhrUpload = function(file) {\n    var formData, k, v, _ref;\n    formData = new FormData();\n    formData.append(file.fileKey, file.obj);\n    formData.append(\"original_filename\", file.name);\n    if (file.params) {\n      _ref = file.params;\n      for (k in _ref) {\n        v = _ref[k];\n        formData.append(k, v);\n      }\n    }\n    return file.xhr = $.ajax({\n      url: file.url,\n      data: formData,\n      dataType: 'json',\n      processData: false,\n      contentType: false,\n      type: 'POST',\n      headers: {\n        'X-File-Name': encodeURIComponent(file.name)\n      },\n      xhr: function() {\n        var req;\n        req = $.ajaxSettings.xhr();\n        if (req) {\n          req.upload.onprogress = (function(_this) {\n            return function(e) {\n              return _this.progress(e);\n            };\n          })(this);\n        }\n        return req;\n      },\n      progress: (function(_this) {\n        return function(e) {\n          if (!e.lengthComputable) {\n            return;\n          }\n          return _this.trigger('uploadprogress', [file, e.loaded, e.total]);\n        };\n      })(this),\n      error: (function(_this) {\n        return function(xhr, status, err) {\n          return _this.trigger('uploaderror', [file, xhr, status]);\n        };\n      })(this),\n      success: (function(_this) {\n        return function(result) {\n          _this.trigger('uploadprogress', [file, file.size, file.size]);\n          return _this.trigger('uploadsuccess', [file, result]);\n        };\n      })(this),\n      complete: (function(_this) {\n        return function(xhr, status) {\n          return _this.trigger('uploadcomplete', [file, xhr.responseText]);\n        };\n      })(this)\n    });\n  };\n\n  Uploader.prototype.cancel = function(file) {\n    var f, _i, _len, _ref;\n    if (!file.id) {\n      _ref = this.files;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        f = _ref[_i];\n        if (f.id === file * 1) {\n          file = f;\n          break;\n        }\n      }\n    }\n    this.trigger('uploadcancel', [file]);\n    if (file.xhr) {\n      file.xhr.abort();\n    }\n    return file.xhr = null;\n  };\n\n  Uploader.prototype.readImageFile = function(fileObj, callback) {\n    var fileReader, img;\n    if (!$.isFunction(callback)) {\n      return;\n    }\n    img = new Image();\n    img.onload = function() {\n      return callback(img);\n    };\n    img.onerror = function() {\n      return callback();\n    };\n    if (window.FileReader && FileReader.prototype.readAsDataURL && /^image/.test(fileObj.type)) {\n      fileReader = new FileReader();\n      fileReader.onload = function(e) {\n        return img.src = e.target.result;\n      };\n      return fileReader.readAsDataURL(fileObj);\n    } else {\n      return callback();\n    }\n  };\n\n  Uploader.prototype.destroy = function() {\n    var file, _i, _len, _ref;\n    this.queue.length = 0;\n    _ref = this.files;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      file = _ref[_i];\n      this.cancel(file);\n    }\n    $(window).off('.uploader-' + this.id);\n    return $(document).off('.uploader-' + this.id);\n  };\n\n  Uploader.i18n = {\n    'zh-CN': {\n      leaveConfirm: '正在上传文件，如果离开上传会自动取消'\n    }\n  };\n\n  Uploader.locale = 'zh-CN';\n\n  return Uploader;\n\n})(SimpleModule);\n\nuploader = function(opts) {\n  return new Uploader(opts);\n};\n\n\nreturn uploader;\n\n\n}));\n\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/suggest/data.json",
    "content": "{\n\t\"message\": \"\",\n\t\"value\": [\n\t\t{\n\t\t\t\"userName\": \"淳芸\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20001\n\t\t}, {\n\t\t\t\"userName\": \"orion-01\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20000\n\t\t}, {\n\t\t\t\"userName\": \"穆晓晨\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20002\n\t\t}, {\n\t\t\t\"userName\": \"张欢引\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20003\n\t\t}, {\n\t\t\t\"userName\": \"吴琼\",\n\t\t\t\"shortAccount\": \"wuqiong\",\n\t\t\t\"userId\": 20004\n\t\t}, {\n\t\t\t\"userName\": \"吴东鹏\",\n\t\t\t\"shortAccount\": \"wudongpeng\",\n\t\t\t\"userId\": 20005\n\t\t}, {\n\t\t\t\"userName\": \"黄少铅\",\n\t\t\t\"shortAccount\": \"huangshaoqian\",\n\t\t\t\"userId\": 20006\n\t\t}, {\n\t\t\t\"userName\": \"胡运燕\",\n\t\t\t\"shortAccount\": \"yunyan\",\n\t\t\t\"userId\": 20007\n\t\t}, {\n\t\t\t\"userName\": \"刘幸\",\n\t\t\t\"shortAccount\": \"liuxing\",\n\t\t\t\"userId\": 20008\n\t\t}, {\n\t\t\t\"userName\": \"陈媛媛\",\n\t\t\t\"shortAccount\": \"chenyuanyuan\",\n\t\t\t\"userId\": 20009\n\t\t}, {\n\t\t\t\"userName\": \"旷东林\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20010\n\t\t}, {\n\t\t\t\"userName\": \"唐宏禹\",\n\t\t\t\"shortAccount\": \"chunyun\",\n\t\t\t\"userId\": 20011\n\t\t}, {\n\t\t\t\"userName\": \"旷东林\",\n\t\t\t\"shortAccount\": \"kuangdonglin\",\n\t\t\t\"userId\": 20010\n\t\t}, {\n\t\t\t\"userName\": \"唐宏禹\",\n\t\t\t\"shortAccount\": \"tanghongyu\",\n\t\t\t\"userId\": 20011\n\t\t}\n\t],\n\t\"code\": 200,\n\t\"redirect\": \"\"\n}\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/summernote/summernote-zh-CN.js",
    "content": "(function ($) {\n  $.extend($.summernote.lang, {\n    'zh-CN': {\n      font: {\n        bold: '粗体',\n        italic: '斜体',\n        underline: '下划线',\n        strikethrough: '删除线',\n        clear: '清除格式',\n        height: '行高',\n        name: '字体',\n        size: '字号'\n      },\n      image: {\n        image: '图片',\n        insert: '插入图片',\n        resizeFull: '调整至 100%',\n        resizeHalf: '调整至 50%',\n        resizeQuarter: '调整至 25%',\n        floatLeft: '左浮动',\n        floatRight: '右浮动',\n        floatNone: '不浮动',\n        dragImageHere: '将图片拖至此处',\n        selectFromFiles: '从本地上传',\n        url: '图片地址'\n      },\n      link: {\n        link: '链接',\n        insert: '插入链接',\n        unlink: '去除链接',\n        edit: '编辑链接',\n        textToDisplay: '显示文本',\n        url: '链接地址',\n        openInNewWindow: '在新窗口打开'\n      },\n      video: {\n        video: '视频',\n        videoLink: '视频链接',\n        insert: '插入视频',\n        url: '视频地址',\n        providers: '(优酷, Instagram, DailyMotion, Youtube等)'\n      },\n      table: {\n        table: '表格'\n      },\n      hr: {\n        insert: '水平线'\n      },\n      style: {\n        style: '样式',\n        normal: '普通',\n        blockquote: '引用',\n        pre: '代码',\n        h1: '标题 1',\n        h2: '标题 2',\n        h3: '标题 3',\n        h4: '标题 4',\n        h5: '标题 5',\n        h6: '标题 6'\n      },\n      lists: {\n        unordered: '无序列表',\n        ordered: '有序列表'\n      },\n      options: {\n        help: '帮助',\n        fullscreen: '全屏',\n        codeview: '源代码'\n      },\n      paragraph: {\n        paragraph: '段落',\n        outdent: '减少缩进',\n        indent: '增加缩进',\n        left: '左对齐',\n        center: '居中对齐',\n        right: '右对齐',\n        justify: '两端对齐'\n      },\n      color: {\n        recent: '最近使用',\n        more: '更多',\n        background: '背景',\n        foreground: '前景',\n        transparent: '透明',\n        setTransparent: '透明',\n        reset: '重置',\n        resetToDefault: '默认'\n      },\n      shortcut: {\n        shortcuts: '快捷键',\n        close: '关闭',\n        textFormatting: '文本格式',\n        action: '动作',\n        paragraphFormatting: '段落格式',\n        documentStyle: '文档样式'\n      },\n      history: {\n        undo: '撤销',\n        redo: '重做'\n      }\n    }\n  });\n})(jQuery);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/summernote/summernote.js",
    "content": "/**\n * Super simple wysiwyg editor v0.8.8\n * http://summernote.org/\n *\n * summernote.js\n * Copyright 2013- Alan Hong. and other contributors\n * summernote may be freely distributed under the MIT license./\n *\n * Date: 2017-09-09T11:03Z\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  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) {\n    // Webpack\n    if (typeof __webpack_require__ === 'function') { // jshint ignore:line\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 require !== 'undefined') {\n      // Browserify\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      // Almond/Require\n      } else if (typeof require.specified !== 'undefined') {\n        hasCodeMirror = require.specified('codemirror');\n      }\n    }\n  }\n\n  var isSupportTouch =\n    (('ontouchstart' in window) ||\n     (navigator.MaxTouchPoints > 0) ||\n     (navigator.msMaxTouchPoints > 0));\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    isSupportTouch: isSupportTouch,\n    hasCodeMirror: hasCodeMirror,\n    isFontInstalled: isFontInstalled,\n    isW3CRangeSupport: !!document.createRange\n  };\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\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|^INPUT/.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    /**\n     * @method isCustomStyleTag\n     *\n     * assert if a node contains a \"note-styletag\" class,\n     * which implies that's a custom-made style tag node\n     *\n     * @param {Node} an HTML DOM node\n     */\n    var isCustomStyleTag = function (node) {\n      return node && !dom.isText(node) && list.contains(node.classList, 'note-styletag');\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      isCustomStyleTag: isCustomStyleTag\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      // trigger custom onDestroy callback\n      this.triggerEvent('destroy', this);\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      this.triggerEvent('disable', false);\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      this.triggerEvent('disable', 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    /**\n     *Some buttons need to change their visual style immediately once they get pressed\n     */\n    this.createInvokeHandlerAndUpdateState = function (namespace, value) {\n      return function (event) {\n        self.createInvokeHandler(namespace, value)(event);\n        self.invoke('buttons.updateCurrentStyle');\n      };\n    };\n\n    this.createInvokeHandler = function (namespace, value) {\n      return function (event) {\n        event.preventDefault();\n        var $target = $(event.target);\n        self.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target);\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\n      // Update 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      options.tooltip = options.tooltip === 'auto' ? !agent.isSupportTouch : options.tooltip;\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\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      var option = (typeof item === 'object') ? item.option : undefined;\n\n      var dataValue = 'data-value=\"' + value + '\"';\n      var dataOption = (option !== undefined) ? ' data-option=\"' + option + '\"' : '';\n      return '<li><a href=\"#\" ' + (dataValue + dataOption) + '>' + content + '</a></li>';\n    }).join('') : options.items;\n\n    $node.html(markup);\n  });\n\n  var dropdownButtonContents = function (contents, options) {\n    return contents + ' ' + icon(options.icons.caret, 'span');\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    if (options.tooltip) {\n      $node.find('.note-color-btn').tooltip({\n        container: 'body',\n        trigger: 'hover',\n        placement: 'bottom'\n      });\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 checkbox = renderer.create('<div class=\"checkbox\"></div>', function ($node, options) {\n      $node.html([\n          ' <label' + (options.id ? ' for=\"' + options.id + '\"' : '') + '>',\n          ' <input type=\"checkbox\"' + (options.id ? ' id=\"' + options.id + '\"' : ''),\n          (options.checked ? ' checked' : '') + '/>',\n          (options.text ? options.text : ''),\n          '</label>'\n      ].join(''));\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    dropdown: dropdown,\n    dropdownButtonContents: dropdownButtonContents,\n    dropdownCheck: dropdownCheck,\n    palette: palette,\n    dialog: dialog,\n    popover: popover,\n    checkbox: checkbox,\n    icon: icon,\n    options: {},\n\n    button: function ($node, options) {\n      return renderer.create('<button type=\"button\" class=\"note-btn btn btn-default btn-sm\" tabindex=\"-1\">', function ($node, options) {\n        if (options && options.tooltip && self.options.tooltip) {\n          $node.attr({\n            title: options.tooltip\n          }).tooltip({\n            container: 'body',\n            trigger: 'hover',\n            placement: 'bottom'\n          });\n        }\n      })($node, options);\n    },\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      self.options = 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        addRowAbove: 'Add row above',\n        addRowBelow: 'Add row below',\n        addColLeft: 'Add column left',\n        addColRight: 'Add column right',\n        delRow: 'Delete row',\n        delCol: 'Delete column',\n        delTable: 'Delete table'\n      },\n      hr: {\n        insert: 'Insert Horizontal Rule'\n      },\n      style: {\n        style: 'Style',\n        p: '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      'DELETE': 46,\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          keyMap.DELETE\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          'font-family': document.queryCommandValue('fontname') || styleInfo['font-family']\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, pre or custom-made styleTag with P tag\n          if ((dom.isHeading(nextPara) || dom.isPre(nextPara) || dom.isCustomStyleTag(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  /**\n   * @class Create a virtual table to create what actions to do in change.\n   * @param {object} startPoint Cell selected to apply change.\n   * @param {enum} where  Where change will be applied Row or Col. Use enum: TableResultAction.where\n   * @param {enum} action Action to be applied. Use enum: TableResultAction.requestAction\n   * @param {object} domTable Dom element of table to make changes.\n   */\n  var TableResultAction = function (startPoint, where, action, domTable) {\n    var _startPoint = { 'colPos': 0, 'rowPos': 0 };\n    var _virtualTable = [];\n    var _actionCellList = [];\n\n    //////////////////////////////////////////////\n    // Private functions\n    //////////////////////////////////////////////\n\n    /**\n     * Set the startPoint of action.\n     */\n    function setStartPoint() {\n      if (!startPoint || !startPoint.tagName || (startPoint.tagName.toLowerCase() !== 'td' && startPoint.tagName.toLowerCase() !== 'th')) {\n        console.error('Impossible to identify start Cell point.', startPoint);\n        return;\n      }\n      _startPoint.colPos = startPoint.cellIndex;\n      if (!startPoint.parentElement || !startPoint.parentElement.tagName || startPoint.parentElement.tagName.toLowerCase() !== 'tr') {\n        console.error('Impossible to identify start Row point.', startPoint);\n        return;\n      }\n      _startPoint.rowPos = startPoint.parentElement.rowIndex;\n    }\n\n    /**\n     * Define virtual table position info object.\n     * \n     * @param {int} rowIndex Index position in line of virtual table.\n     * @param {int} cellIndex Index position in column of virtual table.\n     * @param {object} baseRow Row affected by this position.\n     * @param {object} baseCell Cell affected by this position.\n     * @param {bool} isSpan Inform if it is an span cell/row.\n     */\n    function setVirtualTablePosition(rowIndex, cellIndex, baseRow, baseCell, isRowSpan, isColSpan, isVirtualCell) {\n      var objPosition = {\n        'baseRow': baseRow,\n        'baseCell': baseCell,\n        'isRowSpan': isRowSpan,\n        'isColSpan': isColSpan,\n        'isVirtual': isVirtualCell\n      };\n      if (!_virtualTable[rowIndex]) {\n        _virtualTable[rowIndex] = [];\n      }\n      _virtualTable[rowIndex][cellIndex] = objPosition;\n    }\n\n    /**\n     * Create action cell object.\n     * \n     * @param {object} virtualTableCellObj Object of specific position on virtual table.\n     * @param {enum} resultAction Action to be applied in that item.\n     */\n    function getActionCell(virtualTableCellObj, resultAction, virtualRowPosition, virtualColPosition) {\n      return {\n        'baseCell': virtualTableCellObj.baseCell,\n        'action': resultAction,\n        'virtualTable': {\n          'rowIndex': virtualRowPosition,\n          'cellIndex': virtualColPosition\n        }\n      };\n    }\n\n    /**\n     * Recover free index of row to append Cell.\n     * \n     * @param {int} rowIndex Index of row to find free space.\n     * @param {int} cellIndex Index of cell to find free space in table.\n     */\n    function recoverCellIndex(rowIndex, cellIndex) {\n      if (!_virtualTable[rowIndex]) {\n        return cellIndex;\n      }\n      if (!_virtualTable[rowIndex][cellIndex]) {\n        return cellIndex;\n      }\n\n      var newCellIndex = cellIndex;\n      while (_virtualTable[rowIndex][newCellIndex]) {\n        newCellIndex++;\n        if (!_virtualTable[rowIndex][newCellIndex]) {\n          return newCellIndex;\n        }\n      }\n    }\n\n    /**\n     * Recover info about row and cell and add information to virtual table.\n     * \n     * @param {object} row Row to recover information.\n     * @param {object} cell Cell to recover information.\n     */\n    function addCellInfoToVirtual(row, cell) {\n      var cellIndex = recoverCellIndex(row.rowIndex, cell.cellIndex);\n      var cellHasColspan = (cell.colSpan > 1);\n      var cellHasRowspan = (cell.rowSpan > 1);\n      var isThisSelectedCell = (row.rowIndex === _startPoint.rowPos && cell.cellIndex === _startPoint.colPos);\n      setVirtualTablePosition(row.rowIndex, cellIndex, row, cell, cellHasRowspan, cellHasColspan, false);\n\n      // Add span rows to virtual Table.\n      var rowspanNumber = cell.attributes.rowSpan ? parseInt(cell.attributes.rowSpan.value, 10) : 0;\n      if (rowspanNumber > 1) {\n        for (var rp = 1; rp < rowspanNumber; rp++) {\n          var rowspanIndex = row.rowIndex + rp;\n          adjustStartPoint(rowspanIndex, cellIndex, cell, isThisSelectedCell);\n          setVirtualTablePosition(rowspanIndex, cellIndex, row, cell, true, cellHasColspan, true);\n        }\n      }\n\n      // Add span cols to virtual table.\n      var colspanNumber = cell.attributes.colSpan ? parseInt(cell.attributes.colSpan.value, 10) : 0;\n      if (colspanNumber > 1) {\n        for (var cp = 1; cp < colspanNumber; cp++) {\n          var cellspanIndex = recoverCellIndex(row.rowIndex, (cellIndex + cp));\n          adjustStartPoint(row.rowIndex, cellspanIndex, cell, isThisSelectedCell);\n          setVirtualTablePosition(row.rowIndex, cellspanIndex, row, cell, cellHasRowspan, true, true);\n        }\n      }\n    }\n\n    /**\n     * Process validation and adjust of start point if needed\n     * \n     * @param {int} rowIndex \n     * @param {int} cellIndex \n     * @param {object} cell \n     * @param {bool} isSelectedCell \n     */\n    function adjustStartPoint(rowIndex, cellIndex, cell, isSelectedCell) {\n      if (rowIndex === _startPoint.rowPos && _startPoint.colPos >= cell.cellIndex && cell.cellIndex <= cellIndex && !isSelectedCell) {\n        _startPoint.colPos++;\n      }\n    }\n\n    /**\n     * Create virtual table of cells with all cells, including span cells.\n     */\n    function createVirtualTable() {\n      var rows = domTable.rows;\n      for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n        var cells = rows[rowIndex].cells;\n        for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {\n          addCellInfoToVirtual(rows[rowIndex], cells[cellIndex]);\n        }\n      }\n    }\n\n    /**\n     * Get action to be applied on the cell.\n     * \n     * @param {object} cell virtual table cell to apply action\n     */\n    function getDeleteResultActionToCell(cell) {\n      switch (where) {\n        case TableResultAction.where.Column:\n          if (cell.isColSpan) {\n            return TableResultAction.resultAction.SubtractSpanCount;\n          }\n          break;\n        case TableResultAction.where.Row:\n          if (!cell.isVirtual && cell.isRowSpan) {\n            return TableResultAction.resultAction.AddCell;\n          }\n          else if (cell.isRowSpan) {\n            return TableResultAction.resultAction.SubtractSpanCount;\n          }\n          break;\n      }\n      return TableResultAction.resultAction.RemoveCell;\n    }\n\n    /**\n     * Get action to be applied on the cell.\n     * \n     * @param {object} cell virtual table cell to apply action\n     */\n    function getAddResultActionToCell(cell) {\n      switch (where) {\n        case TableResultAction.where.Column:\n          if (cell.isColSpan) {\n            return TableResultAction.resultAction.SumSpanCount;\n          } else if (cell.isRowSpan && cell.isVirtual) {\n            return TableResultAction.resultAction.Ignore;\n          }\n          break;\n        case TableResultAction.where.Row:\n          if (cell.isRowSpan) {\n            return TableResultAction.resultAction.SumSpanCount;\n          } else if (cell.isColSpan && cell.isVirtual) {\n            return TableResultAction.resultAction.Ignore;\n          }\n          break;\n      }\n      return TableResultAction.resultAction.AddCell;\n    }\n\n    function init() {\n      setStartPoint();\n      createVirtualTable();\n    }\n\n    //////////////////////////////////////////////\n    // Public functions\n    //////////////////////////////////////////////\n\n    /**\n     * Recover array os what to do in table.\n     */\n    this.getActionList = function () {\n      var fixedRow = (where === TableResultAction.where.Row) ? _startPoint.rowPos : -1;\n      var fixedCol = (where === TableResultAction.where.Column) ? _startPoint.colPos : -1;\n\n      var actualPosition = 0;\n      var canContinue = true;\n      while (canContinue) {\n        var rowPosition = (fixedRow >= 0) ? fixedRow : actualPosition;\n        var colPosition = (fixedCol >= 0) ? fixedCol : actualPosition;\n        var row = _virtualTable[rowPosition];\n        if (!row) {\n          canContinue = false;\n          return _actionCellList;\n        }\n        var cell = row[colPosition];\n        if (!cell) {\n          canContinue = false;\n          return _actionCellList;\n        }\n\n        // Define action to be applied in this cell\n        var resultAction = TableResultAction.resultAction.Ignore;\n        switch (action) {\n          case TableResultAction.requestAction.Add:\n            resultAction = getAddResultActionToCell(cell);\n            break;\n          case TableResultAction.requestAction.Delete:\n            resultAction = getDeleteResultActionToCell(cell);\n            break;\n        }\n        _actionCellList.push(getActionCell(cell, resultAction, rowPosition, colPosition));\n        actualPosition++;\n      }\n\n      return _actionCellList;\n    };\n\n    init();\n  };\n  /**\n  * \n  * Where action occours enum.\n  */\n  TableResultAction.where = { 'Row': 0, 'Column': 1 };\n  /**\n  * \n  * Requested action to apply enum.\n  */\n  TableResultAction.requestAction = { 'Add': 0, 'Delete': 1 };\n  /**\n  * \n  * Result action to be executed enum.\n  */\n  TableResultAction.resultAction = { 'Ignore': 0, 'SubtractSpanCount': 1, 'RemoveCell': 2, 'AddCell': 3, 'SumSpanCount': 4 };\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     * Add a new row\n     *\n     * @param {WrappedRange} rng\n     * @param {String} position (top/bottom)\n     * @return {Node}\n     */\n    this.addRow = function (rng, position) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n\n      var currentTr = $(cell).closest('tr');\n      var trAttributes = this.recoverAttributes(currentTr);\n      var html = $('<tr' + trAttributes + '></tr>');\n\n      var vTable = new TableResultAction(cell, TableResultAction.where.Row,\n        TableResultAction.requestAction.Add, $(currentTr).closest('table')[0]);\n      var actions = vTable.getActionList();\n\n      for (var idCell = 0; idCell < actions.length; idCell++) {\n        var currentCell = actions[idCell];\n        var tdAttributes = this.recoverAttributes(currentCell.baseCell);\n        switch (currentCell.action) {\n          case TableResultAction.resultAction.AddCell:\n            html.append('<td' + tdAttributes + '>' + dom.blank + '</td>');\n            break;\n          case TableResultAction.resultAction.SumSpanCount:\n            if (position === 'top') {\n              var baseCellTr = currentCell.baseCell.parent;\n              var isTopFromRowSpan = (!baseCellTr ? 0 : currentCell.baseCell.closest('tr').rowIndex) <= currentTr[0].rowIndex;\n              if (isTopFromRowSpan) {\n                var newTd = $('<div></div>').append($('<td' + tdAttributes + '>' + dom.blank + '</td>').removeAttr('rowspan')).html();\n                html.append(newTd);\n                break;\n              }\n            }\n            var rowspanNumber = parseInt(currentCell.baseCell.rowSpan, 10);\n            rowspanNumber++;\n            currentCell.baseCell.setAttribute('rowSpan', rowspanNumber);\n            break;\n        }\n      }\n\n      if (position === 'top') {\n        currentTr.before(html);\n      }\n      else {\n        var cellHasRowspan = (cell.rowSpan > 1);\n        if (cellHasRowspan) {\n          var lastTrIndex = currentTr[0].rowIndex + (cell.rowSpan - 2);\n          $($(currentTr).parent().find('tr')[lastTrIndex]).after($(html));\n          return;\n        }\n        currentTr.after(html);\n      }\n    };\n\n    /**\n     * Add a new col\n     *\n     * @param {WrappedRange} rng\n     * @param {String} position (left/right)\n     * @return {Node}\n     */\n    this.addCol = function (rng, position) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      var row = $(cell).closest('tr');\n      var rowsGroup = $(row).siblings();\n      rowsGroup.push(row);\n\n      var vTable = new TableResultAction(cell, TableResultAction.where.Column,\n        TableResultAction.requestAction.Add, $(row).closest('table')[0]);\n      var actions = vTable.getActionList();\n\n      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {\n        var currentCell = actions[actionIndex];\n        var tdAttributes = this.recoverAttributes(currentCell.baseCell);\n        switch (currentCell.action) {\n          case TableResultAction.resultAction.AddCell:\n            if (position === 'right') {\n              $(currentCell.baseCell).after('<td' + tdAttributes + '>' + dom.blank + '</td>');\n            } else {\n              $(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');\n            }\n            break;\n          case TableResultAction.resultAction.SumSpanCount:\n            if (position === 'right') {\n              var colspanNumber = parseInt(currentCell.baseCell.colSpan, 10);\n              colspanNumber++;\n              currentCell.baseCell.setAttribute('colSpan', colspanNumber);\n            } else {\n              $(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');\n            }\n            break;\n        }\n      }\n    };\n\n    /*\n    * Copy attributes from element.\n    *\n    * @param {object} Element to recover attributes.\n    * @return {string} Copied string elements.\n    */\n    this.recoverAttributes = function (el) {\n      var resultStr = '';\n\n      if (!el) {\n        return resultStr;\n      }\n\n      var attrList = el.attributes || [];\n\n      for (var i = 0; i < attrList.length; i++) {\n        if (attrList[i].name.toLowerCase() === 'id') {\n          continue;\n        }\n\n        if (attrList[i].specified) {\n          resultStr += ' ' + attrList[i].name + '=\\'' + attrList[i].value + '\\'';\n        }\n      }\n\n      return resultStr;\n    };\n\n    /**\n     * Delete current row\n     *\n     * @param {WrappedRange} rng\n     * @return {Node}\n     */\n    this.deleteRow = function (rng) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      var row = $(cell).closest('tr');\n      var cellPos = row.children('td, th').index($(cell));\n      var rowPos = row[0].rowIndex;\n\n      var vTable = new TableResultAction(cell, TableResultAction.where.Row,\n        TableResultAction.requestAction.Delete, $(row).closest('table')[0]);\n      var actions = vTable.getActionList();\n\n      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {\n        if (!actions[actionIndex]) {\n          continue;\n        }\n\n        var baseCell = actions[actionIndex].baseCell;\n        var virtualPosition = actions[actionIndex].virtualTable;\n        var hasRowspan = (baseCell.rowSpan && baseCell.rowSpan > 1);\n        var rowspanNumber = (hasRowspan) ? parseInt(baseCell.rowSpan, 10) : 0;\n        switch (actions[actionIndex].action) {\n          case TableResultAction.resultAction.Ignore:\n            continue;\n          case TableResultAction.resultAction.AddCell:\n            var nextRow = row.next('tr')[0];\n            if (!nextRow) { continue; }\n            var cloneRow = row[0].cells[cellPos];\n            if (hasRowspan) {\n              if (rowspanNumber > 2) {\n                rowspanNumber--;\n                nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);\n                nextRow.cells[cellPos].setAttribute('rowSpan', rowspanNumber);\n                nextRow.cells[cellPos].innerHTML = '';\n              } else if (rowspanNumber === 2) {\n                nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);\n                nextRow.cells[cellPos].removeAttribute('rowSpan');\n                nextRow.cells[cellPos].innerHTML = '';\n              }\n            }\n            continue;\n          case TableResultAction.resultAction.SubtractSpanCount:\n            if (hasRowspan) {\n              if (rowspanNumber > 2) {\n                rowspanNumber--;\n                baseCell.setAttribute('rowSpan', rowspanNumber);\n                if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) { baseCell.innerHTML = ''; }\n              } else if (rowspanNumber === 2) {\n                baseCell.removeAttribute('rowSpan');\n                if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) { baseCell.innerHTML = ''; }\n              }\n            }\n            continue;\n          case TableResultAction.resultAction.RemoveCell:\n            // Do not need remove cell because row will be deleted.\n            continue;\n        }\n      }\n      row.remove();\n    };\n\n    /**\n     * Delete current col\n     *\n     * @param {WrappedRange} rng\n     * @return {Node}\n     */\n    this.deleteCol = function (rng) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      var row = $(cell).closest('tr');\n      var cellPos = row.children('td, th').index($(cell));\n\n      var vTable = new TableResultAction(cell, TableResultAction.where.Column,\n        TableResultAction.requestAction.Delete, $(row).closest('table')[0]);\n      var actions = vTable.getActionList();\n\n      for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {\n        if (!actions[actionIndex]) {\n          continue;\n        }\n        switch (actions[actionIndex].action) {\n          case TableResultAction.resultAction.Ignore:\n            continue;\n          case TableResultAction.resultAction.SubtractSpanCount:\n            var baseCell = actions[actionIndex].baseCell;\n            var hasColspan = (baseCell.colSpan && baseCell.colSpan > 1);\n            if (hasColspan) {\n              var colspanNumber = (baseCell.colSpan) ? parseInt(baseCell.colSpan, 10) : 0;\n              if (colspanNumber > 2) {\n                colspanNumber--;\n                baseCell.setAttribute('colSpan', colspanNumber);\n                if (baseCell.cellIndex === cellPos) { baseCell.innerHTML = ''; }\n              } else if (colspanNumber === 2) {\n                baseCell.removeAttribute('colSpan');\n                if (baseCell.cellIndex === cellPos) { baseCell.innerHTML = ''; }\n              }\n            }\n            continue;\n          case TableResultAction.resultAction.RemoveCell:\n            dom.remove(actions[actionIndex].baseCell, true);\n            continue;\n        }\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     * Delete current table\n     *\n     * @param {WrappedRange} rng\n     * @return {Node}\n     */\n    this.deleteTable = function (rng) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      $(cell).closest('table').remove();\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      }, 100));\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', '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, $target) {\n      var onApplyCustomStyle = context.options.callbacks.onApplyCustomStyle;\n      if (onApplyCustomStyle) {\n        onApplyCustomStyle.call(this, $target, context, this.onFormatBlock);\n      } else {\n        this.onFormatBlock(tagName);\n      }\n    });\n\n    this.onFormatBlock = 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      } else {\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\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        $(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      var linkInfo = {\n        range: rng,\n        text: rng.toString(),\n        url: $anchor.length ? $anchor.attr('href') : ''\n      };\n\n      // Define isNewWindow when anchor exists.\n      if ($anchor.length) {\n        linkInfo.isNewWindow = $anchor.attr('target') === '_blank';\n      }\n\n      return linkInfo;\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     * Set foreground color\n     *\n     * @param {String} colorCode foreground color code\n     */\n    this.foreColor = this.wrapCommand(function (colorInfo) {\n      document.execCommand('styleWithCSS', false, true);\n      document.execCommand('foreColor', false, colorInfo);\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     * @method addRow\n     *\n     *\n     */\n    this.addRow = function (position) {\n      var rng = this.createRange($editable);\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        beforeCommand();\n        table.addRow(rng, position);\n        afterCommand();\n      }\n    };\n\n     /**\n     * @method addCol\n     *\n     *\n     */\n    this.addCol = function (position) {\n      var rng = this.createRange($editable);\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        beforeCommand();\n        table.addCol(rng, position);\n        afterCommand();\n      }\n    };\n\n    /**\n     * @method deleteRow\n     *\n     *\n     */\n    this.deleteRow = function () {\n      var rng = this.createRange($editable);\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        beforeCommand();\n        table.deleteRow(rng);\n        afterCommand();\n      }\n    };\n\n    /**\n     * @method deleteCol\n     *\n     *\n     */\n    this.deleteCol = function () {\n      var rng = this.createRange($editable);\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        beforeCommand();\n        table.deleteCol(rng);\n        afterCommand();\n      }\n    };\n\n    /**\n     * @method deleteTable\n     *\n     *\n     */\n    this.deleteTable = function () {\n      var rng = this.createRange($editable);\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        beforeCommand();\n        table.deleteTable(rng);\n        afterCommand();\n      }\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.toggleClass('note-float-left', value === 'left');\n      $target.toggleClass('note-float-right', value === 'right');\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      var src = node && node.src;\n      if (dom.isImg(node) && src.indexOf('data:') === 0) {\n        var decodedData = atob(node.src.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        this.destroy();\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        var onMouseMove = 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        };\n\n        $document\n          .on('mousemove', onMouseMove)\n          .one('mouseup', function () {\n            $document.off('mousemove', onMouseMove);\n          });\n      });\n    };\n\n    this.destroy = function () {\n      $statusbar.off();\n      $statusbar.remove();\n    };\n  };\n\n  var Fullscreen = function (context) {\n    var self = this;\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    this.resizeTo = 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    this.onResize = function () {\n      self.resizeTo({\n        h: $window.height() - $toolbar.outerHeight()\n      });\n    };\n\n    /**\n     * toggle fullscreen\n     */\n    this.toggle = function () {\n      $editor.toggleClass('fullscreen');\n      if (this.isFullscreen()) {\n        $editable.data('orgHeight', $editable.css('height'));\n        $window.on('resize', this.onResize).trigger('resize');\n        $scrollbar.css('overflow', 'hidden');\n      } else {\n        $window.off('resize', this.onResize);\n        this.resizeTo({ h: $editable.data('orgHeight') });\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      'summernote.disable': function () {\n        self.hide();\n      },\n      'summernote.codeview.toggled': 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          var onMouseMove = 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          };\n\n          $document\n            .on('mousemove', onMouseMove)\n            .one('mouseup', function (e) {\n              e.preventDefault();\n              $document.off('mousemove', onMouseMove);\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      // Listen for scrolling on the handle overlay.\n      this.$handle.on('wheel', function (e) {\n        e.preventDefault();\n        self.update();\n      });\n    };\n\n    this.destroy = function () {\n      this.$handle.remove();\n    };\n\n    this.update = function (target) {\n      if (context.isDisabled()) {\n        return false;\n      }\n\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 position = $image.position();\n        var pos = {\n          left: position.left + parseInt($image.css('marginLeft'), 10),\n          top: position.top + parseInt($image.css('marginTop'), 10)\n        };\n\n        // exclude margin\n        var imageSize = {\n          w: $image.outerWidth(false),\n          h: $image.outerHeight(false)\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      this.update();\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.addTablePopoverButtons();\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.dropdownButtonContents(ui.icon(options.icons.magic), options),\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.createInvokeHandlerAndUpdateState('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.createInvokeHandlerAndUpdateState('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.createInvokeHandlerAndUpdateState('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.createInvokeHandlerAndUpdateState('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.createInvokeHandlerAndUpdateState('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.createInvokeHandlerAndUpdateState('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: ui.dropdownButtonContents('<span class=\"note-current-fontname\"/>', options),\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.createInvokeHandlerAndUpdateState('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: ui.dropdownButtonContents('<span class=\"note-current-fontsize\"/>', options),\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.createInvokeHandlerAndUpdateState('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.dropdownButtonContents('', options),\n              tooltip: lang.color.more,\n              data: {\n                toggle: 'dropdown'\n              }\n            }),\n            ui.dropdown({\n              items: [\n                '<div class=\"note-palette\">',\n                '  <div class=\"note-palette-title\">' + lang.color.background + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-light\" 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=\"note-palette\">',\n                '  <div class=\"note-palette-title\">' + lang.color.foreground + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-light\" 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              ].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                    tooltip: options.tooltip\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.dropdownButtonContents(ui.icon(options.icons.alignLeft), options),\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.dropdownButtonContents(ui.icon(options.icons.textHeight), options),\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.dropdownButtonContents(ui.icon(options.icons.table), options),\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    /**\n     * table : [\n     *  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],\n     *  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]\n     * ],\n     */\n    this.addTablePopoverButtons = function () {\n      context.memo('button.addRowUp', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.rowAbove),\n          tooltip: lang.table.addRowAbove,\n          click: context.createInvokeHandler('editor.addRow', 'top')\n        }).render();\n      });\n      context.memo('button.addRowDown', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.rowBelow),\n          tooltip: lang.table.addRowBelow,\n          click: context.createInvokeHandler('editor.addRow', 'bottom')\n        }).render();\n      });\n      context.memo('button.addColLeft', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.colBefore),\n          tooltip: lang.table.addColLeft,\n          click: context.createInvokeHandler('editor.addCol', 'left')\n        }).render();\n      });\n      context.memo('button.addColRight', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.colAfter),\n          tooltip: lang.table.addColRight,\n          click: context.createInvokeHandler('editor.addCol', 'right')\n        }).render();\n      });\n      context.memo('button.deleteRow', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.rowRemove),\n          tooltip: lang.table.delRow,\n          click: context.createInvokeHandler('editor.deleteRow')\n        }).render();\n      });\n      context.memo('button.deleteCol', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.colRemove),\n          tooltip: lang.table.delCol,\n          click: context.createInvokeHandler('editor.deleteCol')\n        }).render();\n      });\n      context.memo('button.deleteTable', function () {\n        return ui.button({\n          className: 'btn-md',\n          contents: ui.icon(options.icons.trash),\n          tooltip: lang.table.delTable,\n          click: context.createInvokeHandler('editor.deleteTable')\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    /**\n     * @param {jQuery} [$container]\n     */\n    this.updateCurrentStyle = function ($container) {\n      var $cont = $container || $toolbar;\n      \n      var styleInfo = context.invoke('editor.currentStyle');\n      this.updateBtnStates($cont, {\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        $cont.find('.dropdown-fontname a').each(function () {\n          var $item = $(this);\n          // always compare string to avoid creating another func.\n          var isChecked = ($item.data('value') + '') === (fontName + '');\n          $item.toggleClass('checked', isChecked);\n        });\n        $cont.find('.note-current-fontname').text(fontName);\n      }\n\n      if (styleInfo['font-size']) {\n        var fontSize = styleInfo['font-size'];\n        $cont.find('.dropdown-fontsize a').each(function () {\n          var $item = $(this);\n          // always compare with string to avoid creating another func.\n          var isChecked = ($item.data('value') + '') === (fontSize + '');\n          $item.toggleClass('checked', isChecked);\n        });\n        $cont.find('.note-current-fontsize').text(fontSize);\n      }\n\n      if (styleInfo['line-height']) {\n        var lineHeight = styleInfo['line-height'];\n        $cont.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 ($container, infos) {\n      $.each(infos, function (selector, pred) {\n        ui.toggleBtnActive($container.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 $editor = context.layoutInfo.editor;\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      this.changeContainer(false);\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.changeContainer = function (isFullscreen) {\n      if (isFullscreen) {\n        $toolbar.prependTo($editor);\n      } else {\n        if (options.toolbarContainer) {\n          $toolbar.appendTo(options.toolbarContainer);\n        }\n      }\n    };\n\n    this.updateFullscreen = function (isFullscreen) {\n      ui.toggleBtnActive($toolbar.find('.btn-fullscreen'), isFullscreen);\n\n      this.changeContainer(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 note-form-group\">' +\n                   '<label class=\"note-form-label\">' + lang.link.textToDisplay + '</label>' +\n                   '<input class=\"note-link-text form-control '+\n                   ' note-form-control  note-input\" type=\"text\" />' +\n                 '</div>' +\n                 '<div class=\"form-group note-form-group\">' +\n                   '<label class=\"note-form-label\">' + lang.link.url + '</label>' +\n                   '<input class=\"note-link-url form-control note-form-control ' +\n                   'note-input\" type=\"text\" value=\"http://\" />' +\n                 '</div>' +\n      (!options.disableLinkTarget ?\n          $('<div/>').append(ui.checkbox({ id: 'sn-checkbox-open-in-new-window', text: lang.link.openInNewWindow, checked: true }).render())\n              .html()\n          : '');\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-btn note-btn-primary ' +\n      '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          var isChecked = linkInfo.isNewWindow !== undefined ?\n            linkInfo.isNewWindow : context.options.linkTargetBlank;\n\n          $openInNewWindow.prop('checked', isChecked);\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            ui.hideDialog(self.$dialog);\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.disable 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,.note-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,.note-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-form-group note-group-select-from-files\">' +\n                   '<label class=\"note-form-label\">' + lang.image.selectFromFiles + '</label>' +\n                   '<input class=\"note-image-input form-control note-form-control note-input\" '+\n                   ' 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 class=\"note-form-label\">' + lang.image.url + '</label>' +\n                   '<input class=\"note-image-url form-control note-form-control note-input ' +\n                   ' col-md-12\" type=\"text\" />' +\n                 '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-btn note-btn-primary ' +\n      '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\n  /**\n   * Image popover module\n   *  mouse events that show/hide popover will be handled by Handle.js.\n   *  Handle.js will receive the events and invoke 'imagePopover.update'.\n   */\n  var ImagePopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editable = context.layoutInfo.editable;\n    var editable = $editable[0];\n    var options = context.options;\n\n    this.events = {\n      'summernote.disable': function () {\n        self.hide();\n      }\n    };\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,.note-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        var posEditor = dom.posFromPlaceholder(editable);\n\n        this.$popover.css({\n          display: 'block',\n          left: pos.left,\n          top: Math.min(pos.top, posEditor.top)\n        });\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var TablePopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    this.events = {\n      'summernote.mousedown': function (we, e) {\n        self.update(e.target);\n      },\n      'summernote.keyup summernote.scroll summernote.change': function () {\n        self.update();\n      },\n      'summernote.disable': function () {\n        self.hide();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return !list.isEmpty(options.popover.table);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-table-popover'\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content,.note-popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.table);\n\n      // [workaround] Disable Firefox's default table editor\n      if (agent.isFF) {\n        document.execCommand('enableInlineTableEditing', false, false);\n      }\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function (target) {\n      if (context.isDisabled()) {\n        return false;\n      }\n\n      var isCell = dom.isCell(target);\n\n      if (isCell) {\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      return isCell;\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 note-form-group row-fluid\">' +\n          '<label class=\"note-form-label\">' + lang.video.url + ' <small class=\"text-muted\">' + lang.video.providers + '</small></label>' +\n          '<input class=\"note-video-url form-control  note-form-control note-input span12\" ' + \n          ' type=\"text\" />' +\n          '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-btn note-btn-primary ' + \n      ' 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]*\\/)*(\\d+)[?]?.*/;\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 qqRegExp = /\\/\\/v\\.qq\\.com.*?vid=(.+)/;\n      var qqMatch = url.match(qqRegExp);\n\n      var qqRegExp2 = /\\/\\/v\\.qq\\.com\\/x?\\/?(page|cover).*?\\/([^\\/]+)\\.html\\??.*/;\n      var qqMatch2 = url.match(qqRegExp2);\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 ((qqMatch && qqMatch[1].length) || (qqMatch2 && qqMatch2[2].length)) {\n        var vid = ((qqMatch && qqMatch[1].length) ? qqMatch[1]:qqMatch2[2]);\n        $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')\n            .attr('frameborder', 0)\n            .attr('height', '310')\n            .attr('width', '500')\n            .attr('src', 'http://v.qq.com/iframe/player.html?vid=' + vid + '&amp;auto=0');\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.8</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,.note-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.disable 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          context.invoke('buttons.updateCurrentStyle', this.$popover);\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.disable 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,.note-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        // XXX: consider to move codes to editor for recording redo/undo.\n        this.lastWordRange.insertNode(node);\n        range.createFromNode(node).collapse().select();\n\n        this.lastWordRange = null;\n        this.hide();\n        context.triggerEvent('change', context.layoutInfo.editable.html(), context.layoutInfo.editable);\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.8',\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        'tablePopover': TablePopover,\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        table: [\n          ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],\n          ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]\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      linkTargetBlank: true,\n\n      focus: false,\n      tabSize: 4,\n      styleWithSpan: true,\n      shortcuts: true,\n      textareaAutoSync: true,\n      direction: null,\n      tooltip: 'auto',\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        'rowBelow': 'note-icon-row-below',\n        'colBefore': 'note-icon-col-before',\n        'colAfter': 'note-icon-col-after',\n        'rowAbove': 'note-icon-row-above',\n        'rowRemove': 'note-icon-row-remove',\n        'colRemove': 'note-icon-col-remove',\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-menu-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": "src/main/resources/static/js/plugins/switchery/switchery.js",
    "content": "(function(){function require(path,parent,orig){var resolved=require.resolve(path);if(null==resolved){orig=orig||path;parent=parent||\"root\";var err=new Error('Failed to require \"'+orig+'\" from \"'+parent+'\"');err.path=orig;err.parent=parent;err.require=true;throw err}var module=require.modules[resolved];if(!module._resolving&&!module.exports){var mod={};mod.exports={};mod.client=mod.component=true;module._resolving=true;module.call(this,mod.exports,require.relative(resolved),mod);delete module._resolving;module.exports=mod.exports}return module.exports}require.modules={};require.aliases={};require.resolve=function(path){if(path.charAt(0)===\"/\")path=path.slice(1);var paths=[path,path+\".js\",path+\".json\",path+\"/index.js\",path+\"/index.json\"];for(var i=0;i<paths.length;i++){var path=paths[i];if(require.modules.hasOwnProperty(path))return path;if(require.aliases.hasOwnProperty(path))return require.aliases[path]}};require.normalize=function(curr,path){var segs=[];if(\".\"!=path.charAt(0))return path;curr=curr.split(\"/\");path=path.split(\"/\");for(var i=0;i<path.length;++i){if(\"..\"==path[i]){curr.pop()}else if(\".\"!=path[i]&&\"\"!=path[i]){segs.push(path[i])}}return curr.concat(segs).join(\"/\")};require.register=function(path,definition){require.modules[path]=definition};require.alias=function(from,to){if(!require.modules.hasOwnProperty(from)){throw new Error('Failed to alias \"'+from+'\", it does not exist')}require.aliases[to]=from};require.relative=function(parent){var p=require.normalize(parent,\"..\");function lastIndexOf(arr,obj){var i=arr.length;while(i--){if(arr[i]===obj)return i}return-1}function localRequire(path){var resolved=localRequire.resolve(path);return require(resolved,parent,path)}localRequire.resolve=function(path){var c=path.charAt(0);if(\"/\"==c)return path.slice(1);if(\".\"==c)return require.normalize(p,path);var segs=parent.split(\"/\");var i=lastIndexOf(segs,\"deps\")+1;if(!i)i=0;path=segs.slice(0,i+1).join(\"/\")+\"/deps/\"+path;return path};localRequire.exists=function(path){return require.modules.hasOwnProperty(localRequire.resolve(path))};return localRequire};require.register(\"abpetkov-transitionize/transitionize.js\",function(exports,require,module){module.exports=Transitionize;function Transitionize(element,props){if(!(this instanceof Transitionize))return new Transitionize(element,props);this.element=element;this.props=props||{};this.init()}Transitionize.prototype.isSafari=function(){return/Safari/.test(navigator.userAgent)&&/Apple Computer/.test(navigator.vendor)};Transitionize.prototype.init=function(){var transitions=[];for(var key in this.props){transitions.push(key+\" \"+this.props[key])}this.element.style.transition=transitions.join(\", \");if(this.isSafari())this.element.style.webkitTransition=transitions.join(\", \")}});require.register(\"ftlabs-fastclick/lib/fastclick.js\",function(exports,require,module){function FastClick(layer){\"use strict\";var oldOnClick,self=this;this.trackingClick=false;this.trackingClickStart=0;this.targetElement=null;this.touchStartX=0;this.touchStartY=0;this.lastTouchIdentifier=0;this.touchBoundary=10;this.layer=layer;if(!layer||!layer.nodeType){throw new TypeError(\"Layer must be a document node\")}this.onClick=function(){return FastClick.prototype.onClick.apply(self,arguments)};this.onMouse=function(){return FastClick.prototype.onMouse.apply(self,arguments)};this.onTouchStart=function(){return FastClick.prototype.onTouchStart.apply(self,arguments)};this.onTouchMove=function(){return FastClick.prototype.onTouchMove.apply(self,arguments)};this.onTouchEnd=function(){return FastClick.prototype.onTouchEnd.apply(self,arguments)};this.onTouchCancel=function(){return FastClick.prototype.onTouchCancel.apply(self,arguments)};if(FastClick.notNeeded(layer)){return}if(this.deviceIsAndroid){layer.addEventListener(\"mouseover\",this.onMouse,true);layer.addEventListener(\"mousedown\",this.onMouse,true);layer.addEventListener(\"mouseup\",this.onMouse,true)}layer.addEventListener(\"click\",this.onClick,true);layer.addEventListener(\"touchstart\",this.onTouchStart,false);layer.addEventListener(\"touchmove\",this.onTouchMove,false);layer.addEventListener(\"touchend\",this.onTouchEnd,false);layer.addEventListener(\"touchcancel\",this.onTouchCancel,false);if(!Event.prototype.stopImmediatePropagation){layer.removeEventListener=function(type,callback,capture){var rmv=Node.prototype.removeEventListener;if(type===\"click\"){rmv.call(layer,type,callback.hijacked||callback,capture)}else{rmv.call(layer,type,callback,capture)}};layer.addEventListener=function(type,callback,capture){var adv=Node.prototype.addEventListener;if(type===\"click\"){adv.call(layer,type,callback.hijacked||(callback.hijacked=function(event){if(!event.propagationStopped){callback(event)}}),capture)}else{adv.call(layer,type,callback,capture)}}}if(typeof layer.onclick===\"function\"){oldOnClick=layer.onclick;layer.addEventListener(\"click\",function(event){oldOnClick(event)},false);layer.onclick=null}}FastClick.prototype.deviceIsAndroid=navigator.userAgent.indexOf(\"Android\")>0;FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent);FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\\d(_\\d)?/.test(navigator.userAgent);FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\\d{2})_\\d/.test(navigator.userAgent);FastClick.prototype.needsClick=function(target){\"use strict\";switch(target.nodeName.toLowerCase()){case\"button\":case\"select\":case\"textarea\":if(target.disabled){return true}break;case\"input\":if(this.deviceIsIOS&&target.type===\"file\"||target.disabled){return true}break;case\"label\":case\"video\":return true}return/\\bneedsclick\\b/.test(target.className)};FastClick.prototype.needsFocus=function(target){\"use strict\";switch(target.nodeName.toLowerCase()){case\"textarea\":return true;case\"select\":return!this.deviceIsAndroid;case\"input\":switch(target.type){case\"button\":case\"checkbox\":case\"file\":case\"image\":case\"radio\":case\"submit\":return false}return!target.disabled&&!target.readOnly;default:return/\\bneedsfocus\\b/.test(target.className)}};FastClick.prototype.sendClick=function(targetElement,event){\"use strict\";var clickEvent,touch;if(document.activeElement&&document.activeElement!==targetElement){document.activeElement.blur()}touch=event.changedTouches[0];clickEvent=document.createEvent(\"MouseEvents\");clickEvent.initMouseEvent(this.determineEventType(targetElement),true,true,window,1,touch.screenX,touch.screenY,touch.clientX,touch.clientY,false,false,false,false,0,null);clickEvent.forwardedTouchEvent=true;targetElement.dispatchEvent(clickEvent)};FastClick.prototype.determineEventType=function(targetElement){\"use strict\";if(this.deviceIsAndroid&&targetElement.tagName.toLowerCase()===\"select\"){return\"mousedown\"}return\"click\"};FastClick.prototype.focus=function(targetElement){\"use strict\";var length;if(this.deviceIsIOS&&targetElement.setSelectionRange&&targetElement.type.indexOf(\"date\")!==0&&targetElement.type!==\"time\"){length=targetElement.value.length;targetElement.setSelectionRange(length,length)}else{targetElement.focus()}};FastClick.prototype.updateScrollParent=function(targetElement){\"use strict\";var scrollParent,parentElement;scrollParent=targetElement.fastClickScrollParent;if(!scrollParent||!scrollParent.contains(targetElement)){parentElement=targetElement;do{if(parentElement.scrollHeight>parentElement.offsetHeight){scrollParent=parentElement;targetElement.fastClickScrollParent=parentElement;break}parentElement=parentElement.parentElement}while(parentElement)}if(scrollParent){scrollParent.fastClickLastScrollTop=scrollParent.scrollTop}};FastClick.prototype.getTargetElementFromEventTarget=function(eventTarget){\"use strict\";if(eventTarget.nodeType===Node.TEXT_NODE){return eventTarget.parentNode}return eventTarget};FastClick.prototype.onTouchStart=function(event){\"use strict\";var targetElement,touch,selection;if(event.targetTouches.length>1){return true}targetElement=this.getTargetElementFromEventTarget(event.target);touch=event.targetTouches[0];if(this.deviceIsIOS){selection=window.getSelection();if(selection.rangeCount&&!selection.isCollapsed){return true}if(!this.deviceIsIOS4){if(touch.identifier===this.lastTouchIdentifier){event.preventDefault();return false}this.lastTouchIdentifier=touch.identifier;this.updateScrollParent(targetElement)}}this.trackingClick=true;this.trackingClickStart=event.timeStamp;this.targetElement=targetElement;this.touchStartX=touch.pageX;this.touchStartY=touch.pageY;if(event.timeStamp-this.lastClickTime<200){event.preventDefault()}return true};FastClick.prototype.touchHasMoved=function(event){\"use strict\";var touch=event.changedTouches[0],boundary=this.touchBoundary;if(Math.abs(touch.pageX-this.touchStartX)>boundary||Math.abs(touch.pageY-this.touchStartY)>boundary){return true}return false};FastClick.prototype.onTouchMove=function(event){\"use strict\";if(!this.trackingClick){return true}if(this.targetElement!==this.getTargetElementFromEventTarget(event.target)||this.touchHasMoved(event)){this.trackingClick=false;this.targetElement=null}return true};FastClick.prototype.findControl=function(labelElement){\"use strict\";if(labelElement.control!==undefined){return labelElement.control}if(labelElement.htmlFor){return document.getElementById(labelElement.htmlFor)}return labelElement.querySelector(\"button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea\")};FastClick.prototype.onTouchEnd=function(event){\"use strict\";var forElement,trackingClickStart,targetTagName,scrollParent,touch,targetElement=this.targetElement;if(!this.trackingClick){return true}if(event.timeStamp-this.lastClickTime<200){this.cancelNextClick=true;return true}this.cancelNextClick=false;this.lastClickTime=event.timeStamp;trackingClickStart=this.trackingClickStart;this.trackingClick=false;this.trackingClickStart=0;if(this.deviceIsIOSWithBadTarget){touch=event.changedTouches[0];targetElement=document.elementFromPoint(touch.pageX-window.pageXOffset,touch.pageY-window.pageYOffset)||targetElement;targetElement.fastClickScrollParent=this.targetElement.fastClickScrollParent}targetTagName=targetElement.tagName.toLowerCase();if(targetTagName===\"label\"){forElement=this.findControl(targetElement);if(forElement){this.focus(targetElement);if(this.deviceIsAndroid){return false}targetElement=forElement}}else if(this.needsFocus(targetElement)){if(event.timeStamp-trackingClickStart>100||this.deviceIsIOS&&window.top!==window&&targetTagName===\"input\"){this.targetElement=null;return false}this.focus(targetElement);if(!this.deviceIsIOS4||targetTagName!==\"select\"){this.targetElement=null;event.preventDefault()}return false}if(this.deviceIsIOS&&!this.deviceIsIOS4){scrollParent=targetElement.fastClickScrollParent;if(scrollParent&&scrollParent.fastClickLastScrollTop!==scrollParent.scrollTop){return true}}if(!this.needsClick(targetElement)){event.preventDefault();this.sendClick(targetElement,event)}return false};FastClick.prototype.onTouchCancel=function(){\"use strict\";this.trackingClick=false;this.targetElement=null};FastClick.prototype.onMouse=function(event){\"use strict\";if(!this.targetElement){return true}if(event.forwardedTouchEvent){return true}if(!event.cancelable){return true}if(!this.needsClick(this.targetElement)||this.cancelNextClick){if(event.stopImmediatePropagation){event.stopImmediatePropagation()}else{event.propagationStopped=true}event.stopPropagation();event.preventDefault();return false}return true};FastClick.prototype.onClick=function(event){\"use strict\";var permitted;if(this.trackingClick){this.targetElement=null;this.trackingClick=false;return true}if(event.target.type===\"submit\"&&event.detail===0){return true}permitted=this.onMouse(event);if(!permitted){this.targetElement=null}return permitted};FastClick.prototype.destroy=function(){\"use strict\";var layer=this.layer;if(this.deviceIsAndroid){layer.removeEventListener(\"mouseover\",this.onMouse,true);layer.removeEventListener(\"mousedown\",this.onMouse,true);layer.removeEventListener(\"mouseup\",this.onMouse,true)}layer.removeEventListener(\"click\",this.onClick,true);layer.removeEventListener(\"touchstart\",this.onTouchStart,false);layer.removeEventListener(\"touchmove\",this.onTouchMove,false);layer.removeEventListener(\"touchend\",this.onTouchEnd,false);layer.removeEventListener(\"touchcancel\",this.onTouchCancel,false)};FastClick.notNeeded=function(layer){\"use strict\";var metaViewport;var chromeVersion;if(typeof window.ontouchstart===\"undefined\"){return true}chromeVersion=+(/Chrome\\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1];if(chromeVersion){if(FastClick.prototype.deviceIsAndroid){metaViewport=document.querySelector(\"meta[name=viewport]\");if(metaViewport){if(metaViewport.content.indexOf(\"user-scalable=no\")!==-1){return true}if(chromeVersion>31&&window.innerWidth<=window.screen.width){return true}}}else{return true}}if(layer.style.msTouchAction===\"none\"){return true}return false};FastClick.attach=function(layer){\"use strict\";return new FastClick(layer)};if(typeof define!==\"undefined\"&&define.amd){define(function(){\"use strict\";return FastClick})}else if(typeof module!==\"undefined\"&&module.exports){module.exports=FastClick.attach;module.exports.FastClick=FastClick}else{window.FastClick=FastClick}});require.register(\"switchery/switchery.js\",function(exports,require,module){var transitionize=require(\"transitionize\"),fastclick=require(\"fastclick\");module.exports=Switchery;var defaults={color:\"#64bd63\",secondaryColor:\"#dfdfdf\",className:\"switchery\",disabled:false,disabledOpacity:.5,speed:\"0.4s\"};function Switchery(element,options){if(!(this instanceof Switchery))return new Switchery(element,options);this.element=element;this.options=options||{};for(var i in defaults){if(this.options[i]==null){this.options[i]=defaults[i]}}if(this.element!=null&&this.element.type==\"checkbox\")this.init()}Switchery.prototype.hide=function(){this.element.style.display=\"none\"};Switchery.prototype.show=function(){var switcher=this.create();this.insertAfter(this.element,switcher)};Switchery.prototype.create=function(){this.switcher=document.createElement(\"span\");this.jack=document.createElement(\"small\");this.switcher.appendChild(this.jack);this.switcher.className=this.options.className;return this.switcher};Switchery.prototype.insertAfter=function(reference,target){reference.parentNode.insertBefore(target,reference.nextSibling)};Switchery.prototype.isChecked=function(){return this.element.checked};Switchery.prototype.isDisabled=function(){return this.options.disabled||this.element.disabled};Switchery.prototype.setPosition=function(clicked){var checked=this.isChecked(),switcher=this.switcher,jack=this.jack;if(clicked&&checked)checked=false;else if(clicked&&!checked)checked=true;if(checked===true){this.element.checked=true;if(window.getComputedStyle)jack.style.left=parseInt(window.getComputedStyle(switcher).width)-parseInt(window.getComputedStyle(jack).width)+\"px\";else jack.style.left=parseInt(switcher.currentStyle[\"width\"])-parseInt(jack.currentStyle[\"width\"])+\"px\";if(this.options.color)this.colorize();this.setSpeed()}else{jack.style.left=0;this.element.checked=false;this.switcher.style.boxShadow=\"inset 0 0 0 0 \"+this.options.secondaryColor;this.switcher.style.borderColor=this.options.secondaryColor;this.switcher.style.backgroundColor=\"\";this.setSpeed()}};Switchery.prototype.setSpeed=function(){var switcherProp={},jackProp={left:this.options.speed.replace(/[a-z]/,\"\")/2+\"s\"};if(this.isChecked()){switcherProp={border:this.options.speed,\"box-shadow\":this.options.speed,\"background-color\":this.options.speed.replace(/[a-z]/,\"\")*3+\"s\"}}else{switcherProp={border:this.options.speed,\"box-shadow\":this.options.speed}}transitionize(this.switcher,switcherProp);transitionize(this.jack,jackProp)};Switchery.prototype.setAttributes=function(){var id=this.element.getAttribute(\"id\"),name=this.element.getAttribute(\"name\");if(id)this.switcher.setAttribute(\"id\",id);if(name)this.switcher.setAttribute(\"name\",name)};Switchery.prototype.colorize=function(){this.switcher.style.backgroundColor=this.options.color;this.switcher.style.borderColor=this.options.color;this.switcher.style.boxShadow=\"inset 0 0 0 16px \"+this.options.color};Switchery.prototype.handleOnchange=function(state){if(typeof Event===\"function\"||!document.fireEvent){var event=document.createEvent(\"HTMLEvents\");event.initEvent(\"change\",true,true);this.element.dispatchEvent(event)}else{this.element.fireEvent(\"onchange\")}};Switchery.prototype.handleChange=function(){var self=this,el=this.element;if(el.addEventListener){el.addEventListener(\"change\",function(){self.setPosition()})}else{el.attachEvent(\"onchange\",function(){self.setPosition()})}};Switchery.prototype.handleClick=function(){var self=this,switcher=this.switcher;if(this.isDisabled()===false){fastclick(switcher);if(switcher.addEventListener){switcher.addEventListener(\"click\",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}else{switcher.attachEvent(\"onclick\",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}}else{this.element.disabled=true;this.switcher.style.opacity=this.options.disabledOpacity}};Switchery.prototype.disableLabel=function(){var parent=this.element.parentNode,labels=document.getElementsByTagName(\"label\"),attached=null;for(var i=0;i<labels.length;i++){if(labels[i].getAttribute(\"for\")===this.element.id){attached=true}}if(attached===true||parent.tagName.toLowerCase()===\"label\"){if(parent.addEventListener){parent.addEventListener(\"click\",function(e){e.preventDefault()})}else{parent.attachEvent(\"onclick\",function(e){e.returnValue=false})}}};Switchery.prototype.markAsSwitched=function(){this.element.setAttribute(\"data-switchery\",true)};Switchery.prototype.markedAsSwitched=function(){return this.element.getAttribute(\"data-switchery\")};Switchery.prototype.init=function(){this.hide();this.show();this.setPosition();this.setAttributes();this.markAsSwitched();this.disableLabel();this.handleChange();this.handleClick()}});require.alias(\"abpetkov-transitionize/transitionize.js\",\"switchery/deps/transitionize/transitionize.js\");require.alias(\"abpetkov-transitionize/transitionize.js\",\"switchery/deps/transitionize/index.js\");require.alias(\"abpetkov-transitionize/transitionize.js\",\"transitionize/index.js\");require.alias(\"abpetkov-transitionize/transitionize.js\",\"abpetkov-transitionize/index.js\");require.alias(\"ftlabs-fastclick/lib/fastclick.js\",\"switchery/deps/fastclick/lib/fastclick.js\");require.alias(\"ftlabs-fastclick/lib/fastclick.js\",\"switchery/deps/fastclick/index.js\");require.alias(\"ftlabs-fastclick/lib/fastclick.js\",\"fastclick/index.js\");require.alias(\"ftlabs-fastclick/lib/fastclick.js\",\"ftlabs-fastclick/index.js\");require.alias(\"switchery/switchery.js\",\"switchery/index.js\");if(typeof exports==\"object\"){module.exports=require(\"switchery\")}else if(typeof define==\"function\"&&define.amd){define(function(){return require(\"switchery\")})}else{this[\"Switchery\"]=require(\"switchery\")}})();\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/treeview/bootstrap-treeview.js",
    "content": "/* =========================================================\n * bootstrap-treeview.js v1.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;(function($, window, document, undefined) {\n\n\t/*global jQuery, console*/\n\n\t'use strict';\n\n\tvar pluginName = 'treeview';\n\n\tvar Tree = function(element, options) {\n\n\t\tthis.$element = $(element);\n\t\tthis._element = element;\n\t\tthis._elementId = this._element.id;\n\t\tthis._styleId = this._elementId + '-style';\n\n\t\tthis.tree = [];\n\t\tthis.nodes = [];\n\t\tthis.selectedNode = {};\n\n\t\tthis._init(options);\n\t};\n\n\tTree.defaults = {\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\tnodeIcon: 'glyphicon glyphicon-stop',\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\n\t\tenableLinks: false,\n\t\thighlightSelected: true,\n\t\tshowBorder: true,\n\t\tshowTags: false,\n\n\t\t// Event handler for when a node is selected\n\t\tonNodeSelected: undefined\n\t};\n\n\tTree.prototype = {\n\n\t\tremove: function() {\n\n\t\t\tthis._destroy();\n\t\t\t$.removeData(this, 'plugin_' + pluginName);\n\t\t\t$('#' + this._styleId).remove();\n\t\t},\n\n\t\t_destroy: function() {\n\n\t\t\tif (this.initialized) {\n\t\t\t\tthis.$wrapper.remove();\n\t\t\t\tthis.$wrapper = null;\n\n\t\t\t\t// Switch off events\n\t\t\t\tthis._unsubscribeEvents();\n\t\t\t}\n\n\t\t\t// Reset initialized flag\n\t\t\tthis.initialized = false;\n\t\t},\n\n\t\t_init: function(options) {\n\n\t\t\tif (options.data) {\n\t\t\t\tif (typeof options.data === 'string') {\n\t\t\t\t\toptions.data = $.parseJSON(options.data);\n\t\t\t\t}\n\t\t\t\tthis.tree = $.extend(true, [], options.data);\n\t\t\t\tdelete options.data;\n\t\t\t}\n\n\t\t\tthis.options = $.extend({}, Tree.defaults, options);\n\n\t\t\tthis._setInitialLevels(this.tree, 0);\n\n\t\t\tthis._destroy();\n\t\t\tthis._subscribeEvents();\n\t\t\tthis._render();\n\t\t},\n\n\t\t_unsubscribeEvents: function() {\n\n\t\t\tthis.$element.off('click');\n\t\t},\n\n\t\t_subscribeEvents: function() {\n\n\t\t\tthis._unsubscribeEvents();\n\n\t\t\tthis.$element.on('click', $.proxy(this._clickHandler, this));\n\n\t\t\tif (typeof (this.options.onNodeSelected) === 'function') {\n\t\t\t\tthis.$element.on('nodeSelected', this.options.onNodeSelected);\n\t\t\t}\n\t\t},\n\n\t\t_clickHandler: function(event) {\n\n\t\t\tif (!this.options.enableLinks) { event.preventDefault(); }\n\n\t\t\tvar target = $(event.target),\n\t\t\t\tclassList = target.attr('class') ? target.attr('class').split(' ') : [],\n\t\t\t\tnode = this._findNode(target);\n\n\t\t\tif ((classList.indexOf('click-expand') != -1) ||\n\t\t\t\t\t(classList.indexOf('click-collapse') != -1)) {\n\t\t\t\t// Expand or collapse node by toggling child node visibility\n\t\t\t\tthis._toggleNodes(node);\n\t\t\t\tthis._render();\n\t\t\t}\n\t\t\telse if (node) {\n\t\t\t\tthis._setSelectedNode(node);\n\t\t\t}\n\t\t},\n\n\t\t// Looks up the DOM for the closest parent list item to retrieve the\n\t\t// data attribute nodeid, which is used to lookup the node in the flattened structure.\n\t\t_findNode: function(target) {\n\n\t\t\tvar nodeId = target.closest('li.list-group-item').attr('data-nodeid'),\n\t\t\t\tnode = this.nodes[nodeId];\n\n\t\t\tif (!node) {\n\t\t\t\tconsole.log('Error: node does not exist');\n\t\t\t}\n\t\t\treturn node;\n\t\t},\n\n\t\t// Actually triggers the nodeSelected event\n\t\t_triggerNodeSelectedEvent: function(node) {\n\n\t\t\tthis.$element.trigger('nodeSelected', [$.extend(true, {}, node)]);\n\t\t},\n\n\t\t// Handles selecting and unselecting of nodes,\n\t\t// as well as determining whether or not to trigger the nodeSelected event\n\t\t_setSelectedNode: function(node) {\n\n\t\t\tif (!node) { return; }\n\n\t\t\tif (node === this.selectedNode) {\n\t\t\t\tthis.selectedNode = {};\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis._triggerNodeSelectedEvent(this.selectedNode = node);\n\t\t\t}\n\n\t\t\tthis._render();\n\t\t},\n\n\t\t// On initialization recurses the entire tree structure\n\t\t// setting expanded / collapsed states based on initial levels\n\t\t_setInitialLevels: function(nodes, level) {\n\n\t\t\tif (!nodes) { return; }\n\t\t\tlevel += 1;\n\n\t\t\tvar self = this;\n\t\t\t$.each(nodes, function addNodes(id, node) {\n\n\t\t\t\tif (level >= self.options.levels) {\n\t\t\t\t\tself._toggleNodes(node);\n\t\t\t\t}\n\n\t\t\t\t// Need to traverse both nodes and _nodes to ensure\n\t\t\t\t// all levels collapsed beyond levels\n\t\t\t\tvar nodes = node.nodes ? node.nodes : node._nodes ? node._nodes : undefined;\n\t\t\t\tif (nodes) {\n\t\t\t\t\treturn self._setInitialLevels(nodes, level);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// Toggle renaming nodes -> _nodes, _nodes -> nodes\n\t\t// to simulate expanding or collapsing a node.\n\t\t_toggleNodes: function(node) {\n\n\t\t\tif (!node.nodes && !node._nodes) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (node.nodes) {\n\t\t\t\tnode._nodes = node.nodes;\n\t\t\t\tdelete node.nodes;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnode.nodes = node._nodes;\n\t\t\t\tdelete node._nodes;\n\t\t\t}\n\t\t},\n\n\t\t_render: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tif (!self.initialized) {\n\n\t\t\t\t// Setup first time only components\n\t\t\t\tself.$element.addClass(pluginName);\n\t\t\t\tself.$wrapper = $(self._template.list);\n\n\t\t\t\tself._injectStyle();\n\n\t\t\t\tself.initialized = true;\n\t\t\t}\n\n\t\t\tself.$element.empty().append(self.$wrapper.empty());\n\n\t\t\t// Build tree\n\t\t\tself.nodes = [];\n\t\t\tself._buildTree(self.tree, 0);\n\t\t},\n\n\t\t// Starting from the root node, and recursing down the\n\t\t// structure we build the tree one node at a time\n\t\t_buildTree: function(nodes, level) {\n\n\t\t\tif (!nodes) { return; }\n\t\t\tlevel += 1;\n\n\t\t\tvar self = this;\n\t\t\t$.each(nodes, function addNodes(id, node) {\n\n\t\t\t\tnode.nodeId = self.nodes.length;\n\t\t\t\tself.nodes.push(node);\n\n\t\t\t\tvar treeItem = $(self._template.item)\n\t\t\t\t\t.addClass('node-' + self._elementId)\n\t\t\t\t\t.addClass((node === self.selectedNode) ? 'node-selected' : '')\n\t\t\t\t\t.attr('data-nodeid', node.nodeId)\n\t\t\t\t\t.attr('style', self._buildStyleOverride(node));\n\n\t\t\t\t// Add indent/spacer to mimic tree structure\n\t\t\t\tfor (var i = 0; i < (level - 1); i++) {\n\t\t\t\t\ttreeItem.append(self._template.indent);\n\t\t\t\t}\n\n\t\t\t\t// Add expand, collapse or empty spacer icons\n\t\t\t\t// to facilitate tree structure navigation\n\t\t\t\tif (node._nodes) {\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append($(self._template.iconWrapper)\n\t\t\t\t\t\t\t.append($(self._template.icon)\n\t\t\t\t\t\t\t\t.addClass('click-expand')\n\t\t\t\t\t\t\t\t.addClass(self.options.expandIcon))\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse if (node.nodes) {\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append($(self._template.iconWrapper)\n\t\t\t\t\t\t\t.append($(self._template.icon)\n\t\t\t\t\t\t\t\t.addClass('click-collapse')\n\t\t\t\t\t\t\t\t.addClass(self.options.collapseIcon))\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append($(self._template.iconWrapper)\n\t\t\t\t\t\t\t.append($(self._template.icon)\n\t\t\t\t\t\t\t\t.addClass('glyphicon'))\n\t\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Add node icon\n\t\t\t\ttreeItem\n\t\t\t\t\t.append($(self._template.iconWrapper)\n\t\t\t\t\t\t.append($(self._template.icon)\n\t\t\t\t\t\t\t.addClass(node.icon ? node.icon : self.options.nodeIcon))\n\t\t\t\t\t);\n\n\t\t\t\t// Add text\n\t\t\t\tif (self.options.enableLinks) {\n\t\t\t\t\t// Add hyperlink\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append($(self._template.link)\n\t\t\t\t\t\t\t.attr('href', node.href)\n\t\t\t\t\t\t\t.append(node.text)\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// otherwise just text\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append(node.text);\n\t\t\t\t}\n\n\t\t\t\t// Add tags as badges\n\t\t\t\tif (self.options.showTags && node.tags) {\n\t\t\t\t\t$.each(node.tags, function addTag(id, tag) {\n\t\t\t\t\t\ttreeItem\n\t\t\t\t\t\t\t.append($(self._template.badge)\n\t\t\t\t\t\t\t\t.append(tag)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Add item to the tree\n\t\t\t\tself.$wrapper.append(treeItem);\n\n\t\t\t\t// Recursively add child ndoes\n\t\t\t\tif (node.nodes) {\n\t\t\t\t\treturn self._buildTree(node.nodes, level);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// Define any node level style override for\n\t\t// 1. selectedNode\n\t\t// 2. node|data assigned color overrides\n\t\t_buildStyleOverride: function(node) {\n\n\t\t\tvar style = '';\n\t\t\tif (this.options.highlightSelected && (node === this.selectedNode)) {\n\t\t\t\tstyle += 'color:' + this.options.selectedColor + ';';\n\t\t\t}\n\t\t\telse if (node.color) {\n\t\t\t\tstyle += 'color:' + node.color + ';';\n\t\t\t}\n\n\t\t\tif (this.options.highlightSelected && (node === this.selectedNode)) {\n\t\t\t\tstyle += 'background-color:' + this.options.selectedBackColor + ';';\n\t\t\t}\n\t\t\telse if (node.backColor) {\n\t\t\t\tstyle += 'background-color:' + node.backColor + ';';\n\t\t\t}\n\n\t\t\treturn style;\n\t\t},\n\n\t\t// Add inline style into head\n\t\t_injectStyle: function() {\n\n\t\t\tif (this.options.injectStyle && !document.getElementById(this._styleId)) {\n\t\t\t\t$('<style type=\"text/css\" id=\"' + this._styleId + '\"> ' + this._buildStyle() + ' </style>').appendTo('head');\n\t\t\t}\n\t\t},\n\n\t\t// Construct trees style based on user options\n\t\t_buildStyle: function() {\n\n\t\t\tvar style = '.node-' + this._elementId + '{';\n\t\t\tif (this.options.color) {\n\t\t\t\tstyle += 'color:' + this.options.color + ';';\n\t\t\t}\n\t\t\tif (this.options.backColor) {\n\t\t\t\tstyle += 'background-color:' + this.options.backColor + ';';\n\t\t\t}\n\t\t\tif (!this.options.showBorder) {\n\t\t\t\tstyle += 'border:none;';\n\t\t\t}\n\t\t\telse if (this.options.borderColor) {\n\t\t\t\tstyle += 'border:1px solid ' + this.options.borderColor + ';';\n\t\t\t}\n\t\t\tstyle += '}';\n\n\t\t\tif (this.options.onhoverColor) {\n\t\t\t\tstyle += '.node-' + this._elementId + ':hover{' +\n\t\t\t\t'background-color:' + this.options.onhoverColor + ';' +\n\t\t\t\t'}';\n\t\t\t}\n\n\t\t\treturn this._css + style;\n\t\t},\n\n\t\t_template: {\n\t\t\tlist: '<ul class=\"list-group\"></ul>',\n\t\t\titem: '<li class=\"list-group-item\"></li>',\n\t\t\tindent: '<span class=\"indent\"></span>',\n\t\t\ticonWrapper: '<span class=\"icon\"></span>',\n\t\t\ticon: '<i></i>',\n\t\t\tlink: '<a href=\"#\" style=\"color:inherit;\"></a>',\n\t\t\tbadge: '<span class=\"badge\"></span>'\n\t\t},\n\n\t\t_css: '.list-group-item{cursor:pointer;}span.indent{margin-left:10px;margin-right:10px}span.icon{margin-right:5px}'\n\t\t// _css: '.list-group-item{cursor:pointer;}.list-group-item:hover{background-color:#f5f5f5;}span.indent{margin-left:10px;margin-right:10px}span.icon{margin-right:5px}'\n\n\t};\n\n\tvar logError = function(message) {\n        if(window.console) {\n            window.console.error(message);\n        }\n    };\n\n\t// Prevent against multiple instantiations,\n\t// handle updates and method calls\n\t$.fn[pluginName] = function(options, args) {\n\t\treturn this.each(function() {\n\t\t\tvar self = $.data(this, 'plugin_' + pluginName);\n\t\t\tif (typeof options === 'string') {\n\t\t\t\tif (!self) {\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(self[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 (typeof args === 'string') {\n\t\t\t\t\t\targs = [args];\n\t\t\t\t\t}\n\t\t\t\t\tself[options].apply(self, args);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (!self) {\n\t\t\t\t\t$.data(this, 'plugin_' + pluginName, new Tree(this, $.extend(true, {}, options)));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tself._init(options);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n})(jQuery, window, document);\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/validate/jquery.validate.extend.js",
    "content": "/*this is basic form validation using for validation person's basic information author:Clara Guo data:2017/07/20*/\n$(document).ready(function(){\n\t$.validator.setDefaults({       \n\t\t  submitHandler: function(form) {    \n\t\t \t\tform.submit();    \n\t\t}       \n\t});  \n\t//手机号码验证身份证正则合并：(^\\d{15}$)|(^\\d{17}([0-9]|X)$)\n\tjQuery.validator.addMethod(\"isPhone\",function(value,element){\n\t\tvar length = value.length;\n\t\tvar phone=/^1[3|4|5|7|8][0-9]\\d{8}$/;\n\t\treturn this.optional(element)||(length == 11 && phone.test(value));\n\t},\"请填写正确的11位手机号\");\n\t//电话号码验证\n\tjQuery.validator.addMethod(\"isTel\",function(value,element){\n\t\tvar tel = /^(0\\d{2,3}-)?\\d{7,8}$/g;//区号3,4位,号码7,8位\n\t\treturn this.optional(element) || (tel.test(value));\n\t},\"请填写正确的座机号码\");\n\t//姓名校验\n\tjQuery.validator.addMethod(\"isName\",function(value,element){\n\t\tvar name=/^[\\u4e00-\\u9fa5]{2,6}$/;\n\t\treturn this.optional(element) || (name.test(value));\n\t},\"姓名只能用汉字,长度2-4位\");\n\t//校验用户名\n\tjQuery.validator.addMethod(\"isUserName\",function(value,element){\n\t\tvar userName=/^[a-zA-Z0-9]{2,13}$/;\n\t\treturn this.optional(element) || (userName).test(value);\n\t},'请输入数字或者字母,不包含特殊字符');\n\t\n\t//校验身份证\n\tjQuery.validator.addMethod(\"isIdentity\",function(value,element){\n\t\tvar id= /^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X))$/;\n\t\treturn this.optional(element) || (id.test(value));\n\t},\"请输入正确的15或18位身份证号,末尾为大写X\");\n\t//校验出生日期\n\tjQuery.validator.addMethod(\"isBirth\",function(value,element){\n\t\tvar birth = /^(19|20)\\d{2}-(1[0-2]|0?[1-9])-(0?[1-9]|[1-2][0-9]|3[0-1])$/;\n\t\treturn this.optional(element) || (birth).test(value);\n\t},\"出生日期格式示例2000-01-01\");\n\t//校验新旧密码是否相同\n\tjQuery.validator.addMethod(\"isdiff\",function(){\n\t\tvar p1=$(\"#pwdOld\").val();\n\t\tvar p2=$(\"#pwdNew\").val();\n\t\tif(p1==p2){\n\t\t\treturn false;\n\t\t}else{\n\t\t\t return true;\n\t\t}\n\t\t});\n\t//校验新密码和确认密码是否相同\n\tjQuery.validator.addMethod(\"issame\",function(){\n\t\tvar p3=$(\"#confirm_password\").val();\n\t\tvar p4=$(\"#pwdNew\").val();\n\t\tif(p3==p4){\n\t\t\treturn true;\n\t\t}else{\n\t\t\t return false;\n\t\t}\n\t\t});\n\t//校验基础信息表单\n\t$(\"#basicInfoForm\").validate({\n\t\terrorElement:'span',\n\t\terrorClass:'help-block error-mes',\n\t\trules:{\n\t\t\tname:{\n\t\t\t\trequired:true,\n\t\t\t\tisName:true\n\t\t\t},\n\t\t\tsex:\"required\",\n\t\t\tbirth:\"required\",\n            mobile:{\n\t\t\t\trequired:true,\n\t\t\t\tisPhone:true\n\t\t\t},\n\t\t\temail:{\n\t\t\t\trequired:true,\n\t\t\t\temail:true\n\t\t\t}\n\t\t},\n\t\tmessages:{\n\t\t\tname:{\n\t\t\t\trequired:\"请输入中文姓名\",\n\t\t\t\tisName:\"姓名只能为汉字\"\n\t\t\t},\n\t\t\tsex:{\n\t\t\t\trequired:\"请输入性别\"\n\t\t\t},\n\t\t\tbirth:{\n\t\t\t\trequired:\"请输入出生年月\"\n\t\t\t},\n            mobile:{\n\t\t\t\trequired:\"请输入手机号\",\n\t\t\t\tisPhone:\"请填写正确的11位手机号\"\n\t\t\t},\n\t\t\temail:{\n\t\t\t\trequired:\"请输入邮箱\",\n\t\t\t\temail:\"请填写正确的邮箱格式\"\n\t\t\t}\n\t\t},\n\t\n\t\terrorPlacement:function(error,element){\n\t\t\telement.next().remove();\n\t\t\telement.closest('.gg-formGroup').append(error);\n\t\t},\n\t\t\n\t\thighlight:function(element){\n\t\t\t$(element).closest('.gg-formGroup').addClass('has-error has-feedback');\n\t\t},\n\t\tsuccess:function(label){\n\t\t\tvar el = label.closest('.gg-formGroup').find(\"input\");\n\t\t\tel.next().remove();\n\t\t\tlabel.closest('.gg-formGroup').removeClass('has-error').addClass(\"has-feedback has-success\");\n\t\t\tlabel.remove();\n\t\t},\n\t\tsubmitHandler:function(form){\n\t\t\talert(\"保存成功!\");\n\t\t}\n\t});\n\t\n\t//校验修改密码表单\n\t$(\"#modifyPwd\").validate({\n\t\tonfocusout: function(element) { $(element).valid()},\n\t\t debug:false, //表示校验通过后是否直接提交表单\n\t\t onkeyup:false, //表示按键松开时候监听验证\n\t\trules:{\n\t\t\tpwdOld:{\n\t\t\t\trequired:true,\n\t\t\t\tminlength:6\n\t\t\t},\n            pwdNew:{\n\t\t\t   required:true,\n\t\t\t   minlength:6,\n\t\t\t   isdiff:true,\n\t\t\t   //issame:true,\n\t\t   },\n\t\t\tconfirm_password:{\n\t\t\t  required:true,\n\t\t\t  minlength:6,\n\t\t\t  issame:true,\n\t\t\t}\n\t\t  \n\t\t   },\n\t\tmessages:{\n\t\t\t \tpwdOld : {\n\t\t\t\t\t required:'必填',\n\t\t\t\t\t minlength:$.validator.format('密码长度要大于6')\n\t\t\t\t},\n            \tpwdNew:{\n\t\t\t\t   required:'必填',\n\t\t\t\t   minlength:$.validator.format('密码长度要大于6'),\n\t\t\t\t   isdiff:'原密码与新密码不能重复',\n\t\t\t\t  \n\t\t\t   },\n\t\t\t\tconfirm_password:{\n\t\t\t\t   required:'必填',\n\t\t\t\t   minlength:$.validator.format('密码长度要大于6'),\n\t\t\t\t   issame:'新密码要与确认新密码一致',\n\t\t\t\t}\n\t\t\n\t\t},\n\t\terrorElement:\"mes\",\n\t\terrorClass:\"gg-star\",\n\t\terrorPlacement: function(error, element) \n\t\t{ \n\t\t\telement.closest('.gg-formGroup').append(error);\n\n\t\t}\n\t});\n});"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/README.md",
    "content": "目录说明\n========================\n\n```bash\n├── Uploader.swf                      # SWF文件，当使用Flash运行时需要引入。\n├\n├── webuploader.js                    # 完全版本。\n├── webuploader.min.js                # min版本\n├\n├── webuploader.flashonly.js          # 只有Flash实现的版本。\n├── webuploader.flashonly.min.js      # min版本\n├\n├── webuploader.html5only.js          # 只有Html5实现的版本。\n├── webuploader.html5only.min.js      # min版本\n├\n├── webuploader.noimage.js            # 去除图片处理的版本，包括HTML5和FLASH.\n├── webuploader.noimage.min.js        # min版本\n├\n├── webuploader.custom.js             # 自定义打包方案，请查看 Gruntfile.js，满足移动端使用。\n└── webuploader.custom.min.js         # min版本\n```\n\n## 示例\n\n请把整个 Git 包下载下来放在 php 服务器下，因为默认提供的文件接受是用 php 编写的，打开 examples 页面便能查看示例效果。"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.css",
    "content": ".webuploader-container {\n\tposition: relative;\n}\n.webuploader-element-invisible {\n\tposition: absolute !important;\n\tclip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n    clip: rect(1px,1px,1px,1px);\n}\n.webuploader-pick {\n\tposition: relative;\n\tdisplay: inline-block;\n\tcursor: pointer;\n\tbackground: #00b7ee;\n\tpadding: 10px 15px;\n\tcolor: #fff;\n\ttext-align: center;\n\tborder-radius: 3px;\n\toverflow: hidden;\n}\n.webuploader-pick-hover {\n\tbackground: #00a2d4;\n}\n\n.webuploader-pick-disable {\n\topacity: 0.6;\n\tpointer-events:none;\n}\n\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.custom.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * 直接来源于jquery的代码。\n     * @fileOverview Promise/A+\n     * @beta\n     */\n    define('promise-builtin',[\n        'dollar'\n    ], function( $ ) {\n\n        var api;\n\n        // 简单版Callbacks, 默认memory，可选once.\n        function Callbacks( once ) {\n            var list = [],\n                stack = !once && [],\n                fire = function( data ) {\n                    memory = data;\n                    fired = true;\n                    firingIndex = firingStart || 0;\n                    firingStart = 0;\n                    firingLength = list.length;\n                    firing = true;\n\n                    for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n                        list[ firingIndex ].apply( data[ 0 ], data[ 1 ] );\n                    }\n                    firing = false;\n\n                    if ( list ) {\n                        if ( stack ) {\n                            stack.length && fire( stack.shift() );\n                        }  else {\n                            list = [];\n                        }\n                    }\n                },\n                self = {\n                    add: function() {\n                        if ( list ) {\n                            var start = list.length;\n                            (function add ( args ) {\n                                $.each( args, function( _, arg ) {\n                                    var type = $.type( arg );\n                                    if ( type === 'function' ) {\n                                        list.push( arg );\n                                    } else if ( arg && arg.length &&\n                                            type !== 'string' ) {\n\n                                        add( arg );\n                                    }\n                                });\n                            })( arguments );\n\n                            if ( firing ) {\n                                firingLength = list.length;\n                            } else if ( memory ) {\n                                firingStart = start;\n                                fire( memory );\n                            }\n                        }\n                        return this;\n                    },\n\n                    disable: function() {\n                        list = stack = memory = undefined;\n                        return this;\n                    },\n\n                    // Lock the list in its current state\n                    lock: function() {\n                        stack = undefined;\n                        if ( !memory ) {\n                            self.disable();\n                        }\n                        return this;\n                    },\n\n                    fireWith: function( context, args ) {\n                        if ( list && (!fired || stack) ) {\n                            args = args || [];\n                            args = [ context, args.slice ? args.slice() : args ];\n                            if ( firing ) {\n                                stack.push( args );\n                            } else {\n                                fire( args );\n                            }\n                        }\n                        return this;\n                    },\n\n                    fire: function() {\n                        self.fireWith( this, arguments );\n                        return this;\n                    }\n                },\n\n                fired, firing, firingStart, firingLength, firingIndex, memory;\n\n            return self;\n        }\n\n        function Deferred( func ) {\n            var tuples = [\n                    // action, add listener, listener list, final state\n                    [ 'resolve', 'done', Callbacks( true ), 'resolved' ],\n                    [ 'reject', 'fail', Callbacks( true ), 'rejected' ],\n                    [ 'notify', 'progress', Callbacks() ]\n                ],\n                state = 'pending',\n                promise = {\n                    state: function() {\n                        return state;\n                    },\n                    always: function() {\n                        deferred.done( arguments ).fail( arguments );\n                        return this;\n                    },\n                    then: function( /* fnDone, fnFail, fnProgress */ ) {\n                        var fns = arguments;\n                        return Deferred(function( newDefer ) {\n                            $.each( tuples, function( i, tuple ) {\n                                var action = tuple[ 0 ],\n                                    fn = $.isFunction( fns[ i ] ) && fns[ i ];\n\n                                // deferred[ done | fail | progress ] for\n                                // forwarding actions to newDefer\n                                deferred[ tuple[ 1 ] ](function() {\n                                    var returned;\n\n                                    returned = fn && fn.apply( this, arguments );\n\n                                    if ( returned &&\n                                            $.isFunction( returned.promise ) ) {\n\n                                        returned.promise()\n                                                .done( newDefer.resolve )\n                                                .fail( newDefer.reject )\n                                                .progress( newDefer.notify );\n                                    } else {\n                                        newDefer[ action + 'With' ](\n                                                this === promise ?\n                                                newDefer.promise() :\n                                                this,\n                                                fn ? [ returned ] : arguments );\n                                    }\n                                });\n                            });\n                            fns = null;\n                        }).promise();\n                    },\n\n                    // Get a promise for this deferred\n                    // If obj is provided, the promise aspect is added to the object\n                    promise: function( obj ) {\n\n                        return obj != null ? $.extend( obj, promise ) : promise;\n                    }\n                },\n                deferred = {};\n\n            // Keep pipe for back-compat\n            promise.pipe = promise.then;\n\n            // Add list-specific methods\n            $.each( tuples, function( i, tuple ) {\n                var list = tuple[ 2 ],\n                    stateString = tuple[ 3 ];\n\n                // promise[ done | fail | progress ] = list.add\n                promise[ tuple[ 1 ] ] = list.add;\n\n                // Handle state\n                if ( stateString ) {\n                    list.add(function() {\n                        // state = [ resolved | rejected ]\n                        state = stateString;\n\n                    // [ reject_list | resolve_list ].disable; progress_list.lock\n                    }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n                }\n\n                // deferred[ resolve | reject | notify ]\n                deferred[ tuple[ 0 ] ] = function() {\n                    deferred[ tuple[ 0 ] + 'With' ]( this === deferred ? promise :\n                            this, arguments );\n                    return this;\n                };\n                deferred[ tuple[ 0 ] + 'With' ] = list.fireWith;\n            });\n\n            // Make the deferred a promise\n            promise.promise( deferred );\n\n            // Call given func if any\n            if ( func ) {\n                func.call( deferred, deferred );\n            }\n\n            // All done!\n            return deferred;\n        }\n\n        api = {\n            /**\n             * 创建一个[Deferred](http://api.jquery.com/category/deferred-object/)对象。\n             * 详细的Deferred用法说明，请参照jQuery的API文档。\n             *\n             * Deferred对象在钩子回掉函数中经常要用到，用来处理需要等待的异步操作。\n             *\n             * @for  Base\n             * @method Deferred\n             * @grammar Base.Deferred() => Deferred\n             * @example\n             * // 在文件开始发送前做些异步操作。\n             * // WebUploader会等待此异步操作完成后，开始发送文件。\n             * Uploader.register({\n             *     'before-send-file': 'doSomthingAsync'\n             * }, {\n             *\n             *     doSomthingAsync: function() {\n             *         var deferred = Base.Deferred();\n             *\n             *         // 模拟一次异步操作。\n             *         setTimeout(deferred.resolve, 2000);\n             *\n             *         return deferred.promise();\n             *     }\n             * });\n             */\n            Deferred: Deferred,\n\n            /**\n             * 判断传入的参数是否为一个promise对象。\n             * @method isPromise\n             * @grammar Base.isPromise( anything ) => Boolean\n             * @param  {*}  anything 检测对象。\n             * @return {Boolean}\n             * @for  Base\n             * @example\n             * console.log( Base.isPromise() );    // => false\n             * console.log( Base.isPromise({ key: '123' }) );    // => false\n             * console.log( Base.isPromise( Base.Deferred().promise() ) );    // => true\n             *\n             * // Deferred也是一个Promise\n             * console.log( Base.isPromise( Base.Deferred() ) );    // => true\n             */\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            },\n\n            /**\n             * 返回一个promise，此promise在所有传入的promise都完成了后完成。\n             * 详细请查看[这里](http://api.jquery.com/jQuery.when/)。\n             *\n             * @method when\n             * @for  Base\n             * @grammar Base.when( promise1[, promise2[, promise3...]] ) => Promise\n             */\n            when: function( subordinate /* , ..., subordinateN */ ) {\n                var i = 0,\n                    slice = [].slice,\n                    resolveValues = slice.call( arguments ),\n                    length = resolveValues.length,\n\n                    // the count of uncompleted subordinates\n                    remaining = length !== 1 || (subordinate &&\n                        $.isFunction( subordinate.promise )) ? length : 0,\n\n                    // the master Deferred. If resolveValues consist of\n                    // only a single Deferred, just use that.\n                    deferred = remaining === 1 ? subordinate : Deferred(),\n\n                    // Update function for both resolve and progress values\n                    updateFunc = function( i, contexts, values ) {\n                        return function( value ) {\n                            contexts[ i ] = this;\n                            values[ i ] = arguments.length > 1 ?\n                                    slice.call( arguments ) : value;\n\n                            if ( values === progressValues ) {\n                                deferred.notifyWith( contexts, values );\n                            } else if ( !(--remaining) ) {\n                                deferred.resolveWith( contexts, values );\n                            }\n                        };\n                    },\n\n                    progressValues, progressContexts, resolveContexts;\n\n                // add listeners to Deferred subordinates; treat others as resolved\n                if ( length > 1 ) {\n                    progressValues = new Array( length );\n                    progressContexts = new Array( length );\n                    resolveContexts = new Array( length );\n                    for ( ; i < length; i++ ) {\n                        if ( resolveValues[ i ] &&\n                                $.isFunction( resolveValues[ i ].promise ) ) {\n\n                            resolveValues[ i ].promise()\n                                    .done( updateFunc( i, resolveContexts,\n                                            resolveValues ) )\n                                    .fail( deferred.reject )\n                                    .progress( updateFunc( i, progressContexts,\n                                            progressValues ) );\n                        } else {\n                            --remaining;\n                        }\n                    }\n                }\n\n                // if we're not waiting on anything, resolve the master\n                if ( !remaining ) {\n                    deferred.resolveWith( resolveContexts, resolveValues );\n                }\n\n                return deferred.promise();\n            }\n        };\n\n        return api;\n    });\n    define('promise',[\n        'promise-builtin'\n    ], function( $ ) {\n        return $;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n\n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n\n        if (!enable) {\n            return;\n        }\n\n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n\n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n\n            image.src = url;\n        }\n\n        return Uploader.register({\n            name: 'log',\n\n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n\n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n\n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n\n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n\n        if ( urlAPI ) {\n\n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n\n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n\n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n\n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n\n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n\n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                intArray = new Uint8Array( byteStr.length );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                return intArray.buffer;\n            },\n\n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n\n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n\n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n\n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n\n        var api;\n\n        api = {\n            parsers: {\n                0xffe1: []\n            },\n\n            maxMetaDataSize: 262144,\n\n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n\n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n\n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n\n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n\n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n\n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n\n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n\n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n\n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n\n                            parsers = api.parsers[ markerBytes ];\n\n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n\n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n\n                return ret;\n            },\n\n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n\n\n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n\n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n\n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n\n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n\n                return buf1.buffer;\n            }\n        };\n\n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n\n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n\n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n\n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n\n        var EXIF = {};\n\n        EXIF.ExifMap = function() {\n            return this;\n        };\n\n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n\n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n\n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n\n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n\n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n\n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n\n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n\n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n\n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n\n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n\n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n\n            tagSize = tagType.size * length;\n\n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n\n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n\n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n\n            values = [];\n\n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n\n            if ( tagType.ascii ) {\n                str = '';\n\n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n\n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n\n                return str;\n            }\n            return values;\n        };\n\n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n\n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n\n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n\n            var tagsNumber, dirEndOffset, i;\n\n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n\n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n\n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n\n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n\n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n\n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n\n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n\n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n\n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n\n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n\n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n\n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n\n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n\n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n\n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n\n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n\n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n\n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n\n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n\n        return Html5Runtime.register( 'Image', {\n\n            // flag: 标记是否被修改过。\n            modified: false,\n\n            init: function() {\n                var me = this,\n                    img = new Image();\n\n                img.onload = function() {\n\n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n\n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n\n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n\n                me._img = img;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n\n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n\n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n\n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n\n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n\n                s = s || 1;\n\n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n\n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n\n                cvs.width = w;\n                cvs.height = h;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n\n                type = type || this.type;\n\n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n\n                    if ( type === 'image/jpeg' ) {\n\n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n\n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n\n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n\n                    blob = Util.dataURL2Blob( blob );\n                }\n\n                return blob;\n            },\n\n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n\n                type = type || this.type;\n\n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n\n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n\n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n\n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n\n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n\n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n\n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n\n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n\n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n\n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n\n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n\n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n\n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n\n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n\n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n\n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n\n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n\n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n\n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n\n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n\n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n\n\n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n\n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n\n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n\n                        py = (ey + sy) >> 1;\n                    }\n\n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n\n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n\n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n\n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n\n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n\n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n\n\n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n\n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n\n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n\n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n\n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n\n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n\n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n\n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n\n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n\n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n\n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n\n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n\n        Basic GUI blocking jpeg encoder\n        */\n\n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n\n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n\n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n\n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n\n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n\n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n\n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n\n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n\n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n\n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n\n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n\n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n\n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n\n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n\n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n\n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n\n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n\n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n\n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n\n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n\n                        dataOff += 8; /* advance pointer to next row */\n                    }\n\n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n\n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n\n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n\n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n\n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n\n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n\n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n\n                        dataOff++; /* advance pointer to next column */\n                    }\n\n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n\n                    }\n                    return outputfDCTQuant;\n                }\n\n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n\n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n\n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n\n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n\n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n\n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n\n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n\n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n\n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n\n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was const... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n\n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n\n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n\n                    if(quality) setQuality(quality);\n\n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n\n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n\n\n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n\n                    bytenew=0;\n                    bytepos=7;\n\n\n                    this.encode.displayName = \"_encode_\";\n\n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n\n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n\n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n\n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n\n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n\n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n\n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n\n\n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n\n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n\n                        }\n\n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n\n\n                    ////////////////////////////////////////////////////////////////\n\n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n\n                    writeWord(0xFFD9); //EOI\n\n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n\n                    byteout = [];\n\n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n\n                    return jpegDataUri\n            }\n\n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n\n                if(currentQuality == quality) return // don't recalc if unchanged\n\n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n\n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n\n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n\n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n\n            init();\n\n        };\n\n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n\n            return encoder.encode( data );\n        }\n\n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n\n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n\n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n\n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n\n                parts = fragement.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n\n                fragement = fragement.substring( 0, 2 );\n\n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n\n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n\n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n\n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    define('webuploader',[\n        'base',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/log',\n        'runtime/html5/blob',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/image',\n        'runtime/html5/androidpatch',\n        'runtime/html5/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.fis.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\nvar jQuery = require('example:widget/ui/jquery/jquery.js')\n\nreturn (function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        };\n\n    return makeExport( jQuery );\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n\n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n\n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n\n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n\n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n\n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n\n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n\n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n\n        return Uploader.register({\n            name: 'md5',\n\n\n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n\n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n\n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n\n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n\n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n\n                md5.loadFromBlob( blob );\n\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n\n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n\n        if ( urlAPI ) {\n\n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n\n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n\n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n\n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n\n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n\n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                intArray = new Uint8Array( byteStr.length );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                return intArray.buffer;\n            },\n\n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n\n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n\n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n\n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n\n        var api;\n\n        api = {\n            parsers: {\n                0xffe1: []\n            },\n\n            maxMetaDataSize: 262144,\n\n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n\n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n\n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n\n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n\n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n\n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n\n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n\n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n\n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n\n                            parsers = api.parsers[ markerBytes ];\n\n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n\n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n\n                return ret;\n            },\n\n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n\n\n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n\n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n\n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n\n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n\n                return buf1.buffer;\n            }\n        };\n\n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n\n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n\n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n\n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n\n        var EXIF = {};\n\n        EXIF.ExifMap = function() {\n            return this;\n        };\n\n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n\n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n\n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n\n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n\n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n\n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n\n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n\n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n\n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n\n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n\n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n\n            tagSize = tagType.size * length;\n\n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n\n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n\n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n\n            values = [];\n\n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n\n            if ( tagType.ascii ) {\n                str = '';\n\n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n\n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n\n                return str;\n            }\n            return values;\n        };\n\n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n\n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n\n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n\n            var tagsNumber, dirEndOffset, i;\n\n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n\n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n\n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n\n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n\n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n\n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n\n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n\n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n\n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n\n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n\n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n\n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n\n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n\n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n\n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n\n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n\n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n\n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n\n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n\n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n\n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n\n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n\n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n\n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n\n        Basic GUI blocking jpeg encoder\n        */\n\n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n\n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n\n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n\n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n\n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n\n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n\n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n\n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n\n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n\n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n\n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n\n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n\n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n\n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n\n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n\n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n\n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n\n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n\n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n\n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n\n                        dataOff += 8; /* advance pointer to next row */\n                    }\n\n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n\n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n\n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n\n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n\n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n\n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n\n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n\n                        dataOff++; /* advance pointer to next column */\n                    }\n\n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n\n                    }\n                    return outputfDCTQuant;\n                }\n\n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n\n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n\n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n\n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n\n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n\n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n\n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n\n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n\n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n\n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was const... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n\n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n\n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n\n                    if(quality) setQuality(quality);\n\n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n\n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n\n\n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n\n                    bytenew=0;\n                    bytepos=7;\n\n\n                    this.encode.displayName = \"_encode_\";\n\n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n\n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n\n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n\n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n\n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n\n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n\n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n\n\n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n\n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n\n                        }\n\n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n\n\n                    ////////////////////////////////////////////////////////////////\n\n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n\n                    writeWord(0xFFD9); //EOI\n\n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n\n                    byteout = [];\n\n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n\n                    return jpegDataUri\n            }\n\n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n\n                if(currentQuality == quality) return // don't recalc if unchanged\n\n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n\n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n\n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n\n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n\n            init();\n\n        };\n\n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n\n            return encoder.encode( data );\n        }\n\n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n\n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n\n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n\n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n\n                parts = fragement.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n\n                fragement = fragement.substring( 0, 2 );\n\n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n\n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n\n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n\n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n\n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n\n        return Html5Runtime.register( 'Image', {\n\n            // flag: 标记是否被修改过。\n            modified: false,\n\n            init: function() {\n                var me = this,\n                    img = new Image();\n\n                img.onload = function() {\n\n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n\n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n\n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n\n                me._img = img;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n\n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n\n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n\n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n\n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n\n                s = s || 1;\n\n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n\n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n\n                cvs.width = w;\n                cvs.height = h;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n\n                type = type || this.type;\n\n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n\n                    if ( type === 'image/jpeg' ) {\n\n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n\n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n\n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n\n                    blob = Util.dataURL2Blob( blob );\n                }\n\n                return blob;\n            },\n\n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n\n                type = type || this.type;\n\n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n\n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n\n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n\n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n\n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n\n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n\n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n\n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n\n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n\n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n\n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n\n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n\n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n\n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n\n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n\n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n\n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n\n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n\n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n\n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n\n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n\n\n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n\n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n\n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n\n                        py = (ey + sy) >> 1;\n                    }\n\n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n\n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n\n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n\n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n\n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n\n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n\n\n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n\n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n\n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n\n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n\n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n\n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n\n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n\n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n\n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n\n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n\n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n\n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n\n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n\n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n\n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n\n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n\n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n\n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n\n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n\n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n\n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n\n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n            return state;\n        },\n\n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n\n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n\n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n\n            return state;\n        },\n\n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n\n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n\n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n\n        md5 = function (s) {\n            return hex(md51(s));\n        },\n\n\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n\n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = function (x, y) {\n                var lsw = (x & 0xFFFF) + (y & 0xFFFF),\n                    msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n                return (msw << 16) | (lsw & 0xFFFF);\n            };\n        }\n\n\n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            // then append as binary\n            this.appendBinary(str);\n\n            return this;\n        };\n\n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n\n            var length = this._buff.length,\n                i;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n\n            this._buff = this._buff.substr(i - 64);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n\n\n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            var hash = md51(str);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n\n            this._length += arr.byteLength;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n\n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n\n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n\n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n\n            return result;\n        };\n\n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n\n                fr = new FileReader();\n\n                loadNext = function() {\n                    var start, end;\n\n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n\n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n\n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n\n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n\n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n\n                loadNext();\n            },\n\n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n\n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n\n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n\n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n\n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n\n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n\n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n\n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n\n        if (!enable) {\n            return;\n        }\n\n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n\n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n\n            image.src = url;\n        }\n\n        return Uploader.register({\n            name: 'log',\n\n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n\n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n\n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('webuploader',[\n        'preset/all',\n        'widgets/log'\n    ], function( preset ) {\n        return preset;\n    });\n\n    var _require = require;\n    return _require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.flashonly.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n\n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n\n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n\n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n\n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n\n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n\n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview 只有flash实现的文件版本。\n     */\n    define('preset/flashonly',[\n        'base',\n\n        // widgets\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n\n        // runtimes\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/blob',\n        'runtime/flash/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/flashonly'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.html5only.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n\n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n\n        if ( urlAPI ) {\n\n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n\n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n\n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n\n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n\n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n\n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                intArray = new Uint8Array( byteStr.length );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                return intArray.buffer;\n            },\n\n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n\n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n\n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n\n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n\n        var api;\n\n        api = {\n            parsers: {\n                0xffe1: []\n            },\n\n            maxMetaDataSize: 262144,\n\n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n\n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n\n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n\n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n\n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n\n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n\n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n\n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n\n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n\n                            parsers = api.parsers[ markerBytes ];\n\n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n\n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n\n                return ret;\n            },\n\n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n\n\n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n\n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n\n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n\n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n\n                return buf1.buffer;\n            }\n        };\n\n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n\n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n\n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n\n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n\n        var EXIF = {};\n\n        EXIF.ExifMap = function() {\n            return this;\n        };\n\n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n\n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n\n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n\n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n\n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n\n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n\n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n\n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n\n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n\n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n\n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n\n            tagSize = tagType.size * length;\n\n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n\n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n\n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n\n            values = [];\n\n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n\n            if ( tagType.ascii ) {\n                str = '';\n\n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n\n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n\n                return str;\n            }\n            return values;\n        };\n\n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n\n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n\n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n\n            var tagsNumber, dirEndOffset, i;\n\n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n\n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n\n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n\n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n\n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n\n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n\n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n\n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n\n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n\n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n\n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n\n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n\n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n\n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n\n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n\n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n\n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n\n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n\n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n\n        return Html5Runtime.register( 'Image', {\n\n            // flag: 标记是否被修改过。\n            modified: false,\n\n            init: function() {\n                var me = this,\n                    img = new Image();\n\n                img.onload = function() {\n\n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n\n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n\n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n\n                me._img = img;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n\n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n\n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n\n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n\n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n\n                s = s || 1;\n\n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n\n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n\n                cvs.width = w;\n                cvs.height = h;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n\n                type = type || this.type;\n\n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n\n                    if ( type === 'image/jpeg' ) {\n\n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n\n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n\n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n\n                    blob = Util.dataURL2Blob( blob );\n                }\n\n                return blob;\n            },\n\n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n\n                type = type || this.type;\n\n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n\n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n\n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n\n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n\n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n\n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n\n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n\n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n\n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n\n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n\n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n\n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n\n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n\n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n\n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n\n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n\n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n\n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n\n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n\n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n\n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n\n\n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n\n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n\n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n\n                        py = (ey + sy) >> 1;\n                    }\n\n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n\n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n\n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n\n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n\n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n\n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n\n\n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n\n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n\n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n\n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n\n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n\n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview 只有html5实现的文件版本。\n     */\n    define('preset/html5only',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/image',\n        'runtime/html5/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/html5only'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n\n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n\n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n\n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n\n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n\n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n\n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n\n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n\n        return Uploader.register({\n            name: 'md5',\n\n\n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n\n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n\n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n\n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n\n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n\n                md5.loadFromBlob( blob );\n\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n\n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n\n        if ( urlAPI ) {\n\n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n\n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n\n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n\n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n\n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n\n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                intArray = new Uint8Array( byteStr.length );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                return intArray.buffer;\n            },\n\n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n\n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n\n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n\n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n\n        var api;\n\n        api = {\n            parsers: {\n                0xffe1: []\n            },\n\n            maxMetaDataSize: 262144,\n\n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n\n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n\n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n\n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n\n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n\n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n\n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n\n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n\n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n\n                            parsers = api.parsers[ markerBytes ];\n\n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n\n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n\n                return ret;\n            },\n\n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n\n\n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n\n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n\n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n\n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n\n                return buf1.buffer;\n            }\n        };\n\n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n\n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n\n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n\n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n\n        var EXIF = {};\n\n        EXIF.ExifMap = function() {\n            return this;\n        };\n\n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n\n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n\n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n\n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n\n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n\n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n\n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n\n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n\n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n\n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n\n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n\n            tagSize = tagType.size * length;\n\n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n\n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n\n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n\n            values = [];\n\n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n\n            if ( tagType.ascii ) {\n                str = '';\n\n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n\n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n\n                return str;\n            }\n            return values;\n        };\n\n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n\n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n\n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n\n            var tagsNumber, dirEndOffset, i;\n\n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n\n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n\n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n\n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n\n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n\n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n\n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n\n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n\n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n\n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n\n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n\n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n\n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n\n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n\n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n\n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n\n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n\n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n\n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n\n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n\n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n\n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n\n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n\n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n\n        Basic GUI blocking jpeg encoder\n        */\n\n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n\n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n\n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n\n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n\n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n\n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n\n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n\n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n\n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n\n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n\n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n\n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n\n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n\n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n\n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n\n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n\n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n\n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n\n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n\n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n\n                        dataOff += 8; /* advance pointer to next row */\n                    }\n\n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n\n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n\n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n\n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n\n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n\n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n\n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n\n                        dataOff++; /* advance pointer to next column */\n                    }\n\n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n\n                    }\n                    return outputfDCTQuant;\n                }\n\n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n\n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n\n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n\n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n\n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n\n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n\n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n\n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n\n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n\n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was const... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n\n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n\n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n\n                    if(quality) setQuality(quality);\n\n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n\n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n\n\n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n\n                    bytenew=0;\n                    bytepos=7;\n\n\n                    this.encode.displayName = \"_encode_\";\n\n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n\n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n\n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n\n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n\n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n\n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n\n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n\n\n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n\n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n\n                        }\n\n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n\n\n                    ////////////////////////////////////////////////////////////////\n\n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n\n                    writeWord(0xFFD9); //EOI\n\n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n\n                    byteout = [];\n\n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n\n                    return jpegDataUri\n            }\n\n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n\n                if(currentQuality == quality) return // don't recalc if unchanged\n\n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n\n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n\n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n\n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n\n            init();\n\n        };\n\n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n\n            return encoder.encode( data );\n        }\n\n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n\n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n\n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n\n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n\n                parts = fragement.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n\n                fragement = fragement.substring( 0, 2 );\n\n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n\n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n\n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n\n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n\n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n\n        return Html5Runtime.register( 'Image', {\n\n            // flag: 标记是否被修改过。\n            modified: false,\n\n            init: function() {\n                var me = this,\n                    img = new Image();\n\n                img.onload = function() {\n\n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n\n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n\n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n\n                me._img = img;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n\n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n\n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n\n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n\n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n\n                s = s || 1;\n\n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n\n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n\n                cvs.width = w;\n                cvs.height = h;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n\n                type = type || this.type;\n\n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n\n                    if ( type === 'image/jpeg' ) {\n\n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n\n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n\n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n\n                    blob = Util.dataURL2Blob( blob );\n                }\n\n                return blob;\n            },\n\n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n\n                type = type || this.type;\n\n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n\n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n\n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n\n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n\n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n\n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n\n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n\n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n\n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n\n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n\n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n\n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n\n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n\n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n\n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n\n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n\n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n\n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n\n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n\n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n\n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n\n\n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n\n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n\n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n\n                        py = (ey + sy) >> 1;\n                    }\n\n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n\n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n\n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n\n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n\n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n\n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n\n\n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n\n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n\n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n\n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n\n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n\n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n\n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n\n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n\n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n\n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n\n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n\n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n\n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n\n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n\n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n\n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n\n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n\n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n\n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n\n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n\n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n\n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n            return state;\n        },\n\n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n\n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n\n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n\n            return state;\n        },\n\n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n\n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n\n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n\n        md5 = function (s) {\n            return hex(md51(s));\n        },\n\n\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n\n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = function (x, y) {\n                var lsw = (x & 0xFFFF) + (y & 0xFFFF),\n                    msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n                return (msw << 16) | (lsw & 0xFFFF);\n            };\n        }\n\n\n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            // then append as binary\n            this.appendBinary(str);\n\n            return this;\n        };\n\n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n\n            var length = this._buff.length,\n                i;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n\n            this._buff = this._buff.substr(i - 64);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n\n\n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            var hash = md51(str);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n\n            this._length += arr.byteLength;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n\n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n\n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n\n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n\n            return result;\n        };\n\n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n\n                fr = new FileReader();\n\n                loadNext = function() {\n                    var start, end;\n\n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n\n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n\n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n\n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n\n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n\n                loadNext();\n            },\n\n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n\n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n\n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n\n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n\n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n\n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n\n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n\n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n\n        if (!enable) {\n            return;\n        }\n\n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n\n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n\n            image.src = url;\n        }\n\n        return Uploader.register({\n            name: 'log',\n\n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n\n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n\n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('webuploader',[\n        'preset/all',\n        'widgets/log'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.noimage.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n\n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n\n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview 没有图像处理的版本。\n     */\n    define('preset/withoutimage',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/transport',\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/transport',\n        'runtime/flash/blob'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/withoutimage'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.nolog.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n\n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n\n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n\n        // 默认选项。\n        Image.options = {\n\n            // 默认的图片处理质量\n            quality: 90,\n\n            // 是否裁剪\n            crop: false,\n\n            // 是否保留头部信息\n            preserveHeaders: false,\n\n            // 是否允许放大。\n            allowMagnify: false\n        };\n\n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n\n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n\n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n\n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n\n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n\n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n\n        var $ = Base.$,\n            throttle;\n\n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n\n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n\n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n\n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n\n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n\n        return Uploader.register({\n\n            name: 'image',\n\n\n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n\n                file = this.request( 'get-file', file );\n\n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n\n                opts = $.extend({}, this.options.thumb );\n\n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n\n                width = width || opts.width;\n                height = height || opts.height;\n\n                image = new Image( opts );\n\n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n\n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n\n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n\n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n\n                file = this.request( 'get-file', file );\n\n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n\n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n\n                image = new Image( opts );\n\n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n\n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n\n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n\n                    image.resize( width, height );\n                });\n\n                image.once( 'complete', function() {\n                    var blob, size;\n\n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n\n                        size = file.size;\n\n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n\n                            file.trigger( 'resize', blob.size, size );\n                        }\n\n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n\n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n\n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                var files = [];\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n\n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n\n                if (!file.blocks) {\n                    return;\n                }\n\n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n\n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n\n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n\n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n\n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n\n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n\n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n\n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n\n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n\n        return Uploader.register({\n            name: 'md5',\n\n\n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n\n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n\n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n\n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n\n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n\n                md5.loadFromBlob( blob );\n\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n\n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n\n        if ( urlAPI ) {\n\n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n\n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n\n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n\n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n\n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n\n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n\n                parts = dataURI.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n\n                intArray = new Uint8Array( byteStr.length );\n\n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n\n                return intArray.buffer;\n            },\n\n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n\n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n\n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n\n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n\n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n\n        var api;\n\n        api = {\n            parsers: {\n                0xffe1: []\n            },\n\n            maxMetaDataSize: 262144,\n\n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n\n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n\n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n\n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n\n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n\n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n\n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n\n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n\n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n\n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n\n                            parsers = api.parsers[ markerBytes ];\n\n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n\n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n\n                return ret;\n            },\n\n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n\n\n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n\n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n\n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n\n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n\n                return buf1.buffer;\n            }\n        };\n\n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n\n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n\n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n\n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n\n        var EXIF = {};\n\n        EXIF.ExifMap = function() {\n            return this;\n        };\n\n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n\n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n\n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n\n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n\n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n\n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n\n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n\n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n\n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n\n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n\n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n\n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n\n            tagSize = tagType.size * length;\n\n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n\n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n\n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n\n            values = [];\n\n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n\n            if ( tagType.ascii ) {\n                str = '';\n\n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n\n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n\n                return str;\n            }\n            return values;\n        };\n\n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n\n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n\n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n\n            var tagsNumber, dirEndOffset, i;\n\n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n\n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n\n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n\n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n\n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n\n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n\n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n\n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n\n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n\n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n\n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n\n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n\n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n\n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n\n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n\n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n\n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n\n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n\n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n\n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n\n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n\n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n\n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n\n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n\n        Basic GUI blocking jpeg encoder\n        */\n\n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n\n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n\n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n\n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n\n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n\n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n\n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n\n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n\n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n\n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n\n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n\n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n\n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n\n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n\n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n\n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n\n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n\n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n\n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n\n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n\n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n\n                        dataOff += 8; /* advance pointer to next row */\n                    }\n\n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n\n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n\n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n\n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n\n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n\n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n\n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n\n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n\n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n\n                        dataOff++; /* advance pointer to next column */\n                    }\n\n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n\n                    }\n                    return outputfDCTQuant;\n                }\n\n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n\n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n\n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n\n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n\n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n\n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n\n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n\n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n\n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n\n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was const... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n\n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n\n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n\n                    if(quality) setQuality(quality);\n\n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n\n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n\n\n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n\n                    bytenew=0;\n                    bytepos=7;\n\n\n                    this.encode.displayName = \"_encode_\";\n\n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n\n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n\n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n\n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n\n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n\n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n\n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n\n\n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n\n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n\n                        }\n\n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n\n\n                    ////////////////////////////////////////////////////////////////\n\n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n\n                    writeWord(0xFFD9); //EOI\n\n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n\n                    byteout = [];\n\n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n\n                    return jpegDataUri\n            }\n\n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n\n                if(currentQuality == quality) return // don't recalc if unchanged\n\n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n\n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n\n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n\n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n\n            init();\n\n        };\n\n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n\n            return encoder.encode( data );\n        }\n\n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n\n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n\n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n\n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n\n                parts = fragement.split(',');\n\n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n\n                fragement = fragement.substring( 0, 2 );\n\n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n\n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n\n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n\n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n\n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n\n        return Html5Runtime.register( 'Image', {\n\n            // flag: 标记是否被修改过。\n            modified: false,\n\n            init: function() {\n                var me = this,\n                    img = new Image();\n\n                img.onload = function() {\n\n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n\n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n\n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n\n                me._img = img;\n            },\n\n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n\n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n\n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n\n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n\n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n\n                s = s || 1;\n\n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n\n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n\n                cvs.width = w;\n                cvs.height = h;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n\n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n\n                type = type || this.type;\n\n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n\n                    if ( type === 'image/jpeg' ) {\n\n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n\n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n\n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n\n                    blob = Util.dataURL2Blob( blob );\n                }\n\n                return blob;\n            },\n\n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n\n                type = type || this.type;\n\n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n\n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n\n            info: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n\n                // getter\n                return this._info;\n            },\n\n            meta: function( val ) {\n\n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n\n                // getter\n                return this._meta;\n            },\n\n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n\n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n\n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n\n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n\n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n\n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n\n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n\n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n\n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n\n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n\n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n\n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n\n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n\n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n\n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n\n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n\n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n\n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n\n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n\n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n\n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n\n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n\n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n\n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n\n\n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n\n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n\n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n\n                        py = (ey + sy) >> 1;\n                    }\n\n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n\n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n\n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n\n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n\n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n\n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n\n\n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n\n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n\n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n\n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n\n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n\n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n\n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n\n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n\n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n\n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n\n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n\n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n\n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n\n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n\n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n\n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n\n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n\n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n\n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n\n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n\n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n\n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n\n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n            return state;\n        },\n\n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n\n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n\n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n\n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n\n            md5cycle(state, tail);\n\n            return state;\n        },\n\n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n\n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n\n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n\n        md5 = function (s) {\n            return hex(md51(s));\n        },\n\n\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n\n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = function (x, y) {\n                var lsw = (x & 0xFFFF) + (y & 0xFFFF),\n                    msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n                return (msw << 16) | (lsw & 0xFFFF);\n            };\n        }\n\n\n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            // then append as binary\n            this.appendBinary(str);\n\n            return this;\n        };\n\n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n\n            var length = this._buff.length,\n                i;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n\n            this._buff = this._buff.substr(i - 64);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n\n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n\n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n\n\n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n\n            var hash = md51(str);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n\n        ////////////////////////////////////////////////////////////////////////////\n\n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n\n            this._length += arr.byteLength;\n\n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n\n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n\n            return this;\n        };\n\n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n\n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n\n            this.reset();\n\n            return ret;\n        };\n\n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n\n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n\n            return this;\n        };\n\n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n\n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n\n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n\n            return result;\n        };\n\n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n\n            return !!raw ? hash : hex(hash);\n        };\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n\n                fr = new FileReader();\n\n                loadNext = function() {\n                    var start, end;\n\n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n\n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n\n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n\n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n\n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n\n                loadNext();\n            },\n\n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n\n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n\n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n\n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n\n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n\n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n\n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n\n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n\n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/all'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/plugins/webuploader/webuploader.withoutimage.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n\n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n\n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n\n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n\n        var noop = function() {},\n            call = Function.call;\n\n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n\n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n\n        function createObject( proto ) {\n            var f;\n\n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n\n\n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n\n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n\n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n\n            Deferred: promise.Deferred,\n\n            isPromise: promise.isPromise,\n\n            when: promise.when,\n\n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n\n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n\n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n\n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n\n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n\n                return ret;\n            })( navigator.userAgent ),\n\n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n\n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n\n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n\n                /* jshint camelcase: false */\n\n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n\n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n\n                return child;\n            },\n\n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n\n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n\n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n\n            nextTick: (function() {\n\n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n\n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n\n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n\n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n\n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n\n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n\n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n\n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n\n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n\n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n\n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n\n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n\n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n\n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n\n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n\n            while ( ++i < len ) {\n                handler = events[ i ];\n\n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n\n            return !stoped;\n        }\n\n        protos = {\n\n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n\n                if ( !callback ) {\n                    return this;\n                }\n\n                set = this._events || (this._events = []);\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n\n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n\n                    set.push( handler );\n                });\n\n                return this;\n            },\n\n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n\n                if ( !callback ) {\n                    return me;\n                }\n\n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n\n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n\n                return me;\n            },\n\n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n\n                if ( !events ) {\n                    return this;\n                }\n\n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n\n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n\n                return this;\n            },\n\n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n\n                if ( !this._events || !type ) {\n                    return this;\n                }\n\n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n\n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n\n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n\n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n\n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$;\n\n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n\n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n\n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n\n        $.extend( Uploader.prototype, {\n            state: 'pending',\n\n            _init: function( opts ) {\n                var me = this;\n\n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n\n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n\n                // setter\n                if ( arguments.length > 1 ) {\n\n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n\n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n\n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n\n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n\n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n\n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n\n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n\n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n\n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n\n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n\n                    return false;\n                }\n\n                return true;\n            },\n\n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n\n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n\n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n\n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n\n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            factories = {},\n\n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n\n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n\n        $.extend( Runtime.prototype, {\n\n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n\n                if ( this._container ) {\n                    return this._container;\n                }\n\n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n\n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n\n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n\n            init: Base.noop,\n            exec: Base.noop,\n\n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n\n        Runtime.orders = 'html5,flash';\n\n\n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n\n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n\n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n\n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n\n            type = type || getFirstKey( factories );\n\n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n\n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n\n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n\n        var cache;\n\n        cache = (function() {\n            var obj = {};\n\n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n\n                get: function( ruid, standalone ) {\n                    var i;\n\n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n\n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n\n                        return obj[ i ];\n                    }\n\n                    return null;\n                },\n\n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n\n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n\n            this.uid = Base.guid('client_');\n\n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n\n            this.connectRuntime = function( opts, cb ) {\n\n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n\n                deferred.done( cb );\n\n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n\n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n\n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n\n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                runtime.__client--;\n\n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n\n                runtime = null;\n            };\n\n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n\n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n\n                return runtime.exec.apply( this, args );\n            };\n\n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n\n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n\n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n\n            opts.container = $( opts.container );\n\n            if ( !opts.container.length ) {\n                return;\n            }\n\n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n\n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( DragAndDrop.prototype );\n\n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n\n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n\n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n\n            var length = obj.length,\n                type = $.type( obj );\n\n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n\n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n\n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n\n        $.extend( Widget.prototype, {\n\n            init: Base.noop,\n\n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n\n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n\n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n\n                    return IGNORE;\n                }\n\n                return this[ map[ apiName ] ].apply( this, args );\n\n            },\n\n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n\n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n\n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n\n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n\n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n\n                return _init.apply( me, arguments );\n            },\n\n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n\n                args = isArrayLike( args ) ? args : [ args ];\n\n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n\n                    if ( rlt !== IGNORE ) {\n\n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n\n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n\n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n\n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n\n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n\n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n\n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n\n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n\n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n\n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n\n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n\n            } else {\n                map = $.extend( map, responseMap );\n            }\n\n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n\n            return klass;\n        };\n\n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *\n         *     'make-thumb': function() {\n         *\n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n\n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n\n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n\n        Uploader.options.dnd = '';\n\n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n\n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n\n            init: function( opts ) {\n\n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n\n                this.dnd = dnd = new Dnd( options );\n\n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n\n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n\n                dnd.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n\n        var $ = Base.$;\n\n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n\n            init: function() {\n                var me = this;\n\n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n\n        Mediator.installTo( FilePaste.prototype );\n\n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n\n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n\n            init: function( opts ) {\n\n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n\n                this.paste = paste = new FilePaste( options );\n\n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n\n        function Blob( ruid, source ) {\n            var me = this;\n\n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n\n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n\n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n\n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n\n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n\n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n\n            getSource: function() {\n                return this.source;\n            }\n        });\n\n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n\n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n\n        function File( ruid, file ) {\n            var ext;\n\n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n\n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n\n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n\n            Blob.apply( this, arguments );\n        }\n\n        return Base.inherits( Blob, File );\n    });\n\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n\n        var $ = Base.$;\n\n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n\n            opts.container = $( opts.id );\n\n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n\n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n\n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n\n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n\n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n\n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n\n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n\n                button.addClass('webuploader-pick');\n\n                me.on( 'all', function( type ) {\n                    var files;\n\n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n\n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n\n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n\n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n\n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n\n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n\n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n\n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n\n                    pos = button.offset();\n\n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n\n            enable: function() {\n                var btn = this.options.button;\n\n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n\n            disable: function() {\n                var btn = this.options.button;\n\n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n\n                btn.addClass('webuploader-pick-disable');\n            },\n\n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n\n        return FilePicker;\n    });\n\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n\n        $.extend( Uploader.options, {\n\n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor} 指定选择文件的按钮容器，不指定则不创建按钮。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n\n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n\n        return Uploader.register({\n            name: 'picker',\n\n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n\n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n\n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n\n                if ( !pick ) {\n                    return;\n                }\n\n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n\n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n\n                    deferred = Base.Deferred();\n\n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n\n                    picker = new FilePicker( options );\n\n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n\n                    me.pickers.push( picker );\n\n                    promises.push( deferred.promise() );\n                });\n\n                return Base.when.apply( Base, promises );\n            },\n\n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n\n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n\n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n\n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n\n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n\n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n\n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n\n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n\n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n\n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n\n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n\n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n\n\n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n\n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n\n            this.source = source;\n            this.loaded = 0;\n\n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n\n        $.extend( WUFile.prototype, {\n\n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n\n                var prevStatus = statusMap[ this.id ];\n\n                typeof text !== 'undefined' && (this.statusText = text);\n\n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n\n            },\n\n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n\n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n\n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n\n        Mediator.installTo( WUFile.prototype );\n\n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n\n        return WUFile;\n    });\n\n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n\n        var $ = Base.$,\n            STATUS = WUFile.Status;\n\n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n\n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0,\n            };\n\n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n\n            // 存储所有文件\n            this._map = {};\n        }\n\n        $.extend( Queue.prototype, {\n\n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n\n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n\n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n\n                status = status || STATUS.QUEUED;\n\n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n\n                return null;\n            },\n\n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n\n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n\n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n\n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n\n                    ret.push( file );\n                }\n\n                return ret;\n            },\n\n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n\n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n\n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n\n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n\n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n\n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n\n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n\n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n\n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n\n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n\n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n\n\n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n\n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n\n        });\n\n        Mediator.installTo( Queue.prototype );\n\n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n\n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n\n        return Uploader.register({\n            name: 'queue',\n\n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n\n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n\n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n\n                    me.accept = new RegExp( accept, 'i' );\n                }\n\n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n\n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n\n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n\n\n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n\n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n\n                    file = new WUFile( file );\n                }\n\n                return file;\n            },\n\n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n\n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n\n                return !invalid;\n            },\n\n\n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n\n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n\n            _addFile: function( file ) {\n                var me = this;\n\n                file = me._wrapFile( file );\n\n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n\n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n\n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n\n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n\n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             *\n             */\n\n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n\n                if ( !files.length ) {\n                    files = [ files ];\n                }\n\n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n\n                me.owner.trigger( 'filesQueued', files );\n\n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n\n            getStats: function() {\n                return this.stats;\n            },\n\n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n\n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n\n                file = file.id ? file : me.queue.getFile( file );\n\n                this.request( 'cancel-file', file );\n\n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n\n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n\n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n\n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n\n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n\n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n\n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n\n                me.request('start-upload');\n            },\n\n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n\n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n\n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n\n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n\n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n\n        return Uploader.register({\n            name: 'runtime',\n\n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n\n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n\n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n\n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n\n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n\n        var $ = Base.$;\n\n        function Transport( opts ) {\n            var me = this;\n\n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n\n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n\n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n\n        Transport.options = {\n            server: '',\n            method: 'POST',\n\n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n\n        $.extend( Transport.prototype, {\n\n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n\n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n\n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n\n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n\n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n\n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n\n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n\n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n\n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n\n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n\n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n\n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n\n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n\n                if ( !duration ) {\n                    return;\n                }\n\n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n\n        });\n\n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n\n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n\n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n\n        // 添加默认配置项\n        $.extend( Uploader.options, {\n\n\n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n\n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n\n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n\n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n\n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n\n\n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n\n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n\n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n\n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n\n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n\n            api = {\n                file: file,\n\n                has: function() {\n                    return !!pending.length;\n                },\n\n                shift: function() {\n                    return pending.shift();\n                },\n\n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n\n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n\n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n\n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n\n            return api;\n        }\n\n        Uploader.register({\n            name: 'upload',\n\n            init: function() {\n                var owner = this.owner,\n                    me = this;\n\n                this.runing = false;\n                this.progress = false;\n\n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n\n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n\n                // 缓存分好片的文件。\n                this.stack = [];\n\n                // 缓存即将上传的文件。\n                this.pending = [];\n\n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n\n                owner.on( 'uploadComplete', function( file ) {\n\n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n\n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n\n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n\n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n\n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n\n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n\n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n\n                            v.transport && v.transport.send();\n                        });\n\n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n\n                if ( me.runing ) {\n                    return;\n                }\n\n                me.runing = true;\n\n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n\n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        file.setStatus( Status.PROGRESS );\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n\n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n\n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n\n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n\n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n\n                if ( me.runing === false ) {\n                    return;\n                }\n\n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n\n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n\n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n\n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n\n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n\n                    return Base.nextTick( me.__tick );\n                }\n\n                me.runing = false;\n\n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n\n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n\n                me.owner.trigger('stopUpload');\n            },\n\n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n\n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n\n            _getStats: function() {\n                return this.request('get-stats');\n            },\n\n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n\n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n\n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n\n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n\n                this.owner.trigger( 'uploadSkip', file );\n            },\n\n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n\n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n\n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n\n                    fn = function( val ) {\n                        me._promise = null;\n\n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n\n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n\n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n\n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n\n            _putback: function(block) {\n                var idx;\n\n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n\n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n\n            _getStack: function() {\n                var i = 0,\n                    act;\n\n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n\n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n\n                return null;\n            },\n\n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n\n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n\n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n\n                    return act.shift();\n\n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n\n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n\n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n\n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n\n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n\n                    return done( next );\n                }\n            },\n\n\n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n\n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n\n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n\n                        return me._finishFile( file );\n                    });\n\n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n\n                    promise.file = file;\n\n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n\n                        ~idx && pending.splice( idx, 1, file );\n                    });\n\n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n\n                    pending.push( promise );\n                }\n            },\n\n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n\n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n\n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n\n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n\n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n\n                    return;\n                }\n\n                me.pool.push( block );\n                me.remaning++;\n\n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n\n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n\n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n\n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n\n\n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n\n\n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n\n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n\n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n\n                block.transport = tr;\n\n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n\n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    var totalPercent = 0,\n                        uploaded = 0;\n\n                    // 可能没有abort掉，progress还是执行进来了。\n                    // if ( !file.blocks ) {\n                    //     return;\n                    // }\n\n                    totalPercent = block.percentage = percentage;\n\n                    if ( block.chunks > 1 ) {    // 计算文件的整体速度。\n                        $.each( file.blocks, function( _, v ) {\n                            uploaded += (v.percentage || 0) * (v.end - v.start);\n                        });\n\n                        totalPercent = uploaded / file.size;\n                    }\n\n                    owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n                });\n\n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n\n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n\n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n\n                    return reject;\n                };\n\n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n\n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n\n                        block.retried++;\n                        tr.send();\n\n                    } else {\n\n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n\n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n\n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n\n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n\n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n\n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n\n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n\n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n\n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n\n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n\n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n\n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n\n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            }\n\n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n\n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n\n        var $ = Base.$,\n            validators = {},\n            api;\n\n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n\n        // 暴露给外面的api\n        api = {\n\n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n\n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n\n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n\n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n\n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return count >= max ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n\n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n\n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n\n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n\n                return invalid ? false : true;\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n\n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n\n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n\n            if ( !max ) {\n                return;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n\n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n\n            });\n\n        });\n\n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n\n            if ( opts.duplicate ) {\n                return;\n            }\n\n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n\n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n\n                return hash;\n            }\n\n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n\n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n\n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (mapping[ hash ] = true);\n            });\n\n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n\n                hash && (delete mapping[ hash ]);\n            });\n\n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n\n        return api;\n    });\n\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n\n        function CompBase( owner, runtime ) {\n\n            this.owner = owner;\n            this.options = owner.options;\n\n            this.getRuntime = function() {\n                return runtime;\n            };\n\n            this.getRuid = function() {\n                return runtime.uid;\n            };\n\n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n\n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var type = 'html5',\n            components = {};\n\n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n\n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n\n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n\n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n\n        });\n\n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n\n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n\n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n\n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n\n                blob = slice.call( blob, start, end );\n\n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n\n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n\n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n\n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n\n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n\n                e = e.originalEvent || e;\n\n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n\n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n\n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n\n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n\n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n\n                return false;\n            },\n\n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n\n                return false;\n            },\n\n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n\n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n\n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n\n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n\n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n\n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n\n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n\n                if ( data ) {\n                    return;\n                }\n\n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n\n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n\n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n\n                items = dataTransfer.items;\n                files = dataTransfer.files;\n\n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n\n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n\n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n\n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n\n                Base.when.apply( Base, promises ).done(function() {\n\n                    if ( !results.length ) {\n                        return;\n                    }\n\n                    callback( results );\n                });\n            },\n\n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n\n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n\n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n\n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n\n                return deferred.promise();\n            },\n\n            destroy: function() {\n                var elem = this.elem;\n\n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n\n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n\n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n\n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n\n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n\n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n\n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n\n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n\n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n\n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n\n                    allowed.push( new File( ruid, blob ) );\n                }\n\n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n\n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var $ = Base.$;\n\n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n\n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n\n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n\n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n\n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n\n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n\n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n\n                    input.attr( 'accept', arr.join(',') );\n                }\n\n                container.append( input );\n                container.append( label );\n\n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n\n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n\n                    me.files = e.target.files;\n\n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n\n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n\n                    owner.trigger('change');\n                });\n\n                label.on( 'mouseenter mouseleave', mouseHandler );\n\n            },\n\n\n            getFiles: function() {\n                return this.files;\n            },\n\n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n\n        var noop = Base.noop,\n            $ = Base.$;\n\n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n\n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n\n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n\n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n\n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n\n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n\n            getResponse: function() {\n                return this._response;\n            },\n\n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n\n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n\n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n\n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n\n                    return me.trigger( 'progress', percentage );\n                };\n\n                xhr.onreadystatechange = function() {\n\n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n\n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n\n\n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n\n            _parseJson: function( str ) {\n                var json;\n\n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n\n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n\n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n\n\n        function getFlashVersion() {\n            var version;\n\n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n\n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n\n            Runtime.apply( me, arguments );\n            me.type = type;\n\n\n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n\n                clients[ uid ] = client;\n\n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n\n                    instance = pool[ uid ];\n\n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n\n                return me.flashExec.apply( client, arguments );\n            };\n\n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n\n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n\n                // console.log.apply( console, arguments );\n\n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n\n                // Base.log( evt, obj );\n            }\n\n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n\n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n\n            this.jsreciver = jsreciver;\n\n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n\n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n\n                return flash.exec( this.uid, comp, fn, args );\n            };\n\n            // @todo\n        }\n\n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n\n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n\n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n\n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n\n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n\n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n\n                container.html( html );\n            },\n\n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n\n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n\n        });\n\n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n\n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n\n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n\n            return component;\n        };\n\n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n\n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n\n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n\n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n\n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n\n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n\n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n\n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n\n                xhr.connectRuntime( blob.ruid );\n\n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n\n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n\n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n\n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n\n            getStatus: function() {\n                return this._status;\n            },\n\n            getResponse: function() {\n                return this._response || '';\n            },\n\n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n\n            abort: function() {\n                var xhr = this._xhr;\n\n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n\n            destroy: function() {\n                this.abort();\n            },\n\n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n\n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n\n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n\n                    xhr.off();\n                    me._xhr = null;\n\n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n\n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n\n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n\n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n\n                        // }\n                    }\n\n                    xhr.destroy();\n                    xhr = null;\n\n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n\n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n\n                me._xhr = xhr;\n                return xhr;\n            },\n\n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview 没有图像处理的版本。\n     */\n    define('preset/withoutimage',[\n        'base',\n\n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n\n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/transport',\n\n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/withoutimage'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "src/main/resources/static/js/welcome.js",
    "content": "//欢迎信息\n\nlayer.config({\n    extend: ['extend/layer.ext.js', 'skin/moon/style.css'],\n    skin: 'layer-ext-moon'\n});\n\nlayer.ready(function () {\n\n    var html = $('#welcome-template').html();\n    $('a.viewlog').click(function () {\n        logs();\n        return false;\n    });\n\n    $('#pay-qrcode').click(function(){\n        var html=$(this).html();\n        parent.layer.open({\n            title: false,\n            type: 1,\n            closeBtn:false,\n            shadeClose:true,\n            area: ['600px', 'auto'],\n            content: html\n        });\n    });\n\n    function logs() {\n        parent.layer.open({\n            title: '初见倾心，再见动情',\n            type: 1,\n            area: ['700px', 'auto'],\n            content: html,\n            btn: ['确定', '取消']\n        });\n    }\n\n    console.log('欢迎使用H+，如果您在使用的过程中有碰到问题，可以参考开发文档，感谢您的支持。');\n\n});\n"
  },
  {
    "path": "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": "src/main/resources/templates/act/model/model.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:add\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus \" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash \" aria-hidden=\"true\"></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=\"columns pull-right\">\n\t\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"\">\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 id=\"exampleTable\" data-mobile-responsive=\"true\">\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<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"activiti:model:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"activiti:model:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"activiti:model:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/model/model.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/act/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>\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": "src/main/resources/templates/act/process/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n\n</head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content\">\n    <div class=\"row\">\n        <div class=\"col-sm-8\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <div class=\"col-sm-12\">\n                        <h4>导入流程</h4>\n                    </div>\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-1 control-label\">类别：</label>\n                            <div class=\"col-sm-4\">\n                                <input id=\"category\" name=\"category\" type=\"input\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-1 control-label\">导入流程：</label>\n                            <div class=\"col-sm-4\">\n                                <input id=\"file\" name=\"file\" type=\"file\">\n                            </div>\n                        </div>\n\n                        <div class=\"text-right form-group\">\n                            <a class=\"btn btn-default waves-effect waves-light\"\n                               onclick=\"returnList()\">返回</a>\n                            <button type=\"button\"\n                                    class=\"btn btn-primary waves-effect waves-light\" type=\"submit\">保存\n                            </button>\n\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/act/process/add.js\">\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/act/process/process.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:add\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus \" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash \" aria-hidden=\"true\"></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=\"columns pull-right\">\n\t\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"姓名\">\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 id=\"exampleTable\" data-mobile-responsive=\"true\">\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<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/process/process.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/act/salary/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">变动用户：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"userId\" name=\"userId\" class=\"form-control\" type=\"hidden\">\n                                <input id=\"userName\" name=\"userName\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">归属部门：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"officeId\" name=\"officeId\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">岗位：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"post\" name=\"post\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">性别：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"age\" name=\"age\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden \">\n                            <label class=\"col-sm-3 control-label\">学历：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"edu\" name=\"edu\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">调整原因：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"content\" name=\"content\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden \">\n                            <label class=\"col-sm-3 control-label\">现行标准 薪酬档级：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"olda\" name=\"olda\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">现行标准 月工资额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"oldb\" name=\"oldb\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">现行标准 年薪总额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"oldc\" name=\"oldc\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 薪酬档级：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newa\" name=\"newa\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 月工资额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newb\" name=\"newb\" class=\"form-control\" type=\"number\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 年薪总额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newc\" name=\"newc\" class=\"form-control\" type=\"number\">\n                            </div>\n                        </div>\n                        <div class=\"form-group  hidden\">\n                            <label class=\"col-sm-3 control-label\">月增资：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"addNum\" name=\"addNum\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">执行时间：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"exeDate\" name=\"exeDate\" class=\"form-control\" type=\"date\">\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/act/salary/add.js\">\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/act/salary/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <input id=\"taskId\" name=\"taskId\" th:value=\"${salary.taskId}\" type=\"hidden\">\n                        <input id=\"id\" name=\"id\" th:value=\"${salary.id}\" type=\"hidden\">\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">流程实例ID：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"procInsId\" name=\"procInsId\" th:value=\"${salary.procInsId}\"\n                                       class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">变动用户：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"userId\" name=\"userId\" th:value=\"${salary.userId}\" class=\"form-control\"\n                                       type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">归属部门：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"officeId\" name=\"officeId\" th:value=\"${salary.officeId}\" class=\"form-control\"\n                                       type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">岗位：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"post\" name=\"post\" th:value=\"${salary.post}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group  hidden\">\n                            <label class=\"col-sm-3 control-label\">性别：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"age\" name=\"age\" th:value=\"${salary.age}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">学历：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"edu\" name=\"edu\" th:value=\"${salary.edu}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">调整原因：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"content\" name=\"content\" th:value=\"${salary.content}\" class=\"form-control\"\n                                       type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">现行标准 薪酬档级：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"olda\" name=\"olda\" th:value=\"${salary.olda}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">现行标准 月工资额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"oldb\" name=\"oldb\" th:value=\"${salary.oldb}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">现行标准 年薪总额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"oldc\" name=\"oldc\" th:value=\"${salary.oldc}\" class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 薪酬档级：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newa\" name=\"newa\" th:value=\"${salary.newa}\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 月工资额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newb\" name=\"newb\" th:value=\"${salary.newb}\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">调整后标准 年薪总额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"newc\" name=\"newc\" th:value=\"${salary.newc}\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label\">月增资：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"addNum\" name=\"addNum\" th:value=\"${salary.addNum}\" class=\"form-control\"\n                                       type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">执行时间：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"exeDate\" name=\"exeDate\" th:value=\"${salary.exeDate}\" class=\"form-control\"\n                                       type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">人力资源部门意见：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"hrText\" name=\"hrText\" th:value=\"${salary.hrText}\" class=\"form-control\"\n                                       type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">分管领导意见：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"leadText\" name=\"leadText\" th:value=\"${salary.leadText}\" class=\"form-control\"\n                                       type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">集团主要领导意见：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"mainLeadText\" name=\"mainLeadText\" th:value=\"${salary.mainLeadText}\"\n                                       class=\"form-control\" type=\"text\" readonly=\"readonly\">\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">您的意见：</label>\n                            <div class=\"col-sm-8\">\n                                <textarea id=\"taskComment\" name=\"taskComment\" th:value=\"${salary.taskComment}\"\n                                          class=\"form-control\"></textarea>\n                            </div>\n                        </div>\n                        <input id=\"taskPass\" name=\"taskPass\" class=\"hidden\">\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\n                                <button type=\"submit\" class=\"btn btn-primary\" onclick=\"$('#taskPass').val('1')\">提交\n                                </button>\n                                <button type=\"submit\" class=\"btn btn-warning\" onclick=\"$('#taskPass').val('0')\">退回\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/act/salary/edit.js\">\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/act/salary/start.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"procDefId\" name=\"processId\" th:value=\"${processId}\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">申请人：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobName\" name=\"jobName\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">月增资：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobGroup\" name=\"jobGroup\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务类：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"beanClass\" name=\"beanClass\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">cron表达式：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"cronExpression\" name=\"cronExpression\"\n\t\t\t\t\t\t\t\t\t\t   class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">调整原因：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-10\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"description\" name=\"description\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\t></textarea>\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<div class=\"form-group hidden\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务状态：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobStatus\" name=\"jobStatus\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" value=\"0\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-2 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/js/appjs/act/SalaryAdjustment/form.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/act/task/gotoTask.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\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<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/task/gotoTask.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/act/task/task.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:add\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus \" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash \" aria-hidden=\"true\"></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=\"columns pull-right\">\n\t\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"姓名\">\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 id=\"exampleTable\" data-mobile-responsive=\"true\">\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<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:model:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:model:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:model:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/model/model.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/act/task/todoTask.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<ul class=\"nav nav-tabs\">\n\t\t\t\t\t\t\t<li class=\"active\"><a data-toggle=\"tab\" href=\"#tab-1\"><i class=\"fa fa-file-text\"></i>待办工作</a>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t<li class=\"\"><a data-toggle=\"tab\" href=\"#tab-2\"><i class=\"fa fa-briefcase\"></i>已办工作</a>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t<li class=\"\"><a data-toggle=\"tab\" href=\"#tab-3\"><i class=\"fa fa-briefcase\"></i>发起任务</a>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t<div class=\"tab-content\">\n\t\t\t\t\t\t\t<div id=\"tab-1\" class=\"tab-pane active\">\n\t\t\t\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\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\t<div id=\"tab-2\" class=\"tab-pane \">\n\t\t\t\t\t\t\t\t<table id=\"exampleTable2\" data-mobile-responsive=\"true\"></table>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div id=\"tab-3\" class=\"tab-pane \">\n\t\t\t\t\t\t\t\t<table id=\"exampleTable3\" data-mobile-responsive=\"true\"></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</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"act:process:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/task/totoTask.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/appjs/act/task/gotoTask.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/consumer/add.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">姓名：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">联系电话：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"tel\" name=\"tel\" class=\"form-control\" type=\"text\" maxlength=\"11\" required>\n                            </div>\n                        </div>\n\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/consumer/add.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/consumer/edit.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <!-- HIDDEN -->\n                        <input id=\"id\" name=\"id\" class=\"form-control\" type=\"hidden\" th:value=\"${consumer.id}\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">姓名：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" th:value=\"${consumer.name}\" class=\"form-control\"\n                                       type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">联系电话：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"tel\" name=\"tel\" th:value=\"${consumer.tel}\" class=\"form-control\" type=\"text\"\n                                       maxlength=\"11\" required>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/consumer/edit.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/consumer/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> 添加\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/consumer/index.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/drug/add.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"id\" name=\"id\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品名称：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">规格：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"specification\" name=\"specification\" class=\"form-control\" type=\"text\"\n                                       maxlength=\"10\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">保质期（月）：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"qualityGuaranteePeriod\" name=\"qualityGuaranteePeriod\" class=\"form-control\"\n                                       type=\"number\" max=\"60\" min=\"1\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">库存下限：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"lowerLimit\" name=\"lowerLimit\" class=\"form-control\" type=\"number\" step=\"1\" min=\"0\"\n                                       max=\"9999\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"supplierId\" name=\"supplierId\" type=\"text\" class=\"form-control\" maxlength=\"20\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">价格（元）：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"price\" name=\"price\" class=\"form-control\"\n                                       type=\"number\" max=\"9999\" min=\"1\" required step=\"0.01\">\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drug/add.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/drug/edit.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <!-- HIDDEN -->\n                        <input id=\"id\" name=\"id\" class=\"form-control\" type=\"hidden\" th:value=\"${drug.id}\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品名称：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" th:value=\"${drug.name}\" class=\"form-control\" type=\"text\"\n                                       maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">规格：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"specification\" name=\"specification\" th:value=\"${drug.specification}\"\n                                       class=\"form-control\" type=\"text\"\n                                       maxlength=\"10\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">保质期（月）：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"qualityGuaranteePeriod\" name=\"qualityGuaranteePeriod\"\n                                       th:value=\"${drug.qualityGuaranteePeriod}\"\n                                       class=\"form-control\"\n                                       type=\"number\" max=\"60\" min=\"1\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">库存下限：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"lowerLimit\" name=\"lowerLimit\"\n                                       th:value=\"${drug.lowerLimit}\"\n                                       class=\"form-control\" type=\"number\" step=\"1\" min=\"0\"\n                                       max=\"9999\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"supplierId\" name=\"supplierId\"\n                                       th:value=\"${drug.supplierId}\"\n                                       type=\"text\" class=\"form-control\" maxlength=\"20\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">价格（元）：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"price\" name=\"price\" class=\"form-control\"\n                                       th:value=\"${drug.price}\"\n                                       type=\"number\" max=\"9999\" min=\"1\" required step=\"0.01\">\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drug/edit.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/drug/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> 添加\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drug/index.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/supplier/add.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"id\" name=\"id\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商名称：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/supplier/add.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/supplier/edit.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"id\" name=\"id\" th:value=\"${supplier.id}\" class=\"form-control\" type=\"text\"\n                                       maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">供应商名称：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" th:value=\"${supplier.name}\" class=\"form-control\"\n                                       type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/supplier/edit.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/data-maintenance/supplier/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> 添加\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/supplier/index.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/inventory/drug-in/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"drugId\" name=\"drugId\" class=\"form-control\" type=\"text\" maxlength=\"20\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">入库数量：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"quantity\" name=\"quantity\" class=\"form-control\" type=\"number\" max=\"99999\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">总金额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"ammount\" name=\"ammount\" class=\"form-control\" type=\"number\" step=\"0.01\" max=\"999999\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">生产日期：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"madeDate\" name=\"madeDate\" type=\"text\" class=\"layui-input\">\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/plugins/laydate/laydate.js\"></script>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drugin/add.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/inventory/drug-in/drug-in.html",
    "content": "<!DOCTYPE html>\n<html xmlns:shiro=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> 入库登记\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drugin/drugin.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/inventory/drug-out/drug-out.html",
    "content": "<!DOCTYPE html>\n<html xmlns:shiro=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> 出库登记\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<!--shiro控制bootstraptable行内按钮看见性 -->\n<div>\n    <script type=\"text/javascript\">\n        var s_edit_h = 'hidden';\n        var s_remove_h = 'hidden';\n        var s_resetPwd_h = 'hidden';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:edit\">\n    <script type=\"text/javascript\">\n        s_edit_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:remove\">\n    <script type=\"text/javascript\">\n        var s_remove_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:resetPwd\">\n    <script type=\"text/javascript\">\n        var s_resetPwd_h = '';\n    </script>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drugout/drugout.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/inventory/drug-out/out.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"drugId\" name=\"drugId\" class=\"form-control\" type=\"text\" maxlength=\"20\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">出库数量：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"quantity\" name=\"quantity\" class=\"form-control\" type=\"number\" max=\"99999\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">总金额：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"ammount\" name=\"ammount\" class=\"form-control\" type=\"number\" step=\"0.01\"\n                                       max=\"999999\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">出库原因：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"comment\" name=\"comment\" class=\"form-control\" type=\"text\" maxlength=\"50\"\n                                       required>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/drugout/out.js\">\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/sale/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\">\n</head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"drugId\" name=\"drugId\" class=\"form-control\" type=\"text\" maxlength=\"20\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">数量：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"quantity\" name=\"quantity\" class=\"form-control\" type=\"number\" max=\"99999\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">顾客：</label>\n                            <div class=\"col-sm-8\">\n                                <select id=\"consumer\" name=\"consumer\" class=\"form-control\" required></select>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/sale/add.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/sale/back.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\">\n</head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">订单流水号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"orderId\" name=\"orderId\" class=\"form-control\" type=\"text\" maxlength=\"32\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">药品是否有问题：</label>\n                            <div class=\"col-sm-8\">\n                                <label class=\"radio-inline\"> <input name=\"hasProblem\" type=\"radio\" value=\"true\"\n                                                                    id=\"hasProblem0\" checked=\"checked\"/>\n                                    是\n                                </label> <label class=\"radio-inline\"> <input name=\"hasProblem\" type=\"radio\"\n                                                                             value=\"false\" id=\"hasProblem1\"/>\n                                否\n                            </label>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">原因备注：</label>\n                            <div class=\"col-sm-8\">\n                                <textarea id=\"comment\" name=\"comment\" class=\"form-control\" required></textarea>\n                            </div>\n                        </div>\n                        <!-- -->\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/sale/back.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/app/sale/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:shiro=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button type=\"button\"\n                                class=\"btn  btn-primary\" onclick=\"add()\">\n                            <i class=\"fa fa-cart-plus\" aria-hidden=\"true\"></i> 销售登记\n                        </button>\n                        <button type=\"button\"\n                                class=\"btn  btn-danger\" onclick=\"back()\">\n                            <i class=\"fa fa-cart-arrow-down\" aria-hidden=\"true\"></i> 退货登记\n                        </button>\n                        <!--<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"-->\n                        <!--class=\"btn  btn-danger\" onclick=\"batchRemove()\">-->\n                        <!--<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除-->\n                        <!--</button>-->\n                    </div>\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<!--shiro控制bootstraptable行内按钮看见性 -->\n<div>\n    <script type=\"text/javascript\">\n        var s_edit_h = 'hidden';\n        var s_remove_h = 'hidden';\n        var s_resetPwd_h = 'hidden';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:edit\">\n    <script type=\"text/javascript\">\n        s_edit_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:remove\">\n    <script type=\"text/javascript\">\n        var s_remove_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:resetPwd\">\n    <script type=\"text/javascript\">\n        var s_resetPwd_h = '';\n    </script>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/sale/index.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/sale-detail/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:shiro=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n\n                    <!--<div class=\"columns pull-right\">-->\n                    <!--<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>-->\n                    <!--</div>-->\n                    <!--<div class=\"columns pull-right col-md-2 nopadding\">-->\n                    <!--<input id=\"searchName\" type=\"text\" class=\"form-control\"-->\n                    <!--placeholder=\"\">-->\n                    <!--</div>-->\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<!--shiro控制bootstraptable行内按钮看见性 -->\n<div>\n    <script type=\"text/javascript\">\n        var s_edit_h = 'hidden';\n        var s_remove_h = 'hidden';\n        var s_resetPwd_h = 'hidden';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:edit\">\n    <script type=\"text/javascript\">\n        s_edit_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:remove\">\n    <script type=\"text/javascript\">\n        var s_remove_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"oa:notify:resetPwd\">\n    <script type=\"text/javascript\">\n        var s_resetPwd_h = '';\n    </script>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/sale-detail/index.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app/statistics/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <!-- 销售日统计 -->\n                <div id=\"id_day\" style=\"width: 100%;height:500px;\"></div>\n                <!-- 销售月统计 -->\n                <div id=\"id_month\" style=\"width: 100%;height:500px;\"></div>\n                <!-- 销售年统计 -->\n                <div id=\"id_year\" style=\"width: 100%;height:500px;\"></div>\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/app/statistics/index.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugins/echarts/echarts.min.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/blog/bContent/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n\n</head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t\t\t\t<h4>发布文章</h4>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"cid\" name=\"cid\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">标题：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"title\" name=\"title\" class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">作者：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"author\" name=\"author\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<input id=\"content\" name=\"content\" type=\"hidden\"> <label\n\t\t\t\t\t\t\t\t\tclass=\"col-sm-1 control-label\">内容：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<div class=\"ibox-content no-padding\">\n\t\t\t\t\t\t\t\t\t\t<div id=\"content_sn\" class=\"summernote\"></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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<input id=\"categories\" name=\"categories\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">开启评论：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-1\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input id=\"allowComment\" name=\"allowComment\" checked=\"\"\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\" value=\"1\" class=\"onoffswitch-checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tid=\"example1\"> <label class=\"onoffswitch-label\"\n\t\t\t\t\t\t\t\t\t\t\tfor=\"example1\"> <span class=\"onoffswitch-inner\"></span>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">允许订阅：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-2\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input id=\"allowFeed\" name=\"allowFeed\" type=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"1\" class=\"onoffswitch-checkbox\" id=\"example3\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"onoffswitch-label\" for=\"example3\"> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-inner\"></span> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\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 id=\"status\" name=\"status\" type=\"hidden\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"text-right form-group\">\n\t\t\t\t\t\t\t\t<a class=\"btn btn-default waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"returnList()\">返回列表</a>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-primary waves-effect waves-light\" type=\"submit\">保存文章</button>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-warning waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"save(0)\">存为草稿</button>\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<div th:include=\"include::footer\"></div>\n\n\n\t<script type=\"text/javascript\" src=\"/js/appjs/blog/bContent/add.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/bContent/bContent.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content\">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button shiro:hasPermission=\"blog:bContent:add\" type=\"button\" class=\"btn  btn-primary\"\n                                onclick=\"add()\">\n                            <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n                        </button>\n                        <button shiro:hasPermission=\"blog:bContent:batchRemove\" type=\"button\" class=\"btn  btn-danger\"\n                                onclick=\"batchRemove()\">\n                            <i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n                        </button>\n                    </div>\n                    <div class=\"columns pull-right\">\n                        <button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n                    </div>\n                    <div class=\"columns pull-right col-md-2 nopadding\">\n                        <input id=\"searchName\" type=\"text\" class=\"form-control\"\n                               placeholder=\"\">\n                    </div>\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n    <!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n    <div>\n        <script type=\"text/javascript\">\n            var s_edit_h = 'hidden';\n            var s_remove_h = 'hidden';\n        </script>\n    </div>\n    <div shiro:hasPermission=\"blog:bContent:edit\">\n        <script type=\"text/javascript\">\n            s_edit_h = '';\n        </script>\n    </div>\n    <div shiro:hasPermission=\"blog:bContent:remove\">\n        <script type=\"text/javascript\">\n            var s_remove_h = '';\n        </script>\n    </div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\"\n        src=\"/js/appjs/blog/bContent/bContent.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/blog/bContent/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t\t\t\t<h4>发布文章</h4>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"cid\" name=\"cid\" type=\"hidden\"\n\t\t\t\t\t\t\t\tth:value=\"${bContent.cid}\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">标题：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"title\" name=\"title\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${bContent.title}\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">作者：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"author\" name=\"author\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${bContent.author}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<input id=\"content\" name=\"content\" type=\"hidden\"\n\t\t\t\t\t\t\t\t\tth:value=\"${bContent.content}\"> <label\n\t\t\t\t\t\t\t\t\tclass=\"col-sm-1 control-label\">内容：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<div class=\"ibox-content no-padding\">\n\t\t\t\t\t\t\t\t\t\t<div id=\"content_sn\" class=\"summernote\"></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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<input th:value=\"${bContent.categories}\" id=\"categories\"\n\t\t\t\t\t\t\t\t\t\tname=\"categories\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">开启评论：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-1\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input id=\"allowComment\" name=\"allowComment\" checked=\"\"\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\" value=\"1\" class=\"onoffswitch-checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tth:checked=${bContent.allowComment==1}> <label\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-label\" for=\"allowComment\"> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-inner\"></span> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">允许订阅：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-2\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input id=\"allowFeed\" name=\"allowFeed\" type=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tchecked=\"\" value=\"1\" class=\"onoffswitch-checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tth:checked=${bContent.allowFeed==1}> <label\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-label\" for=\"allowFeed\"> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-inner\"></span> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\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 id=\"status\" name=\"status\" type=\"hidden\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"text-right form-group\">\n\t\t\t\t\t\t\t\t<a class=\"btn btn-default waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"returnList()\">返回列表</a>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-primary waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"save(1)\">保存文章</button>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-warning waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"save(0)\">存为草稿</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/blog/bContent/edit.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/bcomments/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t\t\t\t<h4>发布文章</h4>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">标题：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"title\" name=\"title\" class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">作者：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"author\" name=\"author\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<input id=\"created\" name=\"created\" class=\"form-control\"\n\t\t\t\t\t\t\t\ttype=\"hidden\"> <input id=\"ownerId\" name=\"ownerId\"\n\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">邮箱：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"email\" name=\"email\" class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">链接地址：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"url\" name=\"url\" class=\"form-control\" type=\"text\">\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<input id=\"ip\" name=\"ip\" class=\"form-control\" type=\"hidden\">\n\t\t\t\t\t\t\t<input id=\"agent\" name=\"agent\" class=\"form-control\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<input id=\"content\" name=\"content\" type=\"hidden\"> <label\n\t\t\t\t\t\t\t\t\tclass=\"col-sm-1 control-label\">内容：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<div class=\"ibox-content no-padding\">\n\t\t\t\t\t\t\t\t\t\t<div id=\"content_sn\" class=\"summernote\"></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\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\n\t\t\t\t\t\t\t\t<label class=\"col-sm-1 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t\t\t\t\t\t<input id=\"type\" name=\"type\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">开启评论：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-1\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" checked=\"\" class=\"onoffswitch-checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tid=\"example1\"> <label class=\"onoffswitch-label\"\n\t\t\t\t\t\t\t\t\t\t\tfor=\"example1\"> <span class=\"onoffswitch-inner\"></span>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">允许订阅：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch onoffswitch col-sm-2\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" checked=\"\" class=\"onoffswitch-checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tid=\"example3\"> <label class=\"onoffswitch-label\"\n\t\t\t\t\t\t\t\t\t\t\tfor=\"example3\"> <span class=\"onoffswitch-inner\"></span>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\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\n\t\t\t\t\t\t\t<input id=\"parent\" name=\"parent\" class=\"form-control\"\n\t\t\t\t\t\t\t\ttype=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"text-right form-group\">\n\t\t\t\t\t\t\t\t<a class=\"btn btn-default waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\thref=\"/admin/article\">返回列表</a>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-primary waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"save()\">保存文章</button>\n\t\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn btn-warning waves-effect waves-light\"\n\t\t\t\t\t\t\t\t\tonclick=\"subArticle('draft');\">存为草稿</button>\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\n\t<div th:include=\"include::footer\"></div>\n\n\t<script type=\"text/javascript\" src=\"/js/appjs/blog/bComments/add.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/bcomments/bComments.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div id=\"exampleToolbar\" role=\"group\">\n\t\t\t\t\t\t<div class=\"form-group col-sm-6\">\n\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\" placeholder=\"用户名\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-danger\"\n\t\t\t\t\t\t\tonclick=\"batchRemove()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/blog/bComments/bComments.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/blog/index/about.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n\n<meta charset=\"utf-8\">\n<meta name=\"viewport\"\n\tcontent=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n<meta name=\"description\" content=\"\">\n<meta name=\"author\" content=\"\">\n<title>Clean Blog - Start Bootstrap Theme</title>\n<!-- Bootstrap Core CSS -->\n<link href=\"lib/bootstrap/css/bootstrap.min.css\" rel=\"stylesheet\">\n<!-- Additional fonts for this theme -->\n<link href=\"lib/font-awesome/css/font-awesome.min.css\" rel=\"stylesheet\"\n\ttype=\"text/css\">\n<link\n\thref='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic'\n\trel='stylesheet' type='text/css'>\n<link\n\thref='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800'\n\trel='stylesheet' type='text/css'>\n<!-- Custom styles for this theme -->\n<link href=\"css/clean-blog.min.css\" rel=\"stylesheet\">\n<!-- Temporary navbar container fix until Bootstrap 4 is patched -->\n<style>\n.navbar-toggler {\n\tz-index: 1;\n}\n\n@media ( max-width : 576px) {\n\tnav>.container {\n\t\twidth: 100%;\n\t}\n}\n</style>\n</head>\n<body>\n\t<!-- Navigation -->\n\t<nav class=\"navbar fixed-top navbar-toggleable-md navbar-light\"\n\t\tid=\"mainNav\">\n\t\t<div class=\"container\">\n\t\t\t<button class=\"navbar-toggler navbar-toggler-right\" type=\"button\"\n\t\t\t\tdata-toggle=\"collapse\" data-target=\"#navbarResponsive\"\n\t\t\t\taria-controls=\"navbarResponsive\" aria-expanded=\"false\"\n\t\t\t\taria-label=\"Toggle navigation\">\n\t\t\t\tMenu <i class=\"fa fa-bars\"></i>\n\t\t\t</button>\n\t\t\t<a class=\"navbar-brand page-scroll\" href=\"index.html\">Start\n\t\t\t\tBootstrap</a>\n\t\t\t<div class=\"collapse navbar-collapse\" id=\"navbarResponsive\">\n\t\t\t\t<ul class=\"navbar-nav ml-auto\">\n\t\t\t\t\t<li class=\"nav-item\"><a class=\"nav-link page-scroll\"\n\t\t\t\t\t\thref=\"index.html\">Home</a></li>\n\t\t\t\t\t<li class=\"nav-item\"><a class=\"nav-link page-scroll\"\n\t\t\t\t\t\thref=\"about.html\">About</a></li>\n\t\t\t\t\t<li class=\"nav-item\"><a class=\"nav-link page-scroll\"\n\t\t\t\t\t\thref=\"post.html\">Sample Post</a></li>\n\t\t\t\t\t<li class=\"nav-item\"><a class=\"nav-link page-scroll\"\n\t\t\t\t\t\thref=\"contact.html\">Contact</a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</nav>\n\t<!-- Page Header -->\n\t<header class=\"intro-header\"\n\t\tstyle=\"background-image: url('img/about-bg.jpg')\">\n\t\t<div class=\"container\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-lg-8 offset-lg-2 col-md-10 offset-md-1\">\n\t\t\t\t\t<div class=\"page-heading\">\n\t\t\t\t\t\t<h1>About Me</h1>\n\t\t\t\t\t\t<span class=\"subheading\">This is what I do.</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</header>\n\n\t<!-- Main Content -->\n\t<div class=\"container\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-lg-8 offset-lg-2 col-md-10 offset-md-1\">\n\t\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n\t\t\t\t\tSaepe nostrum ullam eveniet pariatur voluptates odit, fuga atque ea\n\t\t\t\t\tnobis sit soluta odio, adipisci quas excepturi maxime quae totam\n\t\t\t\t\tducimus consectetur?</p>\n\t\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n\t\t\t\t\tEius praesentium recusandae illo eaque architecto error,\n\t\t\t\t\trepellendus iusto reprehenderit, doloribus, minus sunt. Numquam at\n\t\t\t\t\tquae voluptatum in officia voluptas voluptatibus, minus!</p>\n\t\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n\t\t\t\t\tNostrum molestiae debitis nobis, quod sapiente qui voluptatum,\n\t\t\t\t\tplaceat magni repudiandae accusantium fugit quas labore non rerum\n\t\t\t\t\tpossimus, corrupti enim modi! Et.</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<hr>\n\n\t<!-- Footer -->\n\t<footer>\n\t\t<div class=\"container\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-lg-8 offset-lg-2 col-md-10 offset-md-1\">\n\t\t\t\t\t<ul class=\"list-inline text-center\">\n\t\t\t\t\t\t<li class=\"list-inline-item\"><a href=\"#\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-twitter fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t\t<li class=\"list-inline-item\"><a href=\"#\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-facebook fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t\t<li class=\"list-inline-item\"><a href=\"#\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-github fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<p class=\"copyright text-muted\">Copyright &copy; Your Website\n\t\t\t\t\t\t2017</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</footer>\n\n\t<!-- jQuery Version 3.1.1 -->\n\t<script src=\"lib/jquery/jquery.js\"></script>\n\n\t<!-- Tether -->\n\t<script src=\"lib/tether/tether.min.js\"></script>\n\n\t<!-- Bootstrap Core JavaScript -->\n\t<script src=\"lib/bootstrap/js/bootstrap.min.js\"></script>\n\n\t<!-- Theme JavaScript -->\n\t<script src=\"js/clean-blog.min.js\"></script>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/index/include_blog.html",
    "content": "<head th:fragment=\"header\">\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"description\" content=\"\">\n<meta name=\"author\" content=\"\">\n<title>bootdo面向学习型的开源框架</title>\n<link href=\"/css/bootstrap.min.css\" rel=\"stylesheet\">\n<link href=\"/css/blog/clean-blog.css\" rel=\"stylesheet\">\n<link href=\"/css/font-awesome.min.css\" rel=\"stylesheet\" type=\"text/css\">\n<style type=\"text/css\">\n\t@media (max-width:768px){\n\t\t.side{ display:none;  }\n\t\t}\n\t@media (min-width:768px){\n\t\t.side{ display:block;  }\n\t\t}\n\t.side{\n\t\tposition: fixed;\n\t    width: 50px;\n\t    right: 5%;\n\t    bottom: 15%;\n\t    z-index: 100;\n\t}\n\t.side ul{\n\t\tlist-style:none;\n\t}\n\t.side ul li {\n\t    width: 35px;\n\t    height: 35px;\n\t    float: left;\n\t    position: relative;\n\t    margin-top: 9px;\n\t}\n\t.side ul li .qqbdimg {\n\t    padding: 7px;\n\t    margin-top: 5px;\n\t    margin-bottom: 1px;\n\t    /* margin-left: 22px; */\n\t    position: absolute;\n\t    width: 53px;\n\t    height: 54px;\n\t    /* margin-left: 9px; */\n\t    bottom: 0;\n\t    right: -7px;\n\t    transition: all 0.3s;\n\t    background: #fff;\n\t    opacity: 0;\n\t    filter: Alpha(opacity=80);\n\t    color: #fff;\n\t    font: 14px/54px \"微软雅黑\";\n\t    overflow: hidden;\n\t}\n\t.side ul li .qqbdimg:hover{\n\t\toverflow:hidden;\n\t\tpadding: 7px;\n\t    margin-top: 5px;\n\t    width:124px;\n\t    height:124px;\n\t    opacity:1;\n\t    z-index:100;\n\t    right:0;\n\t    background:rgb(142, 142, 142);\n\t}\n\t.side ul li img {\n\t    width: 100%;\n\t    height: 100%;\n\t}\n\t.side ul li .sidetop {\n\t    height: 100%;\n\t    display: block;\n\t    background: #2f4050;\n\t    padding: 2px 0px;\n\t    text-align: center;\n\t    color: #fff;\n\t    border-radius: 50%;\n\t    opacity: .5;\n\t}\n</style>\n</head>\n<nav th:fragment=\"nav\">\n\t<div class=\"container\">\n\t\t<div class=\"navbar-header page-scroll\">\n\t\t\t<button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\"\n\t\t\t\tdata-target=\"#bs-example-navbar-collapse-1\">\n\t\t\t\t<span class=\"sr-only\">Toggle navigation</span> <span\n\t\t\t\t\tclass=\"icon-bar\"></span> <span class=\"icon-bar\"></span> <span\n\t\t\t\t\tclass=\"icon-bar\"></span>\n\t\t\t</button>\n\t\t\t<a class=\"navbar-brand\" href=\"/\" style=\"font-size: 24px;\">BootDo</a>\n\t\t</div>\n\t\t<div class=\"collapse navbar-collapse\"\n\t\t\tid=\"bs-example-navbar-collapse-1\">\n\t\t\t<ul class=\"nav navbar-nav navbar-right\">\n\t\t\t\t<li><a href=\"/\">主页</a></li>\n\t\t\t\t<li><a href=\"/blog/open/page/about\">关于</a></li>\n\t\t\t\t<li><a href=\"/blog/open/page/communication\">交流</a></li>\n\t\t\t\t<li><a href=\"/login\">登录</a></li>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n</nav>\n<div th:fragment=\"footer\">\n\t<footer>\n\t\t<div class=\"container\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n\t\t\t\t\t<ul class=\"list-inline text-center\">\n\t\t\t\t\t\t<li><a href=\"https://jq.qq.com/?_wv=1027&k=5ICuFaQ\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-qq fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t\t<li><a href=\"https://www.oschina.net/p/bootdo\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-home fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t\t<li><a href=\"https://github.com/lcg0124/bootdo.git\"> <span\n\t\t\t\t\t\t\t\tclass=\"fa-stack fa-lg\"> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-circle fa-stack-2x\"></i> <i\n\t\t\t\t\t\t\t\t\tclass=\"fa fa-github fa-stack-1x fa-inverse\"></i>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<p class=\"copyright text-muted\">Copyright &copy; bootdo.com\n\t\t\t\t\t\t2017</p>\n\t\t\t\t\t<p class=\"copyright text-muted\">鲁ICP备17042918号</p>\n\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</footer>\n\t<div class=\"side\" >\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<div class=\"qqbdimg\">\n\t\t\t\t\t<img src=\"/img/blog/qqbootdo.png\" title=\"学习交流\"/>\n\t\t\t\t</div>\n\t\t\t\t<a class=\"sidetop\" id=\"qqbd\" href=\"javascript:scroll(0,0)\" title=\"学习交流\"><i\n\t\t\t\t\tclass=\"fa fa-qq\"></i></a>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a class=\"sidetop\" href=\"javascript:scroll(0,0)\" title=\"返回顶部\"><i\n\t\t\t\t\tclass=\"fa fa-arrow-up\"></i></a>\n\t\t\t\t\t\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n\t<script src=\"/js/jquery.min.js\"></script>\n\t<script src=\"/js/bootstrap.min.js\"></script>\n\t<script src=\"/js/plugins/layer/layer.js\"></script>\n\t<script src=\"/js/ajax-util.js\"></script>\n\t<script src=\"/js/appjs/blog/clean-blog.min.js\"></script>\n\t<script src=\"/js/plugins/summernote/summernote.min.js\"></script>\n\t<script src=\"/js/plugins/summernote/summernote-zh-CN.js\"></script>\n</div>\n\n"
  },
  {
    "path": "src/main/resources/templates/blog/index/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"blog/index/include_blog::header\"></head>\n<body>\n\t<nav th:include=\"blog/index/include_blog::nav\"  class=\"navbar navbar-default navbar-custom navbar-fixed-top\" ></nav>\n\t<header class=\"intro-header\"\n\t\tstyle=\"background-image: url('/img/blog/home-bg.jpg')\">\n\t\t<div class=\"container\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n\t\t\t\t\t<div class=\"site-heading\">\n\t\t\t\t\t\t<h1>BootDo Blog</h1>\n\t\t\t\t\t\t<span class=\"subheading\">bootdo 博客</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</header>\n\n\t<!-- Main Content -->\n\t<div class=\"container\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n\t\t\t\t<div id=\"incomeNum\"></div>\n\t\t\t\t<div class=\"clearfix\">\n\t\t\t\t\t<p id=\"flagLoaded\" style=\"display: none; text-align: center;\">已全部加载</p>\n\t\t\t\t\t<a id=\"flagLoad\" style=\"display: none;\" class=\"btn btn-secondary float-right\" \n\t\t\t\t\t\thref=\"javascript:void(0)\" onclick=\"nextPage()\">更早 &rarr;</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t</body>\n\t<div th:include=\"blog/index/include_blog::footer\"></div>\n\t<script type=\"text/javascript\">\n\t\tvar limit = 10;\n\t\tvar currentPage = 0;\n\t\tvar total;\n\t\t$(function(){\n\t\t\tbindList(0);\n\n\t\t});\n\n\t\tfunction nextPage() {\n\t\t\tbindList(currentPage * limit)\n\t\t}\n\t\tfunction bindList(offset) {\n\t\t\t$\n\t\t\t\t.ajax({\n\t\t\t\t\turl : 'blog/open/list?type=article&limit=10&offset=' + offset,\n\t\t\t\t\tmethod : 'get',\n\t\t\t\t\tdataType : 'json',\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\tvar rows = data.rows;\n\t\t\t\t\t\ttotal = data.total;\n\t\t\t\t\t\tvar htmlText = \"\";\n\t\t\t\t\t\tfor (i = 0; i < rows.length; i++) {\n\t\t\t\t\t\t\thtmlText += '<div class=\"post-preview\">';\n\t\t\t\t\t\t\thtmlText += '<a href=\"/blog/open/post/' + rows[i].cid + '\">';\n\t\t\t\t\t\t\thtmlText += '<h2 class=\"post-title\">';\n\t\t\t\t\t\t\thtmlText += rows[i].title;\n\t\t\t\t\t\t\thtmlText += '</h2>';\n\t\t\t\t\t\t\thtmlText += '</a>';\n\t\t\t\t\t\t\thtmlText += '<p class=\"post-meta\">作者：<a href=\"#\">'\n\t\t\t\t\t\t\t\t+ rows[i].author\n\t\t\t\t\t\t\t\t+ '</a> &nbsp;&nbsp; '\n\t\t\t\t\t\t\t\t+ rows[i].gtmModified + '</p>';\n\t\t\t\t\t\t\thtmlText += '</div>';\n\t\t\t\t\t\t\thtmlText += '<hr>';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(\"#incomeNum\").append(htmlText);\n\t\t\t\t\t\tdocument.getElementById(\"flagLoad\").style.display = \"block\";\n\t\t\t\t\t\tcurrentPage++;\n\t\t\t\t\t\tif (total <= currentPage * limit) {\n\t\t\t\t\t\t\tdocument.getElementById(\"flagLoaded\").style.display = \"block\";\n\t\t\t\t\t\t\tdocument.getElementById(\"flagLoad\").style.display = \"none\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\t</script>\n\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/index/page.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<body>\n\n\t<div id=\"content\" class=\"summernote\"></div>\n\n\t<script type=\"text/javascript\" th:inline=\"javascript\">\n\t\t$().ready(function() {\n\t\t\t$('.summernote').summernote({\n\t\t\t\tlang : 'zh-CN'\n\t\t\t});\n\t\t\tvar content = /*[[${bContent.content}]]*/\n\t\t\t$('#content').code(content);\n\t\t\t$('.summernote').destroy();\n\t\t});\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/blog/index/post.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"blog/index/include_blog::header\"></head>\n<body>\n\t<nav th:include=\"blog/index/include_blog::nav\"  class=\"navbar navbar-default navbar-custom navbar-fixed-top\" ></nav>\n\t<!-- Page Header -->\n\t<header class=\"intro-header\"\n\t\tstyle=\"background-image: url('/img/blog/post-bg.jpg')\">\n\t\t<div class=\"container\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n\t\t\t\t\t<div class=\"post-heading\">\n\t\t\t\t\t\t<h1 th:text=\"${bContent.title}\"></h1>\n\t\t\t\t\t\t<span class=\"meta\">作者 <a href=\"#\"\n\t\t\t\t\t\t\tth:text=\"${bContent.author}\"></a>&nbsp;&nbsp;<a href=\"#\"\n\t\t\t\t\t\t\tth:text=\"${gtmModified}\"></a>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</header>\n\n\t<!-- Post Content -->\n\t<article>\n\t\t<div class=\"container\">\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div id=\"content\" class=\"summernote\"></div>\n\t\t\t</div>\n\n\t\t</div>\n\t</article>\n\t<hr>\n\t<div th:include=\"blog/index/include_blog::footer\"></div>\n\t<script type=\"text/javascript\" th:inline=\"javascript\">\n\t\t$().ready(function() {\n\t\t\t$('.summernote').summernote({\n\t\t\t\tlang : 'zh-CN'\n\t\t\t});\n\t\t\tvar content = /*[[${bContent.content}]]*/\n\t\t\t$('#content').code(content);\n\t\t\t$('.summernote').destroy();\n\t\t});\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/dict/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">标签名：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">数据值：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"value\" name=\"value\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"type\" name=\"type\" th:value=\"${type}\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">描述：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"description\" name=\"description\" th:value=\"${description}\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">排序（升序）：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"sort\" name=\"sort\" class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">备注信息：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"remarks\" name=\"remarks\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/common/dict/add.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/dict/dict.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"common:dict:add\" type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"common:dict:batchRemove\"\n\t\t\t\t\t\t\t\ttype=\"button\" class=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t<select data-placeholder=\"选择类别\" class=\"form-control chosen-select\"\n\t\t\t\t\t\t\t\ttabindex=\"2\" style=\"width: 100%\">\n\t\t\t\t\t\t\t\t<option value=\"\">选择类别</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t<div>\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_edit_h = 'hidden';\n\t\t\tvar s_remove_h = 'hidden';\n\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"common:dict:edit\">\n\t\t<script type=\"text/javascript\">\n\t\t\ts_edit_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"common:dict:remove\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_remove_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"common:dict:add\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_add_h = '';\n\t\t</script>\n\t</div>\n\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/js/appjs/common/dict/dict.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/common/dict/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <input id=\"id\" name=\"id\" th:value=\"${dict.id}\"\n                               class=\"form-control\" type=\"hidden\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">标签名：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" th:value=\"${dict.name}\"\n                                       class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">数据值：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"value\" name=\"value\" th:value=\"${dict.value}\"\n                                       class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">类型：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"type\" name=\"type\" th:value=\"${dict.type}\"\n                                       class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">描述：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"description\" name=\"description\"\n                                       th:value=\"${dict.description}\" class=\"form-control\"\n                                       type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">排序：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"sort\" name=\"sort\" th:value=\"${dict.sort}\"\n                                       class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group hidden\">\n                            <label class=\"col-sm-3 control-label \">父级编号：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"parentId\" name=\"parentId\"\n                                       th:value=\"${dict.parentId}\" class=\"form-control\"\n                                       type=\"text\">\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">备注信息：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"remarks\" name=\"remarks\"\n                                       th:value=\"${dict.remarks}\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/common/dict/edit.js\">\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/file/file.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>bootdo - 文件管理器</title>\n    <meta name=\"keywords\" content=\"\">\n    <meta name=\"description\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"favicon.ico\">\n    <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/layui.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n    <style>\n        .aactive {\n            color: #13b5b7 !important;\n        }\n        .hactive:hover{\n            color: #13b5b7 !important;\n        }\n    </style>\n</head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content\" id=\"app\">\n    <div class=\"row\">\n        <div class=\"col-sm-3\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <div class=\"file-manager\">\n                        <button type=\"button\" class=\"layui-btn\" id=\"test1\">\n                            <i class=\"fa fa-cloud\"></i>上传文件\n                        </button>\n                        <div class=\"hr-line-dashed\"></div>\n                        <ul class=\"folder-list\" style=\"padding: 0\">\n                            <li><a href=\"javascript:void(0)\" class=\"file-control hactive\" :class=\"{'aactive':type === ''}\"\n                                   v-on:click=\"changeType('')\"><i class=\"fa fa-folder\"></i>所有文件</a></li>\n\n                            <li><a href=\"javascript:void(0)\" class=\"file-control hactive\" :class=\"{'aactive':type === 0}\"\n                                   v-on:click=\"changeType(0)\"><i class=\"fa fa-folder\"></i>图片</a></li>\n\n                            <li><a href=\"javascript:void(0)\" :class=\"{'aactive':type === 1}\"\n                                   v-on:click=\"changeType(1)\" class=\"file-control hactive\"><i class=\"fa fa-folder\"></i>文档</a>\n                            </li>\n\n                            <li><a href=\"javascript:void(0)\" v-on:click=\"changeType(2)\" :class=\"{'aactive':type === 2}\"\n                                   class=\"file-control hactive\"><i class=\"fa fa-folder\"></i>视频</a></li>\n\n                            <li><a href=\"javascript:void(0)\" v-on:click=\"changeType(3)\" :class=\"{'aactive':type === 3}\"\n                                   class=\"file-control hactive\"><i class=\"fa fa-folder\"></i>音乐</a></li>\n\n                            <li><a href=\"javascript:void(0)\" v-on:click=\"changeType(99)\" :class=\"{'aactive':type === 99}\"\n                                   class=\"file-control hactive\"><i class=\"fa fa-folder\"></i>其他</a></li>\n                        </ul>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-sm-9 animated fadeInRight\">\n            <div class=\"row\">\n                <div class=\"col-sm-12\">\n                    <div class=\"file-box\" v-for=\"row in rows\">\n                        <div class=\"file\">\n                            <a href=\"#\">\n                                <span class=\"corner\"></span>\n                                <div class=\"image\">\n                                    <img alt=\"image\" class=\"img-responsive\" :src=\"row.url\">\n                                </div>\n                                <div class=\"file-name\">\n                                    <br/>\n                                    <small>{{row.createDate}}</small>\n                                </div>\n                                &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<button\n                                    class=\"btn btn-warning btn-xs copy\" :url=\"row.url\">复制\n                            </button>&nbsp; &nbsp; &nbsp; &nbsp;<button class=\"btn btn-danger btn-xs\"\n                                                                        @click=\"remove(row.id)\">删除\n                            </button>\n                            </a>\n                        </div>\n                    </div>\n                    <div id=\"incomeNum\"></div>\n                </div>\n            </div>\n            <div>\n                <ul id=\"page\"></ul>\n            </div>\n        </div>\n    </div>\n</div>\n\n<!-- 全局js -->\n<script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n<script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n<script src=\"/js/bootstrap-paginator.min.js\"></script>\n\n<script src=\"/js/content.js?v=1.0.0\"></script>\n<script src=\"/js/layui.js\"></script>\n<script src=\"/js/plugins/clipboard/clipboard.min.js\"></script>\n<script src=\"/js/plugins/layer/layer.min.js\"></script>\n<script src=\"/js/vue.min.js\"></script>\n\n<script>\n    var app = new Vue({\n        el: '#app',\n        data: {\n            limit: 12,\n            offset: 0,\n            total: 0,\n            file: '',\n            type: '',\n            rows: '',\n        },\n        methods: {\n            getData: function () {\n                $.getJSON(\"/common/sysFile/list\", {\n                    limit: this.limit,\n                    offset: this.offset,\n                    type: this.type\n                }, function (r) {\n                    app.total = r.total;\n                    app.rows = r.rows;\n                    app.page();\n                });\n            },\n            page: function () {\n                var options = {\n                    currentPage: app.offset / 12 + 1, //当前页\n                    totalPages: app.total / (12 + 1) + 1, //总页数\n                    numberofPages: 4, //显示的页数\n                    bootstrapMajorVersion: 3,\n                    alignment: 'center',\n                    size: 'large',\n                    shouldShowPage: true,\n                    itemTexts: function (type, page, current) { //修改显示文字\n                        switch (type) {\n                            case \"first\":\n                                return \"首页\";\n                            case \"prev\":\n                                return \"上一页\";\n                            case \"next\":\n                                return \"下一页\";\n                            case \"last\":\n                                return \"尾页\";\n                            case \"page\":\n                                return page;\n                        }\n                    },\n                    onPageClicked: function (event, originalEvent, type, page) {\n                        app.offset = (page - 1) * 12;\n                        app.getData();\n                    }\n                };\n                $('#page').bootstrapPaginator(options);\n            },\n            remove: function (id) {\n                layer.confirm('确定要删除选中的记录？', {\n                    btn: ['确定', '取消']\n                }, function () {\n                    $.ajax({\n                        url: \"/common/sysFile/remove\",\n                        type: \"post\",\n                        data: {\n                            'id': id\n                        },\n                        success: function (r) {\n                            if (r.code == 0) {\n                                layer.msg(r.msg);\n                                app.getData();\n                            } else {\n                                layer.msg(r.msg);\n                                app.getData();\n                            }\n                        }\n                    });\n                })\n            },\n            changeType: function (i) {\n                this.type = i;\n                this.offset = 0;\n                this.getData();\n            }\n        },\n        created: function () {\n            this.changeType('')\n        }\n    });\n</script>\n<script type=\"text/javascript\">\n    var clipboard = new Clipboard('button.copy', {\n        text: function (trigger) {\n            layer.msg('文件路径已复制到粘贴板');\n            return $(trigger).attr('url');\n        }\n    });\n    layui.use('upload', function () {\n        var upload = layui.upload;\n        //执行实例\n        var uploadInst = upload.render({\n            elem: '#test1', //绑定元素\n            url: '/common/sysFile/upload', //上传接口\n            size: 1000,\n            accept: 'file',\n            done: function (r) {\n                layer.msg(r.msg);\n                app.getData();\n            },\n            error: function (r) {\n                layer.msg(r.msg);\n            }\n        });\n    });\n\n    // function changeType(i) {\n    //     app.type = i;\n    //     app.offset = 0;\n    //     app.getData();\n    // }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/Controller.java.vm",
    "content": "package ${package}.controller;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport me.zbl.common.utils.PageWrapper;\nimport org.apache.shiro.authz.annotation.RequiresPermissions;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.ui.Model;\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.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport ${package}.domain.${className}DO;\nimport ${package}.service.${className}Service;\nimport me.zbl.common.utils.Query;\nimport me.zbl.common.utils.R;\n\n/**\n * ${comments}\n * \n * @author 郑保乐\n * @email ${email}\n * @date ${datetime}\n */\n \n@Controller\n@RequestMapping(\"/${pathName}/${classname}\")\npublic class ${className}Controller {\n\t@Autowired\n\tprivate ${className}Service ${classname}Service;\n\t\n\t@GetMapping()\n\t@RequiresPermissions(\"${pathName}:${classname}:${classname}\")\n\tString ${className}(){\n\t    return \"${pathName}/${classname}/${classname}\";\n\t}\n\t\n\t@ResponseBody\n\t@GetMapping(\"/list\")\n\t@RequiresPermissions(\"${pathName}:${classname}:${classname}\")\n\tpublic PageWrapper list(@RequestParam Map<String, Object> params){\n\t\t//查询列表数据\n        Query query = new Query(params);\n\t\tList<${className}DO> ${classname}List = ${classname}Service.list(query);\n\t\tint total = ${classname}Service.count(query);\n\t\tPageWrapper pageWrapper = new PageWrapper(${classname}List, total);\n\t\treturn pageWrapper;\n\t}\n\t\n\t@GetMapping(\"/add\")\n\t@RequiresPermissions(\"${pathName}:${classname}:add\")\n\tString add(){\n\t    return \"${pathName}/${classname}/add\";\n\t}\n\n\t@GetMapping(\"/edit/{${pk.attrname}}\")\n\t@RequiresPermissions(\"${pathName}:${classname}:edit\")\n\tString edit(@PathVariable(\"${pk.attrname}\") ${pk.attrType} ${pk.attrname},Model model){\n\t\t${className}DO ${classname} = ${classname}Service.get(${pk.attrname});\n\t\tmodel.addAttribute(\"${classname}\", ${classname});\n\t    return \"${pathName}/${classname}/edit\";\n\t}\n\t\n\t/**\n\t * 保存\n\t */\n\t@ResponseBody\n\t@PostMapping(\"/save\")\n\t@RequiresPermissions(\"${pathName}:${classname}:add\")\n\tpublic R save( ${className}DO ${classname}){\n\t\tif(${classname}Service.save(${classname})>0){\n\t\t\treturn R.ok();\n\t\t}\n\t\treturn R.error();\n\t}\n\t/**\n\t * 修改\n\t */\n\t@ResponseBody\n\t@RequestMapping(\"/update\")\n\t@RequiresPermissions(\"${pathName}:${classname}:edit\")\n\tpublic R update( ${className}DO ${classname}){\n\t\t${classname}Service.update(${classname});\n\t\treturn R.ok();\n\t}\n\t\n\t/**\n\t * 删除\n\t */\n\t@PostMapping( \"/remove\")\n\t@ResponseBody\n\t@RequiresPermissions(\"${pathName}:${classname}:remove\")\n\tpublic R remove( ${pk.attrType} ${pk.attrname}){\n\t\tif(${classname}Service.remove(${pk.attrname})>0){\n\t\treturn R.ok();\n\t\t}\n\t\treturn R.error();\n\t}\n\t\n\t/**\n\t * 删除\n\t */\n\t@PostMapping( \"/batchRemove\")\n\t@ResponseBody\n\t@RequiresPermissions(\"${pathName}:${classname}:batchRemove\")\n\tpublic R remove(@RequestParam(\"ids[]\") ${pk.attrType}[] ${pk.attrname}s){\n\t\t${classname}Service.batchRemove(${pk.attrname}s);\n\t\treturn R.ok();\n\t}\n\t\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/Dao.java.vm",
    "content": "package ${package}.dao;\n\nimport ${package}.domain.${className}DO;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.ibatis.annotations.Mapper;\n\n/**\n * ${comments}\n * @author 郑保乐\n * @email ${email}\n * @date ${datetime}\n */\n@Mapper\npublic interface ${className}Dao {\n\n\t${className}DO get(${pk.attrType} ${pk.attrname});\n\t\n\tList<${className}DO> list(Map<String,Object> map);\n\t\n\tint count(Map<String,Object> map);\n\t\n\tint save(${className}DO ${classname});\n\t\n\tint update(${className}DO ${classname});\n\t\n\tint remove(${pk.attrType} ${pk.columnName});\n\t\n\tint batchRemove(${pk.attrType}[] ${pk.attrname}s);\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/Mapper.java.vm",
    "content": "package ${package}.dao;\n\nimport ${package}.domain.${className}DO;\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.Select;\nimport org.apache.ibatis.annotations.Update;\n/**\n * ${comments}\n * \n * @author 郑保乐\n * @email ${email}\n * @date ${datetime}\n */\n@Mapper\npublic interface ${className}Mapper {\n\n\t@Select(\"select #foreach($column in $columns)\n`$column.columnName`#if($velocityCount != $columns.size()), #end\t\n#end from ${tableName} where ${pk.columnName} = #{id}\")\n\t${className}DO get(${pk.attrType} ${pk.attrname});\n\t\n\t@Select(\"<script>\" +\n\t\"select * from ${tableName} \" + \n\t\t\t\"<where>\" + \n\t\t  #foreach($column in $columns)\n\t\t  \"<if test=\\\"$column.attrname != null and $column.attrname.trim() != ''\\\">\"+ \"and $column.columnName = #{$column.attrname} \" + \"</if>\" + \n\t\t  #end\n\t\t\t\"</where>\"+ \n\t\t\t\" <choose>\" + \n\t            \"<when test=\\\"sort != null and sort.trim() != ''\\\">\" + \n\t                \"order by ${sort} ${order}\" + \n\t            \"</when>\" + \n\t\t\t\t\"<otherwise>\" + \n\t                \"order by ${pk.columnName} desc\" + \n\t\t\t\t\"</otherwise>\" + \n\t        \"</choose>\"+\n\t\t\t\"<if test=\\\"offset != null and limit != null\\\">\"+\n\t\t\t\"limit #{offset}, #{limit}\" + \n\t\t\t\"</if>\"+\n\t\t\t\"</script>\")\n\tList<${className}DO> list(Map<String,Object> map);\n\t\n\t@Select(\"<script>\" +\n\t\"select count(*) from ${tableName} \" + \n\t\t\t\"<where>\" + \n\t\t  #foreach($column in $columns)\n\t\t  \"<if test=\\\"$column.attrname != null and $column.attrname.trim() != ''\\\">\"+ \"and $column.columnName = #{$column.attrname} \" + \"</if>\" + \n\t\t  #end\n\t\t\t\"</where>\"+ \n\t\t\t\"</script>\")\n\tint count(Map<String,Object> map);\n\t\n\t@Insert(\"insert into ${tableName} (#foreach($column in $columns)\n#if($column.columnName != $pk.columnName || $pk.extra != 'auto_increment')\n`$column.columnName`#if($velocityCount != $columns.size()), #end\n#end\t\t\t\n#end)\"\n\t+ \"values (#foreach($column in $columns)\n#if($column.columnName != $pk.columnName || $pk.extra != 'auto_increment')\n#{$column.attrname}#if($velocityCount != $columns.size()), #end\n#end\t\t\t\n#end)\")\n\tint save(${className}DO ${classname});\n\t\n\t@Update(\"<script>\"+ \n\t\t\t\"update ${tableName} \" + \n\t\t\t\t\t\"<set>\" + \n\t\t  #foreach($column in $columns)\n          \"<if test=\\\"$column.attrname != null\\\">`$column.columnName` = #{$column.attrname}, </if>\" + \n          #end\n\t\t\t\t\t\"</set>\" + \n\t\t\t\t\t\"where ${pk.columnName} = #{${pk.attrname}}\"+\n\t\t\t\"</script>\")\n\tint update(${className}DO ${classname});\n\t\n\t@Delete(\"delete from ${tableName} where ${pk.columnName} =#{${pk.attrname}}\")\n\tint remove(${pk.attrType} ${pk.columnName});\n\t\n\t@Delete(\"<script>\"+ \n\t\t\t\"delete from ${tableName} where ${pk.columnName} in \" + \n\t\t\t\t\t\"<foreach item=\\\"${pk.attrname}\\\" collection=\\\"array\\\" open=\\\"(\\\" separator=\\\",\\\" close=\\\")\\\">\" + \n\t\t\t\t\t\t\"#{${pk.attrname}}\" + \n\t\t\t\t\t\"</foreach>\"+\n\t\t\t\"</script>\")\n\tint batchRemove(${pk.attrType}[] ${pk.attrname}s);\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/Mapper.xml.vm",
    "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\n<mapper namespace=\"${package}.dao.${className}Dao\">\n\n\t<select id=\"get\" resultType=\"${package}.domain.${className}DO\">\n\t\tselect #foreach($column in $columns)`$column.columnName`#if($velocityCount != $columns.size()),#end#end from ${tableName} where ${pk.columnName} = #{value}\n\t</select>\n\n\t<select id=\"list\" resultType=\"${package}.domain.${className}DO\">\n\t\tselect #foreach($column in $columns)`$column.columnName`#if($velocityCount != $columns.size()),#end#end from ${tableName}\n        <where>  \n\t\t  #foreach($column in $columns)\n\t\t  <if test=\"$column.attrname != null and $column.attrname.trim() != ''\"> and $column.columnName = #{$column.attrname} </if>\n\t\t  #end\n\t\t</where>\n        <choose>\n            <when test=\"sort != null and sort.trim() != ''\">\n                order by ${sort} ${order}\n            </when>\n\t\t\t<otherwise>\n                order by ${pk.columnName} desc\n\t\t\t</otherwise>\n        </choose>\n\t\t<if test=\"offset != null and limit != null\">\n\t\t\tlimit #{offset}, #{limit}\n\t\t</if>\n\t</select>\n\t\n \t<select id=\"count\" resultType=\"int\">\n\t\tselect count(*) from ${tableName}\n\t\t <where>  \n\t\t  #foreach($column in $columns)\n\t\t  <if test=\"$column.attrname != null and $column.attrname.trim() != ''\"> and $column.columnName = #{$column.attrname} </if>\n\t\t  #end\n\t\t</where>\n\t</select>\n\t \n\t<insert id=\"save\" parameterType=\"${package}.domain.${className}DO\"#if($pk.extra == 'auto_increment') useGeneratedKeys=\"true\" keyProperty=\"$pk.attrname\"#end>\n\t\tinsert into ${tableName}\n\t\t(\n#foreach($column in $columns)\n#if($column.columnName != $pk.columnName || $pk.extra != 'auto_increment')\n\t\t\t`$column.columnName`#if($velocityCount != $columns.size()), #end\n\n#end\t\t\t\n#end\n\t\t)\n\t\tvalues\n\t\t(\n#foreach($column in $columns)\n#if($column.columnName != $pk.columnName || $pk.extra != 'auto_increment')\n\t\t\t#{$column.attrname}#if($velocityCount != $columns.size()), #end\n\n#end\t\t\t\n#end\n\t\t)\n\t</insert>\n\t \n\t<update id=\"update\" parameterType=\"${package}.domain.${className}DO\">\n\t\tupdate ${tableName} \n\t\t<set>\n#foreach($column in $columns)\n#if($column.columnName != $pk.columnName)\n\t\t\t<if test=\"$column.attrname != null\">`$column.columnName` = #{$column.attrname}#if($velocityCount != $columns.size()), #end</if>\n#end\n#end\n\t\t</set>\n\t\twhere ${pk.columnName} = #{${pk.attrname}}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from ${tableName} where ${pk.columnName} = #{value}\n\t</delete>\n\t\n\t<delete id=\"batchRemove\">\n\t\tdelete from ${tableName} where ${pk.columnName} in \n\t\t<foreach item=\"${pk.attrname}\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{${pk.attrname}}\n\t\t</foreach>\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "src/main/resources/templates/common/generator/Service.java.vm",
    "content": "package ${package}.service;\n\nimport ${package}.domain.${className}DO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * ${comments}\n * \n * @author 郑保乐\n * @email ${email}\n * @date ${datetime}\n */\npublic interface ${className}Service {\n\t\n\t${className}DO get(${pk.attrType} ${pk.attrname});\n\t\n\tList<${className}DO> list(Map<String, Object> map);\n\t\n\tint count(Map<String, Object> map);\n\t\n\tint save(${className}DO ${classname});\n\t\n\tint update(${className}DO ${classname});\n\t\n\tint remove(${pk.attrType} ${pk.attrname});\n\t\n\tint batchRemove(${pk.attrType}[] ${pk.attrname}s);\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/ServiceImpl.java.vm",
    "content": "package ${package}.service.impl;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport ${package}.dao.${className}Dao;\nimport ${package}.domain.${className}DO;\nimport ${package}.service.${className}Service;\n\n\n\n@Service\npublic class ${className}ServiceImpl implements ${className}Service {\n\t@Autowired\n\tprivate ${className}Dao ${classname}Dao;\n\t\n\t@Override\n\tpublic ${className}DO get(${pk.attrType} ${pk.attrname}){\n\t\treturn ${classname}Dao.get(${pk.attrname});\n\t}\n\t\n\t@Override\n\tpublic List<${className}DO> list(Map<String, Object> map){\n\t\treturn ${classname}Dao.list(map);\n\t}\n\t\n\t@Override\n\tpublic int count(Map<String, Object> map){\n\t\treturn ${classname}Dao.count(map);\n\t}\n\t\n\t@Override\n\tpublic int save(${className}DO ${classname}){\n\t\treturn ${classname}Dao.save(${classname});\n\t}\n\t\n\t@Override\n\tpublic int update(${className}DO ${classname}){\n\t\treturn ${classname}Dao.update(${classname});\n\t}\n\t\n\t@Override\n\tpublic int remove(${pk.attrType} ${pk.attrname}){\n\t\treturn ${classname}Dao.remove(${pk.attrname});\n\t}\n\t\n\t@Override\n\tpublic int batchRemove(${pk.attrType}[] ${pk.attrname}s){\n\t\treturn ${classname}Dao.batchRemove(${pk.attrname}s);\n\t}\n\t\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/add.html.vm",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n#foreach($column in $columns)\n#if($column.columnName != $pk.columnName)\n<div class=\"form-group\">\t\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">${column.comments}：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"${column.attrname}\" name=\"${column.attrname}\" class=\"form-control\" type=\"text\">\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#end\n\t\t\t\t\t\t\t#end\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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</div>\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/${pathName}/${classname}/add.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/add.js.vm",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tsave();\n\t}\n});\nfunction save() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/${pathName}/${classname}/save\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入姓名\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/templates/common/generator/domain.java.vm",
    "content": "package ${package}.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n#if(${hasBigDecimal})\nimport java.math.BigDecimal;\n#end\n\n\n/**\n * ${comments}\n * \n * @author 郑保乐\n * @email ${email}\n * @date ${datetime}\n */\npublic class ${className}DO implements Serializable {\n\tprivate static final long serialVersionUID = 1L;\n\t\n#foreach ($column in $columns)\n\t//$column.comments\n\tprivate $column.attrType $column.attrname;\n#end\n\n#foreach ($column in $columns)\n\t/**\n\t * 设置：${column.comments}\n\t */\n\tpublic void set${column.attrName}($column.attrType $column.attrname) {\n\t\tthis.$column.attrname = $column.attrname;\n\t}\n\t/**\n\t * 获取：${column.comments}\n\t */\n\tpublic $column.attrType get${column.attrName}() {\n\t\treturn $column.attrname;\n\t}\n#end\n}\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">作者：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"author\" name=\"author\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${property.author}\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">邮箱：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"email\" name=\"email\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\tth:value=\"${property.email}\" readonly>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">包名：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"package\" name=\"package\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${property.package}\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">自动去掉表前缀：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-2  i-checks icheckbox_square-green checked\">\n\t\t\t\t\t\t\t\t<input id=\"autoRemovePre\" name=\"autoRemovePre\"\n\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"checkbox\"\n\t\t\t\t\t\t\t\t\tvalue=\"true\"\n\t\t\t\t\t\t\t\t\tth:checked=\"${property.autoRemovePre}\">\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">去掉指定表前缀：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"tablePrefix\" name=\"tablePrefix\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${property.tablePrefix}\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/common/generator/edit.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/edit.html.vm",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t<input id=\"${pk.columnName}\" name=\"${pk.columnName}\" th:value=\"${${classname}.${pk.columnName}}\"  type=\"hidden\">\n#foreach($column in $columns)\n#if($column.columnName != $pk.columnName)\n<div class=\"form-group\">\t\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">${column.comments}：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"${column.attrname}\" name=\"${column.attrname}\" th:value=\"${${classname}.${column.attrname}}\" class=\"form-control\" type=\"text\">\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#end\n\t\t\t\t\t\t\t#end\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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</div>\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/${pathName}/${classname}/edit.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/generator/edit.js.vm",
    "content": "$().ready(function() {\n\tvalidateRule();\n});\n\n$.validator.setDefaults({\n\tsubmitHandler : function() {\n\t\tupdate();\n\t}\n});\nfunction update() {\n\t$.ajax({\n\t\tcache : true,\n\t\ttype : \"POST\",\n\t\turl : \"/${pathName}/${classname}/update\",\n\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\tasync : false,\n\t\terror : function(request) {\n\t\t\tparent.layer.alert(\"Connection error\");\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif (data.code == 0) {\n\t\t\t\tparent.layer.msg(\"操作成功\");\n\t\t\t\tparent.reLoad();\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\n\t\t\t} else {\n\t\t\t\tparent.layer.alert(data.msg)\n\t\t\t}\n\n\t\t}\n\t});\n\n}\nfunction validateRule() {\n\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t$(\"#signupForm\").validate({\n\t\trules : {\n\t\t\tname : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tname : {\n\t\t\t\trequired : icon + \"请输入名字\"\n\t\t\t}\n\t\t}\n\t})\n}"
  },
  {
    "path": "src/main/resources/templates/common/generator/list.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div  id=\"exampleToolbar\" role=\"group\" >\n\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-primary\"\n\t\t\t\t\t\t\tonclick=\"batchCode()\">\n\t\t\t\t\t\t\t<i class=\"\" aria-hidden=\"true\"></i>批量生成\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-success\"\n\t\t\t\t\t\t\tonclick=\"edit()\">\n\t\t\t\t\t\t\t<i class=\"\" aria-hidden=\"true\"></i>生成策略\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/common/generator/list.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/common/generator/list.html.vm",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"${pathName}:${classname}:add\" type=\"button\" class=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"${pathName}:${classname}:batchRemove\" type=\"button\" class=\"btn  btn-danger\"\n\t\t\t\t\t\t\t\tonclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"${pathName}:${classname}:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\ts_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"${pathName}:${classname}:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"${pathName}:${classname}:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/${pathName}/${classname}/${classname}.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/common/generator/list.js.vm",
    "content": "\nvar prefix = \"/${pathName}/${classname}\"\n$(function() {\n\tload();\n});\n\nfunction load() {\n\t$('#exampleTable')\n\t\t\t.bootstrapTable(\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod : 'get', // 服务器数据的请求方式 get or post\n\t\t\t\t\t\turl : prefix + \"/list\", // 服务器数据的加载地址\n\t\t\t\t\t//\tshowRefresh : true,\n\t\t\t\t\t//\tshowToggle : true,\n\t\t\t\t\t//\tshowColumns : true,\n\t\t\t\t\t\ticonSize : 'outline',\n\t\t\t\t\t\ttoolbar : '#exampleToolbar',\n\t\t\t\t\t\tstriped : true, // 设置为true会有隔行变色效果\n\t\t\t\t\t\tdataType : \"json\", // 服务器返回的数据类型\n\t\t\t\t\t\tpagination : true, // 设置为true会在底部显示分页条\n\t\t\t\t\t\t// queryParamsType : \"limit\",\n\t\t\t\t\t\t// //设置为limit则会发送符合RESTFull格式的参数\n\t\t\t\t\t\tsingleSelect : false, // 设置为true将禁止多选\n\t\t\t\t\t\t// contentType : \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t// //发送到服务器的数据编码类型\n\t\t\t\t\t\tpageSize : 10, // 如果设置了分页，每页数据条数\n\t\t\t\t\t\tpageNumber : 1, // 如果设置了分布，首页页码\n\t\t\t\t\t\t//search : true, // 是否显示搜索框\n\t\t\t\t\t\tshowColumns : false, // 是否显示内容下拉框（选择显示的列）\n\t\t\t\t\t\tsidePagination : \"server\", // 设置在哪里进行分页，可选值为\"client\" 或者 \"server\"\n\t\t\t\t\t\tqueryParams : function(params) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t//说明：传入后台的参数包括offset开始索引，limit步长，sort排序列，order：desc或者,以及所有列的键值对\n\t\t\t\t\t\t\t\tlimit: params.limit,\n\t\t\t\t\t\t\t\toffset:params.offset\n\t\t\t\t\t           // name:$('#searchName').val(),\n\t\t\t\t\t           // username:$('#searchName').val()\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// //请求服务器数据时，你可以通过重写参数的方式添加一些额外的参数，例如 toolbar 中的参数 如果\n\t\t\t\t\t\t// queryParamsType = 'limit' ,返回参数必须包含\n\t\t\t\t\t\t// limit, offset, search, sort, order 否则, 需要包含:\n\t\t\t\t\t\t// pageSize, pageNumber, searchText, sortName,\n\t\t\t\t\t\t// sortOrder.\n\t\t\t\t\t\t// 返回false将会终止请求\n\t\t\t\t\t\tcolumns : [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcheckbox : true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t#foreach($column in $columns)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfield : '${column.attrname}', \n\t\t\t\t\t\t\t\t\ttitle : '${column.comments}' \n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t#end\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttitle : '操作',\n\t\t\t\t\t\t\t\t\tfield : 'id',\n\t\t\t\t\t\t\t\t\talign : 'center',\n\t\t\t\t\t\t\t\t\tformatter : function(value, row, index) {\n\t\t\t\t\t\t\t\t\t\tvar e = '<a class=\"btn btn-primary btn-sm '+s_edit_h+'\" href=\"#\" mce_href=\"#\" title=\"编辑\" onclick=\"edit(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.${pk.attrname}\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-edit\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar d = '<a class=\"btn btn-warning btn-sm '+s_remove_h+'\" href=\"#\" title=\"删除\"  mce_href=\"#\" onclick=\"remove(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.${pk.attrname}\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-remove\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\tvar f = '<a class=\"btn btn-success btn-sm\" href=\"#\" title=\"备用\"  mce_href=\"#\" onclick=\"resetPwd(\\''\n\t\t\t\t\t\t\t\t\t\t\t\t+ row.${pk.attrname}\n\t\t\t\t\t\t\t\t\t\t\t\t+ '\\')\"><i class=\"fa fa-key\"></i></a> ';\n\t\t\t\t\t\t\t\t\t\treturn e + d ;\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});\n}\nfunction reLoad() {\n\t$('#exampleTable').bootstrapTable('refresh');\n}\nfunction add() {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '增加',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/add' // iframe的url\n\t});\n}\nfunction edit(id) {\n\tlayer.open({\n\t\ttype : 2,\n\t\ttitle : '编辑',\n\t\tmaxmin : true,\n\t\tshadeClose : false, // 点击遮罩关闭层\n\t\tarea : [ '800px', '520px' ],\n\t\tcontent : prefix + '/edit/' + id // iframe的url\n\t});\n}\nfunction remove(id) {\n\tlayer.confirm('确定要删除选中的记录？', {\n\t\tbtn : [ '确定', '取消' ]\n\t}, function() {\n\t\t$.ajax({\n\t\t\turl : prefix+\"/remove\",\n\t\t\ttype : \"post\",\n\t\t\tdata : {\n\t\t\t\t'${pk.attrname}' : id\n\t\t\t},\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code==0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t}else{\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t})\n}\n\nfunction resetPwd(id) {\n}\nfunction batchRemove() {\n\tvar rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行，当没有选择的记录时，返回一个空数组\n\tif (rows.length == 0) {\n\t\tlayer.msg(\"请选择要删除的数据\");\n\t\treturn;\n\t}\n\tlayer.confirm(\"确认要删除选中的'\" + rows.length + \"'条数据吗?\", {\n\t\tbtn : [ '确定', '取消' ]\n\t// 按钮\n\t}, function() {\n\t\tvar ids = new Array();\n\t\t// 遍历所有选择的行数据，取每条数据对应的ID\n\t\t$.each(rows, function(i, row) {\n\t\t\tids[i] = row['${pk.attrname}'];\n\t\t});\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\tdata : {\n\t\t\t\t\"ids\" : ids\n\t\t\t},\n\t\t\turl : prefix + '/batchRemove',\n\t\t\tsuccess : function(r) {\n\t\t\t\tif (r.code == 0) {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t\treLoad();\n\t\t\t\t} else {\n\t\t\t\t\tlayer.msg(r.msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}, function() {\n\n\t});\n}"
  },
  {
    "path": "src/main/resources/templates/common/generator/menu.sql.vm",
    "content": "-- 菜单SQL\nINSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)\n    VALUES ('1', '${comments}', 'modules/generator/${pathName}.html', NULL, '1', 'fa fa-file-code-o', '6');\n\n-- 按钮父菜单ID\nset @parentId = @@identity;\n\n-- 菜单对应按钮SQL\nINSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)\n    SELECT @parentId, '查看', null, '${pathName}:list,${pathName}:info', '2', null, '6';\nINSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)\n    SELECT @parentId, '新增', null, '${pathName}:save', '2', null, '6';\nINSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)\n    SELECT @parentId, '修改', null, '${pathName}:update', '2', null, '6';\nINSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)\n    SELECT @parentId, '删除', null, '${pathName}:delete', '2', null, '6';\n"
  },
  {
    "path": "src/main/resources/templates/common/job/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务名称：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobName\" name=\"jobName\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务分组：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobGroup\" name=\"jobGroup\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务类：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"beanClass\" name=\"beanClass\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">cron表达式：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"cronExpression\" name=\"cronExpression\"\n\t\t\t\t\t\t\t\t\t\t   class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务描述：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-10\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"description\" name=\"description\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\t></textarea>\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<div class=\"form-group hidden\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务状态：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobStatus\" name=\"jobStatus\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" value=\"0\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-2 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/js/appjs/common/job/add.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/job/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n                            <input id=\"id\" name=\"id\" class=\"hidden\" th:value=\"${job.id}\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务名称：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobName\" name=\"jobName\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${job.jobName}\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务分组：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"jobGroup\" name=\"jobGroup\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${job.jobGroup}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务类：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"beanClass\" name=\"beanClass\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${job.beanClass}\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">cron表达式：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"cronExpression\" name=\"cronExpression\"\n\t\t\t\t\t\t\t\t\t\t   class=\"form-control\" type=\"text\" th:value=\"${job.cronExpression}\">\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<div class=\"form-group hidden\">\n\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">是否同步：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t\t\t<input id=\"isConcurrent\" name=\"isConcurrent\"\n\t\t\t\t\t\t\t\t\t\tclass=\"radio-inline\" value=\"1\" type=\"radio\">是\n\t\t\t\t\t\t\t\t\t<input id=\"isConcurrent\" name=\"isConcurrent\"\n\t\t\t\t\t\t\t\t\t\tclass=\"radio-inline\" value=\"0\" type=\"radio\">否\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-2 control-label\">任务描述：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-10\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"description\" name=\"description\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\t></textarea>\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<input id=\"jobStatus\" name=\"jobStatus\" class=\"form-control hidden\"\n\t\t\t\t\t\t\t\t   type=\"text\" value=\"0\" th:value=\"${job.jobStatus}\">\n\n\t\t\t\t\t\t\t<!-- <div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">Spring bean：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"springBean\" name=\"springBean\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-2 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/js/appjs/common/job/edit.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/common/job/job.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-danger\"\n\t\t\t\t\t\t\t\tonclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/js/appjs/common/job/job.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/common/log/log.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-danger\"\n\t\t\t\t\t\t\t\tonclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\" role=\"group\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-search\" aria-hidden=\"true\"></i>查询\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"pull-right search col-md-2\">\n\t\t\t\t\t\t\t<input id=\"searchOperation\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"操作\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"pull-right search col-md-2 nopadding\">\n\t\t\t\t\t\t\t<input id=\"searchUsername\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"用户\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/common/log/log.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/error/403.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>403 页面</title>\n<meta name=\"keywords\" content=\"\">\n<meta name=\"description\" content=\"\">\n<link rel=\"shortcut icon\" href=\"favicon.ico\">\n<link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n<link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n<link href=\"/css/animate.css\" rel=\"stylesheet\">\n<link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n</head>\n<body class=\"gray-bg\">\n\t<div class=\"middle-box text-center animated fadeInDown\">\n\t\t<h1>403</h1>\n\t\t<h3 class=\"font-bold\">您没有访问权限！</h3>\n\t\t<div class=\"error-desc\">\n\t\t\t抱歉，请联系管理员哦~\n\t\t\t<form class=\"form-inline m-t\" role=\"form\">\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t<input type=\"email\" class=\"form-control\"\n\t\t\t\t\t\tplaceholder=\"请输入您需要查找的内容 …\">\n\t\t\t\t</div>\n\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">搜索</button>\n\t\t\t</form>\n\t\t</div>\n\t</div>\n\t<!-- 全局js -->\n\t<script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n\t<script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/error/404.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n    <title>Bootdo - 404 页面</title>\n    <meta name=\"keywords\" content=\"\">\n    <meta name=\"description\" content=\"\">\n\n    <link rel=\"shortcut icon\" href=\"favicon.ico\"> <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n\n</head>\n\n<body class=\"gray-bg\">\n    <div class=\"middle-box text-center animated fadeInDown\">\n        <h1>404</h1>\n        <h3 class=\"font-bold\">页面未找到！</h3>\n\n        <div class=\"error-desc\">\n            抱歉，页面好像去火星了~\n            <form class=\"form-inline m-t\" role=\"form\">\n                <div class=\"form-group\">\n                    <input type=\"email\" class=\"form-control\" placeholder=\"请输入您需要查找的内容 …\">\n                </div>\n                <button type=\"submit\" class=\"btn btn-primary\">搜索</button>\n            </form>\n        </div>\n    </div>\n    <!-- 全局js -->\n    <script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n    <script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/error/500.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n\n    <title>500错误</title>\n    <meta name=\"keywords\" content=\"\">\n    <meta name=\"description\" content=\"\">\n\n    <link rel=\"shortcut icon\" href=\"favicon.ico\"> <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n\n</head>\n\n<body class=\"gray-bg\">\n\n\n    <div class=\"middle-box text-center animated fadeInDown\">\n        <h1>500</h1>\n        <h3 class=\"font-bold\">服务器内部错误</h3>\n\n        <div class=\"error-desc\">\n            服务器好像出错了...\n            <br/>您可以返回主页看看\n            <br/><a href=\"/\" class=\"btn btn-primary m-t\">主页</a>\n        </div>\n    </div>\n\n    <!-- 全局js -->\n    <script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n    <script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n\n  \n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/error/error.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>500错误</title>\n    <meta name=\"keywords\" content=\"\">\n    <meta name=\"description\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"favicon.ico\"> <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n</head>\n<body class=\"gray-bg\">\n    <div class=\"middle-box text-center animated fadeInDown\">\n        <h1>500</h1>\n        <h3 class=\"font-bold\">服务器内部错误</h3>\n        <div class=\"error-desc\">\n            \t服务器好像出错了...<br/>\n            \t您可以返回主页看看<br/>\n            \t<div th:text=\"${exception}\"></div>\n            \t<div th:text=\"${url}\"></div>\n            <a href=\"/\" class=\"btn btn-primary m-t\">主页</a>\n        </div>\n    </div>\n    <!-- 全局js -->\n    <script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n    <script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/include.html",
    "content": "<head th:fragment=\"header\" xmlns:th=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t<title></title>\n\t<meta name=\"keywords\" content=\"\">\n\t<meta name=\"description\" content=\"\">\n\t<link rel=\"shortcut icon\" href=\"favicon.ico\">\n\t<link href=\"css/bootstrap.min.css?v=3.3.6\"\n\t\t  th:href=\"@{/css/bootstrap.min.css?v=3.3.6}\" rel=\"stylesheet\">\n\t<link href=\"/css/font-awesome.css?v=4.4.0\"\n\t\t  th:href=\"@{/css/font-awesome.css?v=4.4.0}\" rel=\"stylesheet\">\n\t<link href=\"/css/plugins/bootstrap-table/bootstrap-table.min.css\"\n\t\t  th:href=\"@{/css/plugins/bootstrap-table/bootstrap-table.min.css}\"\n\t\t  rel=\"stylesheet\">\n\t<link href=\"/css/plugins/jsTree/style.min.css\" rel=\"stylesheet\">\n\t<link href=\"/css/plugins/jqTreeGrid/jquery.treegrid.css\"\n\t\t  rel=\"stylesheet\">\n\t<!--summernote css -->\n\t<link href=\"/css/plugins/summernote/summernote-0.8.8.css\"\n\t\t  rel=\"stylesheet\">\n\t<link href=\"css/animate.css\" th:href=\"@{/css/animate.css}\"\n\t\t  rel=\"stylesheet\">\n\t<link href=\"/css/plugins/chosen/chosen.css\" rel=\"stylesheet\">\n\t<link href=\"/css/style.css?v=4.1.0\" th:href=\"@{/css/style.css?v=4.1.0}\"\n\t\t  rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"/js/plugins/select2/css/select2.min.css\">\n\t<!-- layui -->\n\t<link href=\"/css/layui.css\" rel=\"stylesheet\">\n</head>\n<div th:fragment=\"footer\">\n\t<script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n\t<script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n\t<script src=\"/js/plugins/bootstrap-table/bootstrap-table.min.js\"></script>\n\t<script src=\"/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js\"></script>\n    <script src=\"/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js\"></script>\n\t<script src=\"/js/plugins/validate/jquery.validate.min.js\"></script>\n\t<script src=\"/js/plugins/validate/messages_zh.min.js\"></script>\n\t<script src=\"/js/plugins/jsTree/jstree.min.js\"></script>\n\t<script src=\"/js/plugins/jqTreeGrid/jquery.treegrid.min.js\"></script>\n\t<script src=\"/js/plugins/jqTreeGrid/jquery.treegrid.extension.js\"></script>\n\t<script src=\"/js/plugins/jqTreeGrid/jquery.treegrid.bootstrap3.js\"></script>\n\t<script src=\"/js/plugins/chosen/chosen.jquery.js\"></script>\n\t<script src=\"/js/plugins/layer/layer.js\"></script>\n\t<script src=\"/js/content.js?v=1.0.0\"></script>\n\t<!--summernote-->\n\t<script src=\"/js/plugins/summernote/summernote.js\"></script>\n\t<script src=\"/js/plugins/summernote/summernote-zh-CN.min.js\"></script>\n\t<script src=\"/js/ajax-util.js\"></script>\n    <script src=\"/js/plugins/select2/js/select2.min.js\"></script>\n    <script src=\"/js/plugins/select2/js/i18n/zh-CN.js\"></script>\n\t<!-- layui -->\n\t<!--<script src=\"/js/layui.js\"></script>-->\n</div>\n"
  },
  {
    "path": "src/main/resources/templates/index_v1.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"renderer\" content=\"webkit\">\n    <title>医院药品管理系统</title>\n    <!--[if lt IE 9]>\n    <meta http-equiv=\"refresh\" content=\"0;ie.html\"/>\n    <![endif]-->\n    <link rel=\"shortcut icon\" href=\"favicon.ico\">\n    <link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.min.css?v=4.4.0\" rel=\"stylesheet\">\n    <link href=\"/css/plugins/toastr/toastr.min.css\" rel=\"stylesheet\">\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n</head>\n<body class=\"fixed-sidebar full-height-layout gray-bg\"\n      style=\"overflow: hidden\">\n<div id=\"wrapper\">\n    <!--左侧导航开始-->\n    <nav class=\"navbar-default navbar-static-side\" role=\"navigation\">\n        <div class=\"nav-close\">\n            <i class=\"fa fa-times-circle\"></i>\n        </div>\n        <div class=\"sidebar-collapse\">\n            <ul class=\"nav\" id=\"side-menu\">\n                <li class=\"nav-header\">\n                    <div>\n                        <span><img alt=\"image\" class=\"img-circle\" height=\"60\" width=\"60\" th:src=\"${picUrl}\"/></span>\n                        <h3 style=\"color: white;margin: 5px;\" th:text=\"${username}\">\n                        </h3>\n                    </div>\n                    <div class=\"dropdown profile-element hidden\">\n\n                        <a data-toggle=\"dropdown\" class=\"dropdown-toggle\" href=\"#\">\n                            <span class=\"clear\">\n                            <span class=\"block m-t-xs\"><strong class=\"font-bold\"\n                                                               th:text=\"${username}\">admin</strong></span>\n                            <span class=\"text-muted text-xs block\">超级管理员<b class=\"caret\"></b></span>\n                             </span>\n                        </a>\n                        <ul class=\"dropdown-menu animated fadeInRight m-t-xs\">\n                            <li><a @click=\"personal\" href=\"#\">修改头像</a>\n                            </li>\n                            <li><a @click=\"personal\" href=\"#\">个人资料</a>\n                            </li>\n                            <li><a @click=\"personal\" href=\"#\">密码修改</a>\n                            </li>\n                            <li><a @click=\"personal\" href=\"#\">信箱</a>\n                            </li>\n                            <li class=\"divider\"></li>\n                            <li><a href=\"/logout\">安全退出</a>\n                            </li>\n                        </ul>\n                        <div class=\"logo-element\">BootDo</div>\n                    </div>\n                </li>\n                <li><a href=\"#\"> <i class=\"fa fa-home\"></i> <span\n                        class=\"nav-label\">主页</span> <span class=\"fa arrow\"></span>\n                </a>\n                    <ul class=\"nav nav-second-level\">\n                        <li><a id=\"index001\" class=\"J_menuItem\" href=\"index_v1.html\"\n                               data-index=\"0\" th:href=\"@{/main}\">药品管理系统</a></li>\n                    </ul>\n                </li>\n                <li th:each=\"menu : ${menus}\">\n                    <a href=\"#\">\n                        <i class=\"fa fa fa-bar-chart-o\" th:class=\"${menu.attributes.icon}\"></i>\n                        <span class=\"nav-label\" th:text=\"${menu.text}\">基础信息</span> <span class=\"fa arrow\"></span>\n                    </a>\n                    <ul class=\"nav nav-second-level\">\n                        <li th:each=\"cmenu : ${menu.children}\">\n                            <a class=\"J_menuItem\" href=\"graph_echarts.html\"\n                               th:text=\"${cmenu.text}\"\n                               th:href=\"${cmenu.attributes.url}\">\n                                系统管理</a>\n                        </li>\n                    </ul>\n                </li>\n            </ul>\n        </div>\n    </nav>\n    <!--左侧导航结束-->\n    <!--右侧部分开始-->\n    <div id=\"page-wrapper\" class=\"gray-bg dashbard-1\">\n        <div class=\"row border-bottom\">\n            <nav class=\"navbar navbar-static-top\" role=\"navigation\"\n                 style=\"margin-bottom: 0\">\n                <div class=\"navbar-header\">\n\n                    <a class=\"navbar-minimalize minimalize-styl-2 btn btn-default \"\n                       href=\"#\" title=\"收起菜单\"><i class=\"fa fa-bars\"></i></a>\n                </div>\n                <ul class=\"nav navbar-top-links navbar-right\">\n                    <!--<li class=\"hidden-xs\"><a href=\"/blog\" target=\"_Blank\"-->\n                    <!--class=\"\"><i class=\"fa fa-rss-square\"></i>博客</a></li>-->\n                    <!-- 药品提醒 -->\n                    <li class=\"dropdown\"><a class=\"dropdown-toggle count-info\"\n                                            data-toggle=\"dropdown\" href=\"#\"> <i class=\"fa fa-envelope\"></i>\n                        <span class=\"label label-warning\">{{total>0?total:\"\"}}</span>消息提醒\n                    </a>\n                        <ul class=\"dropdown-menu dropdown-messages\">\n                            <!-- 消息列表 -->\n                            <li v-for=\"row in rows\" class=\"m-t-xs\">\n                                <div class=\"dropdown-messages-box\">\n                                    <a class=\"pull-left\"> <i\n                                            class=\"fa fa-server\"></i>\n                                    </a>\n                                    <div class=\"media-body\">\n                                        <small class=\"pull-right\">{{row.before}}</small>\n                                        <strong>{{row.sender}}</strong>\n                                        {{row.title}} <br>\n                                        <small class=\"text-muted\">{{row.updateDate}}</small>\n                                    </div>\n                                </div>\n                                <div class=\"divider\"></div>\n                            </li>\n                            <li>\n                                <div class=\"text-center link-block\">\n                                    <a class=\"J_menuItem\" href=\"/oa/notify/selfNotify\"> <i\n                                            class=\"fa fa-envelope\"></i> <strong> 查看所有消息</strong>\n                                    </a>\n                                </div>\n                            </li>\n                        </ul>\n                    </li>\n                    <li class=\"hidden-xs\"><a @click=\"personal\" href=\"#\"><i class=\"fa fa-id-card\"></i> 个人</a></li>\n                    <li class=\"dropdown hidden-xs\"><a\n                            class=\"right-sidebar-toggle\" aria-expanded=\"false\"> <i\n                            class=\"fa fa-tasks\"></i> 主题\n                    </a></li>\n                </ul>\n            </nav>\n        </div>\n        <div class=\"row content-tabs\">\n            <button class=\"roll-nav roll-left J_tabLeft\">\n                <i class=\"fa fa-backward\"></i>\n            </button>\n            <nav class=\"page-tabs J_menuTabs\">\n                <div class=\"page-tabs-content\">\n                    <a href=\"javascript:;\" class=\"active J_menuTab\"\n                       data-id=\"index_v1.html\">首页</a>\n                </div>\n            </nav>\n            <button class=\"roll-nav roll-right J_tabRight\">\n                <i class=\"fa fa-forward\"></i>\n            </button>\n            <div class=\"btn-group roll-nav roll-right\">\n                <button class=\"dropdown J_tabClose\" data-toggle=\"dropdown\">\n                    关闭操作<span class=\"caret\"></span>\n                </button>\n                <ul role=\"menu\" class=\"dropdown-menu dropdown-menu-right\">\n                    <li class=\"J_tabShowActive\"><a>定位当前选项卡</a></li>\n                    <li class=\"divider\"></li>\n                    <li class=\"J_tabCloseAll\"><a>关闭全部选项卡</a></li>\n                    <li class=\"J_tabCloseOther\"><a>关闭其他选项卡</a></li>\n                </ul>\n            </div>\n            <a href=\"/logout\" class=\"roll-nav roll-right J_tabExit\"><i\n                    class=\"fa fa fa-sign-out\"></i> 退出</a>\n        </div>\n        <div class=\"row J_mainContent\" id=\"content-main\">\n            <iframe class=\"J_iframe\" name=\"iframe0\" width=\"100%\" height=\"100%\"\n                    src=\"\" th:src=\"@{/main}\" frameborder=\"0\" data-id=\"index_v1.html\"\n                    seamless></iframe>\n        </div>\n        <div class=\"footer\">\n            <div class=\"pull-right\">医院药品管理系统</div>\n            <!-- S CNZZ 统计代码 -->\n            <div class=\"pull-right\" style=\"margin-right: 1em\">\n                <script type=\"text/javascript\">var cnzz_protocol = ((\"https:\" == document.location.protocol) ? \" https://\" : \" http://\");\n                document.write(unescape(\"%3Cspan id='cnzz_stat_icon_1273501907'%3E%3C/span%3E%3Cscript src='\" + cnzz_protocol + \"s13.cnzz.com/z_stat.php%3Fid%3D1273501907%26show%3Dpic' type='text/javascript'%3E%3C/script%3E\"));</script>\n            </div>\n            <!-- E CNZZ 统计代码 -->\n        </div>\n    </div>\n    <!--右侧部分结束-->\n    <!--右侧边栏开始-->\n    <div id=\"right-sidebar\">\n        <div class=\"sidebar-container\">\n            <ul class=\"nav nav-tabs navs-3\">\n\n                <li class=\"active\"><a data-toggle=\"tab\" href=\"#tab-1\"> <i\n                        class=\"fa fa-gear\"></i> 主题\n                </a></li>\n                <li class=\"\"><a data-toggle=\"tab\" href=\"#tab-2\"> 通知 </a></li>\n                <li><a data-toggle=\"tab\" href=\"#tab-3\"> 项目进度 </a></li>\n            </ul>\n            <div class=\"tab-content\">\n                <div id=\"tab-1\" class=\"tab-pane active\">\n                    <div class=\"sidebar-title\">\n                        <h3>\n                            <i class=\"fa fa-comments-o\"></i> 主题设置\n                        </h3>\n                        <small><i class=\"fa fa-tim\"></i>\n                            你可以从这里选择和预览主题的布局和样式，这些设置会被保存在本地，下次打开的时候会直接应用这些设置。\n                        </small>\n                    </div>\n                    <div class=\"skin-setttings\">\n                        <div class=\"title\">主题设置</div>\n                        <div class=\"setings-item\">\n                            <span>收起左侧菜单</span>\n                            <div class=\"switch\">\n                                <div class=\"onoffswitch\">\n                                    <input type=\"checkbox\" name=\"collapsemenu\"\n                                           class=\"onoffswitch-checkbox\" id=\"collapsemenu\"> <label\n                                        class=\"onoffswitch-label\" for=\"collapsemenu\"> <span\n                                        class=\"onoffswitch-inner\"></span> <span\n                                        class=\"onoffswitch-switch\"></span>\n                                </label>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"setings-item\">\n                            <span>固定顶部</span>\n\n                            <div class=\"switch\">\n                                <div class=\"onoffswitch\">\n                                    <input type=\"checkbox\" name=\"fixednavbar\"\n                                           class=\"onoffswitch-checkbox\" id=\"fixednavbar\"> <label\n                                        class=\"onoffswitch-label\" for=\"fixednavbar\"> <span\n                                        class=\"onoffswitch-inner\"></span> <span\n                                        class=\"onoffswitch-switch\"></span>\n                                </label>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"setings-item\">\n                            <span> 固定宽度 </span>\n                            <div class=\"switch\">\n                                <div class=\"onoffswitch\">\n                                    <input type=\"checkbox\" name=\"boxedlayout\"\n                                           class=\"onoffswitch-checkbox\" id=\"boxedlayout\"> <label\n                                        class=\"onoffswitch-label\" for=\"boxedlayout\"> <span\n                                        class=\"onoffswitch-inner\"></span> <span\n                                        class=\"onoffswitch-switch\"></span>\n                                </label>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"title\">皮肤选择</div>\n                        <div class=\"setings-item default-skin nb\">\n\t\t\t\t\t\t\t\t<span class=\"skin-name \"> <a href=\"#\" class=\"s-skin-0\">\n\t\t\t\t\t\t\t\t\t\t默认皮肤 </a>\n\t\t\t\t\t\t\t\t</span>\n                        </div>\n                        <div class=\"setings-item blue-skin nb\">\n\t\t\t\t\t\t\t\t<span class=\"skin-name \"> <a href=\"#\" class=\"s-skin-1\">\n\t\t\t\t\t\t\t\t\t\t蓝色主题 </a>\n\t\t\t\t\t\t\t\t</span>\n                        </div>\n                        <div class=\"setings-item yellow-skin nb\">\n\t\t\t\t\t\t\t\t<span class=\"skin-name \"> <a href=\"#\" class=\"s-skin-3\">\n\t\t\t\t\t\t\t\t\t\t黄色/紫色主题 </a>\n\t\t\t\t\t\t\t\t</span>\n                        </div>\n                    </div>\n                </div>\n                <div id=\"tab-2\" class=\"tab-pane\">\n\n                    <div class=\"sidebar-title\">\n                        <h3>\n                            <i class=\"fa fa-comments-o\"></i> 最新通知\n                        </h3>\n                        <small><i class=\"fa fa-tim\"></i> 您当前有10条未读信息</small>\n                    </div>\n                </div>\n                <div id=\"tab-3\" class=\"tab-pane\">\n\n                    <div class=\"sidebar-title\">\n                        <h3>\n                            <i class=\"fa fa-cube\"></i> 最新任务\n                        </h3>\n                        <small><i class=\"fa fa-tim\"></i> 您当前有14个任务，10个已完成</small>\n                    </div>\n                </div>\n            </div>\n\n        </div>\n    </div>\n</div>\n<!-- 全局js -->\n<script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n<script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n<script src=\"/js/plugins/metisMenu/jquery.metisMenu.js\"></script>\n<script src=\"/js/plugins/slimscroll/jquery.slimscroll.min.js\"></script>\n<script src=\"/js/plugins/layer/layer.min.js\"></script>\n<!-- 自定义js -->\n<script src=\"/js/app.js?v=4.1.0\"></script>\n<script type=\"text/javascript\" src=\"/js/contabs.js\"></script>\n<!-- 第三方插件 -->\n<script src=\"/js/plugins/pace/pace.min.js\"></script>\n<!-- vue -->\n<script type=\"text/javascript\"\n        src=\"/js/vue.min.js\">\n\n</script>\n<script src=\"/js/appjs/oa/webSocket/sockjs.min.js\"></script>\n<script src=\"/js/appjs/oa/webSocket/stomp.min.js\"></script>\n<!-- Toastr script -->\n<script src=\"/js/plugins/toastr/toastr.min.js\"></script>\n<script type=\"text/javascript\">\n    var stompClient = null;\n    $(function () {\n        connect();\n    });\n\n    function connect() {\n        var sock = new SockJS(\"/endpointChat\");\n        var stomp = Stomp.over(sock);\n        stomp.connect('guest', 'guest', function (frame) {\n\n            /**  订阅了/user/queue/notifications 发送的消息,这里雨在控制器的 convertAndSendToUser 定义的地址保持一致, \n             *  这里多用了一个/user,并且这个user 是必须的,使用user 才会发送消息到指定的用户。 \n             *  */\n            stomp.subscribe(\"/user/queue/notifications\", handleNotification);\n            stomp.subscribe('/topic/getResponse', function (response) { //订阅/topic/getResponse 目标发送的消息。这个是在控制器的@SendTo中定义的。\n                toastr.options = {\n                    \"closeButton\": true,\n                    \"debug\": false,\n                    \"progressBar\": true,\n                    \"positionClass\": \"toast-bottom-right\",\n                    \"onclick\": null,\n                    \"showDuration\": \"400\",\n                    \"hideDuration\": \"1000\",\n                    \"timeOut\": \"7000\",\n                    \"extendedTimeOut\": \"1000\",\n                    \"showEasing\": \"swing\",\n                    \"hideEasing\": \"linear\",\n                    \"showMethod\": \"fadeIn\",\n                    \"hideMethod\": \"fadeOut\"\n                }\n                toastr.info(JSON.parse(response.body).responseMessage);\n            });\n        });\n\n        function handleNotification(message) {\n            wrapper.notify();\n            toastr.info(message.body);\n        }\n    }\n\n    var wrapper = new Vue({\n        el: '#wrapper',\n        data: {\n            total: '',\n            rows: '',\n        },\n        methods: {\n            notify: function () {\n                $.getJSON('/oa/notify/message', function (r) {\n                    wrapper.total = r.total;\n                    wrapper.rows = r.rows;\n                });\n            },\n            personal: function () {\n                layer.open({\n                    type: 2,\n                    title: '个人设置',\n                    maxmin: true,\n                    shadeClose: false,\n                    area: ['800px', '600px'],\n                    content: '/sys/user/personal'\n                });\n            }\n        },\n        created: function () {\n            this.notify()\n        }\n    })\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<!--suppress ALL -->\n<html lang=\"zh\" xmlns:th=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\"\n          content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n    <title>医院药品管理系统</title>\n    <link href=\"/css/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n    <link href=\"/css/animate.css\" rel=\"stylesheet\">\n    <link href=\"/css/style.css\" rel=\"stylesheet\">\n    <link href=\"/css/login.css\" rel=\"stylesheet\">\n    <!--[if lt IE 9]>\n    <meta http-equiv=\"refresh\" content=\"0;ie.html\"/>\n    <![endif]-->\n    <script>\n        if (window.top !== window.self) {\n            window.top.location = window.location;\n        }\n    </script>\n\n</head>\n\n<body class=\"signin\">\n<div class=\"signinpanel\">\n    <div class=\"row\">\n        <div class=\"col-sm-7\">\n            <div class=\"signin-info\">\n                <div class=\"logopanel m-b\">\n                    <h1>医院药品管理系统</h1>\n                </div>\n                <div class=\"m-b\"></div>\n                <h3>\n                    <strong>欢迎使用 </strong>\n                </h3>\n                <ul class=\"m-b\">\n                    <li><i class=\"fa fa-arrow-circle-o-right m-r-xs\"></i>\n                        springBoot\n                    </li>\n                    <li><i class=\"fa fa-arrow-circle-o-right m-r-xs\"></i> mybatis</li>\n                    <li><i class=\"fa fa-arrow-circle-o-right m-r-xs\"></i> shiro</li>\n                    <li><i class=\"fa fa-arrow-circle-o-right m-r-xs\"></i>\n                        thymeleaf\n                    </li>\n                    <li><i class=\"fa fa-arrow-circle-o-right m-r-xs\"></i>\n                        bootstrap\n                    </li>\n                </ul>\n            </div>\n        </div>\n        <div class=\"col-sm-5\">\n            <form id=\"signupForm\">\n                <h3 class=\"text-center\">用户登录</h3>\n                <p class=\"m-t-md text-center\">欢迎登录医院药品管理系统</p>\n                <input type=\"text\" name=\"username\" class=\"form-control uname\"\n                       value=\"admin\"/>\n                <input id=\"id_password\" type=\"password\" name=\"password\"\n                       class=\"form-control pword m-b\" value=\"111111\"/>\n                <a id=\"login\" class=\"btn btn-login btn-block\">登录</a>\n            </form>\n        </div>\n    </div>\n    <div class=\"signup-footer\">\n        <div class=\"pull-left\">&copy; 2015-2018 JamesZBL All Rights Reserved.\n        </div>\n    </div>\n</div>\n<script th:inline=\"javascript\">\n    // var ctx = [[@{/}]];\n</script>\n<!-- 全局js -->\n<script src=\"/js/jquery.min.js?v=2.1.4\" th:src=\"@{/js/jquery.min.js?v=2.1.4}\"></script>\n<script src=\"/js/bootstrap.min.js?v=3.3.6\" th:src=\"@{/js/bootstrap.min.js?v=3.3.6}\"></script>\n\n<!-- 自定义js -->\n<script src=\"/js/content.js?v=1.0.0\" th:src=\"@{/js/content.js?v=1.0.0}\"></script>\n\n<!-- jQuery Validation plugin javascript-->\n<script src=\"/js/ajax-util.js\"></script>\n<script src=\"/js/plugins/validate/jquery.validate.min.js\"\n        th:src=\"@{/js/plugins/validate/jquery.validate.min.js}\"></script>\n<script src=\"/js/plugins/validate/messages_zh.min.js\" th:src=\"@{/js/plugins/validate/messages_zh.min.js}\"></script>\n<script src=\"/js/plugins/layer/layer.min.js\" th:src=\"@{/js/plugins/layer/layer.min.js}\"></script>\n<script type=\"text/javascript\">\n    $(document).ready(function () {\n        $(\"#login\").on('click', function () {\n            $(\"#signupForm\").submit();\n        });\n        $(\"#id_password\").keydown(function (event) {\n            if (event.keyCode == 13) {\n                login();\n            }\n        });\n        validateRule();\n    });\n\n    $.validator.setDefaults({\n        submitHandler: function () {\n            login();\n        }\n    });\n\n    function login() {\n        $.ajax({\n            type: \"POST\",\n            url: \"/login\",\n            data: $('#signupForm').serialize(),\n            success: function (r) {\n                if (r.code == 0) {\n                    var index = layer.load(1, {\n                        shade: [0.1, '#fff'] //0.1透明度的白色背景\n                    });\n                    parent.location.href = '/index';\n                } else {\n                    layer.msg(r.msg);\n                }\n            },\n        });\n    }\n\n    function validateRule() {\n        var icon = \"<i class='fa fa-times-circle'></i> \";\n        $(\"#signupForm\").validate({\n            rules: {\n                username: {\n                    required: true\n                },\n                password: {\n                    required: true\n                }\n            },\n            messages: {\n                username: {\n                    required: icon + \"请输入您的用户名\",\n                },\n                password: {\n                    required: icon + \"请输入您的密码\",\n                }\n            }\n        })\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <title>欢迎页</title>\n    <meta content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\" name=\"viewport\">\n    <link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"panel panel-default\">\n    <h2 style=\"margin: 20px;color: #2A2E36;text-align: center\">欢迎使用医院药品管理系统</h2>\n</div>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/oa/notify/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">类型：</label>\n                            <div class=\"col-sm-8\">\n                                <select data-placeholder=\"--选择类别--\" name=\"type\" id=\"type\"\n                                        class=\"form-control chosen-select\" tabindex=\"2\" required>\n                                    <option value=\"\">--选择类别--</option>\n                                </select>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">标题：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"title\" name=\"title\" class=\"form-control\" type=\"text\" required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">内容：</label>\n                            <div class=\"col-sm-8\">\n                                <textarea id=\"content\" name=\"content\" class=\"form-control\" required></textarea>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">附件：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"files\" name=\"files\" class=\"form-control\" type=\"file\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">接收人：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"userIds\" name=\"userIds\" class=\"hidden\">\n                                <input id=\"userNames\" name=\"userNames\" class=\"form-control\"\n                                        type=\"text\" onclick=\"openUser()\"\n                                        readonly=\"readonly\" placeholder=\"接收人\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">立即发布：</label>\n                            <div class=\"switch  col-sm-1\">\n                                <div class=\"onoffswitch\">\n                                    <input id=\"status\" name=\"status\" checked=\"\" type=\"checkbox\"\n                                           value=\"1\" class=\"onoffswitch-checkbox\"> <label\n                                        class=\"onoffswitch-label\" for=\"status\"> <span\n                                        class=\"onoffswitch-inner\"></span> <span\n                                        class=\"onoffswitch-switch\"></span>\n                                </label>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">备注信息：</label>\n                            <div class=\"col-sm-8\">\n                                <textarea id=\"remarks\" name=\"remarks\" class=\"form-control\"></textarea>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/oa/notify/add.js\">\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/oa/notify/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \" id=\"app\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"id\" name=\"id\" th:value=\"${notify.id}\" type=\"hidden\">\n\t\t\t\t\t\t\t<input id=\"Ttype\" name=\"Ttype\" th:value=\"${notify.type}\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<select data-placeholder=\"--选择类别--\" name=\"type\" id=\"type\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control chosen-select\" tabindex=\"2\">\n\t\t\t\t\t\t\t\t\t\t<option value=\"\">-- 选择类别 --</option>\n\t\t\t\t\t\t\t\t\t\t<option th:each=\"oaNotifyType : ${oaNotifyTypes}\" th:value=\"${oaNotifyType.value}\" th:text=\"${oaNotifyType.name}\" th:if=\"${oaNotifyType.remarks ==checked}\" th:selected=\"selected\"></option>\n\t\t\t\t\t\t\t\t\t</select>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">标题：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"title\" name=\"title\" th:value=\"${notify.title}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">内容：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"content\" name=\"content\"\n\t\t\t\t\t\t\t\t\t\tth:text=\"${notify.content}\" class=\"form-control\"></textarea>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">附件：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"files\" name=\"files\" th:value=\"${notify.files}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">已经发布：</label>\n\t\t\t\t\t\t\t\t<div class=\"switch  col-sm-1\">\n\t\t\t\t\t\t\t\t\t<div class=\"onoffswitch\">\n\t\t\t\t\t\t\t\t\t\t<input id=\"status\" name=\"status\" checked=\"\" type=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tth:value=\"${notify.status}\" class=\"onoffswitch-checkbox\"> <label\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-label\" for=\"status\"> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-inner\"></span> <span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"onoffswitch-switch\"></span>\n\t\t\t\t\t\t\t\t\t\t</label>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">备注信息：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"remarks\" name=\"remarks\" th:value=\"${notify.remarks}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/oa/notify/edit.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/oa/notify/notify.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"oa:notify:add\" type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t<div>\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_edit_h = 'hidden';\n\t\t\tvar s_remove_h = 'hidden';\n\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:edit\">\n\t\t<script type=\"text/javascript\">\n\t\t\ts_edit_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:remove\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_remove_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:resetPwd\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_resetPwd_h = '';\n\t\t</script>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/oa/notify/notify.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/oa/notify/read.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"type\" name=\"type\" th:value=\"${notify.type}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">标题：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"title\" name=\"title\" th:value=\"${notify.title}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">内容：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"content\" name=\"content\"\n\t\t\t\t\t\t\t\t\t\tth:text=\"${notify.content}\" class=\"form-control\"></textarea>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">附件：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"files\" name=\"files\" th:value=\"${notify.files}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label hidden\">发送人：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 hidden\">\n\t\t\t\t\t\t\t\t\t<input id=\"createBy\" name=\"createBy\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${notify.createBy}\" class=\"form-control\" type=\"text\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label hidden\">发布时间：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 hidden\">\n\t\t\t\t\t\t\t\t\t<input id=\"updateDate\" name=\"updateDate\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${notify.updateDate}\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">备注信息：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<textarea id=\"remarks\" name=\"remarks\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${notify.remarks}\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group hidden\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/oa/notify/read.js\">\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/oa/notify/selfNotify.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn  btn-primary hidden\" onclick=\"read()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>设为已读\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button shiro:hasPermission=\"oa:notify:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"btn  btn-danger hidden\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\tplaceholder=\"\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t<div>\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_edit_h = 'hidden';\n\t\t\tvar s_remove_h = 'hidden';\n\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:edit\">\n\t\t<script type=\"text/javascript\">\n\t\t\ts_edit_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:remove\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_remove_h = '';\n\t\t</script>\n\t</div>\n\t<div shiro:hasPermission=\"oa:notify:resetPwd\">\n\t\t<script type=\"text/javascript\">\n\t\t\tvar s_resetPwd_h = '';\n\t\t</script>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/oa/notify/selfNotify.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/dept/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content animated fadeInRight\">\n    <div class=\"row\">\n        <div class=\"col-sm-12\">\n            <div class=\"ibox float-e-margins\">\n                <div class=\"ibox-content\">\n                    <form class=\"form-horizontal m-t\" id=\"signupForm\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">上级部门：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"parentId\" name=\"parentId\" th:value=\"${pId}\"\n                                       class=\"form-control hidden\" type=\"text\">\n                            </div>\n                            <div class=\"col-sm-8\">\n                                <input id=\"pName\" name=\"pName\" th:value=\"${pName}\"\n                                       class=\"form-control\" type=\"text\" readonly>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">部门名称：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">排序：</label>\n                            <div class=\"col-sm-8\">\n                                <input id=\"orderNum\" name=\"orderNum\" class=\"form-control\"\n                                       type=\"text\">\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">状态:</label>\n                            <div class=\"col-sm-8\">\n                                <label class=\"radio-inline\"> <input type=\"radio\" name=\"delFlag\" value=\"1\" checked/> 正常\n                                </label> <label class=\"radio-inline\"> <input type=\"radio\" name=\"delFlag\" value=\"0\"/> 禁用\n                            </label>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-8 col-sm-offset-3\">\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<div th:include=\"include::footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/system/sysDept/add.js\">\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/dept/dept.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content \">\n    <div class=\"col-sm-12\">\n        <div class=\"ibox\">\n            <div class=\"ibox-body\">\n                <div class=\"fixed-table-toolbar\">\n                    <div class=\"columns pull-left\">\n                        <button shiro:hasPermission=\"system:sysDept:add\" type=\"button\" class=\"btn  btn-primary\"\n                                onclick=\"add(0)\">\n                            <i class=\"fa fa-plus hidden\" aria-hidden=\"true\"></i>添加\n                        </button>\n                        <button shiro:hasPermission=\"system:sysDept:batchRemove\" type=\"button\" class=\"btn  btn-danger\"\n                                onclick=\"batchRemove()\">\n                            <i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n                        </button>\n                    </div>\n                    <div class=\"columns pull-right\">\n                        <button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n                    </div>\n\n                    <div class=\"columns pull-right col-md-2 nopadding\">\n                        <input id=\"searchName\" type=\"text\" class=\"form-control\"\n                               placeholder=\"\">\n                    </div>\n                </div>\n                <table id=\"exampleTable\" data-mobile-responsive=\"true\">\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n<div>\n    <script type=\"text/javascript\">\n        var s_add_h = 'hidden';\n        var s_edit_h = 'hidden';\n        var s_remove_h = 'hidden';\n        var s_resetPwd_h = 'hidden';\n    </script>\n</div>\n<div shiro:hasPermission=\"system:sysDept:edit\">\n    <script type=\"text/javascript\">\n        s_edit_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"system:sysDept:add\">\n    <script type=\"text/javascript\">\n        s_add_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"system:sysDept:remove\">\n    <script type=\"text/javascript\">\n        var s_remove_h = '';\n    </script>\n</div>\n<div shiro:hasPermission=\"system:sysDept:resetPwd\">\n    <script type=\"text/javascript\">\n        var s_resetPwd_h = '';\n    </script>\n</div>\n</div>\n<div th:include=\"include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/system/sysDept/sysDept.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/dept/deptTree.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\n\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t<div id=\"deptTree\"></div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group hidden\">\n\t\t\t\t\t<div class=\"col-sm-12 col-sm-offset-12\">\n\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include :: footer\"></div>\n\n\n\t<script type=\"text/javascript\">\n\t\t$(document).ready(function() {\n\t\t\tgetTreeData()\n\t\t});\n\t\tfunction getTreeData() {\n\t\t\t$.ajax({\n\t\t\t\ttype : \"GET\",\n\t\t\t\turl : \"/system/sysDept/tree\",\n\t\t\t\tsuccess : function(tree) {\n\t\t\t\t\tloadTree(tree);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tfunction loadTree(tree) {\n\t\t\t$('#deptTree').jstree({\n\t\t\t\t'core' : {\n\t\t\t\t\t'data' : tree\n\t\t\t\t},\n\t\t\t\t\"plugins\" : [ \"search\" ]\n\t\t\t});\n\t\t\t$('#deptTree').jstree().open_all();\n\t\t}\n\t\t$('#deptTree').on(\"changed.jstree\", function(e, data) {\n\t\t\tif(data.node.id!=-1){\n\t\t\t\tparent.loadDept(data.node.id,data.node.text);\n\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\t\tparent.layer.close(index);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/dept/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"deptId\" name=\"deptId\" th:value=\"${sysDept.deptId}\"\n\t\t\t\t\t\t\t\tclass=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label \">上级部门：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input th:value=\"${parentDeptName}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\" readonly=\"true\" />\n\t\t\t\t\t\t\t\t\t<input class=\"form-control hidden\" type=\"text\" id=\"parentId\" name=\"parentId\" th:value=\"${sysDept.parentId}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">部门名称：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" th:value=\"${sysDept.name}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">排序：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"orderNum\" name=\"orderNum\" th:value=\"${sysDept.orderNum}\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">状态:</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<label class=\"radio-inline\"> <input type=\"radio\" name=\"delFlag\" value=\"1\" checked/>\n\t\t\t\t\t\t\t\t\t\t正常\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\" name=\"delFlag\" value=\"0\"/>\n\t\t\t\t\t\t\t\t\t禁用\n\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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/system/sysDept/edit.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/menu/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"parentId\" name=\"parentId\" type=\"hidden\"\n\t\t\t\t\t\t\t\tth:value=\"${pId}\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">上级菜单：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"\" name=\"\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${pName}\" readonly>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tname=\"type\" value=\"0\" /> 目录\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tname=\"type\" value=\"1\" /> 菜单\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tname=\"type\" value=\"2\" /> 按钮\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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单名称：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">链接地址：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"url\" name=\"url\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">权限标识：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"perms\" name=\"perms\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">排序号：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"orderNum\" name=\"orderNum\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">图标：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-6\">\n\t\t\t\t\t\t\t\t\t<input id=\"icon\" name=\"icon\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"例如：fa fa-circle-o\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<input id=\"ico-btn\" class=\"btn btn-warning\" type=\"button\" value=\"选择图标\">\n\t\t\t\t\t\t\t</div>\n\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script src=\"/js/appjs/sys/menu/add.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/menu/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n\n<title></title>\n<meta name=\"keywords\" content=\"\">\n<meta name=\"description\" content=\"\">\n\n<link rel=\"shortcut icon\" href=\"favicon.ico\">\n<link href=\"/css/bootstrap.min.css?v=3.3.6\" rel=\"stylesheet\">\n<link href=\"/css/font-awesome.css?v=4.4.0\" rel=\"stylesheet\">\n<link href=\"/css/animate.css\" rel=\"stylesheet\">\n<link href=\"/css/style.css?v=4.1.0\" rel=\"stylesheet\">\n</head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"parentId\" name=\"parentId\" type=\"hidden\"\n\t\t\t\t\t\t\t\tth:value=\"${pId}\" /> <input id=\"menuId\" name=\"menuId\"\n\t\t\t\t\t\t\t\ttype=\"hidden\" th:value=\"${menu.menuId}\" />\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">上级菜单：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"\" name=\"\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${pName}\" readonly>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单类型：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tth:field=\"*{menu.type}\" name=\"type\" value=\"0\" /> 目录\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tth:field=\"*{menu.type}\" name=\"type\" value=\"1\" /> 菜单\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tth:field=\"*{menu.type}\" name=\"type\" value=\"2\" /> 按钮\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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单名称：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${menu.name}\" required>\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">链接地址：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"url\" name=\"url\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${menu.url}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">权限标识：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"perms\" name=\"perms\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tth:value=\"${menu.perms}\">\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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">排序号：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"orderNum\" name=\"orderNum\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${menu.orderNum}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">图标：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-5\">\n\t\t\t\t\t\t\t\t\t<input id=\"icon\" name=\"icon\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"例如：fa fa-circle-o\" th:value=\"${menu.icon}\">\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<input id=\"ico-btn\" class=\"btn btn-warning\" type=\"button\" value=\"选择图标\">\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<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-info\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script src=\"/js/appjs/sys/menu/edit.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/menu/menu.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div id=\"exampleToolbar\" role=\"group\" class=\"t-bar\">\n\t\t\t\t\t\t<button shiro:hasPermission=\"sys:menu:add\" type=\"button\"\n\t\t\t\t\t\t\tclass=\"btn btn-primary\" title=\"在根节点下添加菜单\" onclick=\"add('0')\">\n\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button shiro:hasPermission=\"sys:menu:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\tclass=\"btn btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_add_h = 'hidden';\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:menu:add\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\ts_add_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:user:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\ts_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:user:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script src=\"/js/appjs/sys/menu/menu.js\"></script>\n</body>\n\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/online/online.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t\n\t\t\t<div class=\"col-sm-11\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"columns pull-left\">\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<div class=\"columns pull-right\">\n\t\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"\">\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 id=\"exampleTable\" data-mobile-responsive=\"true\">\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<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/online/online.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/role/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include::header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-title\">\n\t\t\t\t\t\t<h5>   </h5>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"userId\" name=\"userId\" type=\"hidden\"> <input\n\t\t\t\t\t\t\t\tid=\"menuIds\" name=\"menuIds\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">角色名：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"roleName\" name=\"roleName\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">备注：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"remark\" name=\"remark\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单权限：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<div id=\"menuTree\"></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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/role/add.js\">\n\t</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/role/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include::header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"roleId\" name=\"roleId\" type=\"hidden\"\n\t\t\t\t\t\t\t\tth:value=\"${role.roleId}\"> <input id=\"menuIds\"\n\t\t\t\t\t\t\t\tname=\"menuIds\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">角色名：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"roleName\" name=\"roleName\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${role.roleName}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">备注：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"remark\" name=\"remark\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${role.remark}\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">菜单权限：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<div id=\"menuTree\"></div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include::footer\"></div>\n\t<script src=\"/js/appjs/sys/role/edit.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/role/role.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include::header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"col-sm-12\">\n\t\t\t<div class=\"ibox\">\n\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t<div id=\"exampleToolbar\" role=\"group\">\n\t\t\t\t\t\t<button shiro:hasPermission=\"sys:role:add\" type=\"button\"\n\t\t\t\t\t\t\tclass=\"btn btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button shiro:hasPermission=\"sys:role:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\tclass=\"btn btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-trash\" aria-hidden=\"true\"></i>删除\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<table id=\"exampleTable\" data-mobile-responsive=\"true\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<!--shiro控制bootstraptable行内按钮可见性 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:role:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\ts_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:role:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/role/role.js\">\n\t\t\n\t</script>\n</body>\n\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/user/add.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox float-e-margins\">\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t\t<input id=\"userId\" name=\"userId\" type=\"hidden\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">姓名：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">用户名：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"username\" name=\"username\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"text\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">密码：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"password\" name=\"password\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"password\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">部门：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"deptId\" name=\"deptId\" class=\"hidden\"> <input\n\t\t\t\t\t\t\t\t\t\tid=\"deptName\" name=\"deptName\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"cursor: pointer;\" onclick=\"openDept()\"\n\t\t\t\t\t\t\t\t\t\treadonly=\"readonly\" placeholder=\"所属部门\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">E-mail：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"email\" name=\"email\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\t\ttype=\"email\">\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">状态:</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tname=\"status\" value=\"1\" /> 正常\n\t\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input type=\"radio\"\n\t\t\t\t\t\t\t\t\t\tname=\"status\" value=\"0\" /> 禁用\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\t<input type=\"hidden\" name=\"roleIds\" id=\"roleIds\">\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">角色</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<label th:each=\"role:${roles}\" class=\"checkbox-inline\">\n\t\t\t\t\t\t\t\t\t\t<input name=\"role\" type=\"checkbox\" th:value=\"${role.roleId}\"\n\t\t\t\t\t\t\t\t\t\tth:text=\"${role.roleName}\">\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\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\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\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/user/add.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/user/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t<input id=\"userId\" name=\"userId\" th:value=\"${user.userId}\"\n\t\t\t\t\t\t\ttype=\"hidden\">\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">姓名：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"name\" name=\"name\" class=\"form-control\" type=\"text\"\n\t\t\t\t\t\t\t\t\tth:value=\"${user.name}\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">用户名：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"username\" name=\"username\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\ttype=\"text\" th:value=\"${user.username}\" readonly>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">部门：</label>\n\t\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t\t<input id=\"deptId\" name=\"deptId\" class=\"hidden\" th:value=\"${user.deptId}\">\n\t\t\t\t\t\t\t\t\t <input id=\"deptName\" name=\"deptName\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" type=\"text\" style=\"cursor: pointer;\"\n\t\t\t\t\t\t\t\t\t\tonclick=\"openDept()\" readonly=\"readonly\" placeholder=\"所属部门\" th:value=\"${user.deptName}\">\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 class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">E-mail：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"email\" name=\"email\" class=\"form-control\" type=\"email\"\n\t\t\t\t\t\t\t\t\tth:value=\"${user.email}\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">状态:</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<label class=\"radio-inline\"> <input\n\t\t\t\t\t\t\t\t\tth:field=\"*{user.status}\" type=\"radio\" name=\"status\" value=\"1\" />\n\t\t\t\t\t\t\t\t\t正常\n\t\t\t\t\t\t\t\t</label> <label class=\"radio-inline\"> <input\n\t\t\t\t\t\t\t\t\tth:field=\"*{user.status}\" type=\"radio\" name=\"status\" value=\"0\" />\n\t\t\t\t\t\t\t\t\t禁用\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<input type=\"hidden\" name=\"roleIds\" id=\"roleIds\"\n\t\t\t\t\t\t\tth:value=\"${roleIds}\">\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">角色</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<label th:each=\"role:${roles}\" class=\"checkbox-inline\">\n\t\t\t\t\t\t\t\t\t<input name=\"role\" type=\"checkbox\" th:value=\"${role.roleId}\"\n\t\t\t\t\t\t\t\t\tth:text=\"${role.roleName}\" th:checked=\"${role.roleSign}\">\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include::footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/user/edit.js\">\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/user/include.html",
    "content": "<head th:fragment=\"header\">\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t<title></title>\n\t<meta name=\"keywords\" content=\"\">\n\t<meta name=\"description\" content=\"\">\n\t<link rel=\"shortcut icon\" href=\"favicon.ico\">\n\t<link rel=\"stylesheet\" href=\"/css/bootstrap.min.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/animate.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/font-awesome.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/style.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/plugins/iCheck/custom.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/plugins/cropper/cropper.css\" />\n\t<link rel=\"stylesheet\" href=\"/js/plugins/layer/laydate/skins/default/laydate.css\" />\n\t<link rel=\"stylesheet\" href=\"/css/gg-bootdo.css\" />\n</head>\n<div th:fragment=\"footer\">\n\t<script type=\"text/javascript\" src=\"/js/jquery.min.js\" ></script>\n\t<script type=\"text/javascript\" src=\"/js/bootstrap.min.js\" ></script>\n\t<script type=\"text/javascript\" src=\"/js/plugins/iCheck/icheck.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugins/cropper/cropper.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugins/layer/laydate/laydate.js\" ></script>\n\t<script type=\"text/javascript\" src=\"/js/plugins/distpicker/distpicker.data.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugins/distpicker/distpicker.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/user/gg-bootdo.js\"></script>\n\t<!--校验插件-->\n\t<script src=\"/js/plugins/validate/jquery.validate.min.js\"></script>\n\t<script src=\"/js/plugins/validate/jquery.validate.extend.js\"></script>\n\t<script src=\"/js/plugins/validate/messages_zh.min.js\"></script>\n</div>\n"
  },
  {
    "path": "src/main/resources/templates/system/user/personal.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n\n<head th:include=\"system/user/include :: header\"></head>\n\n<body class=\"gray-bg\">\n<div class=\"wrapper wrapper-content animated fadeInRight\">\n    <div class=\"row\">\n        <div class=\"col-lg-12 col-md-12 col-sm-12\">\n            <div class=\"ibox\">\n                <div class=\"ibox-title\" style=\"padding-bottom: 0;\">\n                    <h3 class=\"text-center\">个人资料中心</h3>\n                    <div class=\"gg-nav\">\n                        <ul class=\"nav nav-tabs\">\n                            <li class=\"active\"><a href=\"#basic_info\" data-toggle=\"tab\">基本资料</a></li>\n                            <li><a href=\"#photo_info\" data-toggle=\"tab\">头像修改</a></li>\n                            <li><a href=\"#pwd_info\" data-toggle=\"tab\">修改密码</a></li>\n                        </ul>\n                    </div>\n                </div>\n                <div class=\"tab-content\">\n                    <!--basic info-->\n                    <div class=\"ibox-content tab-pane fade in active\"  id=\"basic_info\">\n                        <form class=\"gg-form\" role=\"form\" id=\"basicInfoForm\">\n                            <input name=\"userId\" type=\"hidden\" th:value=\"${user.userId}\"/>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>姓名:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <input type=\"text\" class=\"form-control\" id=\"userName\" name=\"name\" th:value=\"${user.name}\"  placeholder=\"请输入姓名\" />\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>性别:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <div class=\"radio i-checks\">\n                                        <label class=\"radio-inline\" th:each=\"sex:${sexList}\"> <input\n                                                th:field=\"*{user.sex}\" type=\"radio\" name=\"sex\" th:value=\"${sex.id}\" th:text=\"${sex.name}\"/>\n                                        </label>\n                                    </div>\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>出生年月:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <input type=\"text\" class=\"laydate-icon layer-date form-control\" id=\"birth\" name=\"birth\" th:value=\"${user.birth}==null?null:${#dates.format(user.birth,'yyyy-MM-dd')}\" placeholder=\"请选择出生年月\"\n                                           onclick=\"laydate({istime: true, format: 'YYYY-MM-DD'})\" style=\"background-color: #fff;\" readonly=\"readonly\"/>\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>手机:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <input type=\"text\" class=\"form-control\" id=\"phone\" name=\"mobile\"  th:value=\"${user.mobile}\" placeholder=\"请输入手机号\" />\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>邮箱:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <input type=\"text\" class=\"form-control\" id=\"email\" name=\"email\" th:value=\"${user.email}\" placeholder=\"请输入邮箱\" />\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>居住地:</span>\n                                </div>\n                                <div class=\"gg-formDetail gg-font0\" data-toggle=\"distpicker\"  th:attr=\"data-province=${user.province},data-city=${user.city},data-district=${user.district}\">\n                                    <div class=\"gg-area\">\n                                        <select class=\"form-control\" id=\"province\" name=\"province\">\n                                        </select>\n                                    </div>\n                                    <div class=\"gg-area\">\n                                        <select class=\"form-control\" id=\"city\" name=\"city\">\n                                        </select>\n                                    </div>\n                                    <div class=\"gg-area\">\n                                        <select class=\"form-control\" id=\"district\" name=\"district\">\n                                        </select>\n                                    </div>\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>联系地址:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <input type=\"text\" class=\"form-control\" id=\"address\" name=\"liveAddress\" th:value=\"${user.liveAddress}\" placeholder=\"请输入居住地址\" />\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>爱好:</span>\n                                </div>\n                                <div class=\"gg-formDetail\">\n                                    <div class=\"checxbox i-checks\" >\n                                        <input type=\"hidden\" name=\"hobby\" id=\"hobby\"/>\n                                        <label th:each=\"hobby : ${hobbyList}\">\n                                            <input type=\"checkbox\" class=\"hobby\"  th:value=\"${hobby.id}\" th:text=\"${hobby.name}\" th:checked=\"${hobby.remarks}=='true'\"/>\n                                        </label>\n                                    </div>\n                                </div>\n                            </div>\n                        </form>\n                        <div class=\"gg-btnGroup\">\n                            <button type=\"button\" class=\"btn btn-sm btn-primary\" id=\"base_save\">保存</button>\n                        </div>\n                    </div>\n                    <!--photo_info-->\n                    <div class=\"ibox-content tab-pane fade gg\" id=\"photo_info\">\n                        <div class=\"ggcontainer\" id=\"crop-avatar\">\n                            <form class=\"avatar-form\" action=\"/sys/user/uploadImg\" enctype=\"multipart/form-data\" method=\"post\">\n                                <div class=\"avatar-body\">\n                                    <div class=\"avatar-upload\">\n                                        <input class=\"avatar-src\" name=\"avatar_src\" type=\"hidden\">\n                                        <input class=\"avatar-data\" name=\"avatar_data\" type=\"hidden\">\n                                        <label for=\"avatarInput\">选取文件</label>\n                                        <input class=\"avatar-input\" id=\"avatarInput\" name=\"avatar_file\" type=\"file\">\n                                    </div>\n                                    <!-- Crop and preview -->\n                                    <div class=\"row\">\n                                        <div class=\"col-md-9\">\n                                            <div class=\"avatar-wrapper\"></div>\n                                        </div>\n                                        <div class=\"col-md-3\">\n                                            <div class=\"avatar-preview preview-lg\"></div>\n                                            <div class=\"avatar-preview preview-md\"></div>\n                                            <div class=\"avatar-preview preview-sm\"></div>\n                                        </div>\n                                    </div>\n\n                                    <div class=\"row avatar-btns\">\n                                        <div class=\"col-md-9\">\n                                            <div class=\"btn-group\">\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"-90\" type=\"button\" title=\"Rotate -90 degrees\">左旋转</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"-15\" type=\"button\">-15°</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"-30\" type=\"button\">-30°</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"-45\" type=\"button\">-45°</button>\n                                            </div>\n                                            <div class=\"btn-group\">\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"90\" type=\"button\" title=\"Rotate 90 degrees\">右旋转</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"15\" type=\"button\">15°</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"30\" type=\"button\">30°</button>\n                                                <button class=\"btn btn-primary\" data-method=\"rotate\" data-option=\"45\" type=\"button\">45°</button>\n                                            </div>\n                                        </div>\n                                        <div class=\"col-md-3\">\n                                            <button class=\"btn btn-primary btn-block avatar-save\" type=\"submit\">完成裁剪</button>\n                                        </div>\n                                    </div>\n                                </div>\n                            </form>\n                            <!-- Loading state -->\n                            <div class=\"loading\" aria-label=\"Loading\" role=\"img\" tabindex=\"-1\"></div>\n                        </div>\n                    </div>\n                    <!--pwd_info-->\n                    <div class=\"ibox-content tab-pane fade\" id=\"pwd_info\">\n                        <form class=\"gg-form\" role=\"form\" id=\"modifyPwd\">\n                            <a id=\"logout\" class=\"hidden\" href=\"/logout\"></a>\n                            <input type=\"hidden\" name =\"userDO.userId\" th:value=\"${user.userId}\"/>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>旧密码:</span>\n                                </div>\n                                <div class=\"gg-formDetail gg-dashed\">\n                                    <input type=\"password\" class=\"form-control gg-border0\" id=\"pwdOld\" name=\"pwdOld\" placeholder=\"请输入旧密码\" />\n                                    <span class=\"fa fa-eye gg-faeye\" title=\"鼠标移入显示内容\"><span>\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>新密码:</span>\n                                </div>\n                                <div class=\"gg-formDetail gg-dashed\">\n                                    <input type=\"password\" class=\"form-control gg-border0\" id=\"pwdNew\" name=\"pwdNew\" placeholder=\"请输入新密码\" />\n                                    <span class=\"fa fa-eye gg-faeye\" title=\"鼠标移入显示内容\"></span>\n                                </div>\n                            </div>\n                            <div class=\"gg-formGroup\">\n                                <div class=\"gg-formTitle\">\n                                    <em class=\"gg-star\">*</em>\n                                    <span>确认密码:</span>\n                                </div>\n                                <div class=\"gg-formDetail gg-dashed\">\n                                    <input type=\"password\" class=\"form-control gg-border0\" id=\"confirm_password\" name=\"confirm_password\" placeholder=\"请确认密码\" />\n                                    <span class=\"fa fa-eye gg-faeye\" title=\"鼠标移入显示内容\"></span>\n                                </div>\n                            </div>\n                        </form>\n                        <div class=\"gg-btnGroup\">\n                            <button type=\"button\" class=\"btn btn-sm btn-primary\" id=\"pwd_save\">保存</button>\n                        </div>\n                    </div>\n\n                </div>\n\n            </div>\n        </div>\n    </div>\n</div>\n<div th:include=\"system/user/include :: footer\"></div>\n<script type=\"text/javascript\" src=\"/js/appjs/sys/user/personal.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/user/reset_pwd.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content animated fadeInRight\">\n\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\n\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t<form class=\"form-horizontal m-t\" id=\"signupForm\">\n\t\t\t\t\t\t<input id=\"userId\" name=\"userDO.userId\" th:value=\"${user.userId}\"\n\t\t\t\t\t\t\ttype=\"hidden\">\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<label class=\"col-sm-3 control-label\">输入密码：</label>\n\t\t\t\t\t\t\t<div class=\"col-sm-8\">\n\t\t\t\t\t\t\t\t<input id=\"password\" name=\"pwdNew\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\ttype=\"password\" value=\"111111\">\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t<div class=\"col-sm-8 col-sm-offset-3\">\n\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\">提交</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\n\n\t<!-- 全局js -->\n\t<script src=\"/js/jquery.min.js?v=2.1.4\"></script>\n\t<script src=\"/js/bootstrap.min.js?v=3.3.6\"></script>\n\n\t<!-- 自定义js -->\n\t<script src=\"/js/content.js?v=1.0.0\"></script>\n\n\t<!-- jQuery Validation plugin javascript-->\n\t<script src=\"/js/plugins/validate/jquery.validate.min.js\"></script>\n\t<script src=\"/js/plugins/validate/messages_zh.min.js\"></script>\n\n\n\t<!-- script src=\"/js/demo/form-validate-demo.js\"></script> -->\n\n\n\t<script type=\"text/javascript\">\n\t\t$(document).ready(function() {\n\t\t\tvalidateRule();\n\t\t\t//setCheckedRoles();\n\t\t});\n\t\t$.validator.setDefaults({\n\t\t\tsubmitHandler : function() {\n\t\t\t\tupdate();\n\t\t\t}\n\t\t});\n\t\tfunction update() {\n\t\t\t$.ajax({\n\t\t\t\tcache : true,\n\t\t\t\ttype : \"POST\",\n\t\t\t\turl : \"/sys/user/adminResetPwd\",\n\t\t\t\tdata : $('#signupForm').serialize(),// 你的formid\n\t\t\t\tasync : false,\n\t\t\t\terror : function(request) {\n\t\t\t\t\tparent.layer.msg(\"系统错误，联系管理员\");\n\t\t\t\t},\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tif (data.code == 0) {\n\t\t\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t\t\t\tparent.reLoad();\n\t\t\t\t\t\tvar index = parent.layer.getFrameIndex(window.name); //获取窗口索引\n\t\t\t\t\t\tparent.layer.close(index);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparent.layer.msg(data.msg);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\n\t\tfunction validateRule() {\n\t\t\tvar icon = \"<i class='fa fa-times-circle'></i> \";\n\t\t\t$(\"#signupForm\").validate({\n\t\t\t\trules : {\n\n\t\t\t\t\tpassword : {\n\t\t\t\t\t\trequired : true,\n\t\t\t\t\t\tminlength : 6\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmessages : {\n\t\t\t\t\tpassword : {\n\t\t\t\t\t\trequired : icon + \"请输入您的密码\",\n\t\t\t\t\t\tminlength : icon + \"密码必须6个字符以上\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/main/resources/templates/system/user/user.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh_CN\" xmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:shiro=\"http://www.pollix.at/thymeleaf/shiro\">\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-3\">\n\t\t\t\t<div class=\"ibox ibox-body\">\n\t\t\t\t\t<div class=\"ibox-title\">\n\t\t\t\t\t\t<h5>选择部门</h5>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t\t<div id=\"jstree\"></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=\"col-sm-8\">\n\t\t\t\t<div class=\"ibox\">\n\t\t\t\t\t<div class=\"ibox-body\">\n\t\t\t\t\t\t<div class=\"fixed-table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"columns pull-left\">\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:add\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-primary\" onclick=\"add()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus hidden\" aria-hidden=\"true\"></i>添加\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button shiro:hasPermission=\"sys:user:batchRemove\" type=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"btn  btn-danger\" onclick=\"batchRemove()\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash hidden\" aria-hidden=\"true\"></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=\"columns pull-right\">\n\t\t\t\t\t\t\t\t<button class=\"btn btn-success\" onclick=\"reLoad()\">查询</button>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div class=\"columns pull-right col-md-2 nopadding\">\n\t\t\t\t\t\t\t\t<input id=\"searchName\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"姓名\">\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 id=\"exampleTable\" data-mobile-responsive=\"true\">\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<!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->\n\t\t<div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_edit_h = 'hidden';\n\t\t\t\tvar s_remove_h = 'hidden';\n\t\t\t\tvar s_resetPwd_h = 'hidden';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:user:edit\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\ts_edit_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:user:remove\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_remove_h = '';\n\t\t\t</script>\n\t\t</div>\n\t\t<div shiro:hasPermission=\"sys:user:resetPwd\">\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\tvar s_resetPwd_h = '';\n\t\t\t</script>\n\t\t</div>\n\t</div>\n\t<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\" src=\"/js/appjs/sys/user/user.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/system/user/userTree.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"utf-8\">\n<head th:include=\"include :: header\"></head>\n<body class=\"gray-bg\">\n\t<div class=\"wrapper wrapper-content \">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-sm-12\">\n\t\t\t\t<div class=\"ibox-content\">\n\t\t\t\t\t<div id=\"jsTree\"></div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group \">\n\t\t\t\t\t<div class=\"col-sm-12 col-sm-offset-12\">\n\t\t\t\t\t\t<button type=\"submit\" onclick=\"loadUser()\" class=\"btn btn-primary\">提交</button>\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<div th:include=\"include :: footer\"></div>\n\t<script type=\"text/javascript\">\n\t\t$(document).ready(function() {\n\t\t\tgetTreeData()\n\t\t});\n\t\tfunction getTreeData() {\n\t\t\t$.ajax({\n\t\t\t\ttype : \"GET\",\n\t\t\t\turl : \"/sys/user/tree\",\n\t\t\t\tsuccess : function(tree) {\n\t\t\t\t\tloadTree(tree);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tfunction loadTree(tree) {\n\t\t\t$('#jsTree').jstree({\n\t\t\t\t'core' : {\n\t\t\t\t\t'data' : tree\n\t\t\t\t},\n\t\t\t\t\"plugins\" : [ \"checkbox\" ]\n\t\t\t});\n\t\t\t$('#jsTree').jstree().open_all();\n\t\t}\n\t\tfunction loadUser(){\n\t\t\tvar userNames,userIds;\n\t\t\tvar ref = $('#jsTree').jstree(true); // 获得整个树\n\t\t\tuserIds = ref.get_bottom_selected();\n\t\t\tusers = ref.get_bottom_checked('true');\n\t\t\tvar txt=\"\";\n\t\t\tfor(var user in users){\n\t\t\t\tif(users[user].state.mType==\"user\"){\n\t\t\t\t\ttxt=txt+users[user].text+\",\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tparent.loadUser(userIds,txt);\n\t\t\tvar index = parent.layer.getFrameIndex(window.name); // 获取窗口索引\n\t\t\tparent.layer.close(index);\n\t\t}\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "src/test/java/me/zbl/app/LowerLimitTest.java",
    "content": "/*\n * Copyright 2018 JamesZBL\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 */\npackage me.zbl.app;\n\nimport me.zbl.app.service.DrugOutService;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n/**\n * @author JamesZBL\n * @email 1146556298@qq.com\n * @date 2018-05-12\n */\n@SpringBootTest\n@RunWith(SpringRunner.class)\npublic class LowerLimitTest {\n\n  @Autowired\n  DrugOutService drugOutService;\n\n  /**\n   * 测试库存下限提醒\n   */\n  @Test\n  public void doTest() {\n    drugOutService.checkLowerLimit();\n  }\n}\n"
  },
  {
    "path": "src/test/java/me/zbl/testDemo/TestDemo.java",
    "content": "package me.zbl.testDemo;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.core.ValueOperations;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.concurrent.TimeUnit;\n\n@RestController()\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class TestDemo {\n\n}\n"
  }
]